Vue组件动态添加属性
Dynamically add properties to Vue component
我正在从驱动我显示的组件类型的数据库加载数据
一个 AJAX 电话响了,returns 我得到了一些数据(如果需要可以重组)
{
component_type: 'list-item',
props: {
name: 'test',
value: 'some value'
}
}
这可以在我的父对象上访问一个名为 component
的变量
在我的父对象的模板中,我有以下内容
<component :is="component.component_type" ></component>
这工作正常并按预期加载组件。
接下来我也想将我的数据对象中的属性添加到此标记中
<component :is="component.component_type" {{ component.props }} ></component>
这不起作用,并且拒绝写入带有 {{ 的标签。我认为这是浏览器而不是 Vue 抛出的错误,尽管我不确定。
作为参考,我希望输出看起来像:
<component :is="component.component_type" name='test' value='some value' ></component>
我怎样才能传递这些属性?理想情况下,我希望这些与我所展示的父项的数据/道具相关联,以便可以轻松地在数据库中更改它们,并且 UI 将相应地更改。
在最坏的情况下,我会在服务器端生成它,但我宁愿像我目前正在尝试的那样通过 ajax 来生成它。
据我所知,Vue.js 模板中没有 rest props (spread props) 语法。
一个可能的解决方案是渲染函数。使用渲染函数时,您拥有 JavaScript 的全部功能,因此您可以这样做:
render (h) {
return h('foo', {
props: {
...yourData
}
})
}
我在这里创建了一个简单的例子:http://codepen.io/CodinCat/pen/bgoVrw?editors=1010
组件类型(如foo
)和道具都可以是动态的(但你仍然需要声明所有可能的道具字段(如a
,b
和c
) 在你的子组件中)
还有一个解决方案是 JSX。
使用 JSX babel 插件:https://github.com/vuejs/babel-plugin-transform-vue-jsx
然后你可以使用传播道具语法:
return <foo {...{yourData}}></foo>
在 thread 之后,我看到了两个选项。
一个是传递一个单独的prop,它本身就是一个对象,并传递其中所有相关的键值,可以被子组件使用,像下面这样:
<component :is="component. component_type"
:options="component.props"
</component>
提到的其他解决方案是有一个指令,在该指令中传递对象,它将作为该对象中键的属性设置为相应的值,您可以在工作中看到这个 here.
Vue.directive('props', {
priority: 3000,
bind() {
// set the last component child as the current
let comp = this.vm.$children[this.vm.$children.length - 1];
let values = null;
if(this._scope && this._scope.$eval) {
values = this._scope.$eval(this.expression);
} else {
values = this.vm.$eval(this.expression);
}
if(typeof values !== 'object' || values instanceof Array) {
values = { data: values };
}
// apply properties to component data
for(let key in values) {
if(values.hasOwnProperty(key)) {
let hkey = this.hyphenate(key);
let val = values[key];
if(typeof val === 'string') {
comp.$options.el.setAttribute(hkey, values[key]);
} else {
comp.$options.el.setAttribute(':' + hkey, values[key]);
}
}
}
console.log(comp.$options.el.outerHTML);
comp._initState();
},
/*
* Hyphenate a camelCase string.
*/
hyphenate(str) {
let hyphenateRE = /([a-z\d])([A-Z])/g;
return str.replace(hyphenateRE, '-').toLowerCase();
}
});
并像这样使用它:
<div class="app">
<component is="component.component_type" v-props="component.props"></component>
</div>
如果有人想知道如何使用 Vue 2 执行此操作,您可以将对象传递给 v-bind:
<template>
<component :is="componentType" v-bind="props"></component>
</template>
<script>
export default {
data() {
return {
componentType: 'my-component',
props: {
foo: 'foofoo',
bar: 'barbar'
}
}
}
}
</script>
我正在从驱动我显示的组件类型的数据库加载数据
一个 AJAX 电话响了,returns 我得到了一些数据(如果需要可以重组)
{
component_type: 'list-item',
props: {
name: 'test',
value: 'some value'
}
}
这可以在我的父对象上访问一个名为 component
的变量在我的父对象的模板中,我有以下内容
<component :is="component.component_type" ></component>
这工作正常并按预期加载组件。
接下来我也想将我的数据对象中的属性添加到此标记中
<component :is="component.component_type" {{ component.props }} ></component>
这不起作用,并且拒绝写入带有 {{ 的标签。我认为这是浏览器而不是 Vue 抛出的错误,尽管我不确定。
作为参考,我希望输出看起来像:
<component :is="component.component_type" name='test' value='some value' ></component>
我怎样才能传递这些属性?理想情况下,我希望这些与我所展示的父项的数据/道具相关联,以便可以轻松地在数据库中更改它们,并且 UI 将相应地更改。
在最坏的情况下,我会在服务器端生成它,但我宁愿像我目前正在尝试的那样通过 ajax 来生成它。
据我所知,Vue.js 模板中没有 rest props (spread props) 语法。
一个可能的解决方案是渲染函数。使用渲染函数时,您拥有 JavaScript 的全部功能,因此您可以这样做:
render (h) {
return h('foo', {
props: {
...yourData
}
})
}
我在这里创建了一个简单的例子:http://codepen.io/CodinCat/pen/bgoVrw?editors=1010
组件类型(如foo
)和道具都可以是动态的(但你仍然需要声明所有可能的道具字段(如a
,b
和c
) 在你的子组件中)
还有一个解决方案是 JSX。
使用 JSX babel 插件:https://github.com/vuejs/babel-plugin-transform-vue-jsx
然后你可以使用传播道具语法:
return <foo {...{yourData}}></foo>
在 thread 之后,我看到了两个选项。
一个是传递一个单独的prop,它本身就是一个对象,并传递其中所有相关的键值,可以被子组件使用,像下面这样:
<component :is="component. component_type"
:options="component.props"
</component>
提到的其他解决方案是有一个指令,在该指令中传递对象,它将作为该对象中键的属性设置为相应的值,您可以在工作中看到这个 here.
Vue.directive('props', {
priority: 3000,
bind() {
// set the last component child as the current
let comp = this.vm.$children[this.vm.$children.length - 1];
let values = null;
if(this._scope && this._scope.$eval) {
values = this._scope.$eval(this.expression);
} else {
values = this.vm.$eval(this.expression);
}
if(typeof values !== 'object' || values instanceof Array) {
values = { data: values };
}
// apply properties to component data
for(let key in values) {
if(values.hasOwnProperty(key)) {
let hkey = this.hyphenate(key);
let val = values[key];
if(typeof val === 'string') {
comp.$options.el.setAttribute(hkey, values[key]);
} else {
comp.$options.el.setAttribute(':' + hkey, values[key]);
}
}
}
console.log(comp.$options.el.outerHTML);
comp._initState();
},
/*
* Hyphenate a camelCase string.
*/
hyphenate(str) {
let hyphenateRE = /([a-z\d])([A-Z])/g;
return str.replace(hyphenateRE, '-').toLowerCase();
}
});
并像这样使用它:
<div class="app">
<component is="component.component_type" v-props="component.props"></component>
</div>
如果有人想知道如何使用 Vue 2 执行此操作,您可以将对象传递给 v-bind:
<template>
<component :is="componentType" v-bind="props"></component>
</template>
<script>
export default {
data() {
return {
componentType: 'my-component',
props: {
foo: 'foofoo',
bar: 'barbar'
}
}
}
}
</script>