摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理源码版之创建组件今天就要开启我
写文章不容易,点个赞呗兄弟
专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧
研究基于 Vue版本 【2.5.17】
如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧
【Vue原理】Component - 源码版 之 创建组件VNode
今天就要开启我们 Component 探索之旅,旅途有点长,各位请坐好,不要睡着了
内容的主题是,Component 的创建过程,从调用 component,到 component 挂载,到底经历了什么?欢迎来到 component 的内心世界
建议可以先看看白话版
Component - 白话版
Component 创建,我主要分了两个流程
1、创建 组件 VNode 2、挂载 组件 DOM
每个流程涉及源码都很多,所以每个流程写一篇文章。没错了,今天讲的就是 创建组件 VNode
场景设置首先,我们假定现在有这么一个模板,使用了 test 组件
然后页面噼里啪啦执行到了 准备挂载DOM 的步骤(之前的部分跟本主题无关,跳过)
然后页面准备执行渲染函数 render,嗯,就是执行上面模板生成的渲染函数,如下
没有错,我们的 Vue 已经走到了这一步,那么我们的突破口是什么?
没错,就是 _c
function _createElement( context, tag, data, children ) { var vnode; var options = context.$options // 从父组件选项上拿到 对应的组件的选项 var Ctor = options.components[tag] if (正常的HTML标签) { ....直接新建VNode } else if ( Ctor ) { vnode = createComponent( Ctor, data, context, children, tag ); } return vnode }
今天讲的是 component,跳过其他,直接走到 第二个 if,嗯,他调用了一个 createComponent
好的,我去前面探探路
function createComponent( Ctor, data, context, children, tag ) { var baseCtor = context.$options._base; // 创建组件构造函数 Ctor = baseCtor.extend(Ctor); var vnode = new VNode( "vue-component-" + (Ctor.cid) + name, data, undefined, undefined, undefined, context, { Ctor: Ctor } ); return vnode }
这个 createComponent 什么鬼的,作用大概是
1、创建组件构造函数
2、处理父组件给子组件的数据
3、创建组件 外壳 VNode
由于处理数据什么的,跟本内容无关,所以其他源码一律去掉,那么就只剩下两个流程
下面就开始这两个流程
创建组件构造函数上面的源码中有两句话(如下),作用就是为组件创建一个构造函数!
var baseCtor = context.$options._base; Ctor = baseCtor.extend(Ctor);
看得懂吗?看懂了?好吧,那我就不讲了
算了,算了,还是讲吧,毕竟当时自己也是懵逼的
首先,context 是什么?context 是执行整个渲染函数的上下文对象,很明显,这里就是页面的 实例vm 了
那么,$options 是什么?$options 就是 实例自定义选项 和 全局选项合并之后的 产物
Vue.prototype._init = function(options) { ..... vm.$options = mergeOptions( // 把两个对象合并 vm.constructor.options, options, vm ); ..... }vm.constructor 是什么?
没错,就是 Vue,你使用 new Vue 创建的页面,构造函数肯定是 Vue 啦
vm.constructor.options 是什么?看下面
Vue.options = Object.create(null); Vue.options.components = Object.create(null); Vue.options.directives = Object.create(null); Vue.options.filters = Object.create(null); Vue.options._base = Vue;
Vue 在引入的时候,就完成了很多初始化的内容,这里就是其中给 Vue 增加options 的部分
你看到的 component 啊,filter 什么的啊,没错,保存的就是你全局注册的 component,filter
然后每个页面都能使用到 全局组件,全局filter 的原因
就是因为在 页面实例初始化的时候,把 页面选项 和 全局选项私下合并 了
然后,你应该能看到这一句,保存了 Vue 构造函数在 options._base 中
Vue.options._base = Vue;
那么,你应该能理解前面出现的源码了
var baseCtor = context.$options._base;
没错!baseCtor 拿到的就是 Vue!!!!
然后还有一句
Ctor = baseCtor.extend(Ctor);
既然 baseCtor 是 Vue,那 baseCtor.extend 是 Vue.extend?没有错!
正是他!完成了创建组件构造函数的伟大之举!!让我们一起来欣赏下
Vue.extend = function(extendOptions) { // this 指向Vue var Super = this; var Sub = function VueComponent(options) { this._init(options); }; // 原型链继承 Sub.prototype = Object.create(Super.prototype); Sub.prototype.constructor = Sub; // Super 永远是 Vue,所以这里就是 合并全局选项 // 现在 Super 就是 vue,把 Vue 和 Sub 合并 // 是把一些全局的组件 指令合并到 Sub 中 Sub.options = mergeOptions( // optios 还包括 mixins 注入的全局 Super.options, extendOptions ); return Sub };
这个函数,会返回一个函数 VueComponent,他就是组件的构造函数!用来下篇文章创建组件实例的!!
上面的源码,做的事,简单说,就是继承父类Vue,然后合并 options 等
最后,提一下,所有实例的父类构造函数 Super 都是 Vue
并不是说,组件 a 有一个子组件b,然后组件b 的父类构造函数就是 a.contructor,这是不对的,永远是Vue,谁都是 Vue
创建组件外壳VNode现在就是前面代码 createComponent 中的最后一步了
注意注意,这里创建的是【组件外壳节点】,内部节点还没有上场,在下篇文章才出现
至于,什么是外壳节点,去看下我的 VNode - 源码版
跳到相关内容看就好了
var vnode = new VNode( "vue-component-" + Ctor.cid + name, data, undefined, undefined, undefined, context, { Ctor: Ctor } );那么这个外壳节点的作用是什么?
1、保存刚创建好的组件构造函数,下篇文章中会调用到
2、保存父组件给子组件 关联的数据,比如 event,props 之类的(由于跟本主题无关,为了整洁,统统去掉了)
总结Component 创建 外壳节点的流程,总结如下
1、页面渲染函数执行
2、_c("test") 执行
3、createElement 碰到 tag 是一个组件
4、从父组件中,拿到 test 组件的options,传入 createComponent (作用是创建构造函数和 VNode)
5、createComponent 调用 Vue.extend 创建组件构造函数
6、新建 VNode,并把构造函数和父组件给子组件的数据保存进去
7、返回 VNode
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/105443.html
摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理源码版之挂载组件由这篇文章从模 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于...
摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理源码版之绑定组件自定义事件组件 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于...
摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理白话版从模板上使用到挂载到页面 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于...
摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理源码版之绑定组件事件上一篇已经 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于...
摘要:表示虚拟节点,为什么叫虚拟节点呢,因为不是真的节点。因为是对象,不管还是浏览器,都可以统一操作,从而获得了服务端渲染原生渲染手写渲染函数等能力减少操作。 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版难看,请点击 下面链接 或者 拉到 下...
阅读 3069·2021-10-27 14:16
阅读 2881·2021-09-24 10:33
阅读 2289·2021-09-23 11:21
阅读 3233·2021-09-22 15:14
阅读 816·2019-08-30 15:55
阅读 1679·2019-08-30 15:53
阅读 1747·2019-08-29 11:14
阅读 2191·2019-08-28 18:11