我尝试以编程方式将组件添加到我的Vue单个文件组件中的页面,如果您知道自己想要提前做什么,该组件可以很好地工作。在我的例子中,组件及其布局将通过JSON接收,并且我试图动态创建它们。下面你可以看到我喜欢做类似eval之类的事情,但遗憾的是,这对于未实例化的对象并不起作用。下面的代码通过硬编码值进行了简化,以获得重点。
<template>
<div id="app">
<h2>Static template:</h2>
<InputTemplate type="text"></InputTemplate>
<h2>Dynamically inserted:</h2>
<div ref="container">
<button @click="onClick">Click to insert</button>
<br/>
</div>
</div>
</template>
<script>
import Vue from 'vue'
//the component I'd like to create
import InputTemplate from './components/InputTemplate.vue'
export default {
name: 'app',
components: { InputTemplate },
methods: {
onClick() {
//I'd like to do something like this, but eval doesn't work like this
var ComponentClass = Vue.extend(eval('InputTemplate'))
var instance = new ComponentClass({
propsData: {type: 'text' }
})
instance.$mount()
this.$refs.container.appendChild(instance.$el)
}
}
}
</script>
我在下面放了一个帮助函数,取代了eval并起作用,但对于解决方案来说感觉有点不合适。它还需要为每个添加的新组件进行大量维护。有更好的方法吗?
returnComponent(componentString){
if(componentString === 'InputTemplate'){
return InputTemplate;
}
}
答案 0 :(得分:2)
事实证明,Vue有<component :is="yourComponentType">
,如果你将它扔进v-for
循环,它就完全符合我的希望。 Documents here.
答案 1 :(得分:0)
您可以使用Async components通过API检索组件。
我已经通过Axios使用GraphQL进行了测试,但它可以与任何REST服务一起使用。
主要组件如下:
<template>
<div>
<h1>Test page</h1>
<div><button @click="clicked = true">Load component</button></div>
<async-component v-if="clicked" />
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
clicked: false,
};
},
components: {
'async-component': () => axios.post('http://localhost:5000/graphql', { query: `
{
asyncComponentByRowId(rowId: 1) {
component
content
}
}
`,
}).then((response) => {
const comp = response.data.data.asyncComponentByRowId.content;
// eval can be harmful
return eval(`(${comp})`);
}),
},
};
</script>
检索到的组件采用以下格式:
{
"data": {
"asyncComponentByRowId": {
"component": "my-async-component",
"content": "{\r\n\ttemplate: '<div>{{ msg }}</div>',\r\n\tdata: function() {\r\n\t\treturn {\r\n\t\t\tmsg: 'Async component works!'\r\n\t\t};\r\n\t}\r\n}"
}
}
}
解码的data.asyncComponentByRowId.content
属性是表示JavaScript对象的字符串:
{
template: '<div>{{ msg }}</div>',
data: function() {
return {
msg: 'Async component works!'
};
}
}
按下该按钮后,组件将在从API异步下载后显示。
唯一的问题是我正在使用eval
来解码对象。
结果: