vue的render函數(Vue.js 2.X支持)
- render函數的作用:render 函數 跟 template 一樣都是創建 html 模板的,但是有些場景中用 template 實現起來代碼冗長繁瑣而且有大量重複,這時候就可以用 render 函數。
- render方法的實質就是生成template模板;
- 通過調用一個方法來生成,而這個方法是通過render方法的參數傳遞給它的;
- 這個方法有三個參數,分別提供標籤名,標籤相關屬性,標籤內部的html內容
- 通過這三個參數,可以生成一個完整的模板
render方法可以使用JSX語法,但需要Babel plugin插件;
render方法裏的第三個參數可以使用函數來生成多個組件(特別是如果他們相同的話),只要生成結果是一個數組,且數組元素都是VNode即可;
- 因爲vue是虛擬DOM,所以在拿到template模板時也要轉譯成VNode的函數,而用render函數構建DOM,vue就免去了轉譯的過程。當使用render函數描述虛擬DOM時,vue提供一個函數,這個函數是就構建虛擬DOM所需要的工具。官網上給他起了個名字叫createElement。還有約定的簡寫叫h。
// @returns {VNode}
createElement(
// {String | Object | Function}
// 一個 HTML 標籤字符串,組件選項對象,或者
// 解析上述任何一種的一個 async 異步函數,必要參數。
'div',
// {Object}
// 一個包含模板相關屬性的數據對象
// 這樣,您可以在 template 中使用這些屬性。可選參數。
{
// (詳情見下一節)
},
// {String | Array}
// 子節點 (VNodes),由 `createElement()` 構建而成,
// 或使用字符串來生成“文本節點”。可選參數。
[
'先寫一些文字',
createElement('h1', '一則頭條'),
createElement(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)
createElement(params1,params2,params3)接受三個參數
第一個參數(必要參數):主要用於提供DOM的html內容,類型可以是字符串、對象或函數
第二個參數(類型是對象,可選):用於設置這個DOM的一些樣式、屬性、傳的組件的參數、綁定事件之類
第三個參數(類型是數組,數組元素類型是VNode,可選):主要是指該結點下還有其他結點,用於設置分發的內容,包括新增的其他組件。注意,組件樹中的所有VNode必須是唯一的
render函數的用法:
render:(h) => {
return h('div',{
//給div綁定value屬性
props: {
value:''
},
//給div綁定樣式
style:{
width:'30px'
},
//給div綁定點擊事件
on: {
click: () => {
console.log('點擊事件')
}
},
})
}
擴展:
{
// 和`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'
},
// 事件監聽器基於 `on`
// 所以不再支持如 `v-on:keyup.enter` 修飾器
// 需要手動匹配 keyCode。
on: {
click: this.clickHandler
},
// 僅對於組件,用於監聽原生事件,而不是組件內部使用
// `vm.$emit` 觸發的事件。
nativeOn: {
click: this.nativeClickHandler
},
// 自定義指令。注意,你無法對 `binding` 中的 `oldValue`
// 賦值,因爲 Vue 已經自動爲你進行了同步。
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'
}
render函數中,函數可包含函數
例如:
render: function (h, params) { (h是createElement函數的簡寫)
return h('div', [
h('Button', {
props: {
type: 'primary',
size: 'small'
},
style: {
marginRight: '8px'
},
on: {
click: function () {
mCheck.singleShow(params.row);
}
}
}, '查看'),
h('Button', {
props: {
type: 'error',
size: 'small'
},
on: {
click: function () {
mCheck.singleDel(params.row, params.index);
}
}
}, '刪除')
]);
}
- 在iview中使用:
<Table width="100%" stripe :columns="tableColumns" :data="tableData"></Table>
{
title: "操作",
align: "center",
width: 200,
render: (h, params) => {
return h("div", [
h(
"Button", {
props: {
type: "text",
size: "small"
},
style: {
backgroundColor: "#2db7f5",
color: "#fff",
marginRight: "5px"
},
on: {
click: () => {
parentObj.$router.push({
name: 'equipmentdetail',
params:{
from: parentObj.$route.name,
item: params.row
}
})
}
}
},
"詳情"
),
h(
"Button", {
props: {
type: "text",
size: "small"
},
style: {
backgroundColor: " #19be6b",
color: "#fff",
marginRight: "5px"
},
on: {
click: () => {
parentObj.$router.push({
name: 'editequipment',
params:{
item: params.row
}
})
}
}
},
"修改"
)
}
在element中使用
<el-table-column
:render-header="item.renderHeaderFuc"
v-for="(item,index) in tableColumns"
:key="index"
:prop="item.prop"
:align="item.align"
:minWidth="item.minWidth"
:label="item.label"
>
</el-table-column>
renderHeaderFuc: (h,params)=> {
console.log(h,params)
return h('div',[
h('button', {
props:{
type: "primary",
size: "small"
},
style:{
},
on:{
click: ()=>{
this.$router.push({
name:'tradecustomeredit',
params: {
tradecustomer: params,
}
})
}
}
},'編輯')
])
}
在element中使用時控制檯會報一個警告,
[Element Warn][TableColumn]Comparing to render-header, scoped-slot header is easier to use. We recommend users to use scoped-slot header,與render-header相比,作用域槽頭更易於使用。我們建議用戶使用範圍槽頭,所以建議使用插槽來寫