明致成
人生海海,山山而川,不过尔尔!
展开
-
写在前面的话
相信目前为止,vue.js这款框架,大家已经用的相当熟了吧。但是呢,好多人在使用的过程中,或多或少会出现一些无法理解的问题。 从今天开始,我就带大家一起了解一下这么牛逼的框架,它的内部到底都做了哪些操作呢? 通过这本书,我们主要学习以下几点: 1、Vue.js的响应式原理,理解为什么修改数据视图会自动更新 2、虚拟DOM的概念和原理 ...原创 2019-12-29 17:03:15 · 188 阅读 · 0 评论 -
第一章、Object的变化侦测
为什么要侦测数据的变化?因为Vue.js要根据数据的变化去更新视图。 那么怎样才能侦测到数据的变化呢?我们都知道,在JavaScript中,侦测一个对象的变化,有两种方式:Object.defineProperty和ES6的Proxy。 Vue.js内部使用的是前者: function defineReactive(data,key,value){ Object.defineProperty...原创 2019-12-29 18:35:10 · 256 阅读 · 0 评论 -
第二章、Array的变化侦测
上一章我们讲到,vue对于对象的变化侦测是通过Object.defineProperty方法(实则是通过getter/setter)来实现的。本章我们来讲解vue对于数组的变化侦测是如何实现的。 Array不同于Object,我们在使用的时候其实是通过Array原型上的方法来改变数组的内容的,因此侦测Object变化的那种方式就行不通了。 侦测Array变化的拦截器 拦截器其实就是一个和Array...原创 2020-01-04 13:50:28 · 217 阅读 · 0 评论 -
第三章、变化侦测相关的API实现原理
本章我们来讲解关于变化侦测的三个API:vm.watch、vm.watch、vm.watch、vm.set、vm.$delete 1、vm.$watch 语法:vm.$watch(expOrFn, callback, [options]) 使用: vm.$watch('a.b.c',(newVal,oldVal)=>{ // do something }); 或者 var unwa...原创 2020-01-11 20:27:30 · 293 阅读 · 0 评论 -
第四章、虚拟DOM简介
虚拟DOM是将状态映射成视图的众多解决方案中的一种,它的作用原理是使用状态生成虚拟节点,然后用虚拟节点渲染视图。 之所以需要先试用状态生成生成虚拟节点,是因为如果直接用状态生成真实DOM,会有一定程度的性能浪费。如果先创建虚拟节点再渲染视图,就可以良虚拟节点缓存,然后使用新创建的虚拟节点和上一次渲染时缓存的虚拟节点进行比对,然后根据对比结果只更行需要更新的真实DOM节点,从而避免不必要的DOM操...原创 2020-01-25 14:18:17 · 229 阅读 · 0 评论 -
第五章、VNode
VNode是一个类,可以生成不同类型的vnode实例,而不同类型的vnode表示不同类型的真实DOM元素。 VNode类的代码如下: export default class VNode{ constructor(tag,data,children,text,elm,context,componentOptions,asyncFactory){ this.tag=tag this.da...原创 2020-02-18 12:42:48 · 222 阅读 · 0 评论 -
第六章、patch
虚拟DOM最核心的部分就是patch,它可以将vnode渲染成真实的DOM。 patch渲染并不是暴力的覆盖原有的DOM,而是对比新旧vnode之间的不同,从而只更新不同的地方。其实际作用是在现有DOM上进行修改来实现更新视图的目的。 为什么要用patch?因为DOm操作的执行速度远不如JavaScript的运算速度块,而把大量的DOM操作用JavaScript来代理可以提高不少性能。 pat...原创 2020-02-18 12:59:48 · 168 阅读 · 0 评论 -
第七章、模板编译
模板编译在整个渲染过程中的位置如下: 模板编译的主要目标就是生成渲染函数,而渲染函数的作用是每次执行它,它就会使用当前最新的状态生成一份新的vnode,然后使用这个vnode进行渲染。 模板编译的整体流程: 模板编译分三部分: 【解析器】:将模板解析成AST(抽象语法树) 【优化器】:遍历AST标记静态节点 【代码生成器】:使用AST生成渲染函数 ...原创 2020-02-18 13:32:13 · 168 阅读 · 0 评论 -
第八章、解析器
解析器的作用是通过模板得到AST 生成AST的过程需要借助HTML解释器,当HTML解释器触发不同的钩子函数时,我们可以构建出不同的点 DOM层级是通过栈来维护的,通过栈来得到当前正在构建的节点的父节点,然后将构建出的节点添加到父节点的下面 HTML解析器的内部原理是一小段一小段地截取模板字符串,每截取一小段字符串,就会根据截取出来的字符串类型触发不同的钩子函数,直到模板字符串截空停止运行 模板...原创 2020-02-18 18:27:49 · 179 阅读 · 0 评论 -
第九章、优化器
优化器的作用是在AST中找出静态子树并打上标记,有以下两个好处: 每次重新渲染时,不需要为静态子树创建新节点 在虚拟DOM中打补丁的过程可以跳过 优化器的内部实现主要分为两个步骤: 在AST中找出所有静态节点并打上标记 在AST中找出所有静态根节点并打上标记 通过递归的方式从上向下标记静态节点时,如果一个节点被标记为静态节点,但它的子节点却被标记为动态节点,就说明该节点不是静态节点,可以将...原创 2020-02-18 18:40:23 · 263 阅读 · 0 评论 -
第十章、代码生成器
代码生成器的作用是将AST转换成渲染函数中的内容,即代码字符串。 代码字符串可以被包装在函数中运行,这个函数就是渲染函数。 渲染函数执行之后,可以生成一份VNode,而虚拟DOM可以通过这个VNode来渲染视图。 生成代码字符串是一个递归的过程,从上向下依次吹每一个AST节点: |类型| 创建方法 |别名 |元素节点|createElement|_c |文本节点| createTextVNode ...原创 2020-02-18 18:54:41 · 296 阅读 · 0 评论 -
第十一章、模板到视图总结
前面我们已经介绍过了模板到视图的整个流程,接下来让我们回忆一下: 1、模板编译成渲染函数,渲染函数创建DOM渲染到视图 2、数据的响应式变化 以上便是Vue.js的核心所在。 ...原创 2020-02-20 11:33:54 · 186 阅读 · 0 评论 -
第十二章、实例方法与全局API的实现原理(1)
首先,我们来看一段代码: import {initMixin} from './init' import {startMixin} from './start' import {renderMixin} from './render' import {eventsMixin} from './events' import {lifecycleMixin} from './lifecycle' im...原创 2020-02-20 13:19:16 · 214 阅读 · 0 评论 -
第十二章、实例方法与全局API的实现原理(2)
vm.$nextTick nextTick接收一个回调函数作为参数,它的作用是将回调延迟到下次DOM更新周期之后执行。 如果没有提供回调且在支持Promise的环境中,则返回一个Promise 使用场景: 当更新了状态(数据)后,需要对新DOM做一些操作,但是这时候我们还获取不到更新后的DOM,因为还没有重新渲染。 new Vue({ // ... methods:{ // ... ...原创 2020-02-21 13:49:57 · 158 阅读 · 0 评论 -
第十二章、实例方法与全局API的实现原理(3)
vm.$mount 使用方式: vm.$mount([elementOrSelector]) 参数: {Element | string} [elementOrSelector] 返回值: vm,即实例自身 用法: 如果vue实例在实例化时没有收到el选项,则它处于“未挂载”状态,没有关联的DOM元素。 此时可以使用vm.$mount手动挂在一个未挂载的实例。 如果没有提供elementOrSe...原创 2020-02-22 13:28:50 · 239 阅读 · 0 评论 -
第十二章、实例方法与全局API的实现原理(4)
全局API的实现原理 全局API和实例方法不同:实例方法是在Vue.prototype上挂载方法;全局API是直接在Vue上挂载方法。 1、Vue.extend(options) 参数:{Object} options 用法:使用基础Vue构造器创建一个“子类”,其参数是一个包含“组件选项”的对象。 实例 <div id="mount-point"></div> // 创...原创 2020-02-23 20:07:44 · 168 阅读 · 0 评论 -
第十三章、生命周期(1)
生命周期图示: 初始化阶段 这个阶段的主要目的是在Vue实例上初始化一些属性、事件、响应式数据等。例如:props、methods、data、computed、watch、provide、inject等。 模板编译阶段 这个阶段的主要目的是将模板编译为渲染函数,只存在于完整版中。如果只包含运行时版本中执行new Vue()将不存在这个阶段。 挂载阶段 这个阶段的主要目的是Vue将实例挂载到DOM...原创 2020-02-25 12:09:23 · 206 阅读 · 0 评论 -
第十三章、生命周期(2)
初始化事件 初始化事件指的是将父组件在模板中使用的v-on注册的事件添加到子组件的时间系统中。 例如: // 父组件DOM <div id="counter-event-example"> <p>{{total}}</p> <button-counter v-on:increment="incrementTotal"></button-co...原创 2020-02-26 18:11:36 · 164 阅读 · 0 评论 -
第十三章、生命周期(3)
初始化状态 本节所讲的初始化状态,主要有props、methods、data、computed、watch initState函数的源码: export function initState(vm) { vm._watchers = [] const opts = vm.$options if (opts.props) initProps(vm,opts.props) if (opts.m...原创 2020-02-27 15:54:58 · 154 阅读 · 0 评论 -
第十三章、生命周期(4)
初始化computed 在讲解初始化computed的原理之前,我们先来看一看它的用法: var vm = new Vue({ data:{ a:1 }, computed:{ // 用法1:仅读取,即getter aDouble: function() { return this.a * 2 }, // 用法2:读取和设置 aplus: { ...原创 2020-02-28 16:12:31 · 202 阅读 · 0 评论 -
第十四章、指令的奥秘
指令的奥秘 本章详细介绍自定义指令是如何生效的。 指令原理概述 使用自定义指令时,可以监听5种钩子函数:bind、inserted、update、componentUpdated、bind v-if指令的原理概述 有一部分内置指令是在模板编译阶段实现的。 在代码生成时,通过生成一个特殊的代码字符串来实现指令的功能。 <li v-if="has">if</li> <l...原创 2020-02-29 12:29:48 · 218 阅读 · 0 评论 -
第十五章、过滤器的奥秘
过滤器的奥秘 首先我们回顾一下过滤器的使用: <!-- 在双花括号中使用 --> {{message | capitalize}} <!-- 在v-bind中使用 --> <div v-bind:id="rawId | formatId"></div> // 方式1:在组件的选项中定义本地的过滤器 filters:{ capitalize: f...原创 2020-03-01 10:11:48 · 189 阅读 · 0 评论 -
第十六章、最佳实践
Vue的向关内部原理我们已经讲解的差不多了,这一章我们来讲解在我们的日常开发使用中,Vue相关的注意事项和一些必要的写法。 1、使用v-for时设置属性key 在虚拟DOM更新子节点时,需要从旧虚拟节点列表中查找与新虚拟节点相同的节点进行更新。 如果设置了key,查找速度就会块很多。除非遍历输出的DOM非常简单,或者是刻意依赖默认行为而获得性能提升的,否则尽可能的在使用v-for时提供key &l...原创 2020-03-01 20:13:04 · 179 阅读 · 0 评论