Vue render深入開發(fā)講解
簡介
在使用Vue進行開發(fā)的時候,大多數(shù)情況下都是使用template進行開發(fā),使用template簡單、方便、快捷,可是有時候需要特殊的場景使用template就不是很適合。因此為了很好使用render函數(shù),我決定深入窺探一下。各位看官如果覺得下面寫的有不正確之處還望看官指出,你們與我的互動就是寫作的最大動力。
場景
官網(wǎng)描述的場景當我們開始寫一個通過 level prop 動態(tài)生成 heading 標簽的組件,你可能很快想到這樣實現(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
}
}
})
在這種場景中使用 template 并不是最好的選擇:首先代碼冗長,為了在不同級別的標題中插入錨點元素,我們需要重復地使用 <slot></slot>。
雖然模板在大多數(shù)組件中都非常好用,但是在這里它就不是很簡潔的了。那么,我們來嘗試使用 render 函數(shù)重寫上面的例子:
Vue.component('anchored-heading', {
render: function (createElement) {
return createElement(
'h' + this.level, // tag name 標簽名稱
this.$slots.default // 子組件中的陣列
)
},
props: {
level: {
type: Number,
required: true
}
}
})
簡單清晰很多!簡單來說,這樣代碼精簡很多,但是需要非常熟悉 Vue 的實例屬性。在這個例子中,你需要知道當你不使用 slot 屬性向組件中傳遞內(nèi)容時,比如 anchored-heading 中的 Hello world!,這些子元素被存儲在組件實例中的 $slots.default中。
createElement參數(shù)介紹
接下來你需要熟悉的是如何在 createElement 函數(shù)中生成模板。這里是 createElement 接受的參數(shù):
createElement(
// {String | Object | Function}
// 一個 HTML 標簽字符串,組件選項對象,或者
// 解析上述任何一種的一個 async 異步函數(shù),必要參數(shù)。
'div',
// {Object}
// 一個包含模板相關屬性的數(shù)據(jù)對象
// 這樣,您可以在 template 中使用這些屬性。可選參數(shù)。
{
// (詳情見下一節(jié))
},
// {String | Array}
// 子節(jié)點 (VNodes),由 `createElement()` 構(gòu)建而成,
// 或使用字符串來生成“文本節(jié)點”。可選參數(shù)。
[
'先寫一些文字',
createElement('h1', '一則頭條'),
createElement(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)
深入 data 對象
有一件事要注意:正如在模板語法中,v-bind:class 和 v-bind:style ,會被特別對待一樣,在 VNode 數(shù)據(jù)對象中,下列屬性名是級別最高的字段。該對象也允許你綁定普通的 HTML 特性,就像 DOM 屬性一樣,比如 innerHTML (這會取代 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` 修飾器
// 需要手動匹配 keyCode。
on: {
click: this.clickHandler
},
// 僅對于組件,用于監(jiān)聽原生事件,而不是組件內(nèi)部使用
// `vm.$emit` 觸發(fā)的事件。
nativeOn: {
click: this.nativeClickHandler
},
// 自定義指令。注意,你無法對 `binding` 中的 `oldValue`
// 賦值,因為 Vue 已經(jīng)自動為你進行了同步。
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接下來咱們就來點實戰(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?。。?lt;/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 時template內(nèi)必須被一個標簽包裹
//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>',錯誤
});
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 的完全編程的能力,在性能上是占用絕對的優(yōu)勢,小編只是對它進行剖析。至于實際項目你選擇那種方式進行渲染依舊需要根據(jù)你的項目以及實際情況而定。
- 基于vue2.0動態(tài)組件及render詳解
- vue iview組件表格 render函數(shù)的使用方法詳解
- Vue中render函數(shù)的使用方法
- Vue中render方法的使用詳解
- 詳解vue渲染函數(shù)render的使用
- 淺談vue的iview列表table render函數(shù)設置DOM屬性值的方法
- 如何理解Vue的render函數(shù)的具體用法
- vue Render中slots的使用的實例代碼
- 深入理解vue Render函數(shù)
- vue深入解析之render function code詳解
- 了解VUE的render函數(shù)的使用
- Vue2.x中的Render函數(shù)詳解
- Vue.js render方法使用詳解
相關文章
VUE element上傳動態(tài)設置action路徑和參數(shù)的坑及解決
這篇文章主要介紹了VUE element上傳動態(tài)設置action路徑和參數(shù)的坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
vue3+vite中報錯信息處理方法Error: Module “path“ has&nb
這篇文章主要介紹了vue3+vite中報錯信息處理方法Error: Module “path“ has been externalized for browser compatibility...,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03
VUE3開箱即用的音頻播放組件完整代碼(基于原生audio)
Vue3開箱即用的框架有很多選擇,下面這篇文章主要介紹了VUE3開箱即用的音頻播放組件(基于原生audio)的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-09-09

