vue后端渲染,vue渲染完成

  vue后端渲染,vue渲染完成

  除了响应性原则,视图渲染也是Vue核心中最重要的。下面文章主要介绍Vue组件的渲染过程,通过示例代码详细介绍。有需要的朋友可以参考一下。

  

目录

  简介和示例给出一个可以用在工作中的示例:扩展执行流程1的实现。注册流程(以Vue.component()为例):2。执行流程3。渲染流程总结

注: 本文目的是通过源码方向来讲component组件的渲染流程

  

引言与例子

  当我们创建一个Vue实例时,我们用新的Vue初始化它。_init(options)方法,然后执行$mount等。那么,在组件渲染的时候,我们能不能让组件使用同一套逻辑来处理呢?

  是的,当然可以。需要使用Vue.extend方法来实现。

  

举一个工作中能用到的例子:

  要求:我们将在项目中实现一个类似element-ui的消息框弹出窗口。全局注册(Vue.use)后,就可以像alert方法一样调用函数弹出。

  

实现

  (先简单说一下vue的使用方法的基本用法。使用注册时,如果是函数,就执行函数,如果是对象,就执行对象中的install方法进行注册。)

  根据需求,调用使用方法后,我们需要达到两个目的:直接在dom上注册挂载组件,将方法放在Vue.prototype下;

  先实现弹出的样式和逻辑(不是本文的主要目的,这里就略过了),假设有一个简单的显示函数show(){this.visible=true}。要使用注册组件,必须有一个install方法,其中首先调用Vue.extend(messageBox组件)。然后调用要渲染的对象的$mount()方法,最后把生成的DOM节点messageBox。$el,然后把show方法放在Vue.prototype上,这样就完成了函数install(Vue) {

  //生成messageBox构造函数

  var messageBox=vue . extend(this);

  messageBox=new messageBox();

  //挂载组件,生成dom节点(这里没有参数,只有生成的dom不在树上)

  messageBox。$ mount();

  //节点上的树

  document . body . appendchild(messageBox。$ El);

  show方法是全局安装的。

  vue . prototype . $ show messagebox=messagebox . show;

  }

  根据例子,让我们来看看这个扩展方法:

  

extend

  在Vue中,有一个extend方法,组件渲染就是通过调用extend创建一个继承自Vue的构造函数。在extend中创建的主要过程是:

  在内部创建一个final constructor Sub,这与Vue function在内部是一样的。它称之为。_init(options)继承Vue,并结合Vue.options和component选项在Sub上分配一个静态方法cache子构造函数,在extend方法启动时判断缓存,避免重复渲染同一个组件返回子构造函数(注意扩展调用返回一个未执行的构造函数Sub)。

  //注意:mergeoptions方法通过不同的策略合并选项中的属性。

  Vue.extend=函数(extendOptions: Object):函数{

  extend options=extend options { }

  Const Super=this //父构造函数

  //获取cid,通过_Ctor属性的缓存,判断是否已经创建,避免重复渲染同一个组件。

  const SuperId=Super.cid

  const cached contors=extend options。_Ctor (extendOptions。_Ctor={})

  if (cachedCtors[SuperId]) {

  返回缓存计数器[SuperId]

  }

  //名称检查引发错误

  const name=extend options . name super . options . name

  if (process.env.NODE_ENV!==生产名称){

  validateComponentName(名称)

  }

  //创建构造函数Sub

  const Sub=function VueComponent(选项){

  这个。_init(选项)

  }

  //继承原型对象

  Sub.prototype=Object.create(超级原型)

  Sub.prototype.constructor=Sub

  cid=cid //cid自增

  //父选项与当前传入的组件选项合并

  子选项=合并选项(

  超级选项,

  扩展选项

  )

  Sub[super]=Super //缓存父构造函数

  //对于小道具和计算属性,我们在扩展时在扩展原型上的某视频剪辑软件实例上定义代理吸气剂.这避免了为每个创建的实例调用定义属性.

  //对于小道具和计算属性,我们在扩展时在扩展原型的某视频剪辑软件实例上定义代理吸气剂。这避免了对象。为创建的每个实例调用定义属性。

  if (Sub.options.props) {

  initProps(Sub)

  }

  if(子选项。计算){

  initComputed(Sub)

  }

  //将全局方法放在潜水艇上,允许进一步调用

  子扩展=超级扩展

  亚混合蛋白=超级混合蛋白

  次级用途=超级用途

  //创建资产寄存器,所以扩展类

  //也可以拥有他们的私有资产。

  资产类型。foreach(函数(类型){

  子[类型]=超级[类型]

  })

  //启用递归自查找

  如果(姓名){

  子选项。组件[名称]=Sub

  }

  //在扩展时保留对超级选项的引用。

  //稍后在实例化时,我们可以检查极好的的选项是否有

  //已更新。

  子超级选项=超级选项

  子扩展选项=扩展选项

  子密封选项=扩展({ },子选项)

  //对应上边的_Ctor属性缓存

  缓存的contors[SuperId]=Sub

  返回接头

  }

  }

  看完出口函数后,思考下,生成组件时是一个怎样的执行流程呢?

  

