vue2從template到render模板編譯入口詳解_第1頁
vue2從template到render模板編譯入口詳解_第2頁
vue2從template到render模板編譯入口詳解_第3頁
vue2從template到render模板編譯入口詳解_第4頁
vue2從template到render模板編譯入口詳解_第5頁
已閱讀5頁,還剩6頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第vue2從template到render模板編譯入口詳解目錄正文1、template:模板獲取2、createCompiler:核心參數(shù)3、createCompileToFunctionFn:緩存處理4、compile:參數(shù)合并小結(jié)

正文

在vue的渲染過程中,渲染核心邏輯是vm._update(vm._render(),hydrating),通過vm._render的執(zhí)行獲取到vNode,再通過vm._update的執(zhí)行來將vNode渲染成真實(shí)視圖。

其中,render函數(shù)的來源是:

(1)用戶手寫;

(2)通過vue-loader引入的時(shí)候進(jìn)行轉(zhuǎn)換;

(3)通過compileToFunctions將template進(jìn)行處理產(chǎn)生。

開發(fā)過程中主要以template的方式進(jìn)行代碼的編寫,這里主要梳理compileToFunctions的方法。

1、template:模板獲取

在src/platforms/web/entry-runtime-with-compiler.js中在vue的原型上定義了$mount:

