博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实现一个jQuery的API
阅读量:7237 次
发布时间:2019-06-29

本文共 8765 字,大约阅读时间需要 29 分钟。

1. 封装函数

1.1 获取node的兄弟元素

1.1.1 原始代码

  • 选项1
  • 选项2
  • 选项3
  • 选项4
  • 选项5
let allChildren = item3.parentNode.childrenlet array = { length: 0}for (let i = 0; i < allChildren.length; i++) { if (allChildren[i] !== item3) { array[array.length] = allChildren[i] //给伪数组添加子元素 array.length += 1 }}console.log(array) // 得到items3的兄弟元素的伪数组复制代码

1.1.2 封装函数,得到API,getSiblings()

function getSiblings(node) {  // 这个这就是API     let allChildren = node.parentNode.children    let array = {      length: 0    }    for (let i = 0; i < allChildren.length; i++) {      if (allChildren[i] !== node) {        array[array.length] = allChildren[i]         array.length += 1      }    }    return array}console.log(getSiblings(item3))  // 得到items3的兄弟元素复制代码

1.2 写第二个函数,给元素添加样式

1.2.1 原始代码

let classes = {
'a':true,'b':false,'c':true} for (let key in classes) { // 遍历这个哈希表 let value = classes[key] if (value) { // value值为真则添加,假则删除 node.classList.add(key) } else { node.classList.remove(key) } }复制代码

1.2.2 封装函数, 得到第二个API,addClass()

function addClass(node, classes) {    for (let key in classes) {        let value = classes[key]        if (value) {            node.classList.add(key)        } else {            node.classList.remove(key)        }    }}addClass(item3, {a:true,b:false,c:true})   复制代码

1.2.3 代码优化

只要有相似的代码,就有优化的空间 。

function addClass(node, classes) {    for (let key in classes) {        let value = classes[key]        let methodName = value ? 'add':'remove'  //如果value值为真,methodName为add,假则为remove            node.classList.['methodName'](key)    }}ffdom.addClass(item3, {a:true,b:false,c:true})复制代码

1.2.4 改成数组的形式

function addClass(node, classes) {    classes.forEach((value)=> node.classList.add(value))}addClass(item3, ['a','b','c'])复制代码

2. 关联两个独立的函数 命名空间

利用命名空间的设计模式,关联两个独立的函数,这样还可以防止代码覆盖的问题。

window.xxxxdom = {}  /*yui使用的就是命名空间的模式*/xxxxdom.getSiblings = function(node) {      let allChildren = node.parentNode.children    let array = {                       // 伪数组      length: 0    }    for (let i = 0; i < allChildren.length; i++) {      if (allChildren[i] !== node) {        array[array.length] = allChildren[i]   // 伪数组没有push()方法,利用length来添加元素        array.length += 1      }    }    return array}xxxxdom.addClass = function(node, classes) {    classes.forEach((value)=> node.classList.add(value))}xxxxdom .getSiblings(items)xxxxdom .addClass(item3, ['a','b','c'])复制代码

3. 去掉xxxxdom

去掉xxxxdom,改写成以下模式,我们有两种方法。

item3.getSiblings()item3.addClass(['a','b','c'])复制代码

3.1 第一种方法,直接改node的原型

这样做的缺点:会产生代码覆盖的问题。

Node.prototype.getSiblings = function() {    let allChildren = this.parentNode.children    // this 隐式指向 Node        let array = {          length: 0        }        for (let i = 0; i < allChildren.length; i++) {          if (allChildren[i] !== this) {            array[array.length] = allChildren[i]             array.length += 1          }        }        return array}Node.prototype.addClass = function(classes) {    classes.forEach((value)=> this.classList.add(value))}console.log(item3.getSiblings()) //  得到一个item3的兄弟元素的伪数组item3.addClass(['a','b','c'])复制代码

3.1.1 函数调用,用call与不用call的区别

用call就是显示指定this,this是第一个参数 不用是显示隐式指定this

item3.getSiblings.call(item3)item3.addClass.call(item3,['a','b','c'])复制代码

3.2 第二种方法,自己做个构造函数,

自己创造一个构造函数,就是可以解决代码覆盖的问题。

3.2.1 思路

创造一个Node2的构造函数,它接收一个node参数,返回一个哈希表,它的key就是我们的想要的api。使用时,传入node参数,就可以使用了。

window.Node2 = function(node) {    return {        getSiblings: function() {            let allChildren = node.parentNode.children   // node  是传进来的节点参数            let array = {              length: 0            }            for (let i = 0; i < allChildren.length; i++) {              if (allChildren[i] !== node) {                array[array.length] = allChildren[i]                 array.length += 1              }            }            return array        }        addClass: function(classes) {            classes.forEach((value)=> node.classList.add(value))        }    }}var node2 = Node2(item3)node2.getSiblings()node2.addClass(['a','b','c']))复制代码

3.2.1 将Node2改为jQuery

将Node2改为jQuery,jQuery接收一个旧的dom,返回一个新的对象,这个新的对象有新的api,内部实现还是调用旧的api,只不过好用了一些。jQuery实质上是一个构造函数,接收一个参数,这个参数可以使节点或选择器,然后返回一个方法对象去操作节点。

window.jQuery = function(node) {    return {        getSiblings: function() {            let allChildren = node.parentNode.children            let array = {              length: 0            }            for (let i = 0; i < allChildren.length; i++) {              if (allChildren[i] !== node) {                array[array.length] = allChildren[i]                 array.length += 1              }            }            return array        }        addClass: function(classes) {            classes.forEach((value)=> node.classList.add(value))        }    }}var node2 = jQuery(item3)node2.getSiblings()node2.addClass(['a','b','c']))复制代码

3.2.2 改进这个jQuery,传参改进

传参node可以不只是node还可以是选择器selector,只需要进行类型检测即可。

window.jQuery = function(nodeOrSelector) {    let node    if(typeof nodeOrSelector === 'string') {    // 类型检测        node = document.querySelector(nodeOrSelector)    } else {        node = nodeOrSelector    }    return {        getSiblings: function() {            let allChildren = node.parentNode.children            let array = {              length: 0            }            for (let i = 0; i < allChildren.length; i++) {              if (allChildren[i] !== node) {                array[array.length] = allChildren[i]                 array.length += 1              }            }            return array        }        addClass: function(classes) {            classes.forEach((value)=> node.classList.add(value))        }    }}var node2 = jQuery('#item3')      // 可以通过选择器来找到node了node2.getSiblings()node2.addClass(['red','b','c']))相关csscss    .red {color: red;}复制代码

3.2.3 改进这个jQuery,操作多个节点

window.jQuery = function(nodeOrSelector) {    let nodes    if(typeof nodeOrSelector === 'string') {        let temp = document.querySelectorAll(nodeOrSelector)  // 伪数组        for(let i=0;i
li')console.log(node2)复制代码

3.2.4 改进这个jQuery,给nodes添加方法

window.jQuery = function(nodeOrSelector) {    let nodes    if(typeof nodeOrSelector === 'string') {        let temp = document.querySelectorAll(nodeOrSelector)  // 伪数组        for(let i=0;i
{ for(let i = 0; i < nodes.length; i++) { node[i].classList.add(value) } } } return nodes}var node2 = jQuery('ul > li')node2.addClass(['blue'])复制代码

3.2.5 改进这个jQuery,给nodes添加其他api

添加getText()和setText()

window.jQuery = function(nodeOrSelector) {    let nodes    if(typeof nodeOrSelector === 'string') {        let temp = document.querySelectorAll(nodeOrSelector)  // 伪数组        for(let i=0;i
{ for(let i = 0; i < nodes.length; i++) { node[i].classList.add(value) } } } nodes.getText = function() { // 添加getText() var texts = [] for(let i = 0; i < nodes.length; i++) { text.push(nodes[i].textContent) } return texts } nodes.setText = function() { // 添加setText() for(let i = 0; i < nodes.length: i++) { nodes[i].textContent = texgt } } return nodes}var node2 = jQuery('ul > li')node2.addClass(['blue'])node2.getText()node2.setText('hi')复制代码

3.2.6 优化text() api

window.jQuery = function(nodeOrSelector) {    let nodes = {}    if(typeof nodeOrSelector === 'string') {        let temp = document.querySelectorAll(nodeOrSelector)  // 伪数组        for(let i=0;i
{ for(let i = 0; i < nodes.length; i++) { node[i].classList.add(value) } } } node2.text = function(text) { // 将getText()和setText()合并 if(text === undefined) { var texts = [] for(let i = 0; i < nodes.length; i++) { text.push(nodes[i].textContent) } return texts } } else { for(let i = 0; i < nodes.length: i++) { nodes[i].textContent = text } } return nodes}var node2 = jQuery('ul > li')node2.addClass(['blue'])console.log(node2.text())node2.text('hi')复制代码

4. 总结

jQuery的实现思路:创建一个jQuery构造函数,接收一个node或selector,并把它封装成一个伪数组,然后在这个伪数组上增加几个api,返回这个伪数组。

window.jQuery = function(nodeOrSelector) {  let nodes = {    0: nodeOrSelector,    length: 1  }  nodes.addClass = function(classes) {}  nodes.text = function(text) {}  return nodes}var node2 = jQuery('ul > li'){0: li, 1: li, length: 5, addClass: f, text: f}node2.addClass(['blue'])node2.text()node2[0].classList.add('blue')复制代码

jQuery的优点:

  • jQuery 在兼容性方面做得很好,1.7 版本兼容到 IE 6。
  • jQuery 还有动画、AJAX 等模块,不止 DOM 操作。
  • jQuery 的功能更丰富。

5. 参考链接

饥人谷jQeury相关课程https://xiedaimala.com/

转载于:https://juejin.im/post/5ab90862518825557208622e

你可能感兴趣的文章
前端与移动开发之vue-day6(3)
查看>>
思维导图怎么画呢
查看>>
启明星辰信息安全面试
查看>>
revit 2017下载(附注册码密钥)
查看>>
计算机相关
查看>>
Show/Hide Form Section by Name
查看>>
UI Macro - Get value of other variables
查看>>
百度打造人工智能正循环:使用者越多 机器越聪明
查看>>
linux第一波命令总结
查看>>
LINUX-centos7tomcat安装教程
查看>>
全新JAVA高级架构师项目实战 Springboot+MyBatis+RocketMQ
查看>>
年轻人应该如何培养毅力?
查看>>
MyBatis组件之缓存实现及使用
查看>>
OpenStack 应用调试
查看>>
英国正式启用首批5G服务
查看>>
判断一个字符串是否为另外一个字符串旋转之后的字符串。
查看>>
今天开始采用的十大大数据技术
查看>>
oracle教程之oralce非归档模式下的恢复(一)
查看>>
我的友情链接
查看>>
远程桌面,身份验证错误:要求的函数不正确等解决办法
查看>>