javascript 原生常用api 数组方法大全
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var arr = [
[1, 2, 2],
[3, 4, 5, 5],
[6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10
];
var newArr = [];
function changeArr(arr) {
for(var i = 0; i < arr.length; i++) {
//遍历arr数组得每一个元素,这里也可以用forEach
if(arr[i] instanceof Array) {
//判断元素是否为数组
changeArr(arr[i])
//元素为数组则继续调用changeArr方法遍历
} else {
newArr.push(arr[i])
//元素不是数组则可以直接push进新数组
}
}
//此上的判断也可以直接用三元表达式
}
changeArr(arr);
console.log(newArr); //[1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]
</script>
</head>
<body>
</body>
</html>
方案一(仅去重):
var rusultArr=newArr.reduce(function(rusultArr,a){
if(rusultArr.indexOf(a)==-1){
rusultArr.push(a)
}
return rusultArr
},[])
方案二(去重加排序):
rusultArr=Array.from(new Set(newArr)).sort(function(a,b){return a-b})
truncate方法:用于对字符串进行截断处理。当超过限定长度,默认添加3个点号。
function truncate(target, length, truncation) {
length = length || 30;
truncation = truncation === void(0) ? '...' : truncation;
return target.length > length ?
target.slice(0, length - truncation.length) + truncation : String(target);
}
camelize方法:转换为驼峰风格。
function camelize(target) {
if (target.indexOf('-') < 0 && target.indexOf('') < 0) {
return target;//提前判断,提高getStyle等的效率
}
return target.replace(/[-][^-]/g, function(match) {
return match.charAt(1).toUpperCase();
});
}
underscored方法:转换为下划线风格。
function underscored(target) {
return target.replace(/([a-z\d])([A-Z])/g, '$1$2').
replace(/-/g, '').toLowerCase();
}
dasherize方法:转换为连字符风格,即CSS变量的风格。
function dasherize(target) {
return underscored(target).replace(//g, '-');
}
capitalize方法:首字母大写。
function capitalize(target) {
return target.charAt(0).toUpperCase() + target.substring(1).toLowerCase();
}
POST和GET的区别,HTTP状态码
POST和GET的区别
GET在浏览器回退时是无害的,而POST会再次提交请求
GET产生的URL地址可以被收藏,而POST不可以
GET请求会被浏览器主动缓存,而POST不会,除非手动设置
GET请求只能进行URL编码,而POST支持多种编码方式
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留
GET请求在URL中传送的参数是有长度限制的,而POST没有长度限制
对参数的数据类型,GET只能请求ASCII字符,而POST没有限制
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传敏感信息
GET参数通过URL传递,POST放在Request body中
HTTP状态码
1XX:指示信息-表示请求已接受,继续处理
2XX:成功-表示请求已被成功接收200 OK :客户端请求成功
206 Partial Content:客户发送一个带有Range头的GET请求,服务器完成了它 播放视频和音频
3XX:重定向-要完成请求必须进行更进一步的操作301 Move Permanently:所请求的页面已经转移至新的URL
302 Found:所请求的页面已经临时转移到新的URL
304 Not Modified:客户端有缓冲的文档并发出一个条件性的请求,服务器告诉客户,原来缓冲的文档还可以继续使用
4XX:客户端错误-请求有语法错误或请求无法实现400 Bad Request:客户端请求有语法错误,不能被服务器所理解
401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
403 Forbidden:对被请求页面的访问被禁止
404 Not Found:请求资源不存在
5XX:服务错误-服务器未能实现合法的请求500 Internal Server Error:服务器发生不可预期的错误原来缓冲的文档还可以继续使用
503 Server Unavailable:请求未完成,服务器临时过载或当机,一段事件后恢复正常
http://www.cnblogs.com/milo-wjh/p/6811868.html
有时可能需要在pagehide事件触发时根据persisted的值采取不同的操作。
对于pageshow事件,如果页面是从bfcache中加载的,那么persisted的值就是true;
对于pagehide事件,如果页面在加载之后会保存在bfcache中,那么persisted的值也会被设置为ture。
因此,当第一次触发pageshow时,persisted的值一定是false,而在第一次触发pagehide时,persisted就会变成true(除非页面不会保存在bfcache中)。指定了onunload事件处理程序的页面会被自动排除在bfcache之外,即使事件处理程序是空的。
具体原因:
onunload最常用于撤销在onload中所执行的操作,而跳过onload后再次显示页面很可能会导致页面不正常。
微信后退不刷新【JS不执行】:
+ var isPageHide = false;
+ window.addEventListener('pageshow', function () {
+ if (isPageHide) {
+ window.location.reload();
+ }
+ });
+ window.addEventListener('pagehide', function () {
+ isPageHide = true;
+ });
http://www.cnblogs.com/blogcxz/p/7341978.html
var a = 1;
function foo() {
if (!a) {
var a = 2;
}
alert(a);
};
foo(); //2
大数相加 http://www.cnblogs.com/kindofblue/p/4672129.html
/*let a;
async function correct() {
try {
await Promise.reject('error1')
} catch (error) {
console.log(error);
}
a = await 1;
return a;
}
correct().then(v => console.log(a)); // 1
*/
let a;
async function f() {
await Promise.reject('error');
a = await 1; // 这段 await 并没有执行
}
f().then(v => console.log(a));
@font-face {
font-family: 'source';
src: url('../fonts/source.eot');
src:
url('../fonts/source.eot?#font-spider') format('embedded-opentype'),
url('../fonts/source.woff2') format('woff2'),
url('../fonts/source.woff') format('woff'),
url('../fonts/source.ttf') format('truetype'),
url('../fonts/source.svg') format('svg');
font-weight: normal;
font-style: normal;
}
.home h1, .demo > .test {
font-family: 'source';
}
var EventUtil = { //事件处理程序
addHandler:function(element,type,handler){
if(element.addEventListener){//检测是否存在DOM2
element.addEventListener(type,handler,false)
}else if(element.attachEvent){//存在ie
element.attachEvent('on'+type,handler)
}else{//DOM0
element['on'+type]=handelr;
}
},
removeHandler:function(element,type,handler){
if(element.removeEventListener){
element.removeEventListener(type,handler,false);
}else if(element.detachEvent){
element.detachEvent('on'+type,handler);
}else{
element['on'+type]=null;
}
}
}
构造函数
自己的想法
普通的函数就像是按步骤执行的动作,而构造函数更像是可更改零件的木偶,普通函数可以直接调用,但是构造函数需要new
因为构造函数也是函数,所以可以直接被调用,但是它的返回值为undefine,此时构造函数里面的this对象等于全局this对象
扩展实例和对象的区别,从定义上来讲:1、实例是类的具象化产品,2、而对象是一个具有多种属性的内容结构。funciton Foo(name,age){
this.name = name;
this.age = age;
this.class = 'class-1';
// return this //默认有这一行
}
var f = new Foo('zhangsan',20); //实例化对象
// var f1 = new Foo('lisi',22) //创建多个对象
构造函数-扩展
var a = {} 其实是 var a = new Object()的语法糖
var a = [] 其实是 var a = new Array()的语法糖
function Foo(){...}其实是 var Foo = new Function(...)
使用 instanceof 判断一个函数是否是一个变量的构造函数如果想判断一个变量是否为“数组”:变量 instanceof Array
instanceof
用于判断引用类型属于哪个构造函数的方法
f instanceof Foo 的判断逻辑是:
f的__proto__一层一层往上走,是否能对应到Foo.prototype
再试着判断f instanceof Object
magin重叠:边界叠加的大多数问题可以通过添加透明边框或1px的补白来修复。
补充解决方案:
1.外层padding
2.透明边框border:1pxsolidtransparent;
3.绝对定位postion:absolute:
4.外层DIVoverflow:hidden;
5.内层DIV 加float:left;display:inline;
6.外层DIV有时会用到zoom:1;
// Adding extend function to Object.prototype
Object.prototype.extend = function(obj) {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
this[i] = obj[i];
}
}
};
var objA = {"name": "colin", "car": "suzuki"};
var objB = {"name": "james", "age": 17};
objA.extend(objB);
objA; // {"name": "james", "age": 17, "car": "suzuki"};
// Lodash
_.assign(objA, objB);
//assign 实现浅复制
var _extends = Object.assign || function(target) {
for(var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for(var key in source) {
if(Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
function sum() {
var cur = Array.prototype.slice.call(arguments).reduce(function(a,b){
return a+b;
},0);
function add() {
return arguments.length==0 ? cur : (cur+=Array.prototype.slice.call(arguments).reduce(function(a,b){return a+b},0), add);
};
return arguments.length==0 ? 0 : add;
}
console.log(sum()); //0
console.log(sum(2)(3)()); //5
console.log(sum(2,3)()); //5
console.log(sum(2,3,5)()); //10
console.log(sum(2,3,5)(5)()); //15
console.log(sum(2,3,5)(5)(5,5)()); //25
function add() {
var a = arguments[0];
if(arguments.length == 2) {
return a + arguments[1];
} else {
return function(b) {
return a + b;
}
}
}
console.log(add(2, 3)); //5
console.log(add(2)(3)); //5
add(1)(2)(3)调用方式的方法:
var add = function(a){
return function(b){
return function(c){
return a+b+c;
};
};
};
add(1)(2)(3); //6
首先要一个数记住每次的计算值,所以使用了闭包,在tmp中记住了x的值,第一次调用add(),初始化了tmp,并将x保存在tmp的作用链中,然后返回tmp保证了第二次调用的是tmp函数,后面的计算都是在调用tmp, 因为tmp也是返回的自己,保证了第二次之后的调用也是调用tmp,而在tmp中将传入的参数与保存在作用链中x相加并付给sum,这样就保证了计算;
但是在计算完成后还是返回了tmp这个函数,这样就获取不到计算的结果了,我们需要的结果是一个计算的数字那么怎么办呢,首先要知道JavaScript中,打印和相加计算,会分别调用toString或valueOf函数,所以我们重写tmp的toString和valueOf方法,返回sum的值;
function add(x) {
var sum = x;
var tmp = function (y) {
sum = sum + y;
return tmp;
};
tmp.toString = function () {
return sum;
};
return tmp;
}
console.log(add(1)(2)(3)); //6
console.log(add(1)(2)(3)(4)); //10
1. for of和迭代器
ES5中,forEach可以用来遍历数组元素,但它的缺陷是不能使用break语句中断循环,也不能使用return语句返回到外层函数。
强大的for-of循环
for (let value of [1, 2, 3]) {
console.log(value); //输出 1 2 3
}
最简洁、最直接的遍历数组元素的语法
----------------------------------------------------------------------------------------------
这个方法避开了for-in循环的所有缺陷
与forEach()不同的是,它可以正确响应break、continue和return语句其它集合也支持for-of循环
for-of循环不仅支持数组,还支持大多数类数组对象,例如DOM的NodeList对象。
----------------------------------------------------------------------------------------------
它也支持字符串:
for (let chr of "abc12") {
console.log(chr); // 输出 "a" "b" "c" "1" "2"
}
另外还支持Map和Set对象的遍历。
深入理解
正如其它语言中的for/foreach语句一样,for-of循环语句通过方法调用来遍历各种集合。数组、Map、Set以及我们讨论的其它对象有一个共同点,它们都有一个迭代器方法。
任何对象都可以有/添加迭代器方法。
就像为对象添加myObject.toString()方法,JS知道怎么把这个对象转化为字符串;你为对象添加迭代器方法myObject[Symbol.iterator](),JS也就知道了如何遍历这个对象。
[Symbol.iterator]语法看起来很怪。Symbol是ES6引入的新类型,标准定义了全新的symbol(如Symbol.iterator),来保证不与任何已有代码产生冲突。
任何有迭代器方法[Symbol.iterator]()的对象都是可迭代的。
前端如何设置缓存
通过meta标签的http-equiv属性进行设置
<meta http-equiv="pragram" content="no-cache">
<meta http-equiv="cache-control" content="no-cache, must-revalidate">
在ajax请求中通过setRequestHeaders这个方法设置如果还有其他的设置方法,欢迎留言指教。
var target = { a: 1 };
var source1 = { b: 2 };
var source2 = { c: 3 };
Object.assign(target, source1, source2); //改变了target ,注意和{...a,...b}的区别
target // {a:1, b:2, c:3}
var a={
"a":{
"b":{
"c":100,
"d":200
}
}
};
var b={
"a":{
"b":{
"e":100
}
}
}
console.log({...{},...a,...b})
console.log(a)
//ES5
"use strict";
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var a = {
"a": {
"b": {
"c": 100,
"d": 200
}
}
};
var b = {
"a": {
"b": {
"e": 100
}
}
};
console.log(_extends({}, a, b));
console.log(a);
构造函数 new
JS中的函数即可以是构造函数又可以当作普通函数来调用,当使用new来创建对象时,
对应的函数就是构造函数,通过对象来调用时就是普通函数。
普通函数的创建有:显式声明、匿名定义、new Function() 等三种方式。
当通过new来创建一个新对象时,JS底层将新对象的原型链指向了构造函数的原型对象,
于是就在新对象和函数对象之间建立了一条原型链,通过新对象可以访问到函数对象原型prototype中的方法和属性。
1.创建一个新的空对象;
2.将this绑定到该对象;
3.添加一个名为__proto__的新属性,并且指向构造函数的原型(prototype);
4.返回该this对象。
setTimeout(fn, 0) 的作用
setTimeout(0)单线程和异步队列
setTimeout和setInterval是JS内置的两个定时器,使用很简单,但这两个方法背后的原理却不简单。
我们知道,JS是单线程语言,在浏览器中,当JS代码被加载时,浏览器会为其分配一个主线程来执行任务(函数),
主线程会形成一个全局执行环境,执行环境采用栈的方式将待执行任务按顺序依次来执行。
但在浏览器中有一些任务是非常耗时的,比如http请求、定时器、事件回调等,为了保证其他任务的执行效率不被影响,
JS在执行环境中维护了一个异步队列(也叫工作线程),并将这些任务放入队列中进行等待,这些任务的执行时机并不确定,
只有当主线程的任务执行完成以后,才会去检查异步队列中的任务是否需要开始执行。这就是为什么setTimeout(fn,0)
始终要等到最后执行的原因。关于单线程和异步队列问题请参考:setTimeout(0)
Array的reduce方法 //educe需要两个参数,一个是回调函数,
一个是初始值,没有初始值,会默认把数组第一个当初始值,并从第二个开始
arr.reduce(callback,[initialValue])
callback
执行数组中每个值的函数,包含四个参数
accumulator上一次调用回调返回的值,或者是提供的初始值(initialValue)
currentValue数组中正在处理的元素
currentIndex数据中正在处理的元素索引,如果提供了
initialValue ,从0开始;否则从1开始array调用 reduce 的数组
initialValue可选项,其值用于第一次调用 callback 的第一个参数。
var sum = [0, 1, 2, 3].reduce(function(a, b) {
return a + b;
}, 0);
// sum is 6
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function(allNames, name) {
if (name in allNames) {
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
}, {}); //{}就是上面的allNames,这里当做默认值
// countedNames is { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
Array.from() //扩展运算符(…)也可以将某些数据结构转为数组
将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)
//类似数组的对象
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
console.log(p);
});
// arguments对象
function foo() {
var args = Array.from(arguments);
// ...
}
Array.of()
用于将一组值,转换为数组
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
深拷贝浅拷贝
1、浅拷贝 //Object.assign() //浅拷贝,类似{...obj1,...obj2} 都是浅拷贝
拷贝就是把父对象的属性,全部拷贝给子对象。
接下来,我们看一个拷贝的例子:
function extendCopy(b) {
var a = {};
for (var i in b) {
a[i] = b[i];
}
return a;
}
调用的时候,这样写:
// 调用
var copyA = {
titleA: '标题A'
};
var copyB = extendCopy(copyA);
console.log(copyB.titleA); // 标题A
但是,这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。
接下来,我们看一个篡改的示例:
function extendCopy(b) {
var a = {};
for (var i in b) {
a[i] = b[i];
}
return a;
}
// 调用
var copyA = {
arrayA: [1, 2, 3, 4]
};
var copyB = extendCopy(copyA);
copyB.arrayA.push(5);
console.log(copyA.arrayA); // [1, 2, 3, 4, 5]
结果是增加了一个5。
所以,extendCopy() 只是拷贝了基本类型的数据,我们把这种拷贝叫做“浅拷贝”。
//数组深拷贝 [].concat(arr1), var =[...arr1], arr1.slice(0)
2、深拷贝
function deepCopy(p, c) {
var c = c || {};
for (var i in p) {
if (typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
}
// 调用
var copyA = {
arrayA: [1, 2, 3, 4]
};
var copyB = deepCopy(copyA);
copyB.arrayA.push(5);
console.log(copyA.arrayA); // [1, 2, 3, 4]
Element.matches 精确匹配
document.getElementById('list').addEventListener('click', function (e) {
// 兼容性处理
var event = e || window.event;
var target = event.target || event.srcElement;
if (target.matches('li.class-1')) {
console.log('the content is: ', target.innerHTML);
}
});
移动端touch事件(区分webkit 和 winphone)
当用户手指放在移动设备在屏幕上滑动会触发的touch事件
以下支持webkit
touchstart——当手指触碰屏幕时候发生。不管当前有多少只手指
touchmove——当手指在屏幕上滑动时连续触发。通常我们再滑屏页面,会调用event的preventDefault()可以阻止默认情况的发生:阻止页面滚动
touchend——当手指离开屏幕时触发
touchcancel——系统停止跟踪触摸时候会触发。例如在触摸过程中突然页面alert()一个提示框,此时会触发该事件,这个事件比较少用TouchEvent
touches:屏幕上所有手指的信息
targetTouches:手指在目标区域的手指信息
changedTouches:最近一次触发该事件的手指信息
touchend时,touches与targetTouches信息会被删除,changedTouches保存的最后一次的信息,最好用于计算手指信息参数信息(changedTouches[0])
clientX、clientY在显示区的坐标
target:当前元素
全局错误监控
监听window上的error事件,过滤事件代理的error。
手动触发一个dom事件,需要3步,如果你对document.createEvent,�不是很熟悉,可以点击查看。
创建一个事件对象 document.createEvent(event)
初始化事件对象 event.initEvent(type, bubbles, true)
分发事件 dom.dispatchEvent(event)
Object.preventExtensions(obj) 让一个对象变的不可扩展,也就是永远不能再添加新的属性。
Object.isExtensible(obj) 判断一个对象是否是可扩展的
Object.seal(obj)让一个对象密封(只能读写 不能新增)
Object.isSealed(obj)判断一个对象是否密封
Object.isFrozen(arr) 让一个对象被冻结(只能读)
Object.isFrozen(obj):判断一个对象是否被冻结
Object.keys(obj) 返回一个由给定对象的所有可枚举自身属性的属性名组成的数组
Object.getOwnPropertyNames(obj):返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性)组成的数组
Object.is(value1, value2):判断两个值是否是同一个值,Object.is它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
Object.create(proto [, propertiesObject ]) 是E5中提出的一种新的对象创建方式,第一个参数是要继承的原型,如果不是一个子函数,可以传一个null,第二个参数是对象的属性描述符,这个参数是可选的。
Object.assign 把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。【浅复制】
//var copy = Object.assign({}, obj);
Object.defineProperty() 定义单个对象属性或方法(可以设置读写可枚举)
Object.defineProperties() 定义多个对象属性或方法(可以设置读写可枚举)
Object.assign() //浅拷贝,类似{...obj1,...obj2} 都是浅拷贝
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)
var target = { a: 1 };
var source1 = { b: 2 };
var source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
//如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
var obj1 = {a: {b: 1}};
var obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2
对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加。
var target = { a: { b: 'c', d: 'e' } }
var source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }
停止jq中的ajax请求用abort()函数
<html>
<head>
<mce:script type="text/javascript"><!--
var currentAjax = null;
function startAjax(){
//方法就是将XHR对象指向currentAjax,再调用currentAjax的.abort()来中止请求
currentAjax = $.ajax({
type:'POST',
beforeSend:function(){},
url:'test.php',
data:'username=xxx',
dataType:'JSON',
error:function(){alert('error')},
success:function(data){alert(data)}
});
}
function stopAjax(){
//如若上一次AJAX请求未完成,则中止请求
if(currentAjax) {currentAjax.abort();}
}
// --></mce:script>
</head>
<body>
<input type="button" value="触发请求" onclick="startAjax()" />
<input type="button" value="停止请求" onclick="stopAjax()" />
</body>
</html>
JSONP 超时:
设置超时标志位flag=false,当超时后将flag=true;
异步加载JS文件并执行回调函数:
function loadJS(src, callback){
var script = document.createElement('script');
var head = document.getElementsByTagName('head')[0];
var loaded;
script.src = src;
if(typeof callback === 'function'){
script.onload = script.onreadystatechange = function(){
if(!loaded && (!script.readyState || /loaded|complete/.test(script.readyState))){
script.onload = script.onreadystatechange = null;
loaded = true;
callback();
}
}
}
head.appendChild(script);
}
加setTimeout 超时后,当超时后将标志位设为true,在onload 里面判断flag为true的时候直接return 掉,
后面的回调函数就不会运行了,JOSNP也就失去了作用!
//获取元素的绝对位置
function getPosition(node) {
var width = node.offsetWidth; //元素宽度
var height = node.offsetHeight; //元素高度
var left = node.offsetLeft; //获取元素相对于其根元素的left值var left
var top = node.offsetTop; //获取元素相对于其根元素的top值var top
current = node.offsetParent; // 取得元素的offsetParent
// 一直循环直到根元素
while(current != null) {
left += current.offsetLeft;
top += current.offsetTop;
current = current.offsetParent;
}
return {
"width": width,
"height": height,
"left": left,
"top": top
};
}
// 动画结束时事件
o.addEventListener("webkitAnimationEnd", function() {
console.log("动画结束");
})
-webkit-animation动画有三个事件:
开始事件: webkitAnimationStart
结束事件: webkitAnimationEnd
重复运动事件: webkitAnimationIteration// 动画开始时事件
o.addEventListener("webkitAnimationStart", function() {
console.log("动画开始");
})
// 动画重复运动时事件
o.addEventListener("webkitAnimationIteration", function() {
console.log("动画重复运动");
})
// 动画结束时事件
o.addEventListener("webkitAnimationEnd", function() {
console.log("动画结束");
})
首先我们需要在高度过渡动画完成后执行数字跳动动画,这里我们需要监听'transitionend'事件,对于这个事件需要特别注意的点:
每个过渡属性完成后多会触发一次transitionend;
transitionend事件支持冒泡,如果子元素也有过渡效果的话,一定要阻止冒泡。 // watch :
active (newValue) {
if (newValue) {
this.$refs.zfbitem.addEventListener('transitionend', this.transitionAction, false);
}
}
// methods:
transitionAction (e) {
//不再需要监听时,一定要移除监听
this.$refs.zfbitem.removeEventListener('transitionend', this.transitionAction, false);
this.numberBounce();
}
一、节点
1.1 节点属性
Node.nodeName //返回节点名称,只读
Node.nodeType //返回节点类型的常数值,只读
Node.nodeValue //返回Text或Comment节点的文本值,只读
Node.textContent //返回当前节点和它的所有后代节点的文本内容,可读写
Node.baseURI //返回当前网页的绝对路径
Node.ownerDocument //返回当前节点所在的顶层文档对象,即document
Node.nextSibling //返回紧跟在当前节点后面的第一个兄弟节点
Node.previousSibling //返回当前节点前面的、距离最近的一个兄弟节点
Node.parentNode //返回当前节点的父节点
Node.parentElement //返回当前节点的父Element节点
Node.childNodes //返回当前节点的所有子节点
Node.firstChild //返回当前节点的第一个子节点
Node.lastChild //返回当前节点的最后一个子节点
//parentNode接口
Node.children //返回指定节点的所有Element子节点
Node.firstElementChild //返回当前节点的第一个Element子节点
Node.lastElementChild //返回当前节点的最后一个Element子节点
Node.childElementCount //返回当前节点所有Element子节点的数目。
1.2 操作
Node.appendChild(node) //向节点添加最后一个子节点
Node.hasChildNodes() //返回布尔值,表示当前节点是否有子节点
Node.cloneNode(true); // 默认为false(克隆节点), true(克隆节点及其属性,以及后代)
Node.insertBefore(newNode,oldNode) // 在指定子节点之前插入新的子节点
Node.removeChild(node) //删除节点,在要删除节点的父节点上操作
Node.replaceChild(newChild,oldChild) //替换节点
Node.contains(node) //返回一个布尔值,表示参数节点是否为当前节点的后代节点。
Node.compareDocumentPosition(node) //返回一个7个比特位的二进制值,表示参数节点和当前节点的关系
Node.isEqualNode(noe) //返回布尔值,用于检查两个节点是否相等。所谓相等的节点,指的是两个节点的类型相同、属性相同、子节点相同。
Node.normalize() //用于清理当前节点内部的所有Text节点。它会去除空的文本节点,并且将毗邻的文本节点合并成一个。
//ChildNode接口
Node.remove() //用于删除当前节点
Node.before() //
Node.after()
Node.replaceWith()
1.3 Document节点
1.3.1 Document节点的属性
document.doctype //
document.documentElement //返回当前文档的根节点
document.defaultView //返回document对象所在的window对象
document.body //返回当前文档的<body>节点
document.head //返回当前文档的<head>节点
document.activeElement //返回当前文档中获得焦点的那个元素。
//节点集合属性
document.links //返回当前文档的所有a元素
document.forms //返回页面中所有表单元素
document.images //返回页面中所有图片元素
document.embeds //返回网页中所有嵌入对象
document.scripts //返回当前文档的所有脚本
document.styleSheets //返回当前网页的所有样式表
//文档信息属性
document.documentURI //表示当前文档的网址
document.URL //返回当前文档的网址
document.domain //返回当前文档的域名
document.lastModified //返回当前文档最后修改的时间戳
document.location //返回location对象,提供当前文档的URL信息
document.referrer //返回当前文档的访问来源
document.title //返回当前文档的标题
document.characterSet属性返回渲染当前文档的字符集,比如UTF-8、ISO-8859-1。
document.readyState //返回当前文档的状态
document.designMode //控制当前文档是否可编辑,可读写
document.compatMode //返回浏览器处理文档的模式
document.cookie //用来操作Cookie
1.3.2 Document节点的方法
(1)读写方法
document.open() //用于新建并打开一个文档
document.close() //不安比open方法所新建的文档
document.write() //用于向当前文档写入内容
document.writeIn() //用于向当前文档写入内容,尾部添加换行符。
(2)查找节点
document.querySelector(selectors) //接受一个CSS选择器作为参数,返回第一个匹配该选择器的元素节点。
document.querySelectorAll(selectors) //接受一个CSS选择器作为参数,返回所有匹配该选择器的元素节点。
document.getElementsByTagName(tagName) //返回所有指定HTML标签的元素
document.getElementsByClassName(className) //返回包括了所有class名字符合指定条件的元素
document.getElementsByName(name) //用于选择拥有name属性的HTML元素(比如<form>、<radio>、<img>、<frame>、<embed>和<object>等)
document.getElementById(id) //返回匹配指定id属性的元素节点。
document.elementFromPoint(x,y) //返回位于页面指定位置最上层的Element子节点。
(3)生成节点
document.createElement(tagName) //用来生成HTML元素节点。
document.createTextNode(text) //用来生成文本节点
document.createAttribute(name) //生成一个新的属性对象节点,并返回它。
document.createDocumentFragment() //生成一个DocumentFragment对象
(4)事件方法
document.createEvent(type) //生成一个事件对象,该对象能被element.dispatchEvent()方法使用
document.addEventListener(type,listener,capture) //注册事件
document.removeEventListener(type,listener,capture) //注销事件
document.dispatchEvent(event) //触发事件
(5)其他
document.hasFocus() //返回一个布尔值,表示当前文档之中是否有元素被激活或获得焦点。
document.adoptNode(externalNode) //将某个节点,从其原来所在的文档移除,插入当前文档,并返回插入后的新节点。
document.importNode(externalNode, deep) //从外部文档拷贝指定节点,插入当前文档。
1.4 Element节点
1.4.1 Element节点的属性
(1)特性属性
Element.attributes //返回当前元素节点的所有属性节点
Element.id //返回指定元素的id属性,可读写
Element.tagName //返回指定元素的大写标签名
Element.innerHTML //返回该元素包含的HTML代码,可读写
Element.outerHTML //返回指定元素节点的所有HTML代码,包括它自身和包含的的所有子元素,可读写
Element.className //返回当前元素的class属性,可读写
Element.classList //返回当前元素节点的所有class集合
Element.dataset //返回元素节点中所有的data-*属性。
(2)尺寸属性
Element.clientHeight //返回元素节点可见部分的高度
Element.clientWidth //返回元素节点可见部分的宽度
Element.clientLeft //返回元素节点左边框的宽度
Element.clientTop //返回元素节点顶部边框的宽度
Element.scrollHeight //返回元素节点的总高度
Element.scrollWidth //返回元素节点的总宽度
Element.scrollLeft //返回元素节点的水平滚动条向右滚动的像素数值,通过设置这个属性可以改变元素的滚动位置
Element.scrollTop //返回元素节点的垂直滚动向下滚动的像素数值
Element.offsetHeight //返回元素的垂直高度(包含border,padding)
Element.offsetWidth //返回元素的水平宽度(包含border,padding)
Element.offsetLeft //返回当前元素左上角相对于Element.offsetParent节点的垂直偏移
Element.offsetTop //返回水平位移
Element.style //返回元素节点的行内样式
(3)节点相关属性
Element.children //包括当前元素节点的所有子元素
Element.childElementCount //返回当前元素节点包含的子HTML元素节点的个数
Element.firstElementChild //返回当前节点的第一个Element子节点
Element.lastElementChild //返回当前节点的最后一个Element子节点
Element.nextElementSibling //返回当前元素节点的下一个兄弟HTML元素节点
Element.previousElementSibling //返回当前元素节点的前一个兄弟HTML节点
Element.offsetParent //返回当前元素节点的最靠近的、并且CSS的position属性不等于static的父元素。
1.4.2 Element节点的方法
(1)位置方法
getBoundingClientRect()
// getBoundingClientRect返回一个对象,包含top,left,right,bottom,width,height // width、height 元素自身宽高
// top 元素上外边界距窗口最上面的距离
// right 元素右外边界距窗口最上面的距离
// bottom 元素下外边界距窗口最上面的距离
// left 元素左外边界距窗口最上面的距离
// width 元素自身宽(包含border,padding)
// height 元素自身高(包含border,padding)
getClientRects() //返回当前元素在页面上形参的所有矩形。
// 元素在页面上的偏移量
var rect = el.getBoundingClientRect()
return {
top: rect.top + document.body.scrollTop,
left: rect.left + document.body.scrollLeft
}
(2)属性方法
Element.getAttribute():读取指定属性
Element.setAttribute():设置指定属性
Element.hasAttribute():返回一个布尔值,表示当前元素节点是否有指定的属性
Element.removeAttribute():移除指定属性
(3)查找方法
Element.querySelector()
Element.querySelectorAll()
Element.getElementsByTagName()
Element.getElementsByClassName()
(4)事件方法
Element.addEventListener():添加事件的回调函数
Element.removeEventListener():移除事件监听函数
Element.dispatchEvent():触发事件
//ie8
Element.attachEvent(oneventName,listener)
Element.detachEvent(oneventName,listener)
// event对象
var event = window.event||event;
// 事件的目标节点
var target = event.target || event.srcElement;
// 事件代理
ul.addEventListener('click', function(event) {
if (event.target.tagName.toLowerCase() === 'li') {
console.log(event.target.innerHTML)
}
});
(5)其他
Element.scrollIntoView() //滚动当前元素,进入浏览器的可见区域
//解析HTML字符串,然后将生成的节点插入DOM树的指定位置。
Element.insertAdjacentHTML(where, htmlString);
Element.insertAdjacentHTML('beforeBegin', htmlString); // 在该元素前插入
Element.insertAdjacentHTML('afterBegin', htmlString); // 在该元素第一个子元素前插入
Element.insertAdjacentHTML('beforeEnd', htmlString); // 在该元素最后一个子元素后面插入
Element.insertAdjacentHTML('afterEnd', htmlString); // 在该元素后插入
Element.remove() //用于将当前元素节点从DOM中移除
Element.focus() //用于将当前页面的焦点,转移到指定元素上
二、CSS操作
(1)类名操作
//ie8以下
Element.className //获取元素节点的类名
Element.className += ' ' + newClassName //新增一个类名
//判断是否有某个类名
function hasClass(element,className){
return new RegExp(className,'gi').test(element.className);
}
//移除class
function removeClass(element,className){
element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') +