Vue render深入開發(fā)講解
簡(jiǎn)介
在使用Vue進(jìn)行開發(fā)的時(shí)候,大多數(shù)情況下都是使用template進(jìn)行開發(fā),使用template簡(jiǎn)單、方便、快捷,可是有時(shí)候需要特殊的場(chǎng)景使用template就不是很適合。因此為了很好使用render函數(shù),我決定深入窺探一下。各位看官如果覺得下面寫的有不正確之處還望看官指出,你們與我的互動(dòng)就是寫作的最大動(dòng)力。
場(chǎng)景
官網(wǎng)描述的場(chǎng)景當(dāng)我們開始寫一個(gè)通過 level prop 動(dòng)態(tài)生成 heading 標(biāo)簽的組件,你可能很快想到這樣實(shí)現(xiàn):
<script type="text/x-template" id="anchored-heading-template"> <h1 v-if="level === 1"> <slot></slot> </h1> <h2 v-else-if="level === 2"> <slot></slot> </h2> <h3 v-else-if="level === 3"> <slot></slot> </h3> <h4 v-else-if="level === 4"> <slot></slot> </h4> <h5 v-else-if="level === 5"> <slot></slot> </h5> <h6 v-else-if="level === 6"> <slot></slot> </h6> </script>
Vue.component('anchored-heading', { template: '#anchored-heading-template', props: { level: { type: Number, required: true } } })
在這種場(chǎng)景中使用 template 并不是最好的選擇:首先代碼冗長(zhǎng),為了在不同級(jí)別的標(biāo)題中插入錨點(diǎn)元素,我們需要重復(fù)地使用 <slot></slot>。
雖然模板在大多數(shù)組件中都非常好用,但是在這里它就不是很簡(jiǎn)潔的了。那么,我們來(lái)嘗試使用 render 函數(shù)重寫上面的例子:
Vue.component('anchored-heading', { render: function (createElement) { return createElement( 'h' + this.level, // tag name 標(biāo)簽名稱 this.$slots.default // 子組件中的陣列 ) }, props: { level: { type: Number, required: true } } })
簡(jiǎn)單清晰很多!簡(jiǎn)單來(lái)說,這樣代碼精簡(jiǎn)很多,但是需要非常熟悉 Vue 的實(shí)例屬性。在這個(gè)例子中,你需要知道當(dāng)你不使用 slot 屬性向組件中傳遞內(nèi)容時(shí),比如 anchored-heading 中的 Hello world!,這些子元素被存儲(chǔ)在組件實(shí)例中的 $slots.default中。
createElement參數(shù)介紹
接下來(lái)你需要熟悉的是如何在 createElement 函數(shù)中生成模板。這里是 createElement 接受的參數(shù):
createElement( // {String | Object | Function} // 一個(gè) HTML 標(biāo)簽字符串,組件選項(xiàng)對(duì)象,或者 // 解析上述任何一種的一個(gè) async 異步函數(shù),必要參數(shù)。 'div', // {Object} // 一個(gè)包含模板相關(guān)屬性的數(shù)據(jù)對(duì)象 // 這樣,您可以在 template 中使用這些屬性??蛇x參數(shù)。 { // (詳情見下一節(jié)) }, // {String | Array} // 子節(jié)點(diǎn) (VNodes),由 `createElement()` 構(gòu)建而成, // 或使用字符串來(lái)生成“文本節(jié)點(diǎn)”??蛇x參數(shù)。 [ '先寫一些文字', createElement('h1', '一則頭條'), createElement(MyComponent, { props: { someProp: 'foobar' } }) ] )
深入 data 對(duì)象
有一件事要注意:正如在模板語(yǔ)法中,v-bind:class 和 v-bind:style ,會(huì)被特別對(duì)待一樣,在 VNode 數(shù)據(jù)對(duì)象中,下列屬性名是級(jí)別最高的字段。該對(duì)象也允許你綁定普通的 HTML 特性,就像 DOM 屬性一樣,比如 innerHTML (這會(huì)取代 v-html 指令)。
{ // 和`v-bind:class`一樣的 API 'class': { foo: true, bar: false }, // 和`v-bind:style`一樣的 API style: { color: 'red', fontSize: '14px' }, // 正常的 HTML 特性 attrs: { id: 'foo' }, // 組件 props props: { myProp: 'bar' }, // DOM 屬性 domProps: { innerHTML: 'baz' }, // 事件監(jiān)聽器基于 `on` // 所以不再支持如 `v-on:keyup.enter` 修飾器 // 需要手動(dòng)匹配 keyCode。 on: { click: this.clickHandler }, // 僅對(duì)于組件,用于監(jiān)聽原生事件,而不是組件內(nèi)部使用 // `vm.$emit` 觸發(fā)的事件。 nativeOn: { click: this.nativeClickHandler }, // 自定義指令。注意,你無(wú)法對(duì) `binding` 中的 `oldValue` // 賦值,因?yàn)?Vue 已經(jīng)自動(dòng)為你進(jìn)行了同步。 directives: [ { name: 'my-custom-directive', value: '2', expression: '1 + 1', arg: 'foo', modifiers: { bar: true } } ], // Scoped slots in the form of // { name: props => VNode | Array<VNode> } scopedSlots: { default: props => createElement('span', props.text) }, // 如果組件是其他組件的子組件,需為插槽指定名稱 slot: 'name-of-slot', // 其他特殊頂層屬性 key: 'myKey', ref: 'myRef' }
條件渲染
既然熟讀以上api接下來(lái)咱們就來(lái)點(diǎn)實(shí)戰(zhàn)。
之前這樣寫
//HTML <div id="app"> <div v-if="isShow">我被你發(fā)現(xiàn)啦?。。?lt;/div> </div> <vv-isshow :show="isShow"></vv-isshow> //js //組件形式 Vue.component('vv-isshow', { props:['show'], template:'<div v-if="show">我被你發(fā)現(xiàn)啦2?。?!</div>', }); var vm = new Vue({ el: "#app", data: { isShow:true } });
render這樣寫
//HTML <div id="app"> <vv-isshow :show="isShow"><slot>我被你發(fā)現(xiàn)啦3!??!</slot></vv-isshow> </div> //js //組件形式 Vue.component('vv-isshow', { props:{ show:{ type: Boolean, default: true } }, render:function(h){ if(this.show ) return h('div',this.$slots.default); }, }); var vm = new Vue({ el: "#app", data: { isShow:true } });
列表渲染
之前是這樣寫的,而且v-for 時(shí)template內(nèi)必須被一個(gè)標(biāo)簽包裹
//HTML <div id="app"> <vv-aside v-bind:list="list"></vv-aside> </div> //js //組件形式 Vue.component('vv-aside', { props:['list'], methods:{ handelClick(item){ console.log(item); } }, template:'<div>\ <div v-for="item in list" @click="handelClick(item)" :class="{odd:item.odd}">{{item.txt}}</div>\ </div>', //template:'<div v-for="item in list" @click="handelClick(item)" :class="{odd:item.odd}">{{item.txt}}</div>',錯(cuò)誤 }); var vm = new Vue({ el: "#app", data: { list: [{ id: 1, txt: 'javaScript', odd: true }, { id: 2, txt: 'Vue', odd: false }, { id: 3, txt: 'React', odd: true }] } });
render這樣寫
//HTML <div id="app"> <vv-aside v-bind:list="list"></vv-aside> </div> //js //側(cè)邊欄 Vue.component('vv-aside', { render: function(h) { var _this = this, ayy = this.list.map((v) => { return h('div', { 'class': { odd: v.odd }, attrs: { title: v.txt }, on: { click: function() { return _this.handelClick(v); } } }, v.txt); }); return h('div', ayy); }, props: { list: { type: Array, default: () => { return this.list || []; } } }, methods: { handelClick: function(item) { console.log(item, "item"); } } }); var vm = new Vue({ el: "#app", data: { list: [{ id: 1, txt: 'javaScript', odd: true }, { id: 2, txt: 'Vue', odd: false }, { id: 3, txt: 'React', odd: true }] } });
v-model
之前的寫法
//HTML <div id="app"> <vv-models v-model="txt" :txt="txt"></vv-models> </div> //js //input Vue.component('vv-models', { props: ['txt'], template: '<div>\ <p>看官你輸入的是:{{txtcout}}</p>\ <input v-model="txtcout" type="text" />\ </div>', computed: { txtcout:{ get(){ return this.txt; }, set(val){ this.$emit('input', val); } } } }); var vm = new Vue({ el: "#app", data: { txt: '', } });
render這樣寫
//HTML <div id="app"> <vv-models v-model="txt" :txt="txt"></vv-models> </div> //js //input Vue.component('vv-models', { props: { txt: { type: String, default: '' } }, render: function(h) { var self=this; return h('div',[h('p','你猜我輸入的是啥:'+this.txt),h('input',{ on:{ input(event){ self.$emit('input', event.target.value); } } })] ); }, }); var vm = new Vue({ el: "#app", data: { txt: '', } });
總結(jié)
render函數(shù)使用的是JavaScript 的完全編程的能力,在性能上是占用絕對(duì)的優(yōu)勢(shì),小編只是對(duì)它進(jìn)行剖析。至于實(shí)際項(xiàng)目你選擇那種方式進(jìn)行渲染依舊需要根據(jù)你的項(xiàng)目以及實(shí)際情況而定。
- 基于vue2.0動(dòng)態(tài)組件及render詳解
- vue iview組件表格 render函數(shù)的使用方法詳解
- Vue中render函數(shù)的使用方法
- Vue中render方法的使用詳解
- 詳解vue渲染函數(shù)render的使用
- 淺談vue的iview列表table render函數(shù)設(shè)置DOM屬性值的方法
- 如何理解Vue的render函數(shù)的具體用法
- vue Render中slots的使用的實(shí)例代碼
- 深入理解vue Render函數(shù)
- vue深入解析之render function code詳解
- 了解VUE的render函數(shù)的使用
- Vue2.x中的Render函數(shù)詳解
- Vue.js render方法使用詳解
相關(guān)文章
VUE element上傳動(dòng)態(tài)設(shè)置action路徑和參數(shù)的坑及解決
這篇文章主要介紹了VUE element上傳動(dòng)態(tài)設(shè)置action路徑和參數(shù)的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07vue3+vite中報(bào)錯(cuò)信息處理方法Error: Module “path“ has&nb
這篇文章主要介紹了vue3+vite中報(bào)錯(cuò)信息處理方法Error: Module “path“ has been externalized for browser compatibility...,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03VUE3開箱即用的音頻播放組件完整代碼(基于原生audio)
Vue3開箱即用的框架有很多選擇,下面這篇文章主要介紹了VUE3開箱即用的音頻播放組件(基于原生audio)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-09-09vue實(shí)現(xiàn)多條件篩選超簡(jiǎn)潔代碼
這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)多條件篩選的相關(guān)資料,隨著數(shù)據(jù)的不斷增多,我們往往需要在表格中進(jìn)行多條件的篩選,以便快速定位符合我們需求的數(shù)據(jù),需要的朋友可以參考下2023-09-09vue第三方庫(kù)中存在擴(kuò)展運(yùn)算符報(bào)錯(cuò)問題的解決方案
這篇文章主要介紹了vue第三方庫(kù)中存在擴(kuò)展運(yùn)算符報(bào)錯(cuò)問題,本文給大家分享解決方案,通過結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07