Vue render深入開(kāi)發(fā)講解
簡(jiǎn)介
在使用Vue進(jìn)行開(kāi)發(fā)的時(shí)候,大多數(shù)情況下都是使用template進(jìn)行開(kāi)發(fā),使用template簡(jiǎn)單、方便、快捷,可是有時(shí)候需要特殊的場(chǎng)景使用template就不是很適合。因此為了很好使用render函數(shù),我決定深入窺探一下。各位看官如果覺(jué)得下面寫的有不正確之處還望看官指出,你們與我的互動(dòng)就是寫作的最大動(dòng)力。
場(chǎng)景
官網(wǎng)描述的場(chǎng)景當(dāng)我們開(kāi)始寫一個(gè)通過(guò) 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)說(shuō),這樣代碼精簡(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àn)下一節(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)聽(tīng)器基于 `on`
// 所以不再支持如 `v-on:keyup.enter` 修飾器
// 需要手動(dòng)匹配 keyCode。
on: {
click: this.clickHandler
},
// 僅對(duì)于組件,用于監(jiān)聽(tīng)原生事件,而不是組件內(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)啦?。?!</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?。。?lt;/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)文章
Vue3使用src動(dòng)態(tài)引入本地圖片的詳細(xì)步驟
這篇文章主要給大家介紹了關(guān)于Vue3使用src動(dòng)態(tài)引入本地圖片的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-12-12
vue-class-setup?編寫?class?風(fēng)格組合式API
這篇文章主要為大家介紹了vue-class-setup?編寫?class?風(fēng)格組合式API,支持Vue2和Vue3,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
vue手寫<RouterLink/>組件實(shí)現(xiàn)demo詳解
這篇文章主要為大家介紹了vue手寫<RouterLink/>組件實(shí)現(xiàn)demo詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
vue3項(xiàng)目typescript如何export引入(imported)的interface問(wèn)題
這篇文章主要介紹了vue3項(xiàng)目typescript如何export引入(imported)的interface問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
在vue中實(shí)現(xiàn)PDF文件流預(yù)覽功能
這篇文章主要為大家詳細(xì)介紹如何在vue中實(shí)現(xiàn)PDF文件流預(yù)覽功能,文中的實(shí)現(xiàn)步驟講解詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考價(jià)值,需要的可以參考一下2023-12-12

