![](https://img-blog.csdnimg.cn/20201014180756926.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Vue
lznism666
这个作者很懒,什么都没留下…
展开
-
简单的mvvm实现
// eslint-disable-next-line no-unused-varsclass MVVM { constructor (options = {}) { this.options = options this.observe(options.data) const root = document.querySelector(options.el) this.compile(root) } observe (data) { Object.k原创 2020-11-17 17:16:13 · 1812 阅读 · 0 评论 -
Vue Compile原理分析
Vue中Compile是一个非常复杂的内容,Compile的主要作用是解析模板,生成渲染模板的render, 而render的作用主要是为了生成VNode, Compile主要分为3大块:parse 接受template原始模板,按着模板的节点和数据生成对应的astoptimize 遍历ast的每一个节点,标记静态节点,这样就知道哪部分不会变化,于是在页面需要更新时,减少去对比这部分DOM,提升性能generate 把前两步生成完善的ast,组成render字符串,然后将render字符串通过new原创 2020-09-22 19:20:45 · 3310 阅读 · 2 评论 -
Vue Render原理分析
1. 主要renderrender的主要作用就是执行Compile生成的render函数,然后得到返回的VNode<div :data="data">{{data}}</div>比如以上的一段模板会生成如下的render函数function render() { with(this) { return _c('div', { attrs: { data: 111 } }, [_v(111)]) }}上面生原创 2020-09-22 19:20:13 · 561 阅读 · 0 评论 -
Vue Diff原理分析
Diff的出现,是为了减少更新量,找到最小差异部分DOM,只更新差异部分DOM就好了,这样消耗就会小一些。Vue2.x中的diff只会对新旧节点中父节点是相同节点的那一层子节点进行比较。只有当新旧节点是相同节点的时候,才会去比较他们各自的子节点。新旧VNode进行比较的过程中,不会对这两棵VNode树进行修改,而是以比较结果直接对真实DOM进行修改。比如说在比较VNode的过程中,发现某个节点需要移动,此时不会直接移动VNode中的节点,而是直接移动DOM。vm._update()比较新旧VNode树,原创 2020-09-22 19:19:30 · 325 阅读 · 0 评论 -
Vue nextTick原理分析
this.name = 1;this.name = 2;this.name = 3;为什么只会执行一次?这是nextTick回调和watcher过滤的结果。当数据变化后,将watcher.update函数存放进nextTick的回调数组中,并且会做过滤。通过watcher.id来判断回调数组中是否已经存在这个watcher的更新函数,如果不存在才会push。之后next遍历这个无重复id的回调数组,便会执行更新。因此当3次修改同一个数据时,仅会有一个watcher.update进入回调数组,从而页原创 2020-09-18 15:54:56 · 426 阅读 · 2 评论 -
Vue Events模块原理分析
Vue中事件大致分为4类自定义事件DOM事件组件DOM事件组件自定义事件自定义事件主要由两部分组成事件存储器绑定事件,触发事件,解绑事件Vue的每个实例都会有一个_events对象,用来存放本实例上注册的自定义事件,绑定自定义事件的大致流程如下this.$on 绑定事件this.$emit 触发事件this.$off 解绑事件如果需要给组件绑定原生DOM事件,需要加上native这个修饰符。组件绑定的DOM事件,在父实例解析完毕才开始挂载,遇到子元素是组件,然后去解析内部原创 2020-09-17 14:51:14 · 2677 阅读 · 0 评论 -
Vue 创建组件外壳VNode原理分析
创建组件VNode<div> <test></test></div>上面这个页面被解析成了一个渲染函数function() { with(this) { return _c('div', [ _c('test') ]) }}这个_c就是创建VNode的入口,也就是实际上的_createElement函数function _createElement( co原创 2020-09-17 08:31:20 · 513 阅读 · 0 评论 -
Vue Component原理分析
Component的创建主要分为了两个流程创建组件VNode挂载组件DOM<div> <test></test></div>上面这个页面被解析成了一个渲染函数function() { with(this) { return _c('div', [ _c('test') ]) }}以上渲染函数执行得到模板对应的VNode,得到VNode之后,就会根据VNode原创 2020-09-17 07:41:08 · 1167 阅读 · 0 评论 -
Vue VNode原理分析
1. VNode是什么及其作用使用js对象来描述真是DOM,把DOM的标签,属性,内容都变成对象的属性。模板编译整个过程就是将template描述成VNode,经过一系列操作形成真实DOM,它的好处有两点兼容性强,不受执行环境的影响。VNode因为是js对象,不管是Node环境还是浏览器环境,都可以统一操作,从而获得了SSR,原生渲染等能力减少DOM操作,任何页面的变化,都是用VNode进行操作对比,只需要在最后一步挂载更新DOM即可2. VNode如何生成Vue内部,有一个专门的VNode类原创 2020-09-16 18:15:14 · 1669 阅读 · 2 评论 -
Vue依赖更新原理分析
依赖更新分为两步修改属性值通知之前收集到的依赖,进行更新dep主要用来存储依赖var Dep = function() { this.subs = [];}Dep.prototype.notify = function() { var subs = this.subs.slice(); for (var i = 0; i < subs.length; i++) { // 遍历依赖存储器,然后一个个调用`watcher.update`原创 2020-09-16 15:47:16 · 495 阅读 · 0 评论 -
Vue 依赖收集 引用数据类型原理分析
如果数据是引用数据类型,需要对数据进行额外的处理,处理分为对象和数组两种1. 对象每个对象处理之后,会添加一个__ob__的属性, __ob__下面有一个dep属性,dep就是存储watcher的地方。为什么引用类型不能使用dep,因为dep只存在于defineReactive这个函数中,作为一个闭包形式的存在,__ob__.dep在Vue.prototype.$set和Vue.prototype.$delete中都有使用到。2. 数组对数组而言,__ob__.dep的作用是用于对数组相关方法的重原创 2020-09-16 15:20:29 · 255 阅读 · 0 评论 -
Vue依赖收集基础数据类型
1. 数据初始化流程function initData(vm) { var data = vm.$options.data; data = typeof data === 'function' ? data.call(vm, vm) : data || {}; new Observer(data);}function Observer(data) { var keys = Object.keys(value); for (let i = 0;原创 2020-09-16 11:19:19 · 286 阅读 · 0 评论 -
Vue模板挂载到页面原理分析
Vue模板挂载到页面可以分为两大部分init和mount1. initVue.prototype._init = function() { // 初始化选项,computed data // 初始化实例,给实例绑定方法 // 触发beforeCreated created钩子}2. mount上面介绍的_init方法中,会有一个挂在到dom的方法if (vm.$options.el) { vm.$mount(vm.$options.el);}``不是所有原创 2020-09-16 08:13:17 · 617 阅读 · 0 评论 -
Vue selected原理分析
1. Vue是如何设置selectedIndexVue中有一个专门的setSelected来设置这个selectedIndexfunction setSelected(el, binding, vm) { var selected, option; for (var i = 0, l = el.options.length; i < l; i++) { option = el.options[i]; if (isMultiple)原创 2020-09-15 17:12:54 · 677 阅读 · 0 评论 -
Vue input原理分析
1.input与输入延迟更新先来看Vue给input正常绑定的回调input: function($event) { // 这里就是延迟更新的重点 // 当composing=true时,事件回调不会走到下面的更新操作 if ($event.target.composing) return; name = $event.target.value;}Vue会给input和textarea绑定以下事件compositionstartcompositionendc原创 2020-09-15 11:54:29 · 560 阅读 · 0 评论 -
Vue 表单元素绑定原理分析
1.v-model指令处理// 这个el是ast, 使用树的结构来表示某个dom节点,包含了绑定的事件,指令,绑定的属性等function model(el, dir) { var value = dir.value; var tag = el.tag; var type = el.attrsMap.type; if (tag === 'select') { genSelect(el, value); } else if (tag === 'inp原创 2020-09-15 10:42:53 · 232 阅读 · 0 评论 -
v-model原理分析一
VModel双向绑定分为两个部分的内容初始化绑定:初始化时给表单绑定值,绑定事件,为双向更新做准备双向更新:任意一边发生变化,同时能让另一边更新1. v-model怎么给表单绑定数据v-model绑定的数据赋值给表单元素的value属性解析不同的表单元素,配置相对应的事件名和回调,在插入DOM之前,通过addEventListener绑定事件外部变化,触发事件回调,event.target.value赋值给model绑定的数据内部变化,修改表单元素的value下面来看看普通input原创 2020-09-14 21:52:37 · 604 阅读 · 0 评论 -
Vue生命周期原理分析
1. 生命周期钩子是如何触发vm中由于mixin存在,可能会存在很多个同类别的声明周期钩子,Vue内部会将这些生命周期的钩子合并。vm.$options.created = [fn, fn, ...];Vue中也初始化了一些标记位,用来表示相关的生命周期钩子是否已经触发function initLifecycle(vm) { vm._isMounted = false; vm._isDestoryed = false; vm.isBeingDestroyed = false原创 2020-09-14 19:48:40 · 1173 阅读 · 0 评论 -
Vue作用域slot原理分析
<!-- 场景设置 --><!-- 父组件 --><div> <test> <template slot-scope="slotProps"> 我是放在组件的slot: {{slotProps}} </template> </test></div><!-- 子组件 --><main> 我在子组件里面原创 2020-09-14 17:40:09 · 361 阅读 · 0 评论 -
Vue普通插槽原理分析
1.插槽内容怎么解析的<!-- 场景设置 --><!-- 父组件 --><div> <test>我是放在组件中的slot: {{name}}</test></div>data() { return { name: 11 };}<!-- 子组件 --><main> 我在子组件中 <slot></slot></main>插槽的作原创 2020-09-14 16:31:38 · 470 阅读 · 0 评论 -
Vue slot原理分析一
Vue中插槽可以分为两种普通插槽,就是不给名字的默认插槽和具名插槽作用域插槽,就是使用子作用域数据的插槽1.普通插槽<!-- 场景设置 --><!-- 父组件 --><div> <test>我是slot中的内容</test></div><!-- 子组件:test --><main> 我在子组件中 <slot></slot></main&原创 2020-09-14 11:57:09 · 691 阅读 · 0 评论 -
Vue mixin 原理分析二
1.mixin什么时候开始合并合并分为两种1.1 全局mixin和基础全局options合并Vue.mixin = function(mixin) { this.options = mergeOptions(this.options, mixin); return this;}其中基础全局options就是指components, directives, filters, 这3者一开始就挂载到了Vue.options上,所以这三个是最先存在的全局options1.2 全局opt原创 2020-09-14 08:40:16 · 212 阅读 · 0 评论 -
Vue mixin原理分析
Vue在创建组件实例化之前,会将全局选项和组件选项合并起来,比如全局component, filter, directive, mixin。也就是说我们全局注册的选项会被引入到每个组件中,这样全局选项和组件选项就可以合并起来,之后在组件中就可以访问到全局选项。比如全局过滤器等。为了保证全局选项不被污染,但是又不可能每个组件都深度克隆一遍,这样会导致全局选项的开销过大。如何合并mixin组件合并组件选项和全局选项的优先级组件选项组件mixin组件mixin的mixin组件mixin的…的mix原创 2020-09-13 20:27:31 · 682 阅读 · 0 评论 -
Vue中directive原理分析二
1. Vue怎么获取到设置的指令钩子以下面一段Vue模板为例<div v-test v-test2></div>以上的模板会被编译成渲染函数with(this) { return _c('div', { directives: [{ name: 'test', rawName: 'v-test' }, { name: 'test2', ra原创 2020-09-13 15:51:50 · 409 阅读 · 0 评论 -
Vue中directive原理分析
Vue在处理指令时,会首先判断指令是新的还是旧的。也就是需要对比旧节点和新节点上的指令。比如新节点比旧节点上多了一个指令。// 新节点上指令如下newDirectives = { 'v-test': { name: 'test', rawName: 'v-test', }, 'v-test2': { name: 'test2', rawName: 'v-test2' }}// 旧节点上指令如下newDi原创 2020-09-13 11:48:59 · 633 阅读 · 0 评论 -
Vue中filter原理分析
1. 页面的filter被解析成什么页面中的渲染函数会被生成如下的渲染函数// <div>{{ parentName | all }}</div>(function() { with(this) { return _c('div',[ _v(_s(_f("all")(parentName))) ]) }原创 2020-09-12 20:56:45 · 510 阅读 · 0 评论 -
Vue中methods原理分析
1. methods是如何绑定this的methods绑定上下文执行环境是通过bind来进行的。固定了这个this。Vue考虑到不是所有的浏览器都支持bind。于是也实现了自己的polyfillBindfunction polyfillBind(fn, ctx) { return function boundFn(a) { const l = arguments.length; return l > 0 ? ( l > 1 ? fn.apply(c原创 2020-09-12 11:55:33 · 769 阅读 · 0 评论 -
Vue中watch原理分析
Vue中Watch的初始化流程initWatch遍历watch中的每一个watch函数,执行createWatcher,createWatcher有两个作用:获取到watch监听的回调和调用vm.$watch执行vm.$watch,这个函数主要也是两个功能,判断是否是立即执行的监听回调,如果需要立即执行,那就将回调(也就是watch的handler)立即执行一遍。第二个功能是给每一个watch分配一个Watcher。主要来分析一下,新建这个Watcher的过程都做了些什么。var Watche原创 2020-09-11 17:07:21 · 536 阅读 · 0 评论 -
Vue中Watcher用法分析
Watch在一开始初始化的时候,会读取一次监听的数据的值。于是,这个值就收集到了Watch的watcher。而我们给Watch设置的handler,Watch会放入watcher中。当数据改变时,通知Watch的watcher进行更新,也是handler就被调用了。如果我们设置了immediate: true,就不需要在数据变化时才触发,而是完成初始化之后,就立即执行一次handler。如果我们设置了deep: true,如果被监听的值是对象,Vue会进行深度遍历。这个对象之下的每一个属性都会收集到这个原创 2020-09-11 16:32:16 · 1759 阅读 · 0 评论 -
Vue中computed原理分析
1.Computed也是响应式的Computed是响应式的,读取Computed会触发get,设置Computed会触发set2.Computed如何控制缓存计算属性是有缓存的,比如某个计算属性C,它依赖data中的A,如果没有缓存的话,每次读取C时,C都回去读取A,从而触发A的get。多次触发A的get有时候是一个非常消耗性能的操作。所以Computed必须要有缓存。computed里面控制缓存最重要的一点就是脏数据标记为dirty, dirty是watcher的一个属性。当dirty为tru原创 2020-09-10 14:40:24 · 3745 阅读 · 1 评论