深入浅出 Vue.js

深入浅出 Vue.js
编辑推荐
深入讲解 Vue.js 实现原理和思想
360 奇舞团团长月影和《JavaScript 高级程序设计》译者李松峰作序推荐
360 前端工程师精心打造,带你深入了解 Vue.js 的源码
内容简介
本书从源码层面分析了 Vue.js。首先,简要介绍了 Vue.js;然后详细讲解了其内部核心技术“变化侦测”,这里带领大家从 0 到 1 实现一个简单的“变化侦测”系统;接着详细介绍了虚拟 DOM 技术,其中包括虚拟 DOM 的原理及其 patching 算法;紧接着详细讨论了模板编译技术,其中包括模板解析器的实现原理、优化器的原理以及代码生成器的原理;最后详细介绍了其整体架构以及提供给我们使用的各种 API 的内部原理,同时还介绍了生命周期、错误处理、指令系统与模板过滤器等功能的原理。 本书适合前端开发人员阅读。
作者简介
刘博文,网名 Berwin,95 后,从事 Web 前端工作 5 年,2015 年加入 360 奇舞团,现任 360 导航事业部前端工程师,负责 360 导航首页及二级页创新项目等亿级 PV 站点的设计与优化,推动 Vue.js 成为部门内广泛使用的核心技术栈,独立研发相关开发工具与技术解决方案并使之成功落地。
W3C 性能工作组成员,在 Web 性能领域有深入研究。热爱开源,热爱技术,梦想是用技术改变世界。个人 GitHub 地址:https://github.com/berwin
目录
第 1 章 Vue.js 简介 1
- 1.1 什么是 Vue.js 1
- 1.2 Vue.js 简史 2
第 一篇 变化侦测
第 2 章 Object 的变化侦测 6
- 2.1 什么是变化侦测 6
- 2.2 如何追踪变化 7
- 2.3 如何收集依赖 7
- 2.4 依赖收集在哪里 8
- 2.5 依赖是谁 10
- 2.6 什么是 Watcher 10
- 2.7 递归侦测所有 key 12
- 2.8 关于 Object 的问题 13
- 2.9 总结 14
第 3 章 Array 的变化侦测 16
- 3.1 如何追踪变化 16
- 3.2 拦截器 17
- 3.3 使用拦截器覆盖 Array 原型 18
- 3.4 将拦截器方法挂载到数组的属性上 19
- 3.5 如何收集依赖 21
- 3.6 依赖列表存在哪儿 22
- 3.7 收集依赖 23
- 3.8 在拦截器中获取 Observer 实例 24
- 3.9 向数组的依赖发送通知 25
- 3.10 侦测数组中元素的变化 26
- 3.11 侦测新增元素的变化 27
- 3.11.1 获取新增元素 27
- 3.11.2 使用 Observer 侦测新增元素 28
- 3.12 关于 Array 的问题 29
- 3.13 总结 29
第 4 章 变化侦测相关的 API 实现原理 31
- 4.1 vm.$watch 31
- 4.1.1 用法 31
- 4.1.2 watch 的内部原理 32
- 4.1.3 deep 参数的实现原理 36
- 4.2 vm.$set 38
- 4.2.1 用法 38
- 4.2.2 Array 的处理 39
- 4.2.3 key 已经存在于 target 中 40
- 4.2.4 处理新增的属性 40
- 4.3 vm.$delete 41
- 4.3.1 用法 42
- 4.3.2 实现原理 42
- 4.4 总结 45
第二篇 虚拟 DOM
第 5 章 虚拟 DOM 简介 48
- 5.1 什么是虚拟 DOM 48
- 5.2 为什么要引入虚拟 DOM 51
- 5.3 Vue.js 中的虚拟 DOM 51
- 5.4 总结 53
第 6 章 VNode 54
- 6.1 什么是 VNode 54
- 6.2 VNode 的作用 55
- 6.3 VNode 的类型 56
- 6.3.1 注释节点 57
- 6.3.2 文本节点 57
- 6.3.3 克隆节点 57
- 6.3.4 元素节点 58
- 6.3.5 组件节点 59
- 6.3.6 函数式组件 59
- 6.4 总结 59
第 7 章 patch 60
- 7.1 patch 介绍 60
- 7.1.1 新增节点 61
- 7.1.2 删除节点 62
- 7.1.3 更新节点 63
- 7.1.4 小结 63
- 7.2 创建节点 64
- 7.3 删除节点 67
- 7.4 更新节点 68
- 7.4.1 静态节点 68
- 7.4.2 新虚拟节点有文本属性 69
- 7.4.3 新虚拟节点无文本属性 69
- 7.4.4 小结 70
- 7.5 更新子节点 72
- 7.5.1 更新策略 72
- 7.5.2 优化策略 77
- 7.5.3 哪些节点是未处理过的 82
- 7.5.4 小结 83
- 7.6 总结 86
第三篇 模板编译原理
第 8 章 模板编译 88
- 8.1 概念 88
- 8.2 将模板编译成渲染函数 89
- 8.2.1 解析器 90
- 8.2.2 优化器 91
- 8.2.3 代码生成器 91
- 8.3 总结 92
第 9 章 解析器 93
- 9.1 解析器的作用 93
- 9.2 解析器内部运行原理 94
- 9.3 HTML 解析器 99
- 9.3.1 运行原理 100
- 9.3.2 截取开始标签 101
- 9.3.3 截取结束标签 107
- 9.3.4 截取注释 108
- 9.3.5 截取条件注释 108
- 9.3.6 截取 DOCTYPE 109
- 9.3.7 截取文本 109
- 9.3.8 纯文本内容元素的处理 112
- 9.3.9 使用栈维护 DOM 层级 114
- 9.3.10 整体逻辑 114
- 9.4 文本解析器 117
- 9.5 总结 121
第 10 章 优化器 122
- 10.1 找出所有静态节点并标记 125
- 10.2 找出所有静态根节点并标记 127
- 10.3 总结 129
第 11 章 代码生成器 130
- 11.1 通过 AST 生成代码字符串 131
- 11.2 代码生成器的原理 134
- 11.2.1 元素节点 134
- 11.2.2 文本节点 136
- 11.2.3 注释节点 137
- 11.3 总结 137
第四篇 整体流程
第 12 章 架构设计与项目结构 140
- 12.1 目录结构 140
- 12.2 架构设计 143
- 12.3 总结 145
第 13 章 实例方法与全局 API 的
- 实现原理 146
- 13.1 数据相关的实例方法 147
- 13.2 事件相关的实例方法 147
- 13.2.1 vm.$on 148
- 13.2.2 vm.$off 149
- 13.2.3 vm.$once 152
- 13.2.4 vm.$emit 153
- 13.3 生命周期相关的实例方法 154
- 13.3.1 vm.$forceUpdate 154
- 13.3.2 vm.$destroy 155
- 13.3.3 vm.$nextTick 159
- 13.3.4 vm.$mount 169
- 13.4 全局 API 的实现原理 178
- 13.4.1 Vue.extend 178
- 13.4.2 Vue.nextTick 182
- 13.4.3 Vue.set 183
- 13.4.4 Vue.delete 183
- 13.4.5 Vue.directive 184
- 13.4.6 Vue.filter 185
- 13.4.7 Vue.component 186
- 13.4.8 Vue.use 188
- 13.4.9 Vue.mixin 189
- 13.4.10 Vue.compile 190
- 13.4.11 Vue.version 190
- 13.5 总结 191
第 14 章 生命周期 192
- 14.1 生命周期图示 192
- 14.1.1 初始化阶段 193
- 14.1.2 模板编译阶段 194
- 14.1.3 挂载阶段 194
- 14.1.4 卸载阶段 194
- 14.1.5 小结 194
- 14.2 从源码角度了解生命周期 195
- 14.3 errorCaptured 与错误处理 199
- 14.4 初始化实例属性 203
- 14.5 初始化事件 204
- 14.6 初始化 inject 208
- 14.6.1 provide/inject 的使用方式 208
- 14.6.2 inject 的内部原理 210
- 14.7 初始化状态 215
- 14.7.1 初始化 props 216
- 14.7.2 初始化 methods 224
- 14.7.3 初始化 data 225
- 14.7.4 初始化 computed 228
- 14.7.5 初始化 watch 238
- 14.8 初始化 provide 241
- 14.9 总结 241
第 15 章 指令的奥秘 242
- 15.1 指令原理概述 242
- 15.1.1 v-if 指令的原理概述 243
- 15.1.2 v-for 指令的原理概述 243
- 15.1.3 v-on 指令 244
- 15.2 自定义指令的内部原理 246
- 15.3 虚拟 DOM 钩子函数 250
- 15.4 总结 251
第 16 章 过滤器的奥秘 252
- 16.1 过滤器原理概述 253
- 16.1.1 串联过滤器 254
- 16.1.2 滤器接收参数 254
- 16.1.3 resolveFilter 的内部原理 255
- 16.2 解析过滤器 256
- 16.3 总结 258
第 17 章 最佳实践 259
- 17.1 为列表渲染设置属性 key 259
- 17.2 在 v-if/v-if-else/v-else 中使用 key 259
- 17.3 路由切换组件不变 260
- 17.3.1 路由导航守卫 beforeRouteUpdate 261
- 17.3.2 观察 $route 对象的变化 261
- 17.3.3 为 router-view 组件添加属性 key 262
- 17.4 为所有路由统一添加 query 262
- 17.4.1 使用全局守卫 beforeEach 263
- 17.4.2 使用函数劫持 263
- 17.5 区分 Vuex 与 props 的使用边界 264
- 17.6 避免 v-if 和 v-for 一起使用 264
- 17.7 为组件样式设置作用域 266
- 17.8 避免在 scoped 中使用元素选择器 267
- 17.9 避免隐性的父子组件通信 268
- 17.10 单文件组件如何命名 268
- 17.10.1 单文件组件的文件名的大小写 268
- 17.10.2 基础组件名 269
- 17.10.3 单例组件名 270
- 17.10.4 紧密耦合的组件名 270
- 17.10.5 组件名中的单词顺序 271
- 17.10.6 完整单词的组件名 272
- 17.10.7 组件名为多个单词 273
- 17.10.8 模板中的组件名大小写 273
- 17.10.9 JS/JSX 中的组件名大小写 274
- 17.11 自闭合组件 275
- 17.12 prop 名的大小写 276
- 17.13 多个特性的元素 276
- 17.14 模板中简单的表达式 276
- 17.15 简单的计算属性 277
- 17.16 指令缩写 278
- 17.17 良好的代码顺序 278
- 17.17.1 组件 / 实例的选项的顺序 278
- 17.17.2 元素特性的顺序 280
- 17.17.3 单文件组件顶级元素的顺序 281
- 17.18 总结 282