将插槽传递给子组件的Vue方式

huangapple go评论76阅读模式
英文:

Vue - pass down slots to child components

问题

我想从Vuetify创建一个可重用的数据表格组件。某些列可能包含v-slot以修改该列内的数据。例如:我将用户角色存储为整数,并希望它们在表格中显示为用户管理员。目前,我是通过以下v-slot来实现的:

<template v-slot:item.role="{ item }">
  {{ (item.role === 1) ? 'Administrator' : 'User' }}
</template>

因为这不是每个数据表格的使用情况,我想从使用数据表格的父组件中传递这些v-slot。我的数据表格组件目前如下所示:

<template>
  <v-data-table :headers="headers" :items="items">
    <template v-slot:item.role="{ item }">
      {{ (item.role === 1) ? 'Administrator' : 'User' }}
    </template>
    <template v-slot:item.action="{ item }">
      <v-icon @click="deleteItem(item)" small>fas fa-trash</v-icon>
    </template>
  </v-data-table>
</template>

<script>
export default {
  name: "DataTable",
  props: {
    title: String,
    headers: Array,
    items: Array
  },
  methods: {
    deleteItem(item) {
      this.$emit("clicked", item);
    }
  }
};
</script>

这是我使用DataTable的组件(UserTable.vue):

<template>
  <DataTable :title="title" :headers="headers" :items="items" @clicked="onDelete" />
</template>

<script>
import DataTable from "../../../components/DataTable";
import axios from "axios";

export default {
  name: "UserTable",
  components: {
    DataTable
  },
  props: {
    items: Array
  },
  data: () => ({
    title: "Users",
    headers: [
      {
        text: "Name",
        value: "name"
      },
      {
        text: "Email",
        value: "email"
      },
      {
        text: "Role",
        value: "role"
      },
      { text: "Actions", value: "action", sortable: false }
    ]
  }),
  methods: {
    onDelete(item) {
      this.$emit("clicked", item);
    }
  }
};
</script>

在理想情况下,我希望在UserTable组件中像这样使用它:

<template>
  <DataTable :title="title" :headers="headers" :items="items" @clicked="onDelete">
    <template v-slot:item.role="{ item }">
      {{ (item.role === 1) ? 'Administrator' : 'User' }}
    </template>
    <template v-slot:item.action="{ item }">
      <v-icon @click="deleteItem(item)" small>fas fa-trash</v-icon>
    </template>
  </DataTable>
</template>

然后,将DataTable保持简洁和简单,像这样:

<template>
  <v-data-table :headers="headers" :items="items">
    <slot></slot>
  </v-data-table>
</template>

但显然这不像我预期的那样工作,因为现在它不会显示所需列中的任何内容。我创建了一个CodeSandbox,让您看看我现在的情况:

CodeSandbox链接

有人可以告诉我为什么我的方法不起作用,或者我如何修复这个问题吗?

英文:

I want to make a reusable Data Table component from Vuetify. Some columns could contain v-slot to modify the data inside that column. For example: I store the user roles as integers and want them displayed as user or adminin the table. Currently I do this with thisv-slot`:

 &lt;template v-slot:item.role=&quot;{item} &quot;&gt;
    {{ (item.role === 1) ? &#39;Administrator&#39; : &#39;User&#39; }}
 &lt;/template&gt;

Because this will not be the use-case for every Data Table I want to pass these v-slot from a parent component which uses the Data Table. My Data Table component currently looks like this:

&lt;template&gt;
  &lt;v-data-table :headers=&quot;headers&quot; :items=&quot;items&quot;&gt;
    &lt;template v-slot:item.role=&quot;{item} &quot;&gt;
      {{ (item.role === 1) ? &#39;Administrator&#39; : &#39;User&#39; }}
    &lt;/template&gt;
    &lt;template v-slot:item.action=&quot;{ item }&quot;&gt;
      &lt;v-icon @click=&quot;deleteItem(item)&quot; small&gt;fas fa-trash&lt;/v-icon&gt;
    &lt;/template&gt;
  &lt;/v-data-table&gt;
&lt;/template&gt;

&lt;script&gt;
export default {
  name: &quot;DataTable&quot;,
  props: {
    title: String,
    headers: Array,
    items: Array
  },
  methods: {
    deleteItem(item) {
      this.$emit(&quot;clicked&quot;, item);
    }
  }
};
&lt;/script&gt;

And this is the component (UserTable.vue) where I use the DataTable:

&lt;template&gt;
  &lt;DataTable :title=&quot;title&quot; :headers=&quot;headers&quot; :items=&quot;items&quot; @clicked=&quot;onDelete&quot; /&gt;
&lt;/template&gt;

&lt;script&gt;
import DataTable from &quot;../../../components/DataTable&quot;;
import axios from &quot;axios&quot;;

export default {
  name: &quot;UserTable&quot;,
  components: {
    DataTable
  },
  props: {
    items: Array
  },
  data: () =&gt; ({
    title: &quot;Users&quot;,
    headers: [
      {
        text: &quot;Name&quot;,
        value: &quot;name&quot;
      },
      {
        text: &quot;Email&quot;,
        value: &quot;email&quot;
      },
      {
        text: &quot;Role&quot;,
        value: &quot;role&quot;
      },
      { text: &quot;Actions&quot;, value: &quot;action&quot;, sortable: false }
    ],
  }),
  methods: {
    onDelete(item) {
      this.$emit(&quot;clicked&quot;, item);
    }
  }
};
&lt;/script&gt; 

In an ideal situation I would like to have it something like this in the UserTable component:

&lt;template&gt;
  &lt;DataTable :title=&quot;title&quot; :headers=&quot;headers&quot; :items=&quot;items&quot; @clicked=&quot;onDelete&quot;&gt;
      &lt;template v-slot:item.role=&quot;{item} &quot;&gt;
      {{ (item.role === 1) ? &#39;Administrator&#39; : &#39;User&#39; }}
    &lt;/template&gt;
    &lt;template v-slot:item.action=&quot;{ item }&quot;&gt;
      &lt;v-icon @click=&quot;deleteItem(item)&quot; small&gt;fas fa-trash&lt;/v-icon&gt;
    &lt;/template&gt;
  &lt;/DataTable&gt;
&lt;/template&gt;

And then keep the DataTable clean and simple like this:

&lt;template&gt;
  &lt;v-data-table :headers=&quot;headers&quot; :items=&quot;items&quot;&gt;
    &lt;slot&gt;&lt;/slot&gt;
  &lt;/v-data-table&gt;
&lt;/template&gt;

But that obviously doesn't seem to work as I expected because it doesn't show anything in the desired columns now. I created a CodeSandBox to let you see how I have it now:

https://codesandbox.io/s/priceless-bohr-oxu18?fontsize=14&amp;hidenavigation=1&amp;theme=dark

Can someone tell me why my approach doesn't work or how I might fix this?

答案1

得分: 4

我通过查看这个答案成功修复了这个问题:
https://stackoverflow.com/a/52823029/7603806

我在我的DataTable组件中添加了上面的代码,并现在从使用DataTableUserTable组件中传递插槽。

英文:

I managed to fix this by looking at this answer:
https://stackoverflow.com/a/52823029/7603806

&lt;template v-for=&quot;slot in Object.keys($scopedSlots)&quot; :slot=&quot;slot&quot; slot-scope=&quot;scope&quot;&gt;&lt;slot :name=&quot;slot&quot; v-bind=&quot;scope&quot;/&gt;&lt;/template&gt;

I added the code above in my DataTable component and pass the slots now from the UserTable component which uses the DataTable.

huangapple
  • 本文由 发表于 2020年1月6日 17:13:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/59609361.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定