Open AnnVoV opened 6 years ago
希望我们的后台页面可以靠拖拽组件来生成,开发时只要处理js部分。拖拽后可以查看code直接复制代码。目前设计了一个大框子,大概长下面这个样子:
先说下我在设计这个大框子时遇到的几个问题:
$slots
$createElement
$slots.default
handleNest(result) { const container = result.vueComp; const son = this.$createElement(`my-${this.compName.toLowerCase()}`); container.$slots.default.push(son); container.$mount(); this.component = son.componentInstance;// 这样我们还可以使用this.component去拿到我们添加的方法和属性 },
import { getStringTypeAttr, getResultStringTypeAttr } from '@/components/template'; import mixins from './mixin.js';
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 这个包
设计及初步实现
希望我们的后台页面可以靠拖拽组件来生成,开发时只要处理js部分。拖拽后可以查看code直接复制代码。目前设计了一个大框子,大概长下面这个样子:
思路
先说下我在设计这个大框子时遇到的几个问题:
解决方法
$slots
代码如下(1)通过
$createElement
生成vnode (2)把vnode push到container的$slots.default
数组里 (3)vnode.componentInstance 绑定了这个vnode 最终生成的vue实例,这样有了它,我们就能把修改的属性更新到其身上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;
(2)父子关系之间的查找其实很简单,当我们拖拽一个组件的时候,我们就生成一个id,并且遍历这个组件,为其子元素设置id和对应的parentId。当组件之间发生嵌套时,同样进行处理,这样我们最终只要找到根元素id就能遍历出整个dom结构。 (3)html 代码的格式化使用了pretty这个包, html语法高亮使用了vue-highlightjs 这个包
接下来要做的功能