澄清
我意识到我没有很好地写出我的问题(抱歉)。因此,我改写了我的问题和随附的例子。
我想使用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)文件,它运行Render Function来创建一个标签组件和一个单独的icon.js文件,它运行基本上完全相同的渲染函数来创建一个图标组件
这是我做想要做的事情: 有一个文件循环遍历数据数组,运行和导出数据,每个循环通过渲染函数。
这可能吗?如果是这样,关于如何做的任何想法?
感谢。
答案 0 :(得分:1)
有几种方法可以做到这一点。这是一个注册组件作为全局组件。
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>
如果你不想要全局组件,你可以这样做。
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
})
答案 1 :(得分:1)
您可以在Vue声明之外生成组件:
(我重命名了组件,因为当您使用label
或icon
等常用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
});
&#13;
.green { color: green; font-weight: bold }
.mytype { background-color: beige }
&#13;
<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>
&#13;