




版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 預(yù)防傳染病管理制度
- 芯片測試流程管理制度
- 抽汲撈油安全管理制度
- 高分秘籍系統(tǒng)集成試題及答案
- 電力后勤信息化管理制度
- 藥房周轉(zhuǎn)庫管理制度
- 高升本語文試題及答案
- 2025年軟件評測師考試課程安排試題與答案
- 房車營地日常管理制度
- 電力分公司安全管理制度
- T-CAS 886-2024 輸血相容性檢測設(shè)備檢測性能驗(yàn)證技術(shù)規(guī)范
- 公司安全生產(chǎn)事故隱患內(nèi)部報(bào)告獎(jiǎng)勵(lì)工作制度
- 【詞匯】311個(gè)四級核心高頻詞匯
- 稻鴨共作及其環(huán)境效應(yīng)
- 農(nóng)業(yè)機(jī)械安裝調(diào)試及驗(yàn)收方案
- 氣壓傳動(dòng)課件 項(xiàng)目四任務(wù)二 折彎機(jī)氣動(dòng)系統(tǒng)組裝與調(diào)試
- 土菜館策劃方案
- 技能人才評價(jià)新職業(yè)考評員培訓(xùn)在線考試(四川省)
- 江蘇省揚(yáng)州市2024-2025學(xué)年高一化學(xué)下學(xué)期期末考試試題
- 成本加酬金合同協(xié)議書
- 創(chuàng)新創(chuàng)業(yè)實(shí)戰(zhàn)案例解析智慧樹知到期末考試答案章節(jié)答案2024年東北農(nóng)業(yè)大學(xué)
評論
0/150
提交評論