未分类

益米主页总结(2)

你们知道弄了一整天才把博客重新弄好是什么心情吗。。
给笔记本换了固态硬盘格了C盘D盘什么软件都要重装。
折腾了好久才知道原来HEXO升级为3.0了。
之前2.7用的好好的现在弄了好久真的是心好累啊心好累啊。
不过算是弄好了,自己把public文件夹手动deploy【再见】。
好了记一下主页里用到的JS吧。
最终页面:益米,让校园生活轻松自在

JS-base

不知道为什么我自己就是不喜欢用jQuery。就是喜欢自己写长长的JS代码。所以把自己之前写过的函数都收集起来真的是太有必要了:

判断是否在数组内

1
2
3
4
5
6
7
8
function is_inArray (array,target) {
for (var i = 0; i < array.length; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}

其实我觉得写得还好。。不过来看看zepto.js的:

1
2
3
$.inArray = function(elem, array, i){
return emptyArray.indexOf.call(array, elem, i)
}

先来了解这个call()函数:
这是每个函数非继承而来的方法,还有一个是apply()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。apple()接受两个参数:一个是在其中运行函数的作用域,另一个是参数数组。
call()方法和apply()方法的区别在于接受参数的方式不同,第一个参数是this值,变化的是其余参数都直接传递给函数。具体参考《JavaScript高级程序设计》P117。这里写个例子:

1
2
3
4
5
6
7
8
9
10
11
window.color = "red";
var o = {color: "blue" };
function sayColor(){
alert(this.color);
}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue 函数执行的环境不一样了,之前是在window下,现在是在o下。

使用call()来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。

1
2
3
4
5
6
7
8
9
10
window.color = "red";
var o = {color: "blue" };
function sayColor(){
alert(this.color);
}
sayColor(); //red
o.sayColor = sayColor;
o.sayColor(); //blue

对比这两种写法,发现前面那种好很多了。
然后是数组的index()方法:
接受两个参数:要查找的项和(可选的)表示查找起点位置的索引。
我之前一直以为这个方法只是在字符串里面使用。。用在查找类名。。
擦原来系统已经提供了这个方法我还在自己写。
对了,回到我写的那个方法。
for (var i = 0; i < array.length; i++)最好不要这么写,因为如果数组是DOM节点的集合,每次都需要获取一遍长度,比较消耗资源,所以改写成:for(var i = 0,var max = array.length; i < max; i++)

移除元素的某个类

先不要脸的放上自己写的:

1
2
3
4
5
6
function removeClassName (target,clsName) {
var allcls = target.className;
if (allcls.indexOf(clsName)) {
target.className = allcls.replace(clsName," ");
}
}

zepto.js版:

1
2
3
4
5
6
7
8
9
10
11
removeClass: function(name){
return this.each(function(idx){
if (!('className' in this)) return
if (name === undefined) return className(this, '')
classList = className(this)
funcArg(this, name, idx, classList).split(/\s+/g).forEach(function(klass){
classList = classList.replace(classRE(klass), " ")
})
className(this, classList.trim())
})
},

看我慢慢读懂他在做些什么…
第4行有个函数className:

1
2
3
4
5
6
7
8
// access className property while respecting SVGAnimatedString
function className(node, value){
var klass = node.className || '',
svg = klass && klass.baseVal !== undefined
if (value === undefined) return svg ? klass.baseVal : klass
svg ? (klass.baseVal = value) : (node.className = value)
}

哇擦后面他在干什么。。应该是在respecting SVGAnimatedString
所以第四行就是如果传入的类名为空,则设置该元素的类为空(移除所有类)。
还有个funcArg(),一看就觉得是来获得函数参数的:

1
2
3
function funcArg(context, arg, idx, payload) {
return isFunction(arg) ? arg.call(context, idx, payload) : arg
}

好像不是呢哈哈哈。。。
在这里是返回了原来的name。(name有可能是函数,这个会比较复杂)
然后对返回的字符串进行正则表达式匹配:/\s+/g\s代表空格,+代表一个或者多个。所以这样就把类名通过空格分开来存放到数组里面了。
然后又有一个新函数:

1
2
3
4
function classRE(name) {
return name in classCache ?
classCache[name] : (classCache[name] = new RegExp('(^|\\s)' + name + '(\\s|$)'))
}

这里的正则表达式:'(^|\\s)'代表以空格或者什么都没有开始,'(\\s|$)'代表以空格或什么都没有结束。连起来就是:
className可以匹配,className也可以匹配。
所以就是设置类名。。。
回到原来的函数,就是找到那个类名,然后换回” “。
最后是删除字符串前后的空格符trim()赋值给元素的类。和String.prototype.trim()一样。
啊终于看了个七七八八了。。

函数节流

1
2
3
4
5
6
7
8
9
/* 函数节流throttle */
function throttle (method, context) {
if (method.tId) {
clearTimeout(method.tId);
};
method.tId = setTimeout(function () {
method.call(context);
}, 150);
}

这个东西用在window.onsize()或者window.onscroll()之前就在想我擦网页滚动一下就执行函数会不会太消耗性能了,后来就发现了这个东西,不过最后没有这么用,而是:

1
2
3
4
5
6
7
8
9
10
window.onscroll = function() {
if (onscrollTimer) {
clearTimeout(onscrollTimer);
}
onscrollTimer = setTimeout(function() {
//code
},
100);
}

每隔0.1s触发一次。实际运行效果很OK。

事件函数

前面有篇文章写了,这次也用到了。兼容性良好。。

分享到