vue 模板的本质是渲染函数
上節(jié)內(nèi)容我們學(xué)習(xí)了 Vue 組件的本質(zhì)?,這節(jié)內(nèi)容看看 vue 模板的本質(zhì)是什么。
模板 - 內(nèi)容的承載體
Vue 在渲染組件的時(shí)候,需要使用者提供一個(gè)渲染模板或者渲染函數(shù)。渲染模板就是一個(gè)HTML字符串,中間加入了一些Vue特制的語法規(guī)則,這樣能夠讓 Vue 把數(shù)據(jù)和模板進(jìn)行了綁定,當(dāng)數(shù)據(jù)發(fā)生變化時(shí)會(huì)讓頁面能夠及時(shí)刷新。這節(jié)內(nèi)容,我們學(xué)習(xí)一下 Vue 的模板及其本質(zhì)。
數(shù)據(jù)綁定
通過雙大括號(hào)把屬性與模板進(jìn)行綁定,當(dāng)屬性變化時(shí)頁面也會(huì)實(shí)時(shí)更新。雙大括號(hào)中可以是:
data 或 props 中聲明的屬性;
計(jì)算屬性;
JS 表達(dá)式;
經(jīng)過編譯后的渲染函數(shù)(render):
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?(_openBlock(),?_createBlock(_Fragment,?null,?[_createVNode("div",?null,?_toDisplayString(_ctx.title),?1?/*?TEXT?*/),_createCommentVNode("?可接收?JS?表達(dá)式?"),_createVNode("div",?null,?_toDisplayString(_ctx.age?+?1),?1?/*?TEXT?*/),_createVNode("div",?null,?_toDisplayString(_ctx.age?>?18???'大朋友'?:?'小朋友'),?1?/*?TEXT?*/)],?64?/*?STABLE_FRAGMENT?*/)) }指令 v-if
v-if 指令如同編程語言中的 if 條件語句,使用方法可以參考編程語言中的 if 語句,根據(jù)不同的條件來渲染不同的模板。v-if 內(nèi)容部分只要是一個(gè)表達(dá)式即可,可以使用 v-else-if 和 v-else。
<!--?v-if?條件渲染?--> <h1?v-if="age?<?18">我是小朋友</h1> <h1?v-else-if="age?>?18?&&?age?<?60">我是中年人</h1> <h1?v-else>我是老年人</h1>經(jīng)過編譯后的渲染函數(shù)(render):
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?(_ctx.age?<?18)??(_openBlock(),?_createBlock("h1",?{?key:?0?},?"我是小朋友")):?(_ctx.age?>?18?&&?_ctx.age?<?60)??(_openBlock(),?_createBlock("h1",?{?key:?1?},?"我是中年人")):?(_openBlock(),?_createBlock("h1",?{?key:?2?},?"我是老年人")) }v-for 指令
如同編程語言中的 for 循環(huán),用來循環(huán)創(chuàng)建一個(gè)模板,遍歷對(duì)象可以是數(shù)組或者對(duì)象。
<!--?for?指令,循環(huán)創(chuàng)建?--> <p?v-for="name?in?welcomes">{{?name?}}</p> <!--?in?和?of?等價(jià)?--> <p?v-for="name?of?welcomes">{{?name?}}</p> <p?v-for="(name,?index)?in?welcomes">{{?name?}}</p> <p?v-for="(name,?index)?in?welcomes"?:key="name.id">{{?name?}}</p> <!--?遍歷對(duì)象?--> <p?v-for="(value,?name)?in?myObject">{{?name?}}:?{{?value?}}</p>經(jīng)過編譯后的渲染函數(shù)(render):
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?(_openBlock(),?_createBlock(_Fragment,?null,?[(_openBlock(true),?_createBlock(_Fragment,?null,?_renderList(_ctx.welcomes,?(name)?=>?{return?(_openBlock(),?_createBlock("p",?null,?_toDisplayString(name),?1?/*?TEXT?*/))}),?256?/*?UNKEYED_FRAGMENT?*/)),(_openBlock(true),?_createBlock(_Fragment,?null,?_renderList(_ctx.myObject,?(value,?name)?=>?{return?(_openBlock(),?_createBlock("p",?null,?_toDisplayString(name)?+?":?"?+?_toDisplayString(value),?1?/*?TEXT?*/))}),?256?/*?UNKEYED_FRAGMENT?*/))],?64?/*?STABLE_FRAGMENT?*/)) }class 綁定
可以給 HTML 元素綁定一個(gè) class,也可以根據(jù)數(shù)據(jù)內(nèi)容動(dòng)態(tài)綁定一個(gè) class。
<!--?class?--> <!--?動(dòng)態(tài)綁定?class,當(dāng)?isActive?為真時(shí)才會(huì)使用選擇器?active?--> <div?:class="{?active:?isActive?}">class1</div> <!--?可以綁定多個(gè)?--> <div?:class="{?active:?isActive,?selected:?isSelect}">class2</div> <!--?可直接通過一個(gè)對(duì)象來告訴?vue?該用哪個(gè)屬性,也就是把模板里的對(duì)象換個(gè)地方寫--> <div?:class="clsObj">class3</div> <!--?可使用多個(gè)對(duì)象,類似于數(shù)組?--> <div?:class="[clsObj,?clsObj2]">class4</div> <!--?直接使用三元表達(dá)式?--> <div?:class="[isActive???activeClass?:?'']">class5</div> <!--?還可以這樣用?--> <div?:class="[{?active:?isActive?},?errorClass]">class6</div> <!--?class?和??:class?可同時(shí)存在?--> <div?class="one-line"?:class="{?active:?isActive?}">class7</div>經(jīng)過編譯后的渲染函數(shù)(render),通過渲染函數(shù),你可以看到給元素設(shè)置 css 的本質(zhì):
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?(_openBlock(),?_createBlock(_Fragment,?null,?[_createVNode("div",?{class:?{?active:?_ctx.isActive?}},?"class1",?2?/*?CLASS?*/),_createVNode("div",?{class:?{?active:?_ctx.isActive,?selected:?_ctx.isSelect}},?"class2",?2?/*?CLASS?*/),_createVNode("div",?{?class:?_ctx.clsObj?},?"class3",?2?/*?CLASS?*/),_createVNode("div",?{class:?[_ctx.clsObj,?_ctx.clsObj2]},?"class4",?2?/*?CLASS?*/),_createVNode("div",?{class:?[_ctx.isActive???_ctx.activeClass?:?'']},?"class5",?2?/*?CLASS?*/),_createVNode("div",?{class:?[{?active:?_ctx.isActive?},?_ctx.errorClass]},?"class6",?2?/*?CLASS?*/),_createVNode("div",?{class:?["one-line",?{?active:?_ctx.isActive?}]},?"class7",?2?/*?CLASS?*/)],?64?/*?STABLE_FRAGMENT?*/)) }style 綁定
style 綁定和 class 綁定語法規(guī)則基本一樣,它的作用是給元素通過 style 添加 css 樣式。
<!--?style?--> <div?:style="{?color:?activeColor,?fontSize:?fontSize?+?'px'?}">style1</div> <!--?直接使用對(duì)象?--> <div?:style="styleObject">style2</div> <!--?使用多個(gè)對(duì)象?--> <div?:style="[colorObj,?edgeObj]">style3</div> <!--?支持多個(gè)值?--> <div?:style="{?display:?['-webkit-box',?'-ms-flexbox',?'flex']?}">style4</div>經(jīng)過編譯后的渲染函數(shù)(render)
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?(_openBlock(),?_createBlock(_Fragment,?null,?[_createCommentVNode("?style?"),_createVNode("div",?{style:?{?color:?_ctx.activeColor,?fontSize:?_ctx.fontSize?+?'px'?}},?"style1",?4?/*?STYLE?*/),_createVNode("div",?{?style:?_ctx.styleObject?},?"style2",?4?/*?STYLE?*/),_createVNode("div",?{style:?[_ctx.colorObj,?_ctx.edgeObj]},?"style3",?4?/*?STYLE?*/),_createVNode("div",?{?style:?{?display:?['-webkit-box',?'-ms-flexbox',?'flex']?}?},?"style4")],?64?/*?STABLE_FRAGMENT?*/)) }事件
可通過 v-on 進(jìn)行事件綁定,基本規(guī)則為 v-on:eventName,eventName 為 DOM 元素所支持的事件。v-on 可以簡(jiǎn)寫換成 @
<!--?監(jiān)聽事件?--> <button?v-on:click="clickMe">von</button> <!--?簡(jiǎn)寫?--> <button?@click="clickMe">von</button> <!--?支持動(dòng)態(tài)屬性名,?eventName?可動(dòng)態(tài)變化,它的值可以是?click、focus--> <button?v-on:[eventName]="eventChange">von</button> <!--?指令的特殊修飾符,表示指令以某種特定的方式觸發(fā)?--> <form?v-on:submit.prevent="onSubmit">提交</form>經(jīng)過編譯后的渲染函數(shù)(render)
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?(_openBlock(),?_createBlock(_Fragment,?null,?[_createVNode("button",?{?onClick:?_ctx.clickMe?},?"von",?8?/*?PROPS?*/,?["onClick"]),_createVNode("button",?{?onClick:?_ctx.clickMe?},?"von",?8?/*?PROPS?*/,?["onClick"]),_createVNode("button",?{?[_toHandlerKey(_ctx.eventName)]:?_ctx.eventChange?},?"von",?16?/*?FULL_PROPS?*/),_createVNode("form",?{onSubmit:?_withModifiers(_ctx.onSubmit,?["prevent"])},?"提交",?40?/*?PROPS,?HYDRATE_EVENTS?*/,?["onSubmit"])],?64?/*?STABLE_FRAGMENT?*/)) }綁定屬性
無論是自定義組件還是 HTML標(biāo)簽都可以通過 v-bind 把 DOM元素的屬性和數(shù)據(jù)屬性進(jìn)行綁定。
<!--?通過?v-bind?來綁定屬性?--> <a?v-bind:href="url">點(diǎn)我</a> <!--?可簡(jiǎn)寫?--> <a?:href="url">點(diǎn)我</a>經(jīng)過編譯后的渲染函數(shù)(render)
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?(_openBlock(),?_createBlock(_Fragment,?null,?[_createVNode("a",?{?href:?_ctx.url?},?"點(diǎn)我",?8?/*?PROPS?*/,?["href"]),_createVNode("a",?{?href:?_ctx.url?},?"點(diǎn)我",?8?/*?PROPS?*/,?["href"])],?64?/*?STABLE_FRAGMENT?*/)) }v-show 指令
控制元素的顯示隱藏,其原理是通過控制 css 屬性 display。它屬于自定義指令的范疇,你可以使用 Vue 提供的機(jī)制進(jìn)行自定義指令。
<h1?v-show="isShow">Hello!</h1>經(jīng)過編譯后的渲染函數(shù)(render),發(fā)現(xiàn)這個(gè)渲染函數(shù)與上面的都不一樣,它使用了 _withDirectives,這個(gè)是與指令相關(guān)的函數(shù)。
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?_withDirectives((_openBlock(),?_createBlock("h1",?null,?"Hello!",?512?/*?NEED_PATCH?*/)),?[[_vShow,?_ctx.isShow]]) }v-model 雙向綁定
與 v-show 指令一樣屬于自定義指令的范疇,最常用的場(chǎng)景是使用表單的時(shí)候,把用戶輸入的內(nèi)容和數(shù)據(jù)進(jìn)行雙向綁定。
<input?v-model="question"?/>經(jīng)過編譯后的渲染函數(shù)(render)
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?_withDirectives((_openBlock(),?_createBlock("input",?{"onUpdate:modelValue":?$event?=>?(_ctx.question?=?$event)},?null,?8?/*?PROPS?*/,?["onUpdate:modelValue"])),?[[_vModelText,?_ctx.question]]) }v-html 指令
直接渲染 HTML 字符串,HTML 不被看做是文本,它會(huì)當(dāng)做 HTML 渲染到頁面上。
<div?v-html="html">v-html</div>經(jīng)過編譯后的渲染函數(shù)(render)
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?(_openBlock(),?_createBlock("div",?{?innerHTML:?_ctx.html?},?null,?8?/*?PROPS?*/,?["innerHTML"])) }v-once 指令
只修改一次,即使數(shù)據(jù)以后更新了,頁面也不會(huì)自動(dòng)更新。
<div?v-once>{{?from?}}</div>經(jīng)過編譯后的渲染函數(shù)(render)
export?function?render(_ctx,?_cache,?$props,?$setup,?$data,?$options)?{return?_cache[1]?||?(_setBlockTracking(-1),_cache[1]?=?_createVNode("div",?null,?_toDisplayString(_ctx.from),?1?/*?TEXT?*/),_setBlockTracking(1),_cache[1]) }最后
本節(jié)內(nèi)容我們重點(diǎn)學(xué)習(xí)了各個(gè)模板的語法規(guī)則,以及各個(gè)指令的作用。在介紹模板時(shí),也給大家演示了最終生成的渲染函數(shù),有助于大家理解模板的本質(zhì)。
模板的本質(zhì)其實(shí)就是渲染函數(shù);渲染函數(shù)的本質(zhì)其實(shí)就是操作虛擬DOM;虛擬DOM的本質(zhì)其實(shí)就是操作真正的 DOM;最終達(dá)到通過 JS 操作真正的 DOM,以讓頁面動(dòng)態(tài)更新;
渲染函數(shù)
本節(jié)內(nèi)容同步在網(wǎng)站 https://lefex.gitee.io/ 上,我會(huì)把大家的問題匯總到網(wǎng)站上。大家加油!!
長(zhǎng)按關(guān)注
素燕《前端小課》
幫助 10W 人入門并進(jìn)階前端
官網(wǎng):https://lefex.gitee.io/
總結(jié)
以上是生活随笔為你收集整理的vue 模板的本质是渲染函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mySQL全指令学习记录
- 下一篇: 2021-技能大赛-信息安全管理与评估-