为我所有的渲染函数创建一个数组 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>
如果您不想要全局组件,您可以这样做。
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
})
您可以在 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
});
.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>
澄清
我意识到我没有很好地写下我的问题(对此感到抱歉)。因此,我重写了我的问题和随附的示例。
我想使用 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>
如果您不想要全局组件,您可以这样做。
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
})
您可以在 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
});
.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>