Vue中 render 函式應用
阿新 • • 發佈:2020-12-06
前言
因為最近接手維護一個基於 ivew 的專案, 新增模組中包含很多自定義功能, 所以大量使用到了 render函式; 故對其做一下總結...關於 render函式, 官方文件也做了比較詳細的介紹:render 函式:https://cn.vuejs.org/v2/guide...; 一般元件我們都是用 template模板的方式去寫; 有時候會造成程式碼上的冗餘, 不好擴充套件.
瞭解 render 函式
在學習 render 函式之前, 最好先了解一下虛擬節點 vNode, 以及虛擬節點樹組成的虛擬vDom, 這樣會更好的理解 render 函式
/*
*@describe {渲染函式}
*@params {見下方}
*@returns {一段VNode}
*/
createElement函式: 通常寫為 h 函式, 也是官方推薦的
h(
// {String | Object | Function} => 'p' | 'Select' | (h, p) => {}
// 一個 html 標籤名、元件選項物件,或者
// resolve 了上述任何一種的一個 async 函式。必填項。
'div',
// {Object}
// 一個與模板中屬性對應的資料物件。可選。
{
style: {
width: '100px'
},
},
// {String | Array}
// 子級虛擬節點 (VNodes),一般是陣列: 由 `h()` 構建而成,引數: ('標籤|元件', {attrs}, text)
// 也可以使用字串來生成“文字虛擬節點”。可選。
[
'先寫一些文字',
h('h1', '一則頭條'),
h(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)
render 函式應用1: 函式式元件
函式式元件 可以看做是元件裡的一個函式,入參是渲染上下文(render context),返回值是渲染好的html字串
對於函式式元件,可以這樣定義:
Stateless(無狀態):元件自身是沒有狀態的
Instanceless(無例項):元件自身沒有例項,也就是沒有this
由於函式式元件中沒有this,引數需要靠context來傳遞;
export default {
name: 'functional-button',
functional: true,
render (h, context) {
return h('button', '按鈕 1 號')
}
}
由官方文件可知: context 引數如下:
props:提供所有 prop 的物件
children: VNode 子節點的陣列
slots: 一個函式,返回了包含所有插槽的物件
scopedSlots: (2.6.0+) 一個暴露傳入的作用域插槽的物件。也以函式形式暴露普通插槽。
data:傳遞給元件的整個資料物件,作為 createElement 的第二個引數傳入元件
parent:對父元件的引用
listeners: (2.3.0+) 一個包含了所有父元件為當前元件註冊的事件監聽器的物件。這是data.on 的一個別名。
injections: (2.3.0+) 如果使用了 inject 選項,則該物件包含了應當被注入的屬性。
使用函式式元件
<template>
<div class="home">
<func-button>
hello button
</func-button>
</div>
</template>
<script>
import FuncButton from '../function-components/func-button'
export default {
name: 'home',
components: {
FuncButton
}
}
</script>
現在我們將這個 func-button.js元件改造一下, 上面的hello button 文字節點為func-button.js的childern屬性(陣列|String),我們可以讓父元件去控制組件的button按鈕內容, 改寫如下:
// export default {
// name: 'functional-button',
// functional: true,
// render (h, context) {
// return h('button', '按鈕 1 號')
// }
// }
export default {
name: 'funtional-button',
functional: true,
render (h, { children }) {
return h('button', children)
}
}
如何新增事件呢?
code如下:
<template>
<div class="home">
<func-button @click="handleClick">
hello button
</func-button>
</div>
</template>
<script>
import FuncButton from '../function-components/func-button'
export default {
name: 'home',
components: {
FuncButton
},
methods: {
handleClick () {
alert('你點到我了')
}
}
}
</script>
// func-button元件
export default {
functional: true,
// 元件的屬性整合在data裡, 為了簡便,我們可以用 data 來替換下面的 props, listeners等
// 寫成 h('button', data, ['hello', ...children])
render (h, { props, listeners, children }) {
return h(
'button',
{
attrs: props,
on: {
click: listeners.click
}
},
children
)
}
}
render 函式應用2: JSX語法
平時開發還是多用temlate因為直觀簡潔,各種指令用著很方便,但是經常寫template有時會覺得程式碼看著很冗餘,如果想自己控制渲染邏輯比如循,判斷等等時我們就可以考慮使用JSX
<script>
export default {
name: 'h-title',
props: {
id: {
type: Number,
default: 1
}
},
render () {
const hText = `<h${this.id}>${this.$slots.default[0].text}</h${this.id}>`
return <div domPropsInnerHTML={hText}></div>
}
}
</script>
資源搜尋網站大全 https://www.renrenfan.com.cn 廣州VI設計公司https://www.houdianzi.com
render 函式應用 3: 定製化元件
// List.vue 元件
<template>
<div>
<template v-for="(item, index) in data">
<li :key="index" v-if="!render">{{ item }}</li>
<ListItem
v-else
:key="`a${index}`"
:render="render"
:item="item"
></ListItem>
</template>
</div>
</template>
<script>
import ListItem from "./list-item"
export default {
components: {
ListItem
},
props: {
// 支援自定義渲染
render: {
type: Function
},
data: {
type: Array,
default: () => []
}
}
};
</script>
// list-item.js
export default {
props: {
render: {
type: Function
},
item: {
type: String
}
},
render(h) { // createElement
return this.render(h, this.item)
}
}
// 父元件中
<List :data="['香蕉','蘋果','橘子']" :render="render"></List>
// 可以渲染你想要的標籤和內容
render (h, data) {
return <span>{data}</span>
}