📔
饥人谷前端体系课程笔记
黑马程序员笔记前端面试押题前端精进
  • 课程大纲
  • Git入门
    • 3. 软件安装详解
    • 4. Mac环境搭建
    • 5. 命令行入门
    • 6. 本地仓库
    • 7. Git远程仓库-GitHub
  • HTML全解
    • 8. HTML概览
    • 9. HTML标签
    • 10. HTML重难点
    • 11. HTML实践 & 手机调试
  • CSS全解
    • 12. CSS基础
    • 13. CSS布局(上)
    • 14. CSS布局(下)
    • 15. CSS定位
    • 16. CSS动画
  • HTTP全解
    • 17. URL 是什么
    • 18. 请求和响应 & Node.js Server
  • JS全解
    • 19. JavaScript概览
    • 20. 内存图与JS世界(精品课)
    • 21. Canvas 实践—画图板
    • 22. JS语法
    • 23. JS数据类型
    • 24. JS 对象
    • 25. JS 对象分类
    • 26. JS 数组
    • 27. JS 函数
    • 28. JS 实战,会动的代码
    • 29. JS运算符
    • 30. JS总结
  • JS编程接口
    • 31. DOM编程
    • 32. 手写DOM库
    • 33. JQuery中的设计模式(上)
    • 34. JQuery中的设计模式(下)
    • 35. DOM事件与事件委托
  • 项目 前端导航站点
    • 前端导航项目笔记
  • 前后分离
    • 40. AJAX的原理
    • 41. 异步与Promise
    • 42. 跨域、CORS、JSONP
    • 43. 静态服务器
    • 44. AJAX实战:Cookie、Session
  • JS进阶MVC
    • 48. MVC(上)
    • 49. MVC(中)
    • 50. MVC(下)
  • 项目构建
    • 51. Webpack(上)
    • 52. Webpack(下)
  • 算法与数据结构
    • 62. 伪代码与流程图
  • React全解
    • 75. React起手式
    • 76. React类组件和函数组件
    • 77. Class组件详解
    • 78. 函数组件
    • 79. Hooks原理解析
    • 80. Hooks各个击破
    • 81. 精通Redux
  • Node.js
    • 84. Node.js技术架构
    • 85. 文件模块
    • 86. 单元测试之文件模块
    • 87. 调试 Node.js 程序
    • 88. 静态服务器
    • 89. 命令行翻译工具
    • 90. 操作数据库
    • 91. 数据库基础知识
    • 92. Stream 流
    • 93. child_process
    • 94. 总结
  • TypeScript
    • 112. 基础
    • 113. 泛型
  • Next.js全解
    • Next.js 上
    • Next.js 下
  • ES6精讲
    • Promise,async/await
  • 大屏可视化笔记
    • 大屏可视化项目
  • SCSS全解
    • SCSS全解
  • 拓展
    • 一次性弄懂性能优化
    • Web性能优化
由 GitBook 提供支持
在本页
  • 链式风格
  • jQuery 是构造函数吗?
  • 术语
  • 链式风格
  • 命名风格
  • 链式风格
  • 链式风格
  • 设计模式
  • 我应该学习设计模式吗?
  • 有人说不用学 jQuery

这有帮助吗?

  1. JS编程接口

34. JQuery中的设计模式(下)

上一页33. JQuery中的设计模式(上)下一页35. DOM事件与事件委托

最后更新于2年前

这有帮助吗?

用 jQuery 风格重新封装

这节课你可能经常对自己说:我怎么没想到?!

不用慌张因为你肯定想不到

这是许多程序员多年摸索出来的经典代码

你只需要站在巨人的肩膀上,继续向上探索

