AnnVoV / blog

24 stars 2 forks source link

拖拽后台页面的设计思路 #13

Open AnnVoV opened 6 years ago

AnnVoV commented 6 years ago

设计及初步实现

希望我们的后台页面可以靠拖拽组件来生成,开发时只要处理js部分。拖拽后可以查看code直接复制代码。目前设计了一个大框子,大概长下面这个样子: demo2

思路

先说下我在设计这个大框子时遇到的几个问题:

const handle = function (_attr, _slots) { // 定义默认属性 const attributes = { content: { type: 'text', valueType: 'text', value: 'el-button', }, type: { type: 'select', valueType: 'text', items: ['primary', 'success', 'warning', 'danger', 'info', 'text'], value: 'primary', }, size: { type: 'select', valueType: 'text', items: ['medium', 'small', 'mini'], value: 'medium', }, disabled: { type: 'select', valueType: 'boolean', items: ['true', 'false'], value: 'false', }, }; const props = { content: { default: 'el-button', }, type: { default: 'primary', }, size: { default: 'medium', }, disabled: { default: false, }, }; const slots = { default: [], };

// 覆盖默认属性 Object.assign(slots, _slots); Object.assign(attributes, _attr); // 获取组件模板 const template = mixins.getStrTemplate(attributes, 'el-button'); // 获取代码模板(组件模板 + 绑定数据值) const getTemplate = (attr, child) => mixins.getTemplateByTag(attributes, attr, 'el-button', child);

return { template, props, attributes, slots, getTemplate, }; }; export default handle;

* 第3个问题-第5个问题其实可以归为一类,都是生成组件后代码展示问题。  
我们利用我们添加的template属性,可以比较容易的获取到字符串模板。但也遇到了以下一些问题:
(1)比如我们左边是可以修改组件的属性信息的,那么模板如何与属性信息进行绑定的?  
(2)组件之间是可以嵌套的,如何建立组件之间的父子关系?
(3)我们最终得到的字符串在代码模式下如何格式化和高亮?
**让我们来依次回答下这些问题:**
(1)其实我们本质是要用下面这个方法,来获取最终模板, 里面核心的就是获取最终attributes字符串的方法
```javascript
export default {
  getTemplateByTag(attributes, attr, tagName, child) {
    const newAttr = _.overwriteDeep(attributes, attr);
    const resStringAttr = getResultStringTypeAttr(newAttr);
    const resTemplate = `<${tagName}
                        ${resStringAttr}>
                        ${child || ''}
                    </${tagName}>`;
    return resTemplate;
  },
}
const getResultStringTypeAttr = function (attributes) {
  // value为空的不添加到模板中
  let stringAttr = '';
  Object.keys(attributes).forEach((key) => {
    let attrKey;
    const arr = ['text', 'selection', 'icon', 'ionicon', 'color']; // 这些类型都不用加bind
    if (arr.includes(attributes[key].valueType)) {
      attrKey = key;
    } else {
      attrKey = `:${key}`;
    }
    if (attrKey === 'value') {
      attrKey = 'v-model';
    }
    const attr = attributes[key].value ? `${attrKey}="${attributes[key].value}"\n` : '';
    stringAttr += attr;
  });
  return stringAttr;
};

(2)父子关系之间的查找其实很简单,当我们拖拽一个组件的时候,我们就生成一个id,并且遍历这个组件,为其子元素设置id和对应的parentId。当组件之间发生嵌套时,同样进行处理,这样我们最终只要找到根元素id就能遍历出整个dom结构。 (3)html 代码的格式化使用了pretty这个包, html语法高亮使用了vue-highlightjs 这个包

接下来要做的功能