vue

基于vue的动态组件配置系统设计二:设计思路与实现

2018-01-23  本文已影响60人  小熊前端

上篇文章地址

本文重点

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啦

上一篇 下一篇

猜你喜欢

热点阅读