Vue如何将动态插槽元素绑定到数据?

3
我想通过插槽将一个按钮传递给组件,以便进行操作。例如,一个具有“添加行”功能的表格。
<my-table :data="data" :cols="cols"> 
   <button slot="add_row"></button>
</my-table>

或者,这个被拆解的警告:
<alert>
   <button slot="close">Remove the alert</button>
</alert>

以下是模板:

<div class="alert alert-info">
   <slot></slot>
</div>

事实上,我想在组件定义内部将事件动作绑定到<slot>按钮,但仍然让组件用户提供自己的按钮(有时甚至是链接,<a>元素)。
我考虑使用指令来处理操作按钮,类似于这个库:https://bootstrap-vue.js.org/docs/components/modal,其中模态框按钮具有v-b-modal指令。但是我不知道如何实现。
更新: 我正在尝试使用指令来实现此功能。这是我目前的代码:https://jsfiddle.net/uvd6knLh/
Vue.component('alert', {
    template: `
  <div class="alert alert-info" v-if="show">
    <slot></slot>
  </div>`,

  data() {
        return {
    show: true
    }
  },
  mounted() {
     // directive event
     this.$root.$on("alert:close", () => this.show = false);
  }
});

Vue.directive('alert-dismiss', {
   inserted: function(el, binding, vnode) {
    el.addEventListener("click", () => {
        vnode.context.$root.$emit("alert:close");
    });
   }
});

所以我监听指令事件。问题在于,指令事件会导致所有警报组件关闭,正如您在jsfiddle中所看到的那样。 如何使这种模式起作用?


1
这是一个使用作用域插槽的示例。https://codepen.io/Kradek/pen/GGWKPE?editors=1010 - Bert
1
如果您想采用这种方法,v-b-modal指令的源代码在这里 - Bert
我正在尝试使用指令,但无法弄清指令如何与组件通信。 - user3599803
1
他们正在做的是当具有指令的元素被点击时,从$root发出一个事件,并在模态组件中监听该事件。 - Bert
谢谢!我正在尝试实现使用指令的设计模式,但是它并不正常工作,请看我的更新。如何使其正常工作? - user3599803
1个回答

1
为了将子元素(<my-table>)的数据和操作提供给其父元素,您可以查看作用域插槽
当子元素具有一些对父元素不相关的内部状态或需要向子元素提供自定义属性或回调并将标记和样式留给父组件时,作用域插槽非常有效。
然而,在您的情况下,由于是父元素持有data属性,我不确定这是否是最佳解决方案。子元素不应该改变它。
您可以简单地在父组件上解决事件。

我宁愿将警报的可见性放在父组件上,否则警报在挂载时总是需要设置为可见,而不是由父组件控制。 - Christophe
从评论中,我发现作用域插槽确实解决了这个问题。我可以传递自定义按钮并在父组件中设置其处理程序。但我实际上不喜欢这种语法,它不够清晰。我更喜欢采用指令的方式。我找不到如何在内部指令和组件之间通信的方法。 - user3599803
指令在最新版本中已经发生了变化,不再与组件实例相关联,而是仅与DOM节点相关联(使它们非常适用于集成js库)。如果您真的想使用指令方式,那么这将是一个hacky的方法,您可以直接在DOM节点上持久化状态。 - Christophe
你能举个例子,什么是在DOM节点上持久化状态?或者有没有任何方法为组件提供操作指令,就像我在一些Vue组件中看到的那样。使用slot-scope方式“导出”处理程序函数对我来说似乎不太直观。 - user3599803
如果指令过于hacky,我也会考虑事件委托(检查event.target)。但是我更喜欢直接绑定点击事件。 - user3599803

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接