自己封装两个函数
封装函数的方法。这两个函数分别为:
function getSiblings(node){}
getSiblings 函数的功能为获取传入节点的所有"兄弟",结果返回一个包装好的对象 以及函数:addClass
function addClass(node,classes){}
此函数的功能为:对节点添加或删除class,传入一个节点和一个对象如:{a:true,b:false,c:true}
当传入对象的value值为true则表示在node的classList中添加它的key,如果为false,则表示在node的classList中删除key。
代码如下:
function getSiblings(node){
// children 与 childNodes的区别:
// 非IE浏览器下 childNodes为获取元素节点与文本节点
// children则是获取元素节点,且浏览器表现相同
var allChildren = node.parentNode.children;
var array = {
length:0
}
for(var i=0;i
function addClass(node,classes) {
for(var key in classes){
if(classes[key]){
node.classList.add(key);
}else{
node.classList.remove(key);
}
}
}
代码优化
对于函数addClass 可以进行代码优化,如果不考虑性能,仅从代码的“美观度”来讲,优化原则其实非常简单即:
如果在代码中,存在类似的代码,就说明代码存在优化的可能。
函数addClass中,存在类似的代码node.classList.add(key);以及node.classList.remove(key); 优化后的代码如下:
function addClass(node,classes){
for(var key in classes){
var methodName = classes[key]? 'add':'remove';
node.classList[methodName](key);
}
}
命名空间
将一个对象封装好函数,设置到全局对象window当中,这就是所谓的命名空间。代码如下:
var item3 = document.getElementById('item3');
window.chDom = {};
chDom.getSiblings = function(node){
var allChildren = node.parentNode.children;
var array = {
length:0
}
for(var i=0;i
使用Node.prototype
当我们想调用getSiblings与addClass时,如果每一次都这样去调用我们的API:chDom.getSiblings(node);,
我们难免会觉得这样写代码都有一点臃肿,如果代码是node.getSiblings(),那么就最好不过了,不仅简洁,
而且更容易让人明白代码的“语意”。使用Node的原型就可以做到这一点:
Node.prototype.getSiblings = function(){
var allChildren = this.parentNode.children;
var array = {
length:0
}
for(var i=0;i
我们将getSiblings以及addClass 添加到了Node的原型当中,这样一来,我们就可以使用node.getSiblings()这样的写法来调用我们封装好的函数。
this是call()的第一个参数
this是什么?this就是call()的第一个参数,没有然后了。回顾下call():call(this,arguments[0],arguments[1],...arguments[n])。
对于item3.getSiblings.call(item3) 即相当于 :item3.getSiblings() 为什么要使用call()?
因为,不使用call()的话,你怎么会理解this呢?试想一下这段代码打印的结果是什么?
console.log(item3.getSiblings.call(item4));
打印在控制台上的结果为:
Object
0: li#item1
1: li#item2
2: li#item3
3: li#item5
length: 4
__proto__: Object
当使用call里面的第一个参数为item4时,this代表的就是item4了,打印出来的结果自然是除了item4以外的其他li节点包装的对象。所以只有使用call,你才会明白this到底是什么东西
简易的jQuery
使用Node.prototype固然可以,但是试想一下,张三在Node原型里添加了某某属性,李四又在Node原型里面添加了某某属性,你填了一撇,我写了一捺,这样一来,岂不是全都乱掉了吗?于是乎,我们可以这样做。
// 继Node.prototype后,我们将jQuery这个属性添加到window这个全局对象当中
// var node = jQuery(argument);向 jQuery这个函数中传入的参数可以是节点或者是选择器(字符串);函数返回一个对象
// 对象中有 addClass,text等属性,这些属性对应了上节课所实现的函数;对于getSiblings()这个方法实现起来相对比较复杂,所以先忽略这个方法
window.jQuery = function (nodeOrSelector) {
let nodes = {};
if(typeof nodeOrSelector === 'string'){
var temp = document.querySelectorAll(nodeOrSelector);
for(var i=0;ili');
console.log(node.text());
node.text.call(node,'hi');
node.addClass.call(node,{'red':true});
上面就是个简易的jQuery,当然jQuery可远远没有这么简单。不过,通过上面的代码最起码可以了解到jQuery是什么,那么,jQuery到底是什么?
jQuery其实就是一堆javaScript的函数,因为原生Dom提供的API太垃圾了,所以jQuery将我们常用的一些功能进行了封装,方便我们来调用,
提高开发的效率,jQuery这个js库应用最为广泛,于是乎成为了行业的标准。所以说jQuery的本质就是个调用了DomAPI的函数库。
初探jQuery
jQuery引入地址:https://cdnjs.com/
前端参考文档手册(中文):http://cndevdocs.com/
jQuery addClass:
var nodes = jQuery('ul>li');
// jQuery addClass 支持两种方法
// 1 .addClass( className )
// 示例:
// nodes.addClass('red');
// 2 .addClass( function(index, currentClass) )
// 示例:
/*nodes.addClass((index,currentClass)=> {
if(index<3){return 'red'};
})*/
// 3 jQuery支持链式操作
// 示例:
var classes = ['red','green','yellow','blue','black'];
nodes.removeClass('red').addClass(function (index,currentClass) {
return classes[index];
})
jQuery toggleClass:
var nodes = jQuery('ul>li');
btn.onclick = function () {
// toggle的含义为:开关,切换
// 如果nodes有red这样的class则删除,如果没有则添加
nodes.toggleClass('red');
}
jQuery 优点 与 $符号建议
jQuery 的优点有:
jQuery 在兼容性方面做得很好,1.7 版本兼容到 IE 6
jQuery 还有动画、AJAX 等模块,不止 DOM 操作
jQuery 的功能更丰富
jQuery 使用了 prototype,我们没有使用,等讲了 new 之后再用
$符号的建议:
window.$ = jQuery
在jQuery中,$
符号可以替代jQuery,如声明一个jQuery的对象:var nodes = jQuery('ul>li');
。我们可以写成:var $nodes = $('ul>li');
这里面,注意,我将原本的nodes
变为了$nodes
。这当然不是强制要求,但是我们确实应该这么做,这样我们的代码才便于维护,这样我们才能知道,哪些是jQuery
对象。
作业查看