關於 Vue render jsx 與 template 的實踐總結

場景

iview Table 單元格數據是一個下拉選擇框vue

起初直接 render 了一個通過二次封裝的 iview Dropdown 組件,在接入後臺數據後發現-等待請求返回數據形成必定時間延緩而不能正常 render 這個組件,因此又考慮採用 template 的寫法,結果就出現參數 undefined 的問題:bash

(最後發現直接在 Table 上綁定 vif ,等數據請求完後再渲染整個 Table 也行)iview

render jsx 寫法ide

template 寫法:測試

問題分析

進行 template 寫法測試過程當中發現,父組件方法 handleChangeCharac 不能正常獲取到下拉列表的 name 值,但在子組件 handleCommand 中是能獲取到的,就產生疑問:爲何 render 中沒有出現這個 undefined 問題呢?ui

因而回到封裝組件 xz-dropdown 裏面看邏輯,簡單點說 Dropdown 提供了一個 @on-click 方法返回當前點擊下拉列表的 name 值,我用 handleDropDown 接受這個 name並傳給了一個類型爲 Functionprop : handleCommandthis

// xz-dropdown.vuespa

解決方案

再次理清了一下流程, xz-dropdown 中觸發 handleDropDown 方法並傳 namehandleCommand,並同時調用 父組件的 handleChangeCharac 方法 , 這時 handleCommand 才能接收 name, 以上調用封裝組件的寫法是有問題的,父組件中應改寫成3d

父組件調用:code

<template slot-scope="{ row }" slot="roleName">
        <xz-dropdown
            :title="row.roles[0].roleName"
            class="charac-type-btn"
            :transferDom="true"
            :handleCommad="handleChangeCharac"                  // 更改
            :commands="characCommands"
        ></xz-dropdown>
    </template>
複製代碼

結果:

此時父組件中是能接收到 name, 可是我還必須獲取到 當前的行數據row, 若是直接在上面基礎上寫 :handleCommand="handleChangeCharac(row)" 這時是會覆蓋 name 結構仍是隻能操做一個對象而不是兩個。

進而應該審視一下 xz-dropdown 中的邏輯代碼,看是否可以改善以上的問題,父子組件通訊中經常使用的方式除了 prop外,還有$emit,因而開始邏輯修改:(採用$emit)

xz-dropdown.vue:

// template
    <Dropdown
      trigger="click"
      @on-click="handleOnClick"           // 更改
      :transfer="transferDom"
      @on-clickoutside="handleClickOutside"
    >
// js
methods: {
    
}
複製代碼

父組件:

<template slot-scope="{ row }" slot="roleName">
        <xz-dropdown
            :title="row.roles[0].roleName"
            class="charac-type-btn"
            :transferDom="true"
            @handle-on-click="handleChangeCharac($event, row)"                // 更改
            :commands="characCommands"
        ></xz-dropdown>
    </template>
複製代碼

點擊目標後(順序是先觸發xz-dropdown 中的 handleOnClick 接着觸發父組件的 handleChangcharac

這樣就能實現個人需求,同時獲取到 namerow

回顧緣由

致使出現問題的緣由:子組件中經過自定義方法傳一個參給類型爲functionprop,此處纔是調用該方法的地方,若是須要增長參數個數,也應該在此處增長。這種狀況下父組件觸發是可以獲取到該參數(這種方式有點相似於子組件$emit出一個參數給父組件),卻混淆了$emitprop的使用結果,

若是要堅持用prop的方式並達到需求,就須要更改邏輯爲:

xz-dropdown.vue:

// template 
    <Dropdown
      trigger="click"
      @on-click="handleDropDown($event, item)"
      :transfer="transferDom"
      @on-clickoutside="handleClickOutside"
    >
    
// js 
    props: {
        item: {                            // 添加
            type: Object
        },
        handleCommand: {
            type: Function
        }
    },
    methods: {
        handleDropDown(name, item) {          // 添加
            this.handleCommand(name, item)
        }
    }
複製代碼

父組件:

<template slot-scope="{ row }" slot="roleName">
        <xz-dropdown
            :title="row.roles[0].roleName"
            class="charac-type-btn"
            :transferDom="true"
            :item="row"                                       // 添加
            :handleCommad="handleChangeCharac($event, row)"
            :commands="characCommands"
        ></xz-dropdown>
    </template>
複製代碼

爲何 render的寫法可以避免出現這種問題呢? 其實就是這裏起了做用

傳給 handleCommand的一個方法裏面得到了 name, 再將 name 傳給了 handleChangeCharac的同時, handleChangeCharac也得到了第二個參數 row, 這偏偏是 render寫法的好處

它等價於:

handkeCommand={this.funtionA}

functionA(name) {
    this.handleChangeCharac(name)
}
複製代碼

而普通的template寫法是不能同時得到上文的row

總結

使用vue過程當中常常出現父子組件數據傳遞的現象,而prop$emit又是實現這種需求較爲經常使用的方法,這次使用prop達到了必定的$emit效果,但也出現了弊端,混淆了對prop$emit的理解,是不能經過prop傳遞一個帶參的方法給子組件。

相關文章
相關標籤/搜索