Vue. js передать обратный вызов как опору дочернему компоненту и выполнить для родительского компонента при нажатии на него - PullRequest
0 голосов
/ 13 июля 2020

Я пытаюсь создать раскрывающийся компонент, в котором он получает различные данные, а элементы списка создаются динамически, но мне трудно определить щелчок по любому элементу в списке

родительский

<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).

Я знаю, что это возможно, потому что vuetify js так оно и есть, но я попытался проверить исходный код, но у меня ничего не вышло.

Ответы [ 2 ]

1 голос
/ 13 июля 2020

То, чего вы хотите достичь, может быть достигнуто с помощью

parent.vue 

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

...

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

обратите внимание, что метод, переданный внутри опоры, не имеет круглой скобки (), потому что вы передаете ссылку на него.

Чтобы использовать его внутри дочернего компонента, добавьте ()

@click="parentMethod()"

To go обратно в свой пример, измените это:

<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) как есть. Аргумент будет введен автоматически.

Несмотря на то, что это решение будет работать, лучший способ добиться такого взаимодействия между родителем и потомком - передать значение в дочернем элементе, а затем прослушать его

0 голосов
/ 13 июля 2020

есть способы сделать это лучше, но ваша идея должна быть такой:

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>
...