背景

每一次新项目的准备开发工作,都总是在重复使用组件去开发一个项目。组件的复用率虽然高,但还是需要开发人员去进行路由页面的开发工作,工作任务仍归类给前端。在这样的背景下,搭建可视化页面编辑的中台系统尤为重要,这样可以解决大部分的前台开发工作。

效果图

veui效果图

思路示意图

思路分析图

思路分析

  1. 所有面板之间的数据交互使用Vuex进行管理;
  2. 组件使用封装的mount方法实例化组件;
  3. 使用scopedStyle方法为组件插入scoped css
  4. 拖曳组件时,设置被拖曳的组件数据,拖曳结束后,为预览面板新增一条组件数据,并实例化被拖曳的组件;
  5. 属性面板只显示当前组件(currentComponent)的属性。

核心代码解析

  • mount()
// 给定模板,和要挂载的元素id,挂载组件
var mount = function (id, _component) {
    // 数据响应关系脱离
    let _vue = global.deepClone(_component.vue);
    
    if ( _vue.script && typeof _vue.script==='string' ) {
        _vue.script = eval('(' + _vue.script + ')');
    }

    return new Promise((resolve, reject) => {
        //需要延迟才能取到document.getElementById(id)
        setTimeout(() => {
    
            let VUELint = function (key,type) {
                let _default; 
                let script   = _vue.script || {};
                let toString = Object.prototype.toString;

                switch (type) {
                    case 'Object':
                        _default = {};
                        break;

                    case 'Function':
                        _default = ()=> {};
                        break;
                }

                if ( !script.hasOwnProperty(key) ) {
                    return _default;
                } else if ( toString.call(script[key]).slice(8,-1)===type ) {
                    if ( type==='Object' ) {
                        return script[key];
                    } else if ( type==='Function' ) {
                        return script[key].call(this);
                    }
                }
            };
            
            // 返回一个对象, 融合了组件暴露的属性和data数据,暴露的属性(attributes)优先于data, 且不一定存在于data
            let VUEdata = function (){
                let data = {};
                let attributes = {};

                if ( _vue.script.data ) {
                    data = _vue.script.data();
                }

                if ( _component.attributes ) {
                    Object.keys(_component.attributes).forEach(key => {
                        attributes[key] = _component.attributes[key].value;
                    });
                }
                
                return Object.assign(data, attributes);
            };
            
            // 核心代码
            let vm = new Vue({
                router,
                store,
                name         : id.toString(),
                el           : document.getElementById(id),
                template     : _vue.template,
                data         : VUEdata.call(this),
                beforeCreate : VUELint.call(this,'beforeCreate','Function'),
                created      : VUELint.call(this,'created','Function'),
                beforeMount  : VUELint.call(this,'beforeMount','Function'),
                mounted () {
                    this.$el.id = id;
                    
                    scopedStyle(this.$el, _vue.css);

                    VUELint.call(this,'mounted','Function');
                },
                beforeUpdate : VUELint.call(this,'beforeUpdate','Function'),
                updated      : VUELint.call(this,'updated','Function'),
                beforeDestroy: VUELint.call(this,'beforeDestroy','Function'),
                destroyed    : VUELint.call(this,'destroyed','Function'),
                computed     : VUELint.call(this,'computed','Object'),
                watch        : VUELint.call(this,'watch','Object'),
                filters      : VUELint.call(this,'filters','Object'),
                methods      : VUELint.call(this,'methods','Object'),
            });

            resolve(vm); 
            
        }, 200);
    });

项目地址

vue-veui

Logo

前往低代码交流专区

更多推荐