【问题标题】:Vue.js pass a callback as prop to child component and execute on parent when it is clickedVue.js 将回调作为 prop 传递给子组件,并在单击时在父组件上执行
【发布时间】:2020-07-13 18:21:15
【问题描述】:

我正在尝试创建一个下拉组件,它在其中接收各种数据并且列表项是动态构建的,但是我很难检测到对列表中任何项目的点击

父母

<Dropdown
  :items="[
    {
      text: 'Edit',
      icon: 'fal fa-edit',
      click: editFunction(id)
    },
    {
      text: 'Delete',
      icon: 'fal fa-trash-alt',
      click: deleteFunction(id)
    }
  ]"
/>

孩子Dropdown.vue

<template>
  <div class="dropdown">
    <a class="trigger">
      <i class="far fa-ellipsis-h"></i>
    </a>

    <ul class="items">
      <li v-for="(item, index) in items" :key="index" class="item">
        <a>
          <i :class="item.icon"></i>
          {{ item.text }}
        </a>
      </li>
    </ul>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
  props: {
    items: {
      type: Array,
      default: () => []
    }
  }
})
</script>

目前这种方式,只要创建父组件,就会执行editFunction(id)deleteFunction(id)方法。

我知道这是可能的,因为 vuetifyjs 就是这样做的,但我试图检查源代码,但一无所获。

【问题讨论】:

标签: javascript vue.js vue-component


【解决方案1】:

你想达到的可以通过

parent.vue 

<child-componet :parent-method="thisIsTheMethod" />

...

methods: {
      thisIsTheMethod()
           {
              //here it does something
           } 
     }

请注意,在 prop 内部传递的方法没有括号 (),因为您传递的是对它的引用。

要在子组件中使用它,请添加 ()

@click="parentMethod()"

回到你的例子,改变这个:

<Dropdown
  :items="[
    {
      text: 'Edit',
      icon: 'fal fa-edit',
      click: editFunction(id)
    },
    {
      text: 'Delete',
      icon: 'fal fa-trash-alt',
      click: deleteFunction(id)
    }
  ]"
/>

<Dropdown
  :items="[
    {
      text: 'Edit',
      icon: 'fal fa-edit',
      click: () => editFunction(10)
    },
    {
      text: 'Delete',
      icon: 'fal fa-trash-alt',
      click: () => deleteFunction(20)
    }
  ]"
/>

并保持您的 editFunction(id) 方法声明不变。参数将被自动注入。

尽管这种解决方案可行,但实现父母与孩子之间这种沟通的最佳方式是在孩子身上发出价值,然后倾听它

【讨论】:

  • @click="parentMethod()" recebo este erro parentMethod is not a function 可以显示它在子组件中的外观吗?此外,假设我正在创建用户列表,我将使用 v-for 构建一个列表,然后动态创建 &lt;Dropdown /&gt;,如果我没有将 id 作为参数传递,我怎么知道点击了哪个用户?
  • 必须在props中定义parentMethod
  • 您必须在孩子内部传递 id 参数。我写的
  • 编辑了你的答案,这样我们就可以在父组件中传递 id 参数,这样做是不切实际的
【解决方案2】:

有更好的方法可以做到,但你的想法应该如下:

Vue.component('dropdown', {
  template: '#dropdown-template',
  props: {
    items: {
      type: Array,
      default: () => []
    }
  }
})

new Vue({
  el: '#app',
  data() {
    return {
      users: [
        { id: 1, name: 'foo' },
        { id: 2, name: 'bar' },
      ]
    }
  },
  methods: {
    editFunction(id) {
      console.warn('edit item ' + id)
    },
    deleteFunction(id) {
      console.warn('delete item ' + id)
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
  <table border="1">
     <thead>
       <tr>
         <th>id</th>
         <th>name</th>
         <th>actions</tr>
       </tr>
    </thead>
    <tbody>
      <tr v-for="user in users" :key="user.id">
        <td>{{ user.id }}</td>
        <td>{{ user.name }}</td>
        <td>
            <dropdown
              :items="[
                {
                  text: 'Edit',
                  icon: 'fal fa-edit',
                  event: 'edit-function'
                },
                {
                  text: 'Delete',
                  icon: 'fal fa-trash-alt',
                  event: 'delete-function'
                }
              ]"
              @edit-function="editFunction(user.id)"
              @delete-function="deleteFunction(user.id)"     
            />
        </td>
      </tr>
    </tbody>
  </table>
</div>

<script type="text/x-template" id="dropdown-template">
<div class="dropdown">
  <a class="trigger">
    <i class="far fa-ellipsis-h"></i>
  </a>

  <ul class="items">
    <li v-for="(item, index) in items" :key="index" class="item">
      <a @click="$emit(item.event)">
        <i :class="item.icon"></i>
        {{ item.text }}
      </a>
    </li>
  </ul>
</div>
</script>

【讨论】:

  • 我猜范围插槽应该是正确的方式
猜你喜欢
  • 2016-12-13
  • 2020-07-23
  • 2020-08-11
  • 2020-11-01
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
  • 2017-11-07
  • 2018-11-30
相关资源
最近更新 更多