根据名称,字符串或配置加载和创建VueJS组件。
首先,如果您刚开始使用VueJS,这对您来说可能有点太高级了,我强烈建议您阅读VueJS上的文档,尤其是组件。
前言
根据用户输入交换组件,甚至只是通过json文件设置表单,这是一个非常有用的方法,可以在整个大项目中保持较低的理智水平,因为通常有数百个组件/表单/页面/等,所以进行更改在代码中,它可能会导致涟漪效应,并打破其他地方的东西。
由于VueJS将处理DOM的所有脏细节,因此我们可以专注于解决业务问题。
我将介绍按名称加载组件,创建动态和异步组件。
组件的“神奇”
如果没有<component v-bind:is="dynComponent"></component>
检查动态和异步组件以获取更多详细信息,那么动态操作就不那么容易了。基本上,组件将呈现组件,异步功能或组件名称。
按名称加载组件
使用<component/>
将允许您按名称访问全局和本地组件。
// add some different components globaly
Vue.component("test-comp0", {
template: `<p>comp0</p>`
});
Vue.component("test-comp1", {
template: `<p>comp1</p>`
});
Vue.component("test-comp2", {
template: `<p>comp2</p>`
});
// sample app
new Vue({
el: "#app",
components: {
// add a local component
// check https://vuejs.org/v2/guide/components-registration.html#Component-Names
TestComp3: {
template: `<p>comp3 locally registered component</p>`
}
// you can also add some components from other files, using ES6 import or required.
},
data() {
return {
componentIndex: 0
};
},
computed: {
componentName() {
return "test-comp" + this.componentIndex;
}
},
template: `
<div>
Component: {{componentIndex}} <button @click="componentIndex=(++componentIndex)%4">change</button>
<component :is="componentName"></component>
</div>`
});
组件之间的动态循环
组件之间的循环很有用,但在现实世界中,你会传递一些道具。要添加道具,我们可以更改组件test-comp0
和应用模板。
Vue.component("test-comp0", {
props: ["name"], // please use the object props for production
template: `<p>Hello {{name}}</p>`
});
...
// add name prop
<component :is="componentName" name="pikax"></component>
在动态组件上使用prop
这会将prop名称传递给每个组件。为了解决这个问题,我们可以有一个计算属性并将其绑定到组件。
// app becomes
new Vue({
el: "#app",
components: {
// add a local component
// check https://vuejs.org/v2/guide/components-registration.html#Component-Names
TestComp3: {
template: `<p>comp3 locally registered component</p>`
}
// you can also add some components from other files, using ES6 import or required.
},
data() {
return {
componentIndex: 0,
name: "pikax"
};
},
computed: {
componentName() {
return "test-comp" + this.componentIndex;
},
componentProps() {
if (this.componentIndex == 0) {
return {
name: this.name
};
}
return {}; // return empty object
}
},
template: `
<div>
Component: {{componentIndex}} <button @click="componentIndex=(++componentIndex)%4">change</button>
<component :is="componentName" v-bind="componentProps"></component>
</div>`
});
根据组件传递道具
即时组件
即时组件是我们使用javascript生成的组件,<component></component>
这显示了它的强大功能,一些用例场景将构建小部件。
我们可以根据用户输入生成和测试组件。
注意:要非常小心,这可能允许攻击者攻击您的应用程序,请确保源是可信的!
new Vue({
el: "#app",
data() {
return {
componentDefinition: `{ template: "<div>Hello</div>" }`
};
},
computed: {
myComponent() {
return eval(`(${this.componentDefinition})`);
}
},
template: `<div>
<p>Change me</p>
<textarea v-model="componentDefinition" rows="4" cols="50"></textarea>
<component v-if="myComponent" :is="myComponent"></component>
</div>
`
});
使用textarea的完全动态组件
您可以在更改textarea时看到,组件应该立即渲染。我不建议使用它,但我认为这是一个很好的例子<component></component>
。
导入异步组件
这对我来说是组件最有用的用例。我非常推荐阅读官方指南。
Vue.component(
"async-webpack-example",
// The `import` function returns a Promise.
() => import("./my-async-component")
);
导入异步webpack
真实世界的问题
在我的上一个项目中,我们遇到了一个问题,我们想收集用户信息,但字段会根据旅程而改变,有些旅程需要电子邮件,其他人需要电子邮件和电话。
解决方案是将旅程定义放在JSON文件中,每次用户启动旅程时我们都会加载该文件并加载字段。策略是使用名称加载组件按名称动态加载组件,但我们最终加载了所有可能的编辑器Vue.Component
,这工作...但在启动时加载它们意味着启动时间和应用程序大小更大比需要的。
解决方法
// returning equivalent of webpack : import(name)
const getComponent = async path => {
/* I recomend having an switch with the possible components you will load, this
* will allow you only load specific components.
*/
if (path == 1) {
return async () => {
template: `<p>component 0</p>`;
};
} else {
return async () => {
template: `<p>${path}</p>`;
};
}
};
Vue.component("component-fallback", {
template: `<div>This is not the component you're looking for</div>`
});
new Vue({
el: "#app",
data() {
return {
componentIndex: 0,
component: "component-fallback"
};
},
methods: {
changeComponent() {
const newIndex = ++this.componentIndex;
this.loadComponent(newIndex);
},
// returns the component
loadComponent(name) {
const componentFunc = getComponent(name)
.then(x => {
this.component = x;
})
.catch(e => {
this.component = "component-fallback";
});
}
},
template: `
<div>
Component: {{componentIndex}} <button @click="changeComponent">change</button>
<component :is="component"></component>
</div>
`
});
使用回退加载动态组件
希望我的第一篇文章对你有用,我发现它有多么强大和灵活<component></component>
。
如果您有任何更多用例,请<component></component>
在评论中告诉我。
转:https://medium.com/@pikax.dev/dynamic-components-using-vuejs-9a633cbc0ad0