美文网首页
vue的组件渲染流程

vue的组件渲染流程

作者: 小码农_影 | 来源:发表于2021-11-22 19:41 被阅读0次
    1、给组件创建个构造函数,基于Vue。
    export default function globalApiMixin(Vue){
        Vue.options = {}
        Vue.mixin = function (options){
            this.options = mergeOptions(this.options,options);//合并options
        }
        Vue.options.components = {};
        Vue.options._base = Vue 
        Vue.component = function (id,definition){
            //保证组件的隔离,每个组件都会产生一个新的类,去继承父类
            definition = this.options._base.extend(definition);
            this.options.components[id] = definition;
        }
        //给个对象返回类
        Vue.extend = function (definition){//extend方法就是返回一个继承于Vue的类
            //并且身上应该有父类的所有功能
            let Super = this;
            let Sub = function VueComponent(options){
                this._init(options);
            }
            //原型继承
            Sub.prototype = Object.create(Super.prototype);
            Sub.prototype.constructor = Sub;
            Sub.options = mergeOptions(Super.options, definition);//只和vue.options合并
            return Sub
        }
    }
    
    2、开始生成虚拟节点,对组件进行特殊处理 data.hook = {init(){}}
    export function createElement(vm, tag, data = {}, ...children) {
      if(isReservedTag(tag)){
        return vnode(vm, tag, data, data.key, children, undefined);
      }else{
        const Ctor = vm.$options.components[tag];
        return createComponent(vm, tag, data, data.key, undefined, undefined,Ctor);
      }
    }
    function createComponent(vm, tag, data, key, children, text, Ctor) {
        
        if(isObject(Ctor)){
          Ctor = vm.$options._base.extend(Ctor)
        }
        data.hook = {
          init(vnode){
            let vm = vnode.componentInstance  = new Ctor({_isComponent:true})//new sub 
            debugger
            vm.$mount();
          }
        }
        return vnode(vm,`vue-component-${tag}`,data,key,undefined,undefined,{Ctor,children});
    }
    export function createTextElement(vm, text) {
      return vnode(vm, undefined, undefined, undefined, undefined, text);
    }
    function vnode(vm, tag, data, key, children, text,componentOptions) {
      return { vm, tag, data, key, children, text, componentOptions };
    }
    
    function isReservedTag(str){ //判断是否是组件
      let strList = 'a,div,span,p,ul,li';
      return strList.includes(str);
    }
    
    3、生成dom元素,如果当前虚拟节点上有hook.init属性,说明是组件
    function createComponent(vnode){
        let i = vnode.data; 
        if((i = i.hook) && (i = i.init)){
            i(vnode);//调用init方法
        }
        if (vnode.componentInstance) {
          //有属性说明子组件new完毕了,并且组件的真实dom挂载到了vnode。componentInstance
          return true;
        }
    } 
    function createElm(vnode){
        debugger
        let {vm,tag,data,children,text} = vnode;
        if(typeof tag === 'string'){
            //判断是否是组件
            if( createComponent(vnode)){
                //返回组件对应的真实节点
                console.log(vnode.componentInstance.$el);
                return vnode.componentInstance.$el
            }
            vnode.el = document.createElement(tag);
            if(children.length){
                children.forEach(child=>{
                    vnode.el.appendChild(createElm(child));
                })
            }
        }else{
            vnode.el = document.createTextNode(text);
        }
        return vnode.el;
    }
    
    4、对组件进行new 组件().$mount()=>vm.$el; 将组件的$el插入到父容器中 (父组件)
    Vue.prototype.$mount = function (el) {
        debugger
        const vm = this;
        const options = vm.$options;
        el = document.querySelector(el);
        vm.$el = el;
        //将模板转化成对应的渲染函数=》虚拟函数概念 vnode =》diff算法更新虚拟 dom =》产生真实节点,更新
        if (!options.render) {
          //没有render 用template,目前没有render
          let template = options.template;
          if (!template && el) {
            //用户也没有传入template,就取页面上的el
            template = el.outerHTML;
          }
          let render = compileToFunction(template);
          //options.render 就是渲染函数
          options.render = render;
        }
        debugger
        mountComponent(vm, el); //组件的挂载流程
      };
    

    相关文章

      网友评论

          本文标题:vue的组件渲染流程

          本文链接:https://www.haomeiwen.com/subject/ocwqtrtx.html