jquery 对象转string_JQuery

简介:

jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。jQuery的核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。jQuery兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等。

jQuery的语法是选取一个元素,并对其执行操作。

jQuery如何获取元素

使用jQuery的第一步,是将一个选择表达式,放进构造函数jQuery()(简写为$())。

$('#xxx')返回值不是元素,是一个api对象。

$(document) // 选择整个文档对象 $('#xxx').find('.red') //选择#xxx里的.red元素 $('p') // 选择所有p标签 $('#aa') // 选择ID为aa的元素 $('.bb') // 选择class为bb的元素 $('input[name=cc]') // 选择name属性等于cc的input元素 $('p.red,p.green') // 把<p class="red">和<p class="green">都选出来 $('.red').each(fn) //遍历并对每个元素执行fn

jQuery的链式操作

每一步的jQuery()操作,返回的都是jQuery对象,所以不同操作可以连在一起,这就是链式操作,允许我们在相同的元素上运行多条 jQuery 命令,一条接着另一条。

$("#p1").css("color","red").slideUp(2000).slideDown(2000); //选择"p1"元素,使其变为红色,然后向上滑动,再然后向下滑动

jQuery创建元素

创建新元素,只要把新元素直接传入jQuery的构造函数就行了。

$("<div id='test' class='aaron'>我是文本节点</div>")

如需删除元素和内容,一般可使用以下两个 jQuery 方法:

  • remove() - 删除被选元素(及其子元素)
  • empty() - 从被选元素中删除子元素

jQuery移动元素

外部插入:

  • after() - 在被选元素之后插入内容。
  • before() - 在被选元素之前插入内容。

内部插入:

  • append() - 在被选元素内部的结尾插入内容
  • prepend() - 在被选元素内部的开头插入内容

还有另一种方法,insertAfter(),insertBefore(),appendTo(),prependTo(),功能相同,插入内容和目标的位置相反。

jQuery修改元素的属性

常见的取值和赋值函数:

.html() 返回或设置html内容 .text() 返回或设置text内容 .val() 返回或设置某个表单元素的值 .attr() 返回或设置某个属性的值 .width() 返回或设置某个元素的宽度 .height() 返回或设置某个元素的高度

其他常用

addClass()在元素中增加指定的类

removeClass()在元素中删除指定的类

toggleClass()检查元素中指定的类,如果不存在则添加类,如果已设置则删除

闭包:

闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

闭包​developer.mozilla.org
4f39b1289fdd0acb440fbef563a4366d.png

链式结构:

javascript的链式编程的核心就是return this;

连接来自于:

千锋HTML5学院:javascript中的链式操作​zhuanlan.zhihu.com
11670034c04ee4821db0338e8b8b8660.png

jQuery代码:

window.jQuery = function(selectorOrArrayOrTemplate){
  let elements
  if(typeof selectorOrArrayOrTemplate === 'string'){
    if(selectorOrArrayOrTemplate[0] === '<'){
      // 创建 div
      elements=[createElement(selectorOrArrayOrTemplate)]
    }else{
      // 查找 div
      elements = document.querySelectorAll(selectorOrArrayOrTemplate)
    }
  }else if(selectorOrArrayOrTemplate instanceof Array){
    elements = selectorOrArrayOrTemplate
  }

  function createElement(string){
    const container = document.createElement("template");
    container.innerHTML = string.trim();
    return container.content.firstChild;
  }
  // api 可以操作elements
  return {
    jquery: true,
    elements: elements,
    get(index){//闭包因为get用到了他外面的element变量,
      return elements[index]
    },
    appendTo(node){
      if(node instanceof Element){
        this.each(el => node.appendChild(el)) // 遍历 elements,对每个 el 进行 node.appendChild 操作
      }else if(node.jquery === true){
        this.each(el => node.get(0).appendChild(el))  // 遍历 elements,对每个 el 进行 node.get(0).appendChild(el))  操作
      }
    },
    append(children){
      if(children instanceof Element){
        this.get(0).appendChild(children)
      }else if(children instanceof HTMLCollection){
        for(let i =0;i<children.length;i++){
          this.get(0).appendChild(children[i])
        }
      }else if(children.jquery === true){
        children.each(node => this.get(0).appendChild(node))
      }
    },
    find(selector){
      let array = []
      for(let i =0;i<elements.length;i++){
        const elements2 = Array.from(elements[i].querySelectorAll(selector))
        array = array.concat(elements2)
      }
      array.oldApi = this // this 就是 旧 api
      return jQuery(array)
    },
    each(fn){
      for(let i=0; i<elements.length;i++){
        fn.call(null, elements[i], i)//fn(elements[i],i)
      }
      return this
    },
    parent(){
      const array = []
      this.each((node)=>{
        if(array.indexOf(node.parentNode) === -1){
          array.push(node.parentNode)
        }
      })
      return jQuery(array)
    },
    children(){
      const array = []
      this.each((node)=>{
        // 上课的时候这段代码是复制的,复制错了,现已改正
        array.push(...node.children)//...把每个节点分开
        
      })
      //const newApi = jQuery(array)
      //return newApi
      return jQuery(array)
    },
    print(){
      console.log(elements)
    },
    // 闭包:函数访问外部的变量,访问函数只能使用函数访问
    addClass(className){
      for(let i=0;i<elements.length;i++){
        const element = elements[i]
        element.classList.add(className)
      }
      return this
    },
    oldApi: selectorOrArrayOrTemplate.oldApi,
    end(){
      return this.oldApi  // this 就是新 api
    },
  }
}

window.$ = window.jQuery

闭包的好处:用户不可以直接操作element需要通过操作函数才能够操作element比如get(){}函数

main.js代码:

const $div = $('<div><span>1</span></div>')
const $childList = $('.child')
$('body').append($childList)

index.html

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>手写 jQuery</title>
</head>
<body>
  <div class="test">
    你好1
    <div class="child">child1</div>
    <div class="child">child2</div>
    <div class="child">child3</div>
  </div>
  <div class="test">
    你好2
    <div class="child">child2</div>
    <div class="child">child3</div>
  </div>
  <div class="test">
    你好3
    <div class="child">child3</div>
  </div>
  <div id="container">
    container
  </div>
  <script src="jquery.js"></script> 
  <script src="main.js"></script>
</body>
</html>

注意$div在大部分时候对应了多个div元素

querySelectorAll()

HTML DOM querySelectorAll() 方法​www.runoob.com

JavaScript HTML DOM 节点列表

JavaScript HTML DOM 节点列表​www.runoob.com

JavaScript HTML DOM 集合(Collection)

JavaScript HTML DOM 集合(Collection)​www.runoob.com

HTMLCollection 与 NodeList 的区别

  1. HTMLCollection 是 HTML 元素的集合。
  2. NodeList 是一个文档节点的集合。
  3. NodeList 与 HTMLCollection 有很多类似的地方。
  4. NodeList 与 HTMLCollection 都与数组对象有点类似,可以使用索引 (0, 1, 2, 3, 4, ...) 来获取元素。
  5. NodeList 与 HTMLCollection 都有 length 属性。
  6. HTMLCollection 元素可以通过 name,id 或索引来获取。
  7. NodeList 只能通过索引来获取。
  8. 只有 NodeList 对象有包含属性节点和文本节点。
节点列表不是一个数组! 节点列表看起来可能是一个数组,但其实不是。 你可以像数组一样,使用索引来获取元素。 节点列表无法使用数组的方法: valueOf(), pop(), push(), 或 join() 。

后续:

使用原型

把共有的属性(函数)全部放到$.prototype

$.fn = $.prototype//名字太长不爽

然后让.api.__proto__指向$.fn

原理图:

1a7a7fe43daa726120732e4e491ea3ea.png

后续代码:

  window.jQuery = function(selectorOrArrayOrTemplate){
  let elements
  if(typeof selectorOrArrayOrTemplate === 'string'){
    if(selectorOrArrayOrTemplate[0] === '<'){
      // 创建 div
      elements=[createElement(selectorOrArrayOrTemplate)]
    }else{
      // 查找 div
      elements = document.querySelectorAll(selectorOrArrayOrTemplate)
    }
  }else if(selectorOrArrayOrTemplate instanceof Array){
    elements = selectorOrArrayOrTemplate
  }

  function createElement(string){
    const container = document.createElement("template");
    container.innerHTML = string.trim();
    return container.content.firstChild;
  }
  // api 可以操作elements
  const api = Object.create(jQuery.prototype)//创建一个对象,这个对象的__proto__为括号里面的东西,相当于const api = {__proto__:jQuery.prototype}
  Object.assign(api,{
    elements:elements,//不可以再写api={}要不会覆盖前面的api
    oldApi:selectorOrArrayOrTemplate.oldApi,
  })//把后面的属性一个一个复制到前面去
   // api.elements = elements//不可以再写api={}要不会覆盖前面的api
  // api.oldApi = oldApi
  return api
};//完成内存的节约

jQuery.fn = jQuery.prototype ={
  jquery:true,
  constructor:jQuery,
  get(index){
    return this.elements[index]//原先的代码是没有this的,那就获取不到element所以才加this
  },
  appendTo(node){
    if(node instanceof Element){
      this.each(el => node.appendChild(el)) // 遍历 elements,对每个 el 进行 node.appendChild 操作
    }else if(node.jquery === true){
      this.each(el => node.get(0).appendChild(el))  // 遍历 elements,对每个 el 进行 node.get(0).appendChild(el))  操作
    }
  },
  append(children){
    if(children instanceof Element){
      this.get(0).appendChild(children)
    }else if(children instanceof HTMLCollection){
      for(let i =0;i<children.length;i++){
        this.get(0).appendChild(children[i])
      }
    }else if(children.jquery === true){
      children.each(node => this.get(0).appendChild(node))
    }
  },
  find(selector){
    let array = []
    for(let i =0;i<this.elements.length;i++){
      const elements2 = Array.from(this.elements[i].querySelectorAll(selector))
      array = array.concat(this.elements2)
    }
    array.oldApi = this // this 就是 旧 api
    return jQuery(array)
  },
  each(fn){
    for(let i=0; i<this.elements.length;i++){
      fn.call(null,this.elements[i], i)//fn(elements[i],i)
    }
    return this
  },
  parent(){
    const array = []
    this.each((node)=>{
      if(array.indexOf(node.parentNode) === -1){
        array.push(node.parentNode)
      }
    })
    return jQuery(array)
  },
  children(){
    const array = []
    this.each((node)=>{
      // 上课的时候这段代码是复制的,复制错了,现已改正
      array.push(...node.children)//...把每个节点分开
      
    })
    //const newApi = jQuery(array)
    //return newApi
    return jQuery(array)
  },
  print(){
    console.log(this.elements)
  },
  // 闭包:函数访问外部的变量,访问函数只能使用函数访问
  addClass(className){
    for(let i=0;i<this.elements.length;i++){
      const element = this.elements[i]
      element.classList.add(className)
    }
    return this
  },
  end(){
    return this.oldApi  // this 就是新 api
  },
}
window.$ = window.jQuery

    

运行结果:

f26018210f36c5fe349443da956978b2.png

设计模式:
JQuery 用到哪些设计模式

不用new的构造函数,这个模式没有专门的名字

$(支持多种参数),这个模式的叫做重载

用闭包隐藏细节,这个模式没有专门的名字

$div.text()即可读也可写,getter/setter

$.fn是$.prototype的别名,这叫做别名

JQuery针对不同浏览器使用不同的代码,这叫适配器

设计模式是啥?

给自己漂亮的代码写法取个名字,比如适配器模式

设计模式就是对通用代码取个名字

复习关于如何创建分支:

git branch//查看分支
git branch 分支名字
git checkout
git status
git add .
git commit -v/git commit -m "要写的注释"
git push origin 分支名字

完整代码:

1.master

2.branch是分支后续代码

Righthand5/JQuery-dome-2​github.com
1780590260f4f05ff724f915ad898c54.png

大神博客:

jQuery设计思想 - 阮一峰的网络日志​www.ruanyifeng.com
3f14e07bf5aaafb72682a7463f3fae4f.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值