关于 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传递一个带参的方法给子组件。

相关文章
相关标签/搜索