vue.js和vue.runtime.js之间的区别

本文揭示了Vue.js完整版与runtime版在$mount函数中的不同,详解了模板编译过程。完整版自带模板编译,runtime版需手动实现render。对比两者并提供实例代码,适合理解Vue核心原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vue.js 是完整的版本包含了模板编译函数,通过查看vue.js源码发现,当使用完整版本的vue.js 时,调用$mount函数进行挂载的时候,$mount函数调用的是入下函数:

Vue.prototype.$mount = function (
      el,
      hydrating
  ) {
    //query会根据el去查询要挂载到的节点,如果传的是字符串,类似dom元素的id、css类名或者元素类型如P div等等
    el = el && query(el);

    /* istanbul ignore if */
    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;
        } 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');
        }

        //模板编译函数,可以编译模板,生成一个render函数
        var ref = compileToFunctions(template, {
          outputSourceRange: "development" !== 'production',
          shouldDecodeNewlines: shouldDecodeNewlines,
          shouldDecodeNewlinesForHref: shouldDecodeNewlinesForHref,
          delimiters: options.delimiters,
          comments: options.comments
        }, this);
        //生成的render函数
        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)
  };

完全版本可包含了模板编译函数,在上面的代码中通过调用compileToFunctions函数对模板进行编译然后生成了一个匿名的render函数,主要用是通过new Function(code)对一个函数的字符串描述形式生成一内部匿名个函数。compileToFunctions函数挂载到了Vue上面,可以通过Vue.compile进行直接调用进行模板编译。
示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue.js"></script>
</head>
<body>
<div id="app">
    <div>{{message}}</div>
</div>
<script>
    console.log(Vue.compile(document.querySelector("#app").outerHTML).render);
</script>
</body>
</html>

编译结果如下

 ƒ anonymous()
    {
        with (this) {
            return _c('div', {attrs: {"id": "app"}}, [_c('div', [_v(_s(message))])])
        }
    }

所以完整版本的vue.js 库包含了模板编译的功能,在内部会调用模板编译函数生成一个匿名的render函数。
vue.runtime.js版本不包含模板编译函数,所以使用该版本的库时,必须自己实现render函数,不然就会报错。
vue.runtime.js 库的$mount函数定义如下:

Vue.prototype.$mount = function (
      el,
      hydrating
  ) {
    el = el && inBrowser ? query(el) : undefined;
    return mountComponent(this, el, hydrating)
  };

mountComponent定义如下;

function mountComponent (
      vm,
      el,
      hydrating
  ) {
    vm.$el = el;
    if (!vm.$options.render) {
      vm.$options.render = createEmptyVNode;
      {
        /* istanbul ignore if */
        //如果不包含render函数则会抛出如下错误
        if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||
            vm.$options.el || el) {
          warn(
              'You are using the runtime-only build of Vue where the template ' +
              'compiler is not available. Either pre-compile the templates into ' +
              'render functions, or use the compiler-included build.',
              vm
          );
        } else {
          warn(
              'Failed to mount component: template or render function not defined.',
              vm
          );
        }
      }
    }
    callHook(vm, 'beforeMount');

    var updateComponent;
    /* istanbul ignore if */
    if (config.performance && mark) {
      updateComponent = function () {
        var name = vm._name;
        var id = vm._uid;
        var startTag = "vue-perf-start:" + id;
        var endTag = "vue-perf-end:" + id;

        mark(startTag);
        var vnode = vm._render();
        mark(endTag);
        measure(("vue " + name + " render"), startTag, endTag);

        mark(startTag);
        vm._update(vnode, hydrating);
        mark(endTag);
        measure(("vue " + name + " patch"), startTag, endTag);
      };
    } else {
      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
  }

如果以如下方式进行调用的话

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue.runtime.js"></script>
</head>
<body>
<div id="app">
    <div>{{message}}</div>
</div>
<script>
   let app= new Vue({
        data:{
            message:"er",
        }
    });
   app.$mount("#app")
</script>
</body>
</html>

则会抛出如下错误,因为vue.runtime.js缺少模板编译函数,不会再内部生成render函数。
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
当使用vue.runtime.js版本时必须自己实现render函数,如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue.runtime.js"></script>
</head>
<body>
<div id="app">
    <div>{{message}}</div>
</div>
<script>
    let app = new Vue({
        data: {
            message: "er",
        },
        render(c) {
            return c('div', {
                'attrs': {
                    'id':'#app',
                },
            },[this._v(this._s(this.message))])
        }
    });
    app.$mount("#app")
</script>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值