模板轉換成瀏覽器認識的HTML過程以下:javascript
這裏總結下第一步模板編譯成AST render函數的方式,生成的render函數都會加在vue實例的$options上或者$options原型上,調用實例的_render方法時被調用。能夠看vue的源碼:vue
Vue.prototype._render = function () { var vm = this; var ref = vm.$options; var render = ref.render; var _parentVnode = ref._parentVnode; if (_parentVnode) { vm.$scopedSlots = normalizeScopedSlots( _parentVnode.data.scopedSlots, vm.$slots, vm.$scopedSlots ); } // set parent vnode. this allows render functions to have access // to the data on the placeholder node. vm.$vnode = _parentVnode; // render self var vnode; try { // There's no need to maintain a stack becaues all render fns are called // separately from one another. Nested component's render fns are called // when parent component is patched. currentRenderingInstance = vm; vnode = render.call(vm._renderProxy, vm.$createElement); } catch (e) { handleError(e, vm, "render"); // return error render result, // or previous vnode to prevent render error causing blank component /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production' && vm.$options.renderError) { try { vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e); } catch (e) { handleError(e, vm, "renderError"); vnode = vm._vnode; } } else { vnode = vm._vnode; } } finally { currentRenderingInstance = null; } // if the returned array contains only a single node, allow it if (Array.isArray(vnode) && vnode.length === 1) { vnode = vnode[0]; } // return empty vnode in case the render function errored out if (!(vnode instanceof VNode)) { if (process.env.NODE_ENV !== 'production' && Array.isArray(vnode)) { warn( 'Multiple root nodes returned from render function. Render function ' + 'should return a single root node.', vm ); } vnode = createEmptyVNode(); } // set parent vnode.parent = _parentVnode; return vnode }; }
這也是在使用打包工具時,只需引入運行時的vue, 如vue/dist/vue.runtime.esm.jsjava
單文件 HelloWorld.vuenode
<template> <div class="example">{{ msg }}</div> </template> <script> export default { data () { return { msg: 'Hello world!' } } } </script>
測試文件main.jswebpack
import HelloWorld from './components/HelloWorld' console.log("===========vue-template-compiler===========") console.log(HelloWorld);
單文件HelloWorld.vue通過vue-loader處理,由vue-template-compiler編譯生成的render函數:web
詳細內容以下圖,裏面的_h, _c, _v, _s都是vue實例函數的簡稱瀏覽器
import Vue from 'vue' let templateHelloworld = `<div class="example">{{ msg }}</div>` // Vue完整版裏的compiler let vueCompilerResult = Vue.compile(templateHelloworld); console.log("===========vue compiler===========") console.log(vueCompilerResult);
這是一個匿名函數,with包裹做用域,_c同上,是vue實例的方法簡寫dom
import Vue from 'vue' let jsxHellowWorld = new Vue({ render: function(h){ return( <div className = "example"> {msg} </div> ) } }) console.log("===========jsx===========") console.log(jsxHellowWorld.$options.render);