開開森森學前端之函數式組件和JSX

前言

咱們接着上篇學習完render函數,下面咱們來看下Vue中的函數式組件 這也是Vue進階中一個重要的知識點,下面咱們一塊兒來學習下吧(我也不是很熟😄,有錯誤就請指正)javascript

組件封裝階段

咱們先封裝一個簡單的組件,叫作listhtml

代碼以下: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) => {
    //???
  }
}
複製代碼

那麼有人會問了,函數式組件有什麼做用?

通常而言,咱們只給它傳入一些數據,它不作任何響應式的操做,不監聽傳遞給他的狀態,它也沒有生命週期,它只是一個接收參數的函數,當設置functionaltrue時,它是一個沒有狀態的組件,可是當你把他引入到其餘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

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文檔就不會以爲那麼吃力了!你們共勉!

相關文章
相關標籤/搜索