做者:Joshua Bemenderfe前端
譯者:前端小智vue
來源:vuejsbook.comgit
點贊再看,養成習慣github
本文
GitHub
github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。面試
咱們知道 Vue 模板是很是強大的,基本能夠完成咱們平常開發的全部任務。可是,有一些用例,如基於輸入或插槽值建立動態組件方式,render
函數會比模板完成的更好也更出色。數組
用過 React 開發的人對 render
函數應該很是熟悉,由於React組件經過 JSX和 render 函數來構建的。 儘管Vue render
函數也能夠用JSX編寫,但在這裏咱們使用原生 JS方式,由於這樣,咱們能夠更輕鬆地瞭解Vue組件系統的一些基礎。bash
值得注意的是,Vue 的模板實際上在編譯時也是會先解析成 render
函數表示方式。 模板只是在render
函數之上提供了一個方便且熟悉的語法糖。 儘管 render
函數更強大,但render
函數可讀性不好,相對用的也比較少了。微信
帶有 render
函數的組件沒有template
標記或屬性。 相反,該組件定義了一個了名爲render
的函數,該函數接收一個reateElement(renderElement: String | Component, definition: Object, children: String | Array)
參數(因爲某種緣由,一般別名爲h
,歸咎於JSX)並返回使用該函數建立的元素,其餘一切保持不變,來看看事例:dom
export default {
data() {
return {
isRed: true
}
},
/*
* <template>
* <div :class="{'is-red': isRed}">
* <p>這是一個 render 事例</p>
* </div>
* </template>
*/
// render 中的渲染結果與上面等價
render(h) {
return h('div', {
'class': {
'is-red': this.isRed
}
}, [
h('p', '這是一個 render 事例')
])
}
}
複製代碼
Vue 模板具備各類便捷功能,以便向模板添加基本邏輯和綁定功能,如 v-if
、v-for
、v-moel
指令等。 在render
函數中是沒法使用這些指令的。 取而代之的是以純 JS 來實現,對於大多數指令而言,這也是比較簡單的。函數
v-if
用純 JS 實現很簡單,只需圍繞createElement
調用使用 if(expr)
語句便可。
v-for
可使用for-of
,Array.map
,Array.filter
等的JS方法中的任何一種來實現。咱們能夠經過很是有趣的方式將它們組合在一塊兒,以實現過濾或狀態切片,而無需計算屬性。
例如,有如下 Vue 的模板代碼
<template>
<ul>
<li v-for="pea of pod">
</li>
</ul>
</template>
複製代碼
能夠用下面的 render
函數來實現上面的效果:
render(h) {
return h('ul', this.pod.map(pea => h('li', pea.name)));
}
複製代碼
咱們知道,v-model
只是bind
屬性與value
的語法糖,並在觸發input
事件時設置數據屬性。可是,在render
函數沒有這樣的簡寫,咱們須要本身實現。
假設,在 Vue 中,咱們有以下的結構:
<template>
<input v-model='myBoundProperty'/>
</template>
複製代碼
上面代碼等價於:
<template>
<input :value="myBoundProperty" @input="myBoundProperty = $event.target.value"/>
</template>
複製代碼
在 render 函數中能夠用下面方式來實現上面的代碼:
render(h) {
return h('input', {
domProps: {
value: this.myBoundProperty
},
on: {
input: e => {
this.myBoundProperty = e.target.value
}
}
})
}
複製代碼
attribute
和property
這兩種類型的綁定被放在元素定義中,如arttrs
、props
和domProps
( value
和innerHTML
之類的東西)。
render(h) {
return h('div', {
attrs: {
// <div :id="myCustomId">
id: this.myCustomId
},
props: {
// <div :someProp="someonePutSomethingHere">
someProp: this.someonePutSomethingHere
},
domProps: {
// <div :value="somethingElse">
value: this.somethingElse
}
});
}
複製代碼
須要注意的是,對於 class
和style
的綁定是直接在定義的根進行處理,而不是做爲attrs
,props
或domProps
處理。
render(h) {
return h('div', {
// 「類」是JS中的保留關鍵字,所以必須引用它。
'class': {
myClass: true,
theirClass: false
},
style: {
backgroundColor: 'green'
}
});
}
複製代碼
對事件處理程也是直接添加到元素定義中 on
定義
render(h) {
return h('div', {
on: {
click(e) {
console.log('I got clickeded!')
}
}
});
}
複製代碼
事件的修飾符能夠在處理程序內部實現:
.stop -> e.stopPropagation()
.prevent -> e.preventDefault()
.self -> if (e.target !== e.currentTarget) return
鍵盤修飾符
.[TARGET_KEY_CODE]
-> if (event.keyCode !== TARGET_KEY_CODE) return
.[MODIFIER]
-> if (!event.MODIFIERKey) return
Slots
能夠經過this.$slots
做爲createElement()
節點的數組來訪問插槽。
做用域插槽存儲在this.$scopedSlots[scope](props:object)
中,做爲返回createElement()
節點數組的函數。
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。
文章每週持續更新,能夠微信搜索「 大遷世界 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub github.com/qq449245884… 已經收錄,整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,另外關注公衆號,後臺回覆福利,便可看到福利,你懂的。