constidToTemplate=cached(id={

constel=query(id)

returnelel.innerHTML

constmount=Vtotype.$mount

Vtotype.$mount=function(

el:string|Element,

hydrating:boolean

):Component{

el=elquery(el)

/*istanbulignoreif*/

if(el===document.body||el===document.documentElement){

process.env.NODE_ENV!=='production'warn(

`DonotmountVuetohtmlorbody-mounttonormalelementsinstead.`

returnthis

constoptions=this.$options

//resolvetemplate/elandconverttorenderfunction

if(!options.render){

lettemplate=options.template

if(template){

if(typeoftemplate==='string'){

if(template.charAt(0)==='#'){

template=idToTemplate(template)

/*istanbulignoreif*/

if(process.env.NODE_ENV!=='production'!template){

warn(

`Templateelementnotfoundorisempty:${options.template}`,

this

}elseif(template.nodeType){

template=template.innerHTML

}else{

if(process.env.NODE_ENV!=='production'){

warn('invalidtemplateoption:'+template,this)

returnthis

}elseif(el){

template=getOuterHTML(el)

if(template){

/*istanbulignoreif*/

if(process.env.NODE_ENV!=='production'config.performancemark){

mark('compile')

const{render,staticRenderFns}=compileToFunctions(template,{

outputSourceRange:process.env.NODE_ENV!=='production',

shouldDecodeNewlines,

shouldDecodeNewlinesForHref,

delimiters:options.delimiters,

comments:ments

},this)

options.render=render

options.staticRenderFns=staticRenderFns

/*istanbulignoreif*/

if(process.env.NODE_ENV!=='production'config.performancemark){

mark('compileend')

measure(`vue${this._name}compile`,'compile','compileend')

returnmount.call(this,el,hydrating)

*GetouterHTMLofelements,takingcare

*ofSVGelementsinIEaswell.

functiongetOuterHTML(el:Element):string{

if(el.outerHTML){

returnel.outerHTML

}else{

constcontainer=document.createElement('div')

container.appendChild(el.cloneNode(true))

returncontainer.innerHTML

在沒有編寫render時(shí)候才會(huì)去獲取template并進(jìn)行編譯,獲取方式有

在傳入的參數(shù)中獲取options.template如果是真實(shí)節(jié)點(diǎn)則獲取其innerHTML以上都不滿足則通過或者el.outerhTML的方式獲取

獲取到template后通過compileToFunctions的方式進(jìn)行編譯,這里是編譯的入口。

2、createCompiler:核心參數(shù)

在src/platforms/web/compile/index.js中調(diào)用了createCompiler:

import{baseOptions}from'./options'

import{createCompiler}from'compiler/index'

const{compile,compileToFunctions}=createCompiler(baseOptions)

export{compile,compileToFunctions}

這里將baseOptions作為基礎(chǔ)參數(shù)傳入,在src/complile/index.js中定義了createCompiler:

import{parse}from'./parser/index'

import{optimize}from'./optimizer'

import{generate}from'./codegen/index'

import{createCompilerCreator}from'./create-compiler'

exportconstcreateCompiler=createCompilerCreator(functionbaseCompile(

template:string,

options:CompilerOptions

):CompiledResult{

constast=parse(template.trim(),options)

if(options.optimize!==false){

optimize(ast,options)

constcode=generate(ast,options)

return{

ast,

render:code.render,

staticRenderFns:code.staticRenderFns

這里定義了baseCompile核心參數(shù),主要目的是進(jìn)行ast的獲取、ast的優(yōu)化和code的拼接。并將baseCompile作為參數(shù)傳入執(zhí)行了createCompilerCreator:

exportfunctioncreateCompilerCreator(baseCompile:Function):Function{

returnfunctioncreateCompiler(baseOptions:CompilerOptions){

functioncompile(

template:string,

options:CompilerOptions

):CompiledResult{

//...

return{

compile,

compileToFunctions:createCompileToFunctionFn(compile)

createCompiler就是createCompilerCreator的返回函數(shù),createCompiler中返回了compile和compileToFunctions,這里的compileToFunctions就是入口獲取render的函數(shù),由createCompileToFunctionFn(compile)執(zhí)行獲得。

再看createCompileToFunctionFn(compile):

3、createCompileToFunctionFn:緩存處理

functioncreateFunction(code,errors){

try{

returnnewFunction(code)

}catch(err){

errors.push({err,code})

returnnoop

exportfunctioncreateCompileToFunctionFn(compile:Function):Function{

constcache=Object.create(null)

returnfunctioncompileToFunctions(

template:string,

options:CompilerOptions,

vm:Component

):CompiledFunctionResult{

options=extend({},options)

constwarn=options.warn||baseWarn

deleteoptions.warn

/*istanbulignoreif*/

if(process.env.NODE_ENV!=='production'){

//detectpossibleCSPrestriction

try{

newFunction('return1')

}catch(e){

if(e.toString().match(/unsafe-eval|CSP/)){

warn(

'ItseemsyouareusingthestandalonebuildofVue.jsinan'+

'environmentwithContentSecurityPolicythatprohibitsunsafe-eval.'+

'Thetemplatecompilercannotworkinthisenvironment.Consider'+

'relaxingthepolicytoallowunsafe-evalorpre-compilingyour'+

'templatesintorenderfunctions.'

//checkcache

constkey=options.delimiters

String(options.delimiters)+template

:template

if(cache[key]){

returncache[key]

//compile

constcompiled=compile(template,options)

//...

//turncodeintofunctions

constres={}

constfnGenErrors=[]

res.render=createFunction(compiled.render,fnGenErrors)

res.staticRenderFns=compiled.staticRenderFns.map(code={

returncreateFunction(code,fnGenErrors)

//checkfunctiongenerationerrors.

//thisshouldonlyhappenifthereisabuginthecompileritself.

//mostlyforcodegendevelopmentuse

/*istanbulignoreif*/

if(process.env.NODE_ENV!=='production'){

if((!compiled.errors||!compiled.errors.length)fnGenErrors.length){

warn(

`Failedtogeneraterenderfunction:\n\n`+

fnGenErrors.map(({err,code})=`${err.toString()}in\n\n$[code]\n`).join('\n'),

return(cache[key]=res)

這里通過constcache=Object.create(null)的方式定義了緩存,返回的compileToFunctions函數(shù)中執(zhí)行return(cache[key]=res),通過閉包的方式進(jìn)行了計(jì)算的重復(fù)利用。

如果當(dāng)前環(huán)境支持newFunction(return1)則調(diào)用了createFunction將compiled.render通過newFunction(code)進(jìn)行可執(zhí)行代碼的轉(zhuǎn)換,否則進(jìn)行提示(放寬環(huán)境執(zhí)行或預(yù)編譯當(dāng)前模板)。

再看constcompiled=compile(template,options):

4、compile:參數(shù)合并

functioncompile(

template:string,

options:CompilerOptions

):CompiledResult{

constfinalOptions=Object.create(baseOptions)

consterrors=[]

consttips=[]

letwarn=(msg,range,tip)={

(tiptips:errors).push(msg)

if(options){

if(process.env.NODE_ENV!=='production'options.outputSourceRange){

//$flow-disable-line

constleadingSpaceLength=template.match(/^\s*/)[0].length

warn=(msg,range,tip)={

constdata:WarningMessage={msg}

if(range){

if(range.start!=null){

data.start=range.start+leadingSpaceLength

if(range.end!=null){

data.end=range.end+leadingSpaceLength

(tiptips:errors).push(data)

//mergecustommodules

if(options.modules){

finalOptions.modules=

(baseOptions.modules||[]).concat(options.modules)

//mergecustomdirectives

if(options.directives){

finalOptions.directives=extend(

Object.create(baseOptions.directives||null),

options.directives

//copyotheroptions

for(constkey

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論