咱們接着上篇學習完render
函數,下面咱們來看下Vue
中的函數式組件 這也是Vue
進階中一個重要的知識點,下面咱們一塊兒來學習下吧(我也不是很熟😄,有錯誤就請指正)javascript
咱們先封裝一個簡單的組件,叫作list
html
代碼以下:vue
<template>
<ul>
<li v-for="(item, index) in list" :key="`item_${index}`"></li>
</ul>
</template>
<script>
export default {
name: 'List',
props: {
list: {
type: Array,
default: () => []
}
}
}
</script>
複製代碼
簡單封裝後,裏面li
裏面的內容咱們先無論!java
咱們再新建一個叫作render
的組件 咱們把剛剛的list
組件引入到render
組件裏bash
<template>
<div>
<list :list="list"></list>
</div>
</template>
<script>
import List from '../component/list'
export default {
data () {
return {
list: [
{ name: lili},
{ name: Dreams}
]
}
},
components: {
List
}
}
</script>
複製代碼
接下來,咱們回到list
組件裏完善下li
標籤裏面的內容dom
<li v-for="(item, index) in list" :key="`item_${index}`">
<span>{{ item.name }}</span>
</li>
複製代碼
這樣咱們就把剛剛render
組件裏傳遞進來的list
數據給list
組件使用而且渲染出了名字,這裏咱們用span
標籤包裹了,那麼若是咱們想更多的讓用戶個性化,好比用戶想用什麼標籤包裹就用什麼標籤包裹,怎麼作呢?函數
那麼這裏咱們就可使用render
函數,而後讓用戶經過render
函數本身去定義,來看下怎麼寫學習
這裏咱們回到render
組件,把render
函數經過v-bind
傳遞到list
裏去字體
render組件的代碼:
<template>
<div>
<list :list="list" :render="renderFunc"></list>
</div>
</template>
<script>
import List from '../component/list'
export default {
data () {
return {
list: [
{ name: lili},
{ name: Dreams}
]
}
},
components: {
List
},
methods:{
renderFunc(h){
return h('i',{
style:{
color:'pink'
}
},'???')
}
}
}
</script>
複製代碼
上面咱們想使用i標籤包裹,且字體顏色爲粉紅色,但這裏咱們打問號的地方他的值是多少呢?怎麼來呢,由於list
中他是經過v-for
循環的, 那麼咱們想知道當前循環的這個值是多少,那麼這裏咱們就要用到一個組件叫作:函數式組件ui
那麼接着上面,咱們先建立一個render-dom.js
代碼以下
export default {
functional: true,//必須這樣寫纔是一個函數式組件
props: {
name: String,
renderFunc: Function
},
render: (h, ctx) => {
//???
}
}
複製代碼
那麼有人會問了,函數式組件有什麼做用?
通常而言,咱們只給它傳入一些數據,它不作任何響應式的操做,不監聽傳遞給他的狀態,它也沒有生命週期,它只是一個接收參數的函數,當設置functional
爲true
時,它是一個沒有狀態的組件,可是當你把他引入到其餘vue組件中去用的時候,vue
會把它作相關處理,上面咱們寫了一個render
函數,vue
會用render
函數裏的邏輯,把裏面返回的節點作渲染!
接着咱們回到list
組件,在props
裏接收父組件(render組件)傳遞過來的render
函數
props處新增代碼:
render: {
type: Function,
default: () => {}
}
複製代碼
接下來,咱們把函數式組件再完善下
把剛剛render
方法裏的邏輯完善下就是
render: (h, ctx) => {
return ctx.props.renderFunc(h,ctx.props.name)
}
複製代碼
返回的render
其實就是用戶傳進來的那個render
ctx
他其實就指代當前的上下文,那麼咱們就能夠用ctx
獲取到屬性裏的renderFunc
接下來繼續到list
組件裏使用renderDom函數式組件
模板中新增:
<li v-for="(item, index) in list" :key="`item_${index}`"> <span v-if="!render">{{ item.number }}</span> <render-dom v-else :render-func="render" :name="item.name"></render-dom> </li> script引入: import RenderDom from '../component/render-dom' components: { //註冊組件 RenderDom }, 複製代碼
這裏邏輯就是若是用戶傳入了render,咱們就是用傳入的render渲染,不然默認span
接下來咱們回到render組件裏把剛剛的render函數完善下:
renderFunc(h,name){
return h('i',{
style:{
color:'pink'
}
},name)
}
複製代碼
那麼這裏的name其實就是函數式組件返回的name,因此這裏咱們直接使用name
那麼這樣咱們就完成了可讓用戶本身定義這個文字該怎麼樣展示!render配合函數式組件就是這麼靈活!
那麼你們應該也發現了,render加函數式組件其實很是繁瑣!那麼有沒有什麼東西能夠簡化呢? 實際上是有的,那就是JSX!
JSX是React最早提出的,那麼後來Vue也作了相關支持!他的本質其實就是在js中寫html標籤和一些特定的語法,最終呢他會把jsx轉換成render函數去渲染。
接下來咱們回到render組件裏把剛剛的render函數修改下:
以前template是這樣的:
<list :list="list" :render="renderFunc"></list>
以前js是這樣的:
renderFunc(h,name){
return h('i',{
style:{
color:'pink'
}
},name)
}
修改以後的template:
<list :list="list" :render="renderFunc" :style="{color:'red'}"></list>
修改以後的js:
renderFunc(h,name){
return (
<i style={{color:'red'}}>{name}</i>
)
}
複製代碼
這裏要注意了,在jsx中,變量要用花括號包起來!裏面是一個對象,而後又有一個花括號.由於name也是變量,因此也須要使用花括號包起來!
這樣就完成了和剛剛render函數同樣的功能!
若是咱們想給i標籤綁定一個事件,咱們應該怎麼綁定?
methods:{
renderFunc(h,name){
return (
<i on-click={this.handleClick} style={{color:'red'}}>{name}</i>
)
},
handleClick(event){
console.log(event)
}
}
複製代碼
這裏還要注意,綁定事件必須是on-
開頭
那麼普通的渲染標籤咱們會了,那麼若是渲染一個組件呢?
那麼這裏假設咱們這裏有一個組件CountTo(看過上上篇文章的小夥伴應該知道)組件
咱們把他引入到render組件(看過上篇文章的小夥伴應該知道這個組件)中.再寫一遍!
咱們這裏須要修改以前的一些代碼:
render組件中修改後的:(函數式組件和list裏須要作一部分修改,我相信你們能夠的,就不羅列相關代碼了)
<template>
<div>
<list :list="list" :style="{color: 'red'}"></list>
</div>
</template>
<script>
import List from '_c/list'
import CountTo from '_c/count-to'
export default {
data () {
return {
list: [
{ number: 100 },
{ number: 45 }
]
}
},
components: {
List
},
methods: {
renderFunc (h, number) {
return (
<CountTo nativeOn-click={this.handleClick} on-on-animation-end={this.handleEnd} endVal={number} style={{color: 'pink'}}></CountTo>
)
},
handleClick (event) {
// console.log(event)
},
handleEnd () {
// console.log('end!')
}
}
}
</script>
複製代碼
咱們若是是在render或者jsx裏寫的組件是不須要進行註冊的!
那麼這裏咱們也使用了JSX作了相同的事情。其實這裏還可使用做用域插槽作一樣的事情,這篇文章咱們主要講JSX和函數式組件,因此就再也不舉插槽相關的代碼哦,有興趣的能夠下去本身試試!
本篇文章咱們一塊兒學習了render+函數式組件,最終咱們完成了以前的需求,但過程仍是比較繁瑣的,結尾咱們也提到了JSX的解決方案, 感興趣的小夥伴能夠關注我,你們一塊兒學習vue中比較難理解的知識點哦!
各位大佬,若是發現文中的錯誤,請指正,我會及時修改!
感謝大佬們能在百忙中能閱讀完這篇文章!
相信你們看完這篇文章後再去看vue文檔就不會以爲那麼吃力了!你們共勉!