scenario

Iview Table cell data is a drop-down selection box

At first, I directly render a secondary encapsulated iView Dropdown component. After accessing background data, I found that waiting for the request to return data caused a certain delay and could not render the component normally, so I considered using template writing method. The result is undefined:

(Finally, it is found that it is ok to bind vif directly to the Table and render the whole Table after the data request is finished.)

Render JSX

The template of writing:

Problem analysis

In the template writing test, it is found that the parent component method handleChangeCharac cannot obtain the name value of the drop-down list normally, but the child component handleCommand can obtain the name value, so there is a question: Why is this undefined problem not present in render?

Dropdown provides a @on-click method that returns the name value of the current drop-down list. I accept this name with handleDropDown and pass it to a prop: handleCommand of type Function

// xz-dropdown.vue

The solution

Xz-dropdown triggers handleDropDown and passes name to handleCommand. The handleChangeCharac method of the parent component is also called. Then the handleCommand can receive the name

Parent component call:

    <template slot-scope="{ row }" slot="roleName">
        <xz-dropdown
            :title="row.roles[0].roleName"
            class="charac-type-btn"
            :transferDom="true"
            :handleCommad="handleChangeCharac"/ / change: commands ="characCommands"
        ></xz-dropdown>
    </template>
Copy the code

Results:

Now the parent component can receive the name, but I also have to get the current row, HandleCommand =”handleChangeCharac(row)” would that override the name structure or operate on only one object instead of two?

In addition to prop, there is also a common way for parent/child component communication to emit $emit.

xz-dropdown.vue:

// template
    <Dropdown
      trigger="click"
      @on-click="handleOnClick"/ / change: transfer ="transferDom"
      @on-clickoutside="handleClickOutside"
    >
// js
methods: {
    
}
Copy the code

The parent component:

    <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)"/ / change: commands ="characCommands"
        ></xz-dropdown>
    </template>
Copy the code

After clicking on the target, handleOnClick in xZ-Dropdown is triggered and handleChangcharac in the parent component is triggered

name
row

Review the reason

The reason for the problem is that a custom method is passed in the child component to prop of type function. This is where the method is called. If you need to increase the number of parameters, you should also increase it here. In this case, the parent component fires to fetch this parameter (similar to the way that the child $emit emits a parameter to the parent component), but confuses the result of using $emit and prop.

If you want to stick with prop and meet the requirements, you need to change the logic to:

xz-dropdown.vue:

// template 
    <Dropdown
      trigger="click"
      @on-click="handleDropDown($event, item)"
      :transfer="transferDom"
      @on-clickoutside="handleClickOutside"> // js props: {item: {// Addtype: Object
        },
        handleCommand: {
            typeHandleDropDown (name, item) {// Add this.handlecommand (name, item)}}Copy the code

The parent component:

    <template slot-scope="{ row }" slot="roleName">
        <xz-dropdown
            :title="row.roles[0].roleName"
            class="charac-type-btn"
            :transferDom="true"
            :item="row"/ / add: handleCommad ="handleChangeCharac($event, row)"
            :commands="characCommands"
        ></xz-dropdown>
    </template>
Copy the code

Why does render avoid this problem? This is actually where it works

handleCommand
name
name
handleChangeCharac
handleChangeCharac
row
render

It is equivalent to:

handkeCommand={this.funtionA}

functionA(name) {
    this.handleChangeCharac(name)
}
Copy the code

The normal template script does not get both rows

conclusion

In the process of using VUE, father-child component data transfer often occurs, and prop and $emit are common methods to realize this requirement. This time, prop has achieved a certain $EMIT effect, but there are drawbacks, such as confusing the understanding of prop and $emit. It is not possible to pass a parameterized method to a child component through prop.