为我所有的渲染函数创建一个数组 VueJS

Creating an Array for All My Render Functions VueJS

澄清
我意识到我没有很好地写下我的问题(对此感到抱歉)。因此,我重写了我的问题和随附的示例。


我想使用 VueJS 中的渲染函数创建一些 组件。每个功能基本上都是相同的格式,只是插入的数据会发生变化。在我看来,每次都重写渲染函数只是为了创建不同的组件(当每个组件的基本结构相同时),这似乎相当重复(而且根本不是 DRY)。

因此,我想做的是创建一个数组来保存我想用于各种不同组件的所有数据。然后我想遍历该数据,每次 运行 渲染函数。

例如,假设这是我的数据:

var components = [
        { name: 'label',
          props: ['tag', 'type', 'size', 'color', 'direction'],
          class: 'label',
          tagOption: true,
          tag: 'div'},

        { name: 'icon',
          props: ['type', 'size', 'color'],
          class: 'icon',
          tagOption: false,
          tag: 'i'}
    ]

运行 此数据的循环相当于编写渲染函数两次,如下所示:

标签组件

export label {
    props: ['tag', 'type', 'size', 'color', 'direction'],
    render(createElement) {
        let classes = ['ui', 'label']
        if (this.type) { classes.push(this.type) }
        if (this.size) { classes.push(this.size) }
        if (this.color) { classes.push(this.color) }
        if (this.direction) { classes.push(this.direction) }

        return createElement(
            this.tag || 'div',
            { class: classes },
            this.$slots.default
        );
    }
}

图标组件

export icon {
    props: ['type', 'size', 'color'],
    render(createElement) {
        let classes = ['ui', 'label']
        if (this.type) { classes.push(this.type) }
        if (this.size) { classes.push(this.size) }
        if (this.color) { classes.push(this.color) }

        return createElement(
            'i',
            { class: classes },
            this.$slots.default
        );
    }
}

总结

这是我想做的事情: 有一个label.js(或label.vue)文件运行渲染函数来创建标签组件和一个单独的icon.js文件运行基本上完全相同的渲染函数来创建图标组件

这就是我想做的事情: 有一个文件将循环遍历一组数据,运行 并在每次循环遍历渲染函数时导出该数据。

这可能吗?如果是这样,您有什么想法吗?

谢谢。

有几种方法可以做到这一点。这是一个将组件注册为全局组件的方法。

for (let tmpl of components){
  let render = function(createElement){
    let classes = ["ui", tmpl.name]  
    const props = tmpl.props.slice(1)
    for (let prop of props)
      if (this[prop]) classes.push(this[prop])

    return createElement(tmpl.tag, {class: classes}, this.$slots.default)
  }

  Vue.component(`${tmpl.name}-component`,{
    props: tmpl.props,
    render
  })
}

new Vue({
  el:"#app"
})

示例模板:

<div id="app">
  <label-component direction="horizontal">stuff</label-component>
  <icon-component size="large" color="blue">Other stuff</icon-component>
</div>

Example.

如果您不想要全局组件,您可以这样做。

let components = {}
for (let tmpl of componentTemplates){
  let render = function(createElement){
    let classes = ["ui", tmpl.name]  
    const props = tmpl.props.slice(1)
    for (let prop of props)
      if (this[prop]) classes.push(this[prop])

    return createElement(tmpl.tag, {class: classes}, this.$slots.default)
  }

  components[`${tmpl.name}-component`] = {
    props: tmpl.props,
    render 
  }
}

new Vue({
  el:"#app",
  components
})

Example.

您可以在 Vue 声明之外生成组件:

(我重命名了组件,因为当您使用 labelicon 等常见的 HTML 标签名称作为组件名称时,Vue 不喜欢它)

const components = [
  { name: 'child1',
    props: ['tag', 'type', 'size', 'color', 'direction'],
    class: 'label',
    tagOption: true,
    tag: 'div'},
  { name: 'child2',
    props: ['type', 'size', 'color'],
    class: 'icon',
    tagOption: false,
    tag: 'i'}
];

// function to generate components
const generateComponents = components => components
  .map(c => Object.assign({[c.name] : {
    props: c.props,
    render: function(createElement) {
        const classes = ['ui', 'label'];
        classes.push(c.class); // I suppose you've forgot this?
        if (this.type) { classes.push(this.type) };
        if (this.size) { classes.push(this.size) };
        if (this.color) { classes.push(this.color) };
        if (this.direction) { classes.push(this.direction) };

        return createElement(
            c.tag || 'div',
            { class: classes },
            this.$slots.default
        );
      }
    }
  })).reduce((a, v) => Object.assign(a, v), {});

// here you are
const myComponents = generateComponents(components);

new Vue({
  el: '#app',
  components: myComponents
});
.green { color: green; font-weight: bold }
.mytype { background-color: beige }
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
  <child1 type="mytype">hello</child1>
  <child2 color="green">hello again</child2>
</div>