zoukankan      html  css  js  c++  java
  • vue源码分析(四)>>:compile

    今天分析一下$mount后编译文档节点的执行流程,看下指令和插值都是怎么解析的
     
    1. 执行流程
    > 在create钩子函数执行完毕后,判断如果传了el,就走进:vm.$mount(vm.$options.el);//5088行 方法;
    > 进入$mount方法,需要注意的是vue中定义了两个$mount方法,断点发现是先执行11977这一个然后执行9132这一个;
    > 执行第一个$mount时候又走了11757行的compileToFunctions方法,在这个方法里执行了11857行的compile方法;
    > 然后执行第二个$mount,然后执行mountComponent,在这里执行beforeMount钩子函数,这里创建watcher,然后执行mounted钩子函数;
     
    2. 各流程分析
    >2.1 11977行这个$mount方法:没有什么实质性的东西
    var mount = Vue.prototype.$mount; // 改变$mount指向
      Vue.prototype.$mount = function (
        el,
        hydrating
      ) {
        debugger
        el = el && query(el);// 获取元素
    
        // 这里看到el不能是body或者html
        if (el === document.body || el === document.documentElement) {
          warn(
            "Do not mount Vue to <html> or <body> - mount to normal elements instead."
          );
          return this
        }
    
        var options = this.$options;
        // resolve template/el and convert to render function
        if (!options.render) {
          var template = options.template;
          if (template) {
            if (typeof template === 'string') {
              if (template.charAt(0) === '#') {
                template = idToTemplate(template);
                /* istanbul ignore if */
                if (!template) {
                  warn(
                    ("Template element not found or is empty: " + (options.template)),
                    this
                  );
                }
              }
            } else if (template.nodeType) {
              template = template.innerHTML;// 获取#app里边的内容
            } else {
              {
                warn('invalid template option:' + template, this);
              }
              return this
            }
          } else if (el) {
            template = getOuterHTML(el);
          }
          if (template) {
            /* istanbul ignore if */
            if (config.performance && mark) {
              mark('compile');
            }
    
            var ref = compileToFunctions(template, { // 11794
              outputSourceRange: "development" !== 'production',
              shouldDecodeNewlines: shouldDecodeNewlines,
              shouldDecodeNewlinesForHref: shouldDecodeNewlinesForHref,
              delimiters: options.delimiters,
              comments: options.comments
            }, this);
            var render = ref.render;
            var staticRenderFns = ref.staticRenderFns;
            options.render = render;
            options.staticRenderFns = staticRenderFns;
    
            /* istanbul ignore if */
            if (config.performance && mark) {
              mark('compile end');
              measure(("vue " + (this._name) + " compile"), 'compile', 'compile end');
            }
          }
        }
        return mount.call(this, el, hydrating)// 9138
      };
    > 2.2 再看11794行的compileToFunctions:这个方法没看明白什么csp什么catch什么根据render转化成方法的,继续接着看11857行的compile:在这里整合了一下配置信息:然后调用baseCompile:
      var createCompiler = createCompilerCreator(function baseCompile (
        template,
        options
      ) {
        // 把html字符串转化成对象形式
        var ast = parse(template.trim(), options);// 9689
        if (options.optimize !== false) {
          optimize(ast, options);
        }
        // 把解析好的html转化成render函数
        var code = generate(ast, options);
        return {
          ast: ast,
          render: code.render,
          staticRenderFns: code.staticRenderFns
        }
      });
    在这里将把html字符串转化成render函数然后返回generate里边很复杂以后再详细说;
     
    > 2.3再看9138行的$mount:
      Vue.prototype.$mount = function (
        el,
        hydrating
      ) {
        el = el && inBrowser ? query(el) : undefined;
        return mountComponent(this, el, hydrating)
      };
    > 2.4 再看4049行的mountComponent方法
    function mountComponent (
        vm,
        el,
        hydrating
      ) {
        vm.$el = el;
        callHook(vm, 'beforeMount');
    
        var updateComponent = function () {
          vm._update(vm._render(), hydrating);
        };
    
        // we set this to vm._watcher inside the watcher's constructor
        // since the watcher's initial patch may call $forceUpdate (e.g. inside child
        // component's mounted hook), which relies on vm._watcher being already defined
        new Watcher(vm, updateComponent, noop, {
          before: function before () {
            if (vm._isMounted && !vm._isDestroyed) {
              callHook(vm, 'beforeUpdate');
            }
          }
        }, true /* isRenderWatcher */);
        hydrating = false;
    
        // manually mounted instance, call mounted on self
        // mounted is called for render-created child components in its inserted hook
        if (vm.$vnode == null) {
          vm._isMounted = true;
          callHook(vm, 'mounted');
        }
        return vm
      }

    over

  • 相关阅读:
    JSON序列化时消除空格
    appium测试准备记录
    计算器的单元测试dome
    using关键字在C#中的3种用法
    VxWorks多任务功能
    VS2008与MATLAB R2007a混合编程配置过程
    MATLAB和C语言混合编程-----Matlab7.0 编译器设置
    C++虚函数与纯虚函数用法与区别(转载)
    printf("%f ", 3);输出结果为什么是0.000000(转载)
    浮点型数据在内存中存储的表示(转载)
  • 原文地址:https://www.cnblogs.com/rainbowLover/p/13613878.html
Copyright © 2011-2022 走看看