链式风格

  • 也叫 jQuery 风格

    • window.jQuery() 是我们提供的全局函数

    //index.html
    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>手写jQuery</title>
    </head>
    <body>
        <div class="test">Hello</div>
        <script src="jquery.js"></script>
        <script src="main.js"></script>
    </body>
    </html>
    //main.js
    const api = jQuery(".test"); // 不返回元素,返回 api 对象
    api.addClass("red").addClass("blue"); // 链式操作
    
    //jQuery(".test").addClass("red").addClass("blue"); // 链式操作
    //jQuery.js
    window.jQuery = function (selector) {
      const elements = document.querySelectorAll(selector);
      // api 可以操作 elements
      return {
        addClass(className) {
          //闭包:函数访问外部的变量
          for (let i = 0; i < elements.length; i++) {
            elements[i].classList.add(className);
          }
          return this; //函数如果用对象来调用,那么函数里的 this 就指向这个对象
        },
      };
    };
    
  • 特殊函数 jQuery

    • jQuery(选择器) 用于获取对应的元素

    • 但它却不返回这些元素

    • 相反,它返回一个对象,称为 jQuery 构造出来的对象

    • 这个对象可以操作对应的元素

    • 听不懂?直接!

jQuery 是构造函数吗?

  • 是

    • 因为 jQuery 函数确实构造出了一个对象

  • 不是

    • 因为不需要写 new jQuery() 就能构造一个对象

    • 以前讲的构造函数都要结合 new 才行

  • 结论

    • jQuery 是一个不需要加 new 的构造函数

    • jQuery 不是常规意义上的构造函数

    • 这是因为 jQuery 用了一些技巧(目前没必要讲)

jQuery 对象代指 jQuery 函数构造出来的对象

口头约定

jQuery 对象不是说 「jQuery 这个对象」

一定要记清楚

术语

  • 举例

    • Object 是个函数

    • Object 对象 表示 Object 构造出的对象

    • Array 是个函数

    • Array 对象 / 数组对象 表示 Array 构造出来的对象

    • Function 是个函数

    • Function 对象 / 函数对象 表示 Function 构造出来的对象

链式风格

  • 查

    • jQuery('#xxx') 返回值并不是元素,而是一个 api 对象

    • jQuery('#xxx').find('.red') 查找 #xxx 里的 .red 元素

    • jQuery('#xxx').parent() 获取爸爸

    • jQuery('#xxx').children() 获取儿子

    • jQuery('#xxx').siblings() 获取兄弟

    • jQuery('#xxx').index() 获取排行老几(从0开始)

    • jQuery('#xxx').next() 获取弟弟

    • jQuery('#xxx').prev() 获取哥哥

    • jQuery('.red').each(fn) 遍历并对每个元素执行 fn

什么?你嫌 jQuery 太长

你是对的

window.$ = window.jQuery

还记得 bash alias 吗,添加一个别名即可

命名风格

  • 下面的代码令人误解

    • const div = $('div#test')

    • 我们会误以为 div 是一个 DOM

    • 实际上 div 是 jQuery 构造的 api 对象

    • 怎么避免这种误解呢?

  • 改成这样

    • const $div = $('div#test')

    • $div.appendChild 不存在,因为它不是 DOM 对象

    • $div.find 存在,因为它是 jQuery 对象

我代码中所有 $ 开头的变量都是 jQuery 对象

这是约定,除非特殊说明

链式风格

  • 查

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

    • $('#xxx').find('.red') 查找 #xxx 里的 .red 元素

    • $('#xxx').parent() 获取爸爸

    • $('#xxx').children() 获取儿子

    • $('#xxx').siblings() 获取兄弟

    • $('#xxx').index() 获取排行老几(从0开始)

    • $('#xxx').next() 获取弟弟

    • $('#xxx').prev() 获取哥哥

    • $('.red').each(fn) 遍历并对每个元素执行 fn

  • 增

    • $('<div><span>1</span></div>')

    • 等下,你刚刚不是说 $(选择器) 吗?

    • 怎么又可以传标签内容?

  • 所以说 jQuery 牛 X 呀

    • 这是 JS 的函数「重载」

    • 一个函数可以接受不同的参数

    • 怎么做到的?写代码!

  • 增

    • $('<div><span>1</span></div>')

    • 返回值并不是新增的元素,而是 api 对象

    • $('<div><span>1</span>').appendTo(...)

    • appendTo 可以把新增的元素放到另一个元素里

  • 这是一种什么感觉

    • 就感觉 DOM 是不可见的

    • 你不需要知道 DOM 的任何细节

    • 只需要使用简洁的 API 即可

    • 一个好的封装,能让使用者完全不知道内部细节

    • 这是通过 闭包 实现的

我就是想知道细节咋办

  • 举例1

    • const $div= $\('div\#test'\)

    • $div 并不是 DOM 对象,而是 jQuery 构造的 api 对象

    • 我现在就是想从 $div 得到 div 元素,行不行?

  • 满足你

    • $div.get(0) 获取第 0 个元素 // div

    • $div.get(1) 获取第 1 个元素 // undefined

    • $div.get(2) 获取第 2 个元素 // undefined

    • $div.size() 得到元素的个数

    • $div.length 也可以得到元素的个数

    • $div.get() 获取所有元素组成的数组 // [div]

  • 举例2

    • const $div = $\('\.red'\) // 假设有 3 个 div\.red

    • $div 不是 DOM 对象们,而是 jQuery 构造的 api 对象

    • 我现在就是想从 $div 得到 3 个 div 元素,行不行?

  • 满足你

    • $div.get(0) 获取第 0 个元素 // div

    • $div.get(1) 获取第 1 个元素 // div

    • $div.get(2) 获取第 2 个元素 // div

    • $div.size 得到元素的个数

    • $div.length 也可以得到元素的个数

    • $div.get() 获取所有元素组成的数组 // [div,div,div]

觉得 $div.get(0) 太麻烦了

再改简单点!

$div[0] 获取第一个 div

满足吗?那我开始写代码了

链式风格

  • 增

    $('body') 获取 document\.body
    $('body').append($('\<div>1</div>')</span> ) 添加小儿子
    $('body').append('<div>1<div>'</span>) 更方便
    $('body').prepend(div或$div) 添加大儿子
    $('#test').after(div 或 $div) 添个弟弟
    $('#test').before(div 或 $div) 添个哥哥
  • 删

    • $div.remove()

    • $div.empty()

  • 改

    $div.text(?) 读写文本内容
    $div.html(?) 读写 HTML 内容
    $div.attr('title', ?) 读写属性
    $div.css({color: 'red'}) 读写 style // $div.style 更好
    $div.addClass('blue') / removeClass / hasClass
    $div.on('click', fn)
    $div.off('click', fn)
  • 注意

    • $div 可能对应了多个 div 元素

后续

  • 使用原型

    • 把共用属性(函数)全都放到 $.prototype

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

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

  • 把代码公开

    • 发布到 GitHub

    • 添加文档,告诉别人怎么样

    • 获得称赞

    • 这就是程序员的社区,人人为我,我为人人

jQuery 有多牛 X

它是目前前端最长寿的库,2006年发布

它是世界上使用最广泛的库,全球 80% 的网站在用

设计模式

  • jQuery 用到了哪些设计模式

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

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

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

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

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

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

  • 设计模式是啥

    • 老子这个代码写得太漂亮了,别人肯定也用得到

    • 那就给这种写法取个名字吧,比如适配器模式

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

我应该学习设计模式吗?

  • 设计模式不是用来学的

    • 你看了这些代码

    • 但你并不知道这代码用来解决什么问题

    • 看了白看

  • 设计模式是用来总结的

    • 你直管去写代码

    • 把你的代码尽量写好,不断重写

    • 总结你的代码,把写得好的地方抽象出来

    • 看看符合哪个设计模式

    • 你就可以告诉别人你用到了这几个设计模式

    • 显得你特别高端

有人说不用学 jQuery

  • 真相

    • jQuery 这么简单、经典的库为什么不学?

    • 通过 jQuery 可以学会很多封装技巧,为什么不学?

    • 连 jQuery 都理解不了,Vue / React 肯定学不好

  • 推荐文章

  • 学习路线

    • 理解 jQuery 原理

    • 使用 jQuery 做一两个项目

    • 总结一篇博客,然后再也不碰 jQuery 了

    • 滚去学 Vue / React,找工作要紧 

再见

下节课实际使用一下 jQuery 库

《 》

写代码
http://js.jirengu.com/hasok/1/edit?html,js,output
jQuery
都过时了,那我
还学
它干嘛
?