React最佳实践
shouldComponentUpdate
shouldComponentUpdate
2015年完成目标
展望2016
持续集成
现有持续集成CI(Continuous integration)管理系统有Jenkins, Travis CI, TeamCity, gitlab CI
持续集成,自动化构建,自动化发布,自动化测试
Travis CI
主要功能就是为开源社区提供免费的CI服务,对于商业用户可以使用Travis Pro版本, Travis CI只支持github极大的限制了其应用场景。但是也由于其只支持github,其把和github的集成做到了极致的平滑,易用,因此,对于本就把github作为代码托管平台的项目来说,Travis CI可以做为第一选择。
jenkins的特点
流程进化过程
切图-->code-->丢给后端
切图-->code-->提交代码-->手动修改版本号-->手动ftp发
更新项目字体库-->code-->提交代码-->前端自动发布-->自动添加版本号
更新项目字体库-->code-->提交代码-->git通知code reviewer审查代码-->审查通过-->通知测试发布项目-->jenkins自动发布到服务器
更完善的发布流程
持续集成流程
优化点
jenkins配置
生成的mapping json文件
{
"/class/common/bundle.js":"/class/common/bundle-15c92.js",
"/class/common/bundle.css":"/class/common/bundle-b2f6b.css",
"/class/app/courseList/bundle.js":"/class/app/courseList/bundle-15c92.js",
"/class/app/courseList/bundle.css":"/class/app/courseList/bundle-0d8b6.css"
}
静态资源引用方式
读取mapping json文件找到相应的映射文件
<script src="<%=YesHJ.Class.ClassStaticHelper.GetSource("/class/app/course/bundle.js")%>"></script>
后期优化点
继续探索...
添加环境变量
<!--有一定浏览器兼容性问题-->
<style>
.content{
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>
<div class="content">
-webkit-line-clamp is an unsupported WebKit property that limits the number of lines of text displayed in a block element. In order to achieve the effect, it needs to be combo-ed with a couple of other exotic WebKit properties.
</div>
Baseline JPEG 与 Progressive JPEG的区别
Baseline JPEG是从上往下加载,而Progressive JPEG是从模糊到清晰加载
Chrome + Firefox + IE9 下 Progressive JPEG 加载很快
Progressive 比 Baseline 格式小几KB
大于 10K 的图片,Progressive 格式更小 (in 94% of the cases)
小于 10K 的图片,Baseline格式更小(75%)
测试结果:
[此处可选]
参见performance.timing
首屏依赖数据的话,首屏速度参照data-render-end,反之,参照js-called-end
[可选]
[可选]
<script>
//copy from taobao
!function (win) {
function refreshRem() {
var width = docEl.getBoundingClientRect().width;
width / dpr > 540 && (width = 540 * dpr), win.rem = width / 16, docEl.style.fontSize = win.rem + "px"
}
var dpr, scale, tid, doc = win.document, docEl = doc.documentElement, metaEl = doc.querySelector('meta[name="viewport"]'), flexibleEl = doc.querySelector('meta[name="flexible"]');
if (metaEl) {
var match = metaEl.getAttribute("content").match(/initial\-scale=(["']?)([\d\.]+)\1?/);
match && (scale = parseFloat(match[2]), dpr = parseInt(1 / scale))
} else if (flexibleEl) {
var match2 = flexibleEl.getAttribute("content").match(/initial\-dpr=(["']?)([\d\.]+)\1?/);
match2 && (dpr = parseFloat(match2[2]), scale = parseFloat((1 / dpr).toFixed(2)))
}
if (!dpr && !scale) {
var k = (win.navigator.appVersion.match(/android/gi), win.navigator.appVersion.match(/iphone/gi)), devicePixelRatio = win.devicePixelRatio;
dpr = k ? devicePixelRatio >= 3 ? 3 : devicePixelRatio >= 2 ? 2 : 1 : 1, scale = 1 / dpr
}
if (docEl.setAttribute("data-dpr", dpr), !metaEl)if (metaEl = doc.createElement("meta"), metaEl.setAttribute("name", "viewport"), metaEl.setAttribute("content", "initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no"), docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
}else {
var l = doc.createElement("div");
l.appendChild(metaEl), doc.write(l.innerHTML)
}
win.dpr = dpr, win.addEventListener("resize", function () {
clearTimeout(tid), tid = setTimeout(refreshRem, 300)
}, !1), win.addEventListener("pageshow", function (e) {
e.persisted && (clearTimeout(tid), tid = setTimeout(refreshRem, 300))
}, !1), "complete" === doc.readyState ? doc.body.style.fontSize = 12 * dpr + "px" : doc.addEventListener("DOMContentLoaded", function () {
doc.body.style.fontSize = 12 * dpr + "px"
}, !1), refreshRem()
}(window);
</script>
React add-ons
React.addons 是编译react代码的工具方法集合,包含如下方法:
使用方法
引入 react-eith-addons.js 或 require('react/addons')
classSet
// inside some `<Message />` React component
render: function() {
var classString = 'message';
if (this.props.isImportant) {
classString += ' message-important';
}
if (this.props.isRead) {
classString += ' message-read';
}
// 'message message-important message-read'
return <div className={classString}>Great, I'll be there.</div>;
}
上面的处理方式比较冗长,使用classSet()方法处理如下:
render: function() {
var cx = React.addons.classSet;
var classes = cx({
'message': true,
'message-important': this.props.isImportant,
'message-read': this.props.isRead
});
// same final string, but much cleaner
return <div className={classes}>Great, I'll be there.</div>;
}
属性校验
随着应用的增长,确保你的组件正确使用是有必要的。React允许我们指定propTypes。React.PropTypes声明了一系列的校验确保我们接收的数据是合法的。如果不合法的数据出现在属性当中,控制台会打印警告信息。下面是不同的校验类型:
React.createClass({
propTypes: {
// You can declare that a prop is a specific JS primitive. By default, these
// are all optional.
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
// Anything that can be rendered: numbers, strings, elements or an array
// containing these types.
optionalNode: React.PropTypes.node,
// A React element.
optionalElement: React.PropTypes.element,
// You can also declare that a prop is an instance of a class. This uses
// JS's instanceof operator.
optionalMessage: React.PropTypes.instanceOf(Message),
// You can ensure that your prop is limited to specific values by treating
// it as an enum.
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
// An object that could be one of many types
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
]),
// An array of a certain type
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
// An object with property values of a certain type
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
// An object taking on a particular shape
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
}),
// You can chain any of the above with `isRequired` to make sure a warning
// is shown if the prop isn't provided.
requiredFunc: React.PropTypes.func.isRequired,
// A value of any data type
requiredAny: React.PropTypes.any.isRequired,
// You can also specify a custom validator. It should return an Error
// object if the validation fails. Don't `console.warn` or throw, as this
// won't work inside `oneOfType`.
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error('Validation failed!');
}
}
},
/* ... */
});
添加属性默认值
添加自定义属性的默认值
var ComponentWithDefaultProps = React.createClass({
getDefaultProps: function() {
return {
value: 'default value'
};
}
/* ... */
});
批处理语法
echo 表示显示此命令后的字符
echo off 表示在此语句后所有运行的命令都不显示命令行本身
@与echo
off相象,但它是加在每个命令行的最前面,表示运行时不显示这一行的命令行(只能影响当前行)。
call 调用另一个批处理文件(如果不用call而直接调用别的批处理文件,那么执行完那个批处理文件后将无法返回当前文件并执行当前文件的后续命令)。
pause 运行此句会暂停批处理的执行并在屏幕上显示Press any key to continue... 的提示,等待用户按任意键后继续
rem 表示此命令后的字符为解释行(注释),不执行,只是给自己今后参考用的(相当于程序中的注释)。
@echo off //不显示后续命令行及当前命令行
dir c://*.* >a.txt //将c盘文件列表写入a.txt
call c://ucdos//ucdos.bat //调用ucdos
echo 你好 //显示"你好"
pause //暂停,等待按键继续
rem 准备运行wps //注释:准备运行wps
cd ucdos //进入ucdos目录
wps //运行wps
批处理参数
%[1-9]表示参数,参数是指在运行批处理文件时在文件名后加的以空格(或者Tab)分隔的字符串。变量可以从%0到%9,%0表示批处理命令本身,其它参数字符串用%1到%9顺序表示。
@echo off
type %1
type %2
那么运行C://>t a.txt b.txt
%1 : 表示a.txt
%2 : 表示b.txt
批处理条件判断
-if [not] "参数" == "字符串" 待执行的命令,如if "%1"=="a" format a:
参数如果等于(not表示不等,下同)指定的字符串,则条件成立,运行命令,否则运行下一句。
-if [not] exist [路径//]文件名 待执行的命令,如if exist c://config.sys type c://config.sys
如果有指定的文件,则条件成立,运行命令,否则运行下一句。
-if errorlevel <数字> 待执行的命令,如if errorlevel 2 goto x2
很多DOS程序在运行结束后会返回一个数字值用来表示程序运行的结果(或者状态),通过if errorlevel命令可以判断程序的返回值,根据不同的返回值来决定执行不同的命令(返回值必须按照从大到小的顺序排列)。如果返回值等于指定的数字,则条件成立,运行命令,否则运行下一句。
goto
跳到goto所指定的标记处
goto end
:end
echo this is the end
call命令
从一个批处理程序调用另一个批处理程序,并且不终止父批处理程序。
call [[Drive:][Path] FileName [BatchParameters]] [:label [arguments]]
koa-compose 多个中间件合并
下面是使用.call(this,next),将多个中间件合并:
function *random(next) {
if ('/random' == this.path) {
this.body = Math.floor(Math.random()*10);
} else {
yield next;
}
};
function *backwards(next) {
if ('/backwards' == this.path) {
this.body = 'sdrawkcab';
} else {
yield next;
}
}
function *pi(next) {
if ('/pi' == this.path) {
this.body = String(Math.PI);
} else {
yield next;
}
}
function *all(next) {
yield random.call(this, backwards.call(this, pi.call(this, next)));
}
app.use(all);
更好的合并方式:
var compose = require('koa-compose'),
session = require('koa-session'),
jsonp = require('koa-jsonp'),
serve = require('koa-static'),
lusca = require('koa-lusca');
module.exports = function(app) {
return compose([
lusca(),
session(app),
jsonp(),
serve(app.config.publicFolder)
]);
};
$.fn.huiCalendar = function(options){
var args = Array.prototype.slice.call(arguments, 1);
var res = this;
this.each(function(i, _element) {
var element = $(_element);
var calendar = element.data('huiCalendar');
var singleRes;
if (typeof options === 'string') {
if (calendar && $.isFunction(calendar[options])) {
singleRes = calendar[options].apply(calendar, args);
if (!i) {
res = singleRes;
}
if (options === 'destroy') {
element.removeData('huiCalendar');
}
}
}
else if (!calendar) {
calendar = new HuiCalendar(element, options);
element.data('huiCalendar', calendar);
}
});
return res;
};
git add时候报错:LF will be replaced by CRLF
报错如下错误
js
warning: LF will be replaced by CRLF
fatal: CRLF would be replaced by LF
core.autocrlf 设置成false
#备注可以使用--global 也可以不实用,影响不大
git config --global core.autocrlf true #这个是转换,也是默认值
git config --global core.autocrlf input #貌似是上库转换,从库中迁出代码不转换
git config --global core.autocrlf false #这个一般是window上的,不转换
//重复mount一个组件
/* 第一次 render */
getDefaultProps
getInitialState
componentWillMount
render
componentDidMount
/* 第二次 render */
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
//先mount后unmount组件
/* mount */
getDefaultProps
getInitialState
componentWillMount
render
componentDidMount
/* unmount */
componentWillUnmount
mac上安装nginx
下载链接:
http://nginx.org/en/download.html
http://nginx.org/download/nginx-1.2.0.tar.gz
//step1: 解压安装文件
tar -xf nginx-1.2.0.tar.gz
//step2: 进入解压目录
chmod a+rwx *
//step3: 配置nginx要安装的插件
./configure --user=nginx --group=nginx --prefix=/opt/nginx --with-http_realip_module --with-http_addition_module --with-http_gzip_static_module --with-http_random_index_module --with-http_stub_status_module --with-http_sub_module --with-http_dav_module --with-http_perl_module --with-http_ssl_module
//step4: 安装
make && make install
//step5: 启动ngnix
sudo /usr/local/nginx/sbin/nginx
浏览器访问 http://localhost,页面上出现“welcome to nginx!”,说明安装成功!
let
体现了ES6中的块级作用域的效果,只能在代码块中使用
不会变量提升,所以不能提前调用
在同一作用域中不允许重复申明
不会绑定在window上,所以访问是undefined
const
声明变量和常量,一旦申明,值不能修改,其余的跟let规则
跨模块常量使用export,import 去访问
变量的解构赋值
var [a, b, c] = [1, 2, 3];
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [,,third] = ["foo", "bar", "baz"];
third // "baz"
如下都返回undefined,最后两种情况报错
var [foo] = [];
var [foo] = 1;
var [foo] = false;
var [foo] = NaN;
var [bar, foo] = [1];
// 报错
let [foo] = undefined;
let [foo] = null;
字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
函数参数的解构赋值
function add([x, y]){
return x + y;
}
add([1, 2]) // 3
//指定函数的默认值
function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
从函数返回多个值
//返回一个数组
function example() {
return [1, 2, 3];
}
var [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
var { foo, bar } = example();
对象的扩展
function getPoint() {
var x = 1;
var y = 10;
return {x, y};
}
getPoint()
// {x:1, y:10}
class基本语法
与ES5一样,实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)。
//定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '('+this.x+', '+this.y+')';
}
}
var point = new Point(2, 3);
point.toString() // (2, 3)
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true
不存在变量提升
Class不存在变量提升(hoist),这一点与ES5完全不同。
new Foo(); // ReferenceError
class Foo {}
class 继承
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 调用父类的constructor(x, y),如果没有写constructor方法,会非显式定义constructor
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 调用父类的toString()
}
}
ES6新增了let命令,用来声明变量,它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。let不像var那样,会发生“变量提升”现象。
当前作用域内的声明都会提升到作用域的最前面,包括变量和函数的声明
(function(){
var a = "1";
var f = function(){};
var b = "2";
var c = "3";
})();
变量a,f,b,c的声明会被提升到函数作用域的最前面,类似如下:
(function(){
var a,f,b,c;
a = "1";
f = function(){};
b = "2";
c = "3";
})();
请注意函数表达式并没有被提升,这也是函数表达式与函数声明的区别。进一步看二者的区别:
(function(){
//var f1,function f2(){}; //hoisting,被隐式提升的声明
f1(); //ReferenceError: f1 is not defined
f2();
var f1 = function(){};
function f2(){}
})();
上面代码中函数声明f2被提升,所以在前面调用f2是没问题的。虽然变量f1也被提升,但f1提升后的值为undefined,其真正的初始值是在执行到函数表达式处被赋予的。所以只有声明是被提升的。
deepClone = function(obj) { //deep clone a plain object
var input = __slice.call(arguments, 1),
key,
value;
for (var i = 0, length = input.length; i < length; i++) {
for (key in input[i]) {
value = input[i][key];
if (input[i].hasOwnProperty(key) && value !== undefined) {
// Clone objects
if (__isPlainObject(value)) {
obj[key] = __isPlainObject(obj[key]) ?
__extend({}, obj[key], value) :
// Don't extend strings, arrays, etc. with objects
__extend({}, value);
// Copy everything else by reference
} else {
obj[key] = value;
}
}
}
}
return obj;
}
现在chrome,firefox等高级浏览器已经内置Promise对象,提供两个方法:
Promise.reject()
Promise.resolve()
when.js 丰富了API
jQuery中,很多的操作都返回的是Deferred或promise,如animate、ajax:
// animate
$('.box')
.animate({'opacity': 0}, 1000)
.promise()
.then(function() {
console.log('done');
});
// ajax
$.ajax(options).then(success, fail);
$.ajax(options).done(success).fail(fail);
// ajax queue
$.when($.ajax(options1), $.ajax(options2))
.then(function() {
console.log('all done.');
}, function() {
console.error('There something wrong.');
});
Object.getOwnPropertyDescriptor 获取描述属性特性的描述符对象
// Create a user-defined object.
var obj = {};
// Add a data property.
obj.newDataProperty = "abc";
// Get the property descriptor.
var descriptor = Object.getOwnPropertyDescriptor(obj, "newDataProperty");
// Change a property attribute.
descriptor.writable = false;
Object.defineProperty(obj, "newDataProperty", descriptor);
Object.defineProperty 用于添加或修改属性
var _createClass = (function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ('value' in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function(Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
})();
<script>
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD (Register as an anonymous module)
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function($){
// 待转化库
}));
</script>
一. 加载性能优化方案
1.服务器端访问优化
Gzip压缩项目文件大小
CDN加速,加快资源的访问速度
分布式静态服务器请求静态文件,设置浏览器缓存
2.HTTPS请求优化
保证请求资源尽量小
减少文件数量,减少文件请求
3.浏览器端渲染优化
1) DOM加载优化
避免使用iframe,阻塞父级页面onload
精简DOM结构
2)图片加载优化
初始首屏之外的图片资源需延迟加载
图片使用CSS Sprites 或 DATA URL 尽量不使用图片,如果可以使用css3实现
显示设置图片宽高,避免页面repaint 图片压缩,尽量使用JPGE,PNG8,如果图片超过50k,考虑叫设计进行优化
针对不同的设备,用media query调用不同size的图片
根据不同的网络状况,调用不同size的图片
3)css加载优化
合并css文件
使用高性能css选择器
使用css3代理js动画处理,使用translate3d开启GPU动画加速
禁止使用@import引入css文件
避免在低端机上使用大量CSS3渐变阴影效果,可考虑降级效果来提升流畅度
4)js加载优化
合并压缩js文件
单页面应用(SPA)考虑延迟加载非首屏业务模块
不可见Tab页延迟加载
避免使用大型类库
基础类库推荐使用zepto
尽可能使用事件代理,避免批量绑定事件
编写高性能javascript
5)浏览器端数据缓存
使用localStorage进行数据缓存
二. 响应性能优化方案
1.避免使用click事件,避免 iOS 300+ms 点击延时问题
2.避免触发页面重绘restyle,repaint,relayout的操作,注意DOM元素的循环操作
3.小心连续触发的事件scroll/resize/touchmove,避免高频繁触发执行
三. 性能检测方案
使用阿里测,YSlow做性能检测
在线分析:https://developers.google.com/speed/pagespeed/insights/?url=www.souche.com
一些指导原则比较老,不一定准确。
可以使用chrome插件:pagespeed,里面的指导原则比较新:
https://chrome.google.com/webstore/detail/gplegfbjlmmehdoakndmohflojccocli
自己整理了一张前端知识体系图,在业界整理的体系图基础上添加了很多自己梳理的,应该比较全面
补充腾讯的一张前端知识体系图
<!-- 启用360浏览器的极速模式(webkit) -->
<meta name="renderer"content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible"content="IE=edge">
<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->
<meta name="HandheldFriendly"content="true">
<!-- 微软的老式浏览器 -->
<meta name="MobileOptimized"content="320">
<!-- uc强制竖屏 -->
<meta name="screen-orientation"content="portrait">
<!-- QQ强制竖屏 -->
<meta name="x5-orientation"content="portrait">
<!-- UC强制全屏 -->
<meta name="full-screen"content="yes">
<!-- QQ强制全屏 -->
<meta name="x5-fullscreen"content="true">
<!-- UC应用模式 -->
<metaname="browsermode"content="application">
<!-- QQ应用模式 -->
<metaname="x5-page-mode"content="app">
<!-- windows phone 点击无高光 -->
<metaname="msapplication-tap-highlight"content="no">
gem 命令
gem sources --remove https://rubygems.org/ //删除
gem sources -a https://ruby.taobao.org/ //添加
gem sources -l //查看列表
vi 命令
进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filename :打开文件,并将光标置于第n行首 vi + filename :打开文件,并将光标置于最后一行首 vi +/pattern filename:打开文件,并将光标置于第一个与pattern匹配的串处 vi -r filename :在上次正用vi编辑时发生系统崩溃,恢复filename vi filename....filename :打开多个文件,依次进行编辑
移动光标类命令 h :光标左移一个字符 l :光标右移一个字符 space:光标右移一个字符 Backspace:光标左移一个字符 k或Ctrl+p:光标上移一行 j或Ctrl+n :光标下移一行 Enter :光标下移一行 w或W :光标右移一个字至字首 b或B :光标左移一个字至字首 e或E :光标右移一个字至字尾 ) :光标移至句尾 ( :光标移至句首 }:光标移至段落开头 {:光标移至段落结尾 nG:光标移至第n行首 n+:光标下移n行 n-:光标上移n行 n$:光标移至第n行尾 H :光标移至屏幕顶行 M :光标移至屏幕中间行 L :光标移至屏幕最后行 0:(注意是数字零)光标移至当前行首 $:光标移至当前行尾
屏幕翻滚类命令 Ctrl+u:向文件首翻半屏 Ctrl+d:向文件尾翻半屏 Ctrl+f:向文件尾翻一屏 Ctrl+b;向文件首翻一屏 nz:将第n行滚至屏幕顶部,不指定n时将当前行滚至屏幕顶部。
插入文本类命令 i :在光标前 I :在当前行首 a:光标后 A:在当前行尾 o:在当前行之下新开一行 O:在当前行之上新开一行 r:替换当前字符 R:替换当前字符及其后的字符,直至按ESC键 s:从当前光标位置处开始,以输入的文本替代指定数目的字符 S:删除指定数目的行,并以所输入文本代替之 ncw或nCW:修改指定数目的字 nCC:修改指定数目的行
删除命令 ndw或ndW:删除光标处开始及其后的n-1个字 do:删至行首 d$:删至行尾 ndd:删除当前行及其后n-1行 x或X:删除一个字符,x删除光标后的,而X删除光标前的 Ctrl+u:删除输入方式下所输入的文本
搜索及替换命令 /pattern:从光标开始处向文件尾搜索pattern ?pattern:从光标开始处向文件首搜索pattern n:在同一方向重复上一次搜索命令 N:在反方向上重复上一次搜索命令 :s/p1/p2/g:将当前行中所有p1均用p2替代 :n1,n2s/p1/p2/g:将第n1至n2行中所有p1均用p2替代 :g/p1/s//p2/g:将文件中所有p1均用p2替换
选项设置 all:列出所有选项设置情况 term:设置终端类型 ignorance:在搜索中忽略大小写 list:显示制表位(Ctrl+I)和行尾标志($) number:显示行号 report:显示由面向行的命令修改过的数目 terse:显示简短的警告信息 warn:在转到别的文件时若没保存当前文件则显示NO write信息 nomagic:允许在搜索模式中,使用前面不带“\”的特殊字符 nowrapscan:禁止vi在搜索到达文件两端时,又从另一端开始 mesg:允许vi显示其他用户用write写到自己终端上的信息
最后行方式命令 :n1,n2 co n3:将n1行到n2行之间的内容拷贝到第n3行下 :n1,n2 m n3:将n1行到n2行之间的内容移至到第n3行下 :n1,n2 d :将n1行到n2行之间的内容删除 :w :保存当前文件 :e filename:打开文件filename进行编辑 :x:保存当前文件并退出 :q:退出vi :q!:不保存文件并退出vi :!command:执行shell命令command :n1,n2 w!command:将文件中n1行至n2行的内容作为command的输入并执行之,若不指定n1,n2,则表示将整个文件内容作为command的输入 :r!command:将命令command的输出结果放到当前行
问题
终端报错:Please try running this command again as root/Administrator.
解决方法
运行命令:sudo chown -R $USER /usr/local
sudo是给与暂时的root权限,chown是change owner改变文件的归属者。 -r一般是递归 这个就是把~/sites/testsite 文件夹和他的子文件都变成 _www用户的
sudo -s 切换到管理员权限命令
也可以运行命令时前面添加sudo,表示以管理员的权限运行命令,如:
sudo npm install compass
闪屏问题 使用 ng-bind 替换,或 ng-bind-template 替换
问题
grunt compass编译终端报错:grunt compass Error: invalid option --sourcemap
原因
sass版本问题
解决方法
gem list 查看sass版本,要求sass >= 3.3
如果低于该版本就gem update sass, 一般存在依赖比如compass依赖sass
所以最好gem uninstall compass,sass
再重新安装 gem install sass
ok, 重新运行grunt server 搞定
什么是React Mixins
Mixins 作用抽离出公用代码,供多react组件使用
tips
Mixins里也可以编写组件生命周期的方法,需要注意的是:Mixins里的方法并不会覆盖组件的生命周期方法,会在先于组件生命周期方法执行。
除了生命周期方法可以重复以外,其他的方法都不可以重复,否则会报错
var LogMixin = {
componentWillMount: function () {
console.log('Component will mount');
},
componentDidMount: function () {
console.log('Component did mount');
}
};
var AComponent = React.createClass({
mixins: [LogMixin],
render: function () {
return (
<div>AComponent</div>
)
}
});
(function(){
var supportOrientation=(typeof window.orientation == "number" && typeof window.onorientationchange == "object");
var updateOrientation=function(){
if(supportOrientation){
updateOrientation=function(){
var orientation=window.orientation;
switch(orientation){
case 90:
case -90:
orientation="landscape";
break;
default:
orientation="portrait";
}
document.body.parentNode.setAttribute("class",orientation);
};
}else{
updateOrientation=function(){
var orientation=(window.innerWidth > window.innerHeight)? "landscape":"portrait";
document.body.parentNode.setAttribute("class",orientation);
};
}
updateOrientation();
};
var init=function(){
updateOrientation();
if(supportOrientation){
window.addEventListener("orientationchange",updateOrientation,false);
}else{
window.setInterval(updateOrientation,5000);
}
};
window.addEventListener("DOMContentLoaded",init,false);
})();
HTTP状态码
HTTP请求头
从输入url到页面加载都发生了什么事
cookie,localstorage,sessionstorage的区别
doctype的几种模式
strict(严谨模式),transitional(过渡模式),frameset(框架模式)使用的是html 4.0.1的规范
怪异模式是使用浏览器自己的方式解析,因此不同的浏览器不一样,所以称为诡异模式,如果doctype没有设置,会采用怪异模式渲染
jsonp实现原理
var callbackName = 'iAmTheCallback';
window[callbackName] = function (uuu, vvv, www) {
// 对返回的数据做后续处理
}
var script = document.createElement('script');
script.src = 'http://melon.github.io/xxx/yyy?callback='+callbackName;
document.body.appendChild(script);
grunt与gulp的区别
为什么使用流:
如果不使用流,读取文件的时候会缓存在内存中,使用fs.createReadStream替代fs.readFile, steam可以让node读取文件一定量的时候就开始向客户端发送响应的内容,无需服务器缓存
资料参考
捕获与冒泡及IE兼容性区别
DOM的事件模型(DOM事件流):捕获型事件和冒泡型事件z
事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。
事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。
IE只支持事件冒泡
支持W3C标准的浏览器通过addEventListener(event,fn,useCapture)方法的第三个参数来区分是事件冒泡还是事件捕获,不支持W3C标准的浏览器通过attachEvent()方法,默认是事件冒泡时执行,所以要兼容,只能使用addEventListener,并设置useCapture为false
解决跨域访问的几种方法
jsonp、 document.domain+iframe、window.name、window.postMessage、服务器上设置代理页面
其中html5中提供的postMessage不能兼容IE,postMessage传递的参数有data,source,origin(协议+主机+端口号)
同源的话是通过contentWindow获取子窗口元素,通过window.parent获取父窗口
对象的几种创建方法
js实现深度克隆
Object.prototype.deepClone = function(obj){
var newObj = {};
if(typeof(obj) !== "object" || obj === null){
return obj;
}
if(obj instanceof(Array)){
}else{
}
}
js实现数组消重
Array.prototype.unique = function (){
var arrayList = {},
newArray = [];
for (var i = 0; i < this.length; i++) {
if(!arrayList[this[i]]){
arrayList[this[i]] = true;
newArray.push(this[i]);
}
}
return newArray;
}
DOM操作-怎样添加、移除、移动、复制、创建和查找节点
快速排序算法
JQuery源码相关
typeof与instanceof的区别
typeof是检查数据类型,返回字符串,instanceof是测试一个对象是否是原型链构造函数的属性,更形象的说话是判断proto是否是指向同一个对象的prototype,返回boolen
浏览器兼容性举例
解决方法:
(1):.abc{border:1px blue solid;width:200px;height:200px;}
html>body .abc{width:auto;height:auto;min-width:200px;min-height:200px;}
(2):.abc{width:200px;height:200px;_width:200px;_height:200px;}
因为ie6有一个特征,当定义一个高度时,如果内容超过高度,元素会自动调整高度。
AMD,CMD,CommonJs规范之间的区别
AMD是依赖提前加载 CMD是依赖就近加载 commonJs是同步加载,适合用于服务器端使用,然而现在webpack也使用该规范在客户端
reflow & repaint
display:none 会产生reflow,而visibility:hidden 只会发生repaint, repaint是dom节点的外观改变,reflow是布局发生改变
如下情况会发生reflow:
js有哪些常见的兼容性
generator与promise
利用localStorage怎么优化触屏端性能
application cache(离线缓存策略),建立manifest文件,通过存储文件的ETag和文件路径,判断文件是否需要更新
HTTP请求响应头中关于缓存的对应关系
服务器端ETag和Last-Modified都是同样的效果,为了在服务器端验证文件是否修改
webpack的优势是什么
webpack是德国开发者开发的模块加载器,所有的资源如js,css,images都当做模块,来使用和引用
React的优势是什么
XSS与CSRF
XSS:就是脚本注入问题,获取到用户的相关信息,然后通过自己架设一个网站,让用户提交,随后以数据库的方式记录在攻击者自己的服务器上 解决方法:将用户输入的内容进行过滤
CSRF:伪造请求,冒充用户在站内的操作 (XSS只是CSRF其中一种) 解决方法:通过token令牌,保存在session里,访问接口的时候隐性传到服务器上进行比较
js算出字符串的字节数
var str='我我我';
var bytesCount;
for (var i = 0; i < str.length; i++)
{
var c = str.charAt(i);
if (/^[\u0000-\u00ff]$/.test(c)){
bytesCount += 1;
} else {
bytesCount += 2;
}
}
alert(bytesCount);
//结果是6
//原理也很简单,用正则判断是不是中文,如果是的话,字节数就加1。
ajax原理
Ajax的工作原理相当于在用户和服务器之间加了—个中间层,使用户操作与服务器响应异步化。这样把以前的一些服务器负担的工作转嫁到客户端,利于客户端闲置的处理能力来处理,减轻服务器和带宽的负担,从而达到节约ISP的空间及带宽租用成本的目的。 通过XMLHttpRequest向服务器端发送请求,通过onreadystatechange去监听服务器返回的数据,当readyState为400,state为200的时候,通过responseText获取返回数据
常用的两种继承方式是什么
类继承和原型链继承
js动态创建一个table(主要考察基本DOM操作)
var table = document.createElement("table");
table.setAttribute("id","table");
var tr1 = table.insertRow();
var td1 = tr1.insertCell();
td1.width = "200px";
td1.height = "200px";
td1.innerHTML = "内容";
document.body.appendChild(table);
js原生获取屏幕宽度,滚动高度,元素位置
nodeJs篇
用nodeJS实现启一个服务
var http = require("http");
http.createServer(function(request, response){
response.writeHead(200,{"Content-Type","text/html"});
response.end("hello world");
}).listen(3000);
var http = http.createListen();
用nodeJS实现文件copy
React篇
react生命周期
最近几年中,许多浏览器都改善了在页面加载过程中从 JavaScript 回收内存的能力。但是,并不是所有浏览器都具有相同的运行方式。Firefox 和旧版的 Internet Explorer 都存在过内存泄漏,而且内存泄露一直持续到浏览器关闭。
泄露场景
var obj = document.getElementById("btn");
obj.a = document.getElementById("btn");
var a = function() {
var largeStr = new Array(1000000).join('x');
return function() {
return largeStr;
}
}();
当原有的COM被移除时,子结点引用没有被移除则无法回收。
var select = document.querySelector;
var treeRef = select('#tree');
//在COM树中leafRef是treeFre的一个子结点
var leafRef = select('#leaf');
var body = select('body');
body.removeChild(treeRef);
//#tree不能被回收入,因为treeRef还在
//解决方法:
treeRef = null;
//tree还不能被回收,因为叶子结果leafRef还在
leafRef = null;
//现在#tree可以被释放了。
定时器也是常见产生内存泄露的地方:
for (var i = 0; i < 90000; i++) {
var buggyObject = {
callAgain: function() {
var ref = this;
var val = setTimeout(function() {
ref.callAgain();
}, 90000);
}
}
buggyObject.callAgain();
//虽然你想回收但是timer还在
buggyObject = null;
}
heap profile检测方法
<a href="####">#### 增加历史记录,破坏url</a><br>
<a href="####" onclick="location.href='http://www.baidu.com';return false;">#### 缺点同上,其余没有问题</a><br>
<a href="javascript:void(0);" onclick="location.href='http://www.baidu.com';return false;">javascript:void(0);(动态gif停止播放)如果不加return false , 在ie6下链接不跳转</a><br>
<a href="javascript:;" onclick="location.href='http://www.baidu.com';return false;">同javascript:void(0),只是比它更简洁</a><br>
<a href="#">#跳到页面顶部</a><br>
结论是#### return false 与 javascript:; return false 都没有问题,只是javascript:; 较 #### 更严谨
== 与 === 的区别
1、对于string,number等基础类型,==和===是有区别的
1)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等
2)同类型比较,直接进行“值”比较,两者结果一样
2、对于Array,Object等高级类型,==和===是没有区别的
进行“指针地址”比较
3、基础类型与高级类型,==和===是有区别的
1)对于==,将高级转化为基础类型,进行“值”比较
2)因为类型不同,===结果为false
null 与 undefined的比较
null==undefined为真,但是null===undefined为假
如果申明的变量未初始化,则访问的值为undefined
调用函数,如果函数没有返回值时,默认返回undefined。
null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。
var a = {class: "Animal", name: 'Fido'}; a.class
chrome可以输出属性值,但是在IE下面是不能输出值,因为class不能作为key键
正则表达式不能进行比较
iconfont管理平台可以参考fontello
-webkit-overflow-scrolling 提高IOS滚动体验
deviceorientation和 MozOrientation(firefox)
deviceorientation事件可获得三个值alpha,beta,gamma,分别代表绕Z轴的
旋转角度(0~360),绕X轴的旋转角度(-180~180),绕Y轴的旋转角度(-90~90)
MozOrientation事件中可获得三个值z,x,y,分别代表垂直加速度,左右的
斜角度,前后的倾斜角度(取值范围:-1~1
浏览器兼容性处理
window.addEventListener('deviceorientation', orientationListener, false); //方向感应器
window.addEventListener('MozOrientation', orientationListener, false); //方向感应器 for firefox
window.addEventListener('devicemotion', orientationListener, false); //重力加速感应器 for iphone, android
三个旋转方向,z,x,y轴,对应分别是:Alpha,Beta,Gamma
function orientationListener(event) {
var absolute = event.absolute;
var alpha = event.alpha;
var beta = event.beta;
var gamma = event.gamma;
...
}
w3c api:http://w3c.github.io/deviceorientation/spec-source-orientation.html
鬼道分享ppt: http://2014.jsconf.cn/slides/luics-hybrid-api.html
实例:http://www.html5tricks.com/demo/html5-ball-pool/index.html
http://www.pjhome.net/web/Orientation.html
开发环境
environment = :development
调试开关
firesass = false
定义本地文件
cssdir = "css"
sassdir = "sass"
extensionsdir = "sass-extensions"
imagesdir = "images"
javascriptsdir = "js"
linecomments = false 设置是否显示行信息
绝对路径
relative_assets = true
压缩比例
output_style = (environment == :development) ? :expanded : :compressed
调试信息
sassoptions = (environment == :development && firesass == true) ? {:debuginfo => true} : {}
<link href="css/reset.css" rel="stylesheet" type="text/css" media="screen" />"
media 属性值
screen:计算机屏幕(默认)
tty:电传打字机以及类似的使用等宽字符网格的媒介
tv: 电视机类型设备(低分辨率、有限的滚屏能力)
projection:放映机
handheld:手持设备(小屏幕、有限带宽)
print: 打印预览模式/打印页面
braille:盲人点字法反馈设备
aural:语音合成器
all:适用于所有设备
<link rel="stylesheet" media="only screen and (max-width: 600px)" href="small.css" />
<link rel="stylesheet" media="(min-device-width: 600px) and (max-device-width: 1000px)" href="small.css" />
<link rel="stylesheet" media="not print and (max-width: 600px)" href="small.css" />
<link rel="stylesheet" media="screen and (max-width: 600px) and (orientation: landscape)" href="small.css" />
同
@media screen and (max-width: 1000px){
body{
background: red;
}
}
@media screen and (max-width: 1000px) and (orientation: landscape){
body{
background: yellow;
}
}
什么是MongoDB
MongoDB是面向文档存储型数据库,NOSQL数据库
doc命令
>db //检查当前数据库
mydb
>use mydb //新建,切换数据库
switched to db mydb
>show dbs //查看数据库列表,只有新建DB中插入一条数据才能看见新建的数据库
local 0.78125GB
mydb 0.23012GB
test 0.23012GB
>db.dropDatabase() //删除数据库
>db.createCollection("movie") //创建集合,相当于关系型数据库中的table
{ "ok" : 1 }
>show collections //查看数据库中集合
//在MongoDB中,不需要创建集合。当插入一些文件 MongoDB 自动创建的集合。
>db.user.insert({"name":"tutorials point"}) //插入一条数据
>show collections
movie
user
>db.user.drop() //删除集合
>db.user.find() //返回整个集合中的数据
>db.user.find({key1:value1, key2:value2}).pretty() //集合数据查找,pretty是美化返回结果的格式
>db.user.find("likes": {$gt:10}, $or: [{"by": "yiibai"}, {"title": "MongoDB Overview"}] }).pretty() //likes, $or
>db.user.find({},{"title":1,_id:0}).limit(2) //限制条数
>db.mycol.find({},{"title":1,_id:0}).sort({"title":-1}) //sort 1是升序,-1是降序
>db.user.update({'title':'MongoDB Overview'},{$set:{'title':'New MongoDB Tutorial'}}) //更新find的第一条数据
>db.user.update({'title':'MongoDB Overview'},{$set:{'title':'New MongoDB Tutorial'}},{multi:true}) //multi:true 更换所有查到的结果数据
>db.user.save({"_id" : ObjectId(5983548781331adf45ec7), "title":"Yiibai New Topic", "by":"Yiibai"}) //替换该_id的全部数据
>db.user.remove({'title':'MongoDB Overview'}) //删除find的该数据
>db.user.remove() //清空该集合的所有数据
> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}]) //聚合
{
"result" : [
{
"_id" : "yiibai point",
"num_tutorial" : 2
},
{
"_id" : "yiibai point",
"num_tutorial" : 1
}
],
"ok" : 1
}
详细可查看MongoDB官网DOC
HTTP请求头提供了关于请求,响应或者其他的发送实体的信息。HTTP的头信息包括通用头、请求头、响应头和实体头四个部分。每个头域由一个域名,冒号(:)和域值三部分组成。
DNS 实现域名到IP的映射。通过域名访问站点,每次请求都要做DNS解析。目前每次DNS解析,通常在200ms以下。针对DNS解析耗时问题,一些浏览器通过DNS Prefetch 来提高访问的流畅性。
什么是 DNS Prefetch ?
DNS Prefetch 是一种DNS 预解析技术,当你浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在你单击当前网页中的连接时就无需进行DNS的解析,减少用户等待时间,提高用户体验。
浏览器支持情况
目前支持 DNS Prefetch 的浏览器有 google chrome 和 firefox 3.5
使用方法
如果要浏览器端对特定的域名进行解析,可以再页面中添加link标签实现。例如:
<link rel="dns-prefetch" href="www.ytuwlg.iteye.com" />
如果要控制浏览器端是否对域名进行预解析,可以通过Http header 的x-dns-prefetch-control 属性进行控制。
google chrome 中 DNS Prefetch 详细资料
在chrome 中可通过在地址栏中输入 about:histograms/DNS.PrefetchFoundName 和 about:dns 来查看当前浏览器的预解析数据。
进入mongo安装bin目录
命令输入mongo进行启动
use ueapi 进行切换数据库
show dbs 显示该数据库中的表
show collections 显示当前数据库中所有集合
db.table进入相应的表作用域下
db.users.find() 显示表中所有数据
db. users.remove({'name':'xumingxiang'}) 删除记录
db.users.remove() 删除表中所有记录
db.users.drop() 删除集合
db.dropDatabase() 删除
db.test.find({id:10}) 返回test数据集ID=10的数据集
db.test.find({id:10}).count() 返回test数据集ID=10的数据总数
db.test.find({id:10}).limit(2) 返回test数据集ID=10的数据集从第二条开始的数据集
db.test.find({id:10}).skip(8) 返回test数据集ID=10的数据集从0到第八条的数据集
db.test.find({id:10}).limit(2).skip(8) 返回test数据集ID=1=的数据集从第二条到第八条的数据
db.test.find({id:10}).sort() 返回test数据集ID=10的排序数据集
db.test.findOne([query]) 返回符合条件的一条数据
db.test.getDB() 返回此数据集所属的数据库名称
db.test.getIndexes() 返回些数据集的索引信息
db.test.group({key:...,initial:...,reduce:...[,cond:...]})
db.test.mapReduce(mayFunction,reduceFunction,
db.test.remove(query) 在数据集中删除一条数据
db.test.renameCollection(newName) 重命名些数据集名称
db.test.save(obj) 往数据集中插入一条数据
db.test.stats() 返回此数据集的状态
db.test.storageSize() 返回此数据集的存储大小
db.test.totalIndexSize() 返回此数据集的索引文件大小
db.test.totalSize() 返回些数据集的总大小
db.test.update(query,object[,upsert
db.test.validate() 验证此数据集
db.test.getShardVersion() 返回数据集共享版本号
分析竞争状况
(1)市场报告
(2)行业文章
(3)使用竞争对手的产品(竞品分析)
自身资源与满足用户需求的匹配程度
(1)技术资源(是否有技术储备,需要技术预研)
(2)市场资源(媒体资源,推广渠道,公关资源)
(3)运营资源(团队能否支撑可能发生的用户需求)
该阶段目标
(1)发现创新产品的机会
(2)改进现有产品的机会
文档输出
(1)BRD 商业需求文档
(2)MRD 市场需求文档
该注意事项
大胆设想,小心求证
切勿陷入自己营造的主观主义情绪中
产品的规范定义
(1)产品愿景,团队为之去努力的目标与方向
(2)目标市场
(3)竞争分析(得出的结果,共团队成员参考与理解)
(4)产品功能与详细描述
(5)产品功能的优先级
(6)产品用例(use case,主要用于更方便的人理解你的想法)
(7)性能需求(最大并发数,同时在线人数峰值,峰值系统响应时间等)
(8)其他部门支持需求(市场 运营 技术 销售等)
产品设计
(1)明确产品调性
(2)用户体验设计(交互设计 用户体验设计 用户界面设计 前端开发工程)
输出文档
(1)产品信息架构图
(2)产品原型图
(3)产品需求文档(PRD product requirement document)
与各团队充分有效的沟通,协调资源保证产品按照既定目标正确前进
(1)协作并确保各方按既定目标前进
(2)和研发国通合作,确定产品的基本时间节点
(3)产品开发过程中,与项目经理协作,跟踪产品开发进度
(4)与公司高层及时沟通,汇报产品开发过程中的各种问题,困难,协调
(5)及时与团队通报产品进度,确保信息对等
需求管理
(1)新需求(内部的信息反馈和上级的信息反馈,控制好哪些需求是需要加进来,避免产品冻结)
(2)变更需求
产品测试并验收完成
UI设计稿中需要体现的信息
UI设计中怎么帮助用户快速找到他们想要的东西
toFixed()
截取小数位个数
链式书写
通过方法内return this,返回当前实例就可以
aQuery().init().name()
//实现
aQuery.prototype = {
init: function() {
return this;
},
name: function() {
return this
}
}
插件接口
$.extend是对jquery对象进行扩展,$.fn.extend是对jquery.fn对象进行扩展
$.fn与$.prototype指向同一对象,$.fn.extend相当于扩展prototype上面的方法,当别的类继承jquery时,$.fn上扩展的方法会继承过去,$.extend扩展的方法不能继承。
什么叫闭包
我理解的闭包是方法返回值的再执行,可以操作方法内部的局部数据。应用场景:设计私有方法和变量。
var audio = (function(){
var audioObj = function(){
console.log("constructor");
};
audioObj.prototype = {
start: function(){
//...
}
};
return audioObj;
})();
var a = new audio(); //console constructor 类的实例
问题
IE下面textarea使用.focu()方法,不能聚焦
解决方法
$(this).select(); //体验不好,会把textarea内容选中
$(this).attr('contentEditable',true); //只在IE中有效,完美解决
document.createDocumentFragment()的作用是提高性能,避免经常做节点插入操作。
var oFragment = document.createDocumentFragment();
for(var i = 0 ; i < 10; i ++) {
var p = document.createElement("p");
var oTxt = document.createTextNode("段落" + i);
p.appendChild(oTxt);
oFragment.appendChild(p);
}
document.body.appendChild(oFragment);
选择元素
// jQuery
var els = $('.el');
// 原生方法
var els = document.querySelectorAll('.el');
// 函数法
var $ = function (el) {
return document.querySelectorAll(el);
}
var els = $('.el');
创建元素
// jQuery
var newEl = $('<div/>');
// 原生方法
var newEl = document.createElement('div');
添加事件监听器
// jQuery
$('.el').on('event', function() {
});
// 原生方法
[].forEach.call(document.querySelectorAll('.el'), function (el) {
el.addEventListener('event', function() {
}, false);
});
设置/获取属性
// jQuery
$('.el').filter(':first').attr('key', 'value');
$('.el').filter(':first').attr('key');
// 原生方法
document.querySelector('.el').setAttribute('key', 'value');
document.querySelector('.el').getAttribute('key');
添加/移除/切换类
// jQuery
$('.el').addClass('class');
$('.el').removeClass('class');
$('.el').toggleClass('class');
// 原生方法
document.querySelector('.el').classList.add('class');
document.querySelector('.el').classList.remove('class');
document.querySelector('.el').classList.toggle('class');
附加内容(Append)
// jQuery
$('.el').append($('<div/>'));
// 原生方法
document.querySelector('.el').appendChild(document.createElement('div'));
>克隆元素
// jQuery
var clonedEl = $('.el').clone();
// 原生方法
var clonedEl = document.querySelector('.el').cloneNode(true);
移除元素
// jQuery
$('.el').remove();
// 原生方法
remove('.el');
function remove(el) {
var toRemove = document.querySelector(el);
toRemove.parentNode.removeChild(toRemove);
}
获取父元素
// jQuery
$('.el').parent();
// 原生方法
document.querySelector('.el').parentNode;
>上一个/下一个元素
// jQuery
$('.el').prev();
$('.el').next();
// 原生方法
document.querySelector('.el').previousElementSibling;
document.querySelector('.el').nextElementSibling;
XHR或AJAX
// jQuery
$.get('url', function (data) {
});
$.post('url', {data: data}, function (data) {
});
// 原生方法
// get
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = function (data) {
}
xhr.send();
// post
var xhr = new XMLHttpRequest()
xhr.open('POST', url);
xhr.onreadystatechange = function (data) {
}
xhr.send({data: data});
test
arguments返回方法的参数数组,arguments.callee返回自己方法体
function addTime(date, content){
console.log(arguments, arguments.callee);
}
addTime("2015-3-10", "时间");
// 打印出 ["2015-3-10", "时间"]
各浏览器中对 document.all 方法的支持不同,使用它获取元素引用可能造成兼容性问题。
浏览器返回值
| 浏览器 | 返回值 | | :-------- | --------:| | IE6 IE7 IE8(Q) | document.all : [object] | | Opera Safari IE8(S) | document.all : [object HTMLColletion] | | Firefox(Q) | document.all : [object HTML document.all.class] | | Firefox(S) | document.all : undefined | | Chrome(S) | document.all : [object HTMLColletion] |
!!document.all返回值
| 浏览器 | 返回值 | | :-------- | --------:| | IE6 IE7 IE8 | !!document.all : true | | Firefox Chrome Safari Opera | !!document.all : false |
如下代码firefox(s)报错,document.all undefinded
<html id="HTML1">
<script type="text/javascript">
window.onload = function() {
var html = "<table border='1' style='font-size:12px;'>";
function getElement(sec) {
html += "<tr><td>" + sec + "</td>" + "<td>" + eval(sec).id + "</td>";
}
getElement("document.all(0)");
getElement("document.all[0]");
getElement("document.all.item(0)");
getElement("document.all('SPAN1')");
getElement("document.all.SPAN1");
getElement("document.all['SPAN1']");
getElement("document.all.namedItem('SPAN1')");
html += "</table>";
document.getElementById("info").innerHTML = html;
}
</script>
<span id="SPAN1"></span>
<div id="info"></div>
</html>
解决方法
由于firefox对docuemnt.all支持有问题,所以最好使用document.getElementById, document.getElementByTagName 获取dom