前文回顾
我开源的商城零代码可视化搭建平台Mall-Cook受到大家喜爱,使我深受鼓励。本着授人以鱼不如授人以渔思想,在项目新建shelf分支,带大家从零开发一个自己的可视化搭建平台。
前面我们已经:
-
介绍了可视化搭建的架构,开发了可嵌套搭建面板
-
介绍了物料JSON构建属性面板流水线,开发了基础类型与复合类型属性的构建
本章目的
前面我们已经开发了物料JSON构建属性面板流水线,通过物料JSON这张身卡来解析构建物料属性面板。
因为JSON是无规则的,所以我们定义了JSON Schema规范来约束JSON。
可按照规范编写JSON费时费力,且容易出错,为了避免手动繁琐编写的JSON,我们选择开发Json Schema生成器,通过可视化组装属性面板,生成符合平台JSON Schema规范的JSON,补上整条流水线的最后一环。
Json Schema生成器
类似可视化搭建,我们通过拖拽各类型的物料操作组件,可视化的组装属性面板,然后解析成JSON。
基础演示
前文我们介绍了复合类型,所以需提供组件嵌套,实现object、array类型的容器嵌套
对象类型
对象数组类型
构建标题物料属性面板
我们举个栗子可视化组装标题物料的属性面板
标题物料的属性面板
Schema生成器构建
导出JSON
开发
接下来我们来开发Json Schema生成器,功能主要分为:
- 注册属性类型操作组件JSON
- 开发生成器可嵌套搭建面板
- 生成JSON
生成器可嵌套搭建面板
开发逻辑每个类型操作组件包里,也有一个initializing.js作为它的身份卡。然后我就根据这个规则,利用require.context遍历custom-schema-template包下文件,找到所有initializing.js进行注册
注册类型操作组件,创建$cmpConfig(操作组件描述数组)
// 获取所有属性配置组件 initializing
function registerSchemaInitializing() {
const files = require.context("@/custom-schema-template", true, /initializing.js$/);
const list = [];
files.keys().forEach((key) => {
let name = key.replace(/(\.\/|\/initializing.js)/g, "");
let [, , componentName] = key.split('/') // 获取组件名
list.push({ component: componentName, ...files(key).default })
});
Vue.prototype.$cmpConfig = list
}
复制代码
开发生成器可嵌套搭建面板
我们使用的拖拽插件是vuedraggable,主要逻辑为拖拽模板物料到页面面板,深拷贝物料配置数据到页面配置中。
<!-- 生成器搭建面板 -->
<template>
<div class="canvas">
<!-- 页面面板 -->
<div class="canvas-center">
<div class="canvas-center-drag">
<schema-content-item
:componentList.sync="content.model.componentList"
></schema-content-item>
</div>
</div>
<!-- 物料模板列表 -->
<div class="canvas-left">
<draggable
v-model="$cmpConfig"
:options="{ group: { name: 'itxst', pull: 'clone' }, sort: false }"
:clone="handleClone"
animation="300"
>
<div
v-for="(item, index) in $cmpConfig"
:key="index"
class="canvas-left-item"
>
<span class="f13">{{ item.label }}</span>
<span class="canvas-left-item-type">{{ item.type }}</span>
</div>
</draggable>
</div>
<!-- 属性面板 -->
<div class="canvas-right">
<component
v-if="content.curComponent"
:is="curComponentConfig"
v-bind="content.curComponent"
></component>
<schema-component v-else></schema-component>
</div>
</div>
</template>
<script>
export default {
inject: ["content"],
computed: {
curComponentConfig() {
return `${this.content?.curComponent?.component}Config`;
},
},
methods: {
// 拷贝模板,生成组件
handleClone(model) {
return {
...this._.cloneDeep(model),
id: this.$getRandomCode(8),
property: `${model.type}_${this.$getRandomCode(2, false)}`,
};
},
},
};
</script>
复制代码
想要实现可嵌套物料主要有三点:
- 物料中包含slot,已供子物料存放
- 物料配置中增加children属性,用于存放子物料配置
- 递归渲染物料实现无限层级嵌套
<!-- 递归可嵌套组件 -->
<template>
<draggable
v-model="list"
group="itxst"
ghostClass="ghost"
chosenClass="chosen"
selector="selector"
:animation="500"
:sort="true"
:class="[isChild ? 'drag-child' : 'drag-area']"
>
<schema-content-shape v-for="item in list" :key="item.id" :data="item">
<component
:is="item.component"
:component-key="item.id"
:edit="true"
v-bind="item"
:class="[['object', 'array'].includes(item.type) ? '' : 'event-none']"
>
<!-- 包含slot的组件才能进行嵌套渲染 -->
<schema-content-item
:componentList.sync="item.child" // 子物料列表
:isChild="true" // 是否为子物料
></schema-content-item>
</component>
</schema-content-shape>
</draggable>
</template>
复制代码
编译生成JSON
组合把组件列表解析成JSON,由于存在复合类型,所以属性(fields)有可能为树状结构
// 编译物料JSON
parsing () {
this.config = {
label: this.content.model.label,
icon: this.content.model.icon,
fields: {}
}
this.content.model.componentList.map(cmp => {
this.parsingFields(cmp, this.config.fields)
})
this.isComplete = true
},
// 递归解析物料属性
parsingFields (config, fields) {
let { property, label, type, child, value, data, options } = config
let target = (fields[property] = ['object', 'array'].includes(type)
? { label, type }
: { label, type, value })
data && (target.data = data)
options && (target.options = options)
if (child) {
target.child = {}
child.map(c => this.parsingFields(c, target.child))
}
}
复制代码
下一节预告
- 开发多页面构建
- 开发模板项目,实现实时预览与封面自动生成
系列文章
- 【平台开源】基于Vue实现商城可视化无代码搭建平台 Mall-Cook
- 手把手带你开发一个低代码可视化平台(一)拖拽搭建面板开发
- 手把手带你开发一个低代码可视化平台(二)拖拽搭建面板开发
- 手把手带你开发一个低代码可视化平台(三)拖拽搭建面板开发
交流群
交流群二维码可在项目github首页查看Mall-Cook主页