执行流程

  

1. 注册流程(以Vue.component()祖册为例子):

  用户在调用Vue。组件时,其实就只执行了三行代码

  //简化版成分源码

  Vue.component=函数(id,定义){

  定义。名称=定义。名称 id

  //_base指向的是新Vue()时的这个某视频剪辑软件实例,调用的是某视频剪辑软件实例上的扩展方法

  定义=这个。选项。_ base。扩展(定义)

  this.options.components[id]=定义

  退货定义

  }

  获取并赋值组件的名称定义。名字调用根某视频剪辑软件上的扩展方法

  将组件放到选项。组件上

  返回定义

  (如果是异步组件的话,只会走后边两步,不会执行延伸)

  在下文中,我们会将extend方法返回的Sub对象称为Ctor

  在创建组件时,我们实际只是为组件执行了扩展方法,但在选项。组件中传入的组件不会被执行扩展方法,在3.渲染流程中会执行

  

2. 执行流程

  在标签名函数执行时,根据标签字段来判断是不是一个组件,如果是组件,执行组件初始化方法创建组件

  createComponent

  首先判断传入的男演员是否已经执行了扩展方法,没有执行的话执行一遍然后判断是不是异步组件(如果是,调用createAsyncPlaceholder生成并返回)然后处理数据,创建数据钩子中的钩子函数,比如初始化最后调用新虚拟节点()生成节点先看下标签名函数源码,然后在底下主要说下初始化函数

  导出函数创建组件(

  Ctor: ClassComponent 函数对象 void,

  数据:VNodeData,

  上下文:组件,

  孩子:数组节点,

  标签?字符串

  ):VNode ArrayVNode void {

  if (isUndef(Ctor)) {

  返回

  }

  //_base指向的是新Vue()时的这个某视频剪辑软件实例

  const baseCtor=context .$选项._base

  //如果扩展没有执行过,在这里执行

  if (isObject(Ctor)) {

  Ctor=baseCtor.extend(Ctor)

  }

  //报错处理

  if (typeof Ctor!==函数){

  if (process.env.NODE_ENV!==生产){

  警告(`无效的组件定义:${String(Ctor)} `,上下文)

  }

  返回

  }

  //异步处理

  让异步工厂

  if (isUndef(Ctor.cid)) {

  asyncFactory=Ctor

  ctor=resolveAsyncComponent(异步工厂,baseCtor)

  if (Ctor===undefined) {

  //返回呈现的异步组件的占位符节点

  //作为注释节点,但保留节点的所有原始信息。

  //该信息将用于异步服务器渲染和水合。

  返回createAsyncPlaceholder(

  异步工厂,

  数据,

  语境,

  孩子们,

  标签

  )

  }

  }

  //处理数据

  data=data {}

  resolveConstructorOptions(Ctor)

  if (isDef(data.model)) {

  transformModel(Ctor.options,data)

  }

  const props data=extractPropsFromVNodeData(data,Ctor,tag)

  如果(为真(ctor。选项。功能性)){

  返回createFunctionalComponent(Ctor,propsData,Data,context,children)

  }

  const listeners=data.on

  data.on=data.nativeOn

  如果(为真(ctor。选项。摘要)){

  常量插槽=data.slot

  数据={}

  如果(插槽){

  data.slot=插槽

  }

  }

  //重点创建初始化方法

  安装组件挂钩(数据)

  //返回一个占位符虚拟节点

  const name=Ctor.options.name 标记

  //得到虚拟节点

  常数vnode=新虚拟节点(

  vue-component-$ { ctor。cid } $ { name?`-${name}` : } `,

  数据,未定义,未定义,未定义,上下文,

  { Ctor,propsData,listeners,tag,children },

  异步工厂

  )

  返回虚拟节点

  }

  让我们看下init方法

  初始化、预填充、插入、销毁等方法在源码中是创建在componentVNodeHooks对象上,通过installcomponenthhooks和installcomponenthhooks方法判断数据钩子中是否有该值,然后进行合并处理等操作实现的,在这里,我们不考虑其他的直接看初始化方法

  先放上完整代码:

  init (vnode: VNodeWithData,hydrating: boolean):布尔型{

  如果(

  组件实例

  !vnode。组件实例。_被销毁

  虚拟节点

  ) {

  //保持活动的组件,被视为补丁

  const mountedNode: any=vnode //工作流

  componentvnodehooks。预修补(已安装节点,已安装节点)

  }否则{

  //挂载到虚拟节点上,方便取值

  //在这个函数中会新的并返回扩展生成的男演员

  const child=vnode。组件实例=createComponentInstanceForVnode(

  vnode,

  activeInstance

  )

  //重点

  孩子$mount(补水?vnode.elm:未定义,补水)

  }

  }

  //createComponentInstanceForVnode函数示例

  导出函数createComponentInstanceForVnode(

  vnode: any,//我们知道它是MountedComponentVNode,但流动不知道

  家长:处于生命周期状态的any,//activeInstance

  ):组件{

  常量选项:内部组件选项={

  _isComponent: true,

  _parentVnode: vnode,

  父母

  }

  //检查内联模板呈现函数

  const内联模板=vnode。数据。内嵌模板

  if (isDef(inlineTemplate)) {

  选项。render=内联模板。提出

  选项。staticrenderfns=内联模板。静态呈现fns

  }

  返回新的vnode.componentOptions.Ctor(选项)

  }

  在初始化方法中,执行createComponentInstanceForVnode时会调用新Ctor(选项)在上边介绍扩展方法中可以看到新男演员时会调用某视频剪辑软件的_init方法,执行某视频剪辑软件实例的初始化逻辑在Vue.prototype._init方法初始化完毕,执行$mount是,会有下边代码这样一个判断,组件这时没有埃尔,所以不会执行$mount函数如果(虚拟机.$options.el) {

  虚拟机.$mount(虚拟机.$ options。El);

  }

  手动执行$mount函数

  

3. 渲染流程

  在组件渲染流程createElm函数中,有一段代码

  if (createComponent(vnode,insertedVnodeQueue,parentElm,refElm)) {

  返回

  }

  所以,组件的生成和判断都是在创建组件函数中发生的

  createComponent

  因为在执行流程中,生成的虚拟节点就是该函数中传入的vnode,并且在虚拟节点创建时把数据放在了虚拟节点上,那么vnode.data.hook.init就可以获取到上边说的初始化函数,我们可以判断,如果有该值,就可以认定本次虚拟节点为组件,并执行vnode.data.hook.init,init的内容详见上边初始化执行完毕后、Ctor的实例会被挂载到组件实例上,并且已经生成了真实多姆,可以在vnode.componentInstance.$el上获取到最后执行初始化和插入,将组件挂载函数createComponent (vnode,insertedVnodeQueue,parentElm,refElm) {

  让i=vnode.data

  if (isDef(i)) {

  const被重新激活=isDef(vnode。组件实例)I .保持活动

  //在判断是否定义的同时,把变量做了改变,最终拿到了i.hook.init(在扩展函数中注册的男演员的初始化方法)

  if(isDef(I=I . hook)isDef(I=I . init)){

  //执行初始化

  i(vnode,false /*补水*/)

  }

  //调用初始化挂钩后,如果虚拟节点是子组件

  //它应该创建一个子实例并挂载它。那个孩子

  //组件还设置了占位符虚拟节点的榆树.

  //在这种情况下,我们只需返回元素就可以了。

  //调用初始化挂钩之后,如果虚拟节点是子组件

  //它应该创建一个子实例并挂载它。孩子

  //组件还设置了占位符虚拟节点的榆树。

  //在这种情况下,我们只需返回元素就可以了。

  //组件实例是组件的男演员实例,有了代表已经创建了vnode.elm(真实节点)

  if(isDef(vnode。组件实例){

  initComponent(vnode,insertedVnodeQueue)

  insert(parentElm,vnode.elm,refElm)

  如果(为真(已反应)){

  重新激活组件(vnode,insertedVnodeQueue,parentElm,refElm)

  }

  返回真实的

  }

  }

  }

  

总结

  到此这篇关于某视频剪辑软件组件渲染流程的文章就介绍到这了,更多相关某视频剪辑软件组件渲染流程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: