本文將通過解讀render函數的源碼,來分析vue中的vNode是如何創建的。在vue2.x的版本中,無論是直接書寫render函數,還是使用template或el屬性,或是使用.vue單文件的形式,最終都需要編譯成render函數進行vnode的創建,最終再渲染成真實的DOM。 如果對vue源碼的目錄還不是很了解,推薦先閱讀下 深入vue -- 源碼目錄和編譯過程。
01 render函數
render方法定義在文件 src/core/instance/render.js 中
Vue.prototype._render = function (): VNode { const vm: Component = this const { render, _parentVnode } = vm.$options // ... // set parent vnode. this allows render functions to have access // to the data on the placeholder node. vm.$vnode = _parentVnode // render self let vnode try { 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 } } // 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 }_render定義在vue的原型上,會返回vnode,vnode通過代碼render.call(vm._renderProxy, vm.$createElement)進行創建。
在創建vnode過程中,如果出現錯誤,就會執行catch中代碼做降級處理。
_render中最核心的代碼就是:
vnode = render.call(vm._renderProxy, vm.$createElement)
接下來,分析下這里的render,vm._renderProxy,vm.$createElement分別是什么。
render函數
const { render, _parentVnode } = vm.$options
render方法是從$options中提取的。render方法有兩種途徑得來:
在組件中開發者直接手寫的render函數
通過編譯template屬性生成
參數 vm._renderProxy
vm._renderProxy定義在 src/core/instance/init.js 中,是call的第一個參數,指定render函數執行的上下文。
/* istanbul ignore else */if (process.env.NODE_ENV !== 'production') { initProxy(vm)} else { vm._renderProxy = vm}生產環境:
vm._renderProxy = vm,也就是說,在生產環境,render函數執行的上下文就是當前vue實例,即當前組件的this。
新聞熱點
疑難解答
圖片精選