基于vue的动态组件配置系统设计二:设计思路与实现
上篇文章地址
本文重点
1.配置系统设计思路
2.优化:异步组件加载
3.其他奇思妙想
设计思路
上文提到了大致的原理,那接下来就是要作整个的设计了,设计的内容分为:选择组件-预览窗口—编辑窗口
选择组件:一个列表,通过点击组件添加组件到预览窗口
预览组件:用循环动态组件的方式,将组件添加到数组viewList中
编辑窗口:用动态组件将当前选中的组件的配置属性(props)展示并提供调整(vue天然的双向数据绑定)
所以,每个类型的组件就由两种类型的组件:一种提供预览,一种提供编辑,(还有一种是发布的,大致跟预览一样,这里不说发布的事,就不写了)
//app.vue
<template>
<div>
<h3 class="mbsm">预览窗口(iphone6)</h3>
<div class="window-ip6">
<component v-for="(currentView,index) in viewList" :key="index" :is="currentView.name" :props.sync="currentView.props" :index="index" @showEditWindow="showEditWindow"></component>
</div>
<h3 class="mbsm">编辑窗口</h3>
<component :is="`edit-${editData.name}`" :props.sync="editData.props" :index="currentIndex"></component>
</div>
</template>
<script>
export default {
data() {
return {
viewList: [
{
name: "default",
props: { msg: "在这里新建你的页面吧" }
}
],
editData: {
name: "default",
props: { msg: "在这里新建你的页面吧" }
},
currentIndex:0
}
},
}
components:{ home ,edit-home }
</script>
上面定义了两个动态组件,一个是预览窗口的循环动态组件,通过viewList
操作组件集合,一个是编辑窗口的动态组件,通过editData
来编辑组件属性。两者通过.sync
来传递属性值,也就是会实时变动。
再来看看组件的编写:
preview目录下(预览组件目录)
//home.vue
<template>
<div @click="showEditWindow">
<!--this is home component-->
{{props.msg}}{{props.width}}
</div>
</template>
<script>
export default {
props:{
props:Object,
index:Number
},
methods: {
showEditWindow() {
this.$emit("showEditWindow",this.index)
}
},
}
</script>
这里给了一个全局的事件showEditWindow
,每次添加组件,app.vue组件就会通过index
把选中的组件在viewList
的顺序(即index)传给home.vue,然后选择点击home.vue组件,再把index传回app.vue,让app.vue可以在viewList中找到选中项的编辑组件
编辑目录下(edit)
//home.vue
<template>
<div>
home edit template
文字:<el-input v-model="props.msg" size="small" placeholder="请输入内容"></el-input>
尺寸:<el-input v-model="props.width" size="small" placeholder="请输入内容"></el-input>
</div>
</template>
<script>
export default {
props:{
props:Object
}
}
</script>
编辑组件主要暴露可以调整的props
,这里用的是element的ui,用普通的input也行,用v-model
进行双向数据绑定即可
选择组件主要是向viewList
添加组件对象,诸如:
//app.vue
addComponent(){
const component = {
"name":"student",
"props":{
"age":12,
"sex":"boy"
}
}
this.viewList.push(component)
//设置当前选中组件序号,编辑组件可显示新添加的组件的编辑属性
this.currentIndex = this.viewList.length-1
}
整体的思路就是这样子的,稍后会有github实践项目开源给大家。
至于其他的功能,就发挥大家的想象力了
优化-异步组件
一般引入组件的方式都是
import home from 'components/home'
import about from 'components/about'
components:{ home ,about }
但是对于我们的动态组件集合,如果每个组件在还没用到的时候先注入了,那么整个js文件就会变得很大,这个问题尤其在配置后的发布页面尤其严重,比如,只需要home和about组件,但是整个模板(app.vue)引用了home、about、index、test...等等十几个组件,这种情况绝对不能过。那么怎么办呢
vue提供了一种异步组件的方式,就是在用到a组件的时候,才引入a组件
具体写法大致如:
components:{
home: ()=>import('components/home'),
about: ()=>import('components/about')
}
这样,页面只会在使用到home和about的时候加载组件
奇思妙想
1.组件在组件列表中的位置移动、删除怎么实现
2.模板(app.vue)的异步动态组件引用如何一次性配置完成,之后再添加组件后不需要手动去注入组件,减少开发异常
3.组件的保存之后台(我用的是monogoose),取数据到发布页面,发布页面如何动态拼凑组件
4.其他功能欢迎补充添加,(觉得好的我会采纳来实现)
补充
对于第二点,说一下我这半年多来做项目的理解,我们做一个项目,设计一套框架流程,其中很重要的一点就是要保证项目页面开发的稳定性和便利性,因为是一个团队开发,所以你开发的页面必然别人也会使用到,所以,如何保证,在团队其他人开发的时候能够迅速的学习,还有开发的稳定性,就成为一个必须要思考的问题。而以我的经验来看,就是可分离
(尽量将其他人编辑的页面与自己的页面分离开),可配置
(把别人需要做的重复工作用代码实现,并提供可配置的相关代码)
就以上面举例,有一个主页面app.vue,用于加载动态组件,还有一对自定义组件,如home.vue、test.vue、about.vue等等。
在app.vue中常规引入自定义组件的方式就是上面的异步组件的方式,然而,这需要每写一个自定义组件,都在主页面添加一次components
,改动主页面风险太大,所以,我做了一下操作
1.定义一个文件夹components
,用于放置自定义组件,在定义一个js文件defaultSeting.js
,用于记录自定义组件
|-components
|-preview
|-home.vue
|-test.vue
|-edit
|-home.vue
|-test.vue
defaultSetting.js
//defaultSetting.js
export default [{
name: 'home',
props: {
tip: 'this.is home component',
}
},
{
name: 'test',
props: {
msg: 'this.is test component',
}
}]
在主页面app.vue可以这么写
import componentList from "component/activity/defaultSetting";
function createComponents(path, type) {
const components = {};
componentList.map(function(element) {
const name = element.name;
let showname = name;
if (!!type) showname = type + "-" + name;
components[showname] = () =>
import(`components/${path}${name}.vue`);
});
return components;
}
export default{
components: Object.assign({},createComponents("preview/"),createComponents("edit/", "edit"))
....
}
这样主页面就一次搞定,之后要添加新组件,就在components
文件夹和defaultSetting.js
两个地方添加修改即可
如果我的文章给了你一点思路上的帮助,那麻烦你去我的github上给个star啦