【问题标题】:Renderless Vue component with a click listener带有点击监听器的无渲染 Vue 组件
【发布时间】:2019-03-05 11:29:42
【问题描述】:

我读过这篇文章,深入探讨了无渲染组件:

https://adamwathan.me/renderless-components-in-vuejs/

一个无渲染的组件看起来像这样:

export default {
  render() {
    return this.$scopedSlots.default({})
  },
}

现在我想使用这个无渲染组件,但也想添加一个点击监听器到任何被传递到插槽的东西。

在我的例子中,它是一个按钮。我的无渲染组件将简单地包装一个按钮并向其添加一个单击侦听器,然后执行 AJAX 请求。

我将如何为正在传递到插槽的元素添加点击侦听器?

【问题讨论】:

    标签: vue.js vuejs2 vue-component


    【解决方案1】:

    假设您想在无渲染组件中绑定点击处理程序,我认为从this post 开始,您需要克隆传入renderless 的vnode,以增强它的属性。

    createElements Arguments,第二个arg是要增强的对象

    与您将在模板中使用的属性相对应的数据对象。可选。

    console.clear()
    Vue.component('renderless', {
      render(createElement) {
        var vNode = this.$scopedSlots.default()[0]
        var children  = vNode.children || vNode.text
        const clone = createElement(
          vNode.tag, 
          {
            ...vNode.data, 
            on: { click: () => alert('clicked') }
          },
          children
        )
        return clone
      },
    });
    new Vue({}).$mount('#app');
    <script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
    
    <div id="app">
      <renderless>
        <button type="button" slot-scope="{props}">Click me</button>
      </renderless>
    </div>

    【讨论】:

    • 这在 2.6.11 中不起作用,请参阅:codepen.io/Livijn/pen/WNraBZo 您需要将 const vNode = this.$scopedSlots.default({}); 替换为 const vNode = this.$scopedSlots.default({})[0];
    【解决方案2】:

    这是解决此问题的一种方法。

    您的无渲染组件包装器将包含一个 action(即发出 AJAX 请求的函数)属性。

    Vue.component('renderless-action-wrapper', {
      props: ['action'],
      render() {
        return this.$scopedSlots.default({
          action: this.action,
        });
      },
    });
    

    然后使用上述包装器的另一个组件将使用@click 处理程序封装一个可自定义的槽,该处理程序在触发时调用传入的操作。

    Vue.component('clickable', {
      props: ['action'],
      template: `
        <renderless-action-wrapper :action="action">
          <span slot-scope="{ url, action }">
            <span @click="action()">
              <slot name="action"></slot>
            </span>
          </span>
        </renderless-action-wrapper>
      `,
    });
    

    最后,连接包装器的专用版本。

    <clickable :action="doAjaxRequest">
      <button type="button" slot="action">Button</button>
    </clickable>
    

    Here's a live example of the above suggestion you can play around with.

    【讨论】:

      猜你喜欢
      • 2021-08-07
      • 2019-03-20
      • 1970-01-01
      • 1970-01-01
      • 2019-04-19
      • 1970-01-01
      • 2015-11-22
      • 2021-11-23
      • 2021-12-27
      相关资源
      最近更新 更多