具有动态事件的VueJS动态组件

时间:2019-03-07 15:07:50

标签: vue.js vuejs2

从外部来源(例如api),我得到了一个组件定义:

{
    "component": "b-btn",
    "content": "Button",
    "attr": {
        "title": "Edit"
    },
    "events": {
        "click": "doSomething"
    }
}

此定义与动态组件一起使用:

<component :is="item.component" v-bind="item.attr">
    {{ item.content }}
</component>

,并且按预期方式工作(显示了vue-bootstrap按钮,标题为“ Edit”,按钮文本为“ Button”)。

现在我也想添加事件。从VueJS 2.4(https://vuejs.org/v2/api/#v-on)开始,您可以使用<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>之类的对象语法来定义事件,我认为,仅添加v-on="item.events"可能会起作用:

<component :is="item.component" v-bind="item.attr" v-on="item.events">
    {{ item.content }}
</component>

但这不是,因为对象属性click的值是一个字符串("doSomething")而不是可调用的。

// Just to make it clear
{"click": "doSomething"} != {"click": doSomething}

是否可以将动态事件(从JSON)绑定到组件?

1 个答案:

答案 0 :(得分:1)

是的,有可能。您必须以编程方式检查组件中是否存在具有给定名称的函数,如果存在,则使用该函数代替字符串。 因此,您需要操作JSON。 我在CodeSandbox中构建了一个测试用例,其中使用一个计算字段来更新events属性,方法是检查events对象中每个键是否存在具有给定名称的函数,并将该值替换为该函数

说我的子组件有一个事件clicked,该事件会在单击按钮时触发。

我的父组件如下所示:

data() {
return {
  item: {
    component: "TestComponent",
    content: "Button",
    attr: {
      title: "Edit"
    },
    events: {
      clicked: "alertText"
    }
  }
};
},
computed: {
  componentItem() {
    let item = this.item;
    if (item.hasOwnProperty("events")) {
      let events = item.events;
      for (let i in events) {
        if (events.hasOwnProperty(i)) {
          let functionName = events[i];
          if (
            this.hasOwnProperty(functionName) &&
            typeof this[functionName] === "function"
          ) {
            // function exists
            item.events[i] = this[functionName];
          }
        }
      }
    }
    return item;
  }
},

methods: {
  alertText() {
    console.log("I was clicked");
  }
}

在这里查看工作示例: https://codesandbox.io/s/oo9zj8qy9y