手把手帶你開發(fā)一個(gè)低代碼可視化平臺(tái)(二)(低代碼開發(fā)平臺(tái)設(shè)計(jì))
前文回顧
我開源的商城零代碼可視化搭建平臺(tái)Mall-Cook受到大家喜愛,使我深受鼓勵(lì)。本著授人以魚不如授人以漁思想,在項(xiàng)目新建shelf分支,帶大家從零開發(fā)一個(gè)自己的可視化搭建平臺(tái)。
上一節(jié)我們:
- 介紹了可視化搭建的架構(gòu)
- 詳細(xì)講解了可視化搭建的核心 – 一套規(guī)范
- 開發(fā)了一個(gè)搭建面板,包括物料的嵌套,物料的工具容器等。
物料JSON構(gòu)建屬性面板流水線
構(gòu)建邏輯
今天我們來開發(fā)通過物料JSON構(gòu)建數(shù)據(jù)面板的邏輯
我們以圖片物料的生成的過程為例(內(nèi)容過多,請(qǐng)放大圖片觀看),物料JSON解析為兩塊:
- 物料屬性描述,用于生成屬性表單面板
- 物料初始數(shù)據(jù),生成物料深拷貝初始數(shù)據(jù),并傳入對(duì)應(yīng)屬性表單,可通過表單修改數(shù)據(jù)
物料JSON
每個(gè)物料JSON都是物料的身份證,記載了物料的詳細(xì)信息。我們解析其中數(shù)據(jù)使用在:
- 物料模板列表 (使用物料初始數(shù)據(jù))
- 生成物料屬性表單面板 (使用物料屬性描述)
{ "name": "圖片", // 物料名稱 "icon": "icon-image", // 物料圖標(biāo) "fields": { // 物料屬性 "imagePath": { // imagePath 屬性 "label": "圖片上傳", // label "type": "upload", // upload 類型 "value": "" // 值 }, "radius": { // radius 屬性 "label": "圖片圓角", // label "type": "number", // number 類型 "value": 0 // 值 } }}
其中屬性type定義了屬性的類型,同時(shí)也選擇了操作此屬性所用的操作組件,我現(xiàn)在定義的基礎(chǔ)類型如下:
開發(fā)實(shí)現(xiàn)
大家清楚邏輯后我們開始開發(fā),實(shí)際開發(fā)主要分為:
- 實(shí)現(xiàn)物料JSON注冊(cè)方法開發(fā)(初始化所有物料的屬性描述、初始數(shù)據(jù))
- 開發(fā)物料屬性面板解析器開發(fā)
- 實(shí)現(xiàn)上述基礎(chǔ)類型操作組件開發(fā)
物料JSON注冊(cè)
開發(fā)邏輯我們把每個(gè)物料的JSON放在自己的包下。然后我就可以根據(jù)這個(gè)規(guī)則,利用require.context遍歷custom-components包下文件,找到所有component.json進(jìn)行物料注冊(cè)
物料JSON注冊(cè)方法實(shí)現(xiàn):
/* * 解析物料Schmea,注冊(cè)各物料屬性參數(shù)與初始值 */import Vue from 'vue'// 調(diào)用注冊(cè)物料registerComponentsSchema()// 注冊(cè)物料方法function registerComponentsSchema () { // 獲取custom-components包下所有component.json const files = require.context('@/custom-components', true, /component.json$/) // 物料屬性描述對(duì)象 (使用object類型方便調(diào)用) let fields = {} // 物料初始化數(shù)據(jù)集合 let initializing = [] // 遍歷component.json注冊(cè)物料 files.keys().forEach(key => { // 獲取物料名 const [, name] = key.split('/') let config = { component: name, ...files(key) } // 添加物料屬性描述 fields[name] = config.fields // 添加物料初始數(shù)據(jù) initializing.push(initDefaulValue(config)) }) // Vue原型上綁定物料屬性描述對(duì)象,方便調(diào)用 Vue.prototype.$fields = fields // Vue原型上綁定物料初始化數(shù)據(jù)集合,方便調(diào)用 Vue.prototype.$initializing = initializing}// 獲取物料初始數(shù)據(jù),默認(rèn)過濾fields屬性function initDefaulValue (config) { let { component, name, icon, fields } = config let temp = { component, name, icon } setDefaultValue(fields, temp) return temp}// 遞歸設(shè)置各層級(jí)初始數(shù)據(jù)(會(huì)存在多層級(jí)復(fù)雜對(duì)象類型)function setDefaultValue (fields, initializing) { for (let key in fields) { let { type, value, child } = fields[key] if (type == 'object') { initializing[key] = {} child && setDefaultValue(fields[key].child, initializing[key]) } else { initializing[key] = value } } return initializing}
通過注冊(cè)我們會(huì)獲得:
- Vue.prototype.$fields (物料屬性描述對(duì)象)
- Vue.prototype.$initializing(物料初始化數(shù)據(jù)集合)
屬性面板解析器
開發(fā)邏輯
- 遍歷屬性描述對(duì)象,獲取每個(gè)屬性的label、type等信息,然后渲染對(duì)應(yīng)操作組件,生成屬性表單。
- 傳入物料數(shù)據(jù),把value設(shè)到對(duì)應(yīng)屬性操作組件,即可通過操作屬性表單進(jìn)行修改
<template> <ul> <!-- 遍歷物料屬性描述對(duì)象 --> <li v-for="(s, key, index) in schema" :key="index"> <!-- 根據(jù)屬性類型,渲染對(duì)應(yīng)的操作組件 --> <component :key="index" :is="getComponents(s.type)" v-model="value[key]" v-bind="s" :schema="s" > <!-- 遞歸組件 --> <custom-schema-template v-if="s.child" :schema="s.child" :value="value[key]" ></custom-schema-template> </component> </li> </ul></template><script>export default { name: 'custom-schema-template', provide () { return { mode: this } }, props: { schema: { // 物料屬性描述對(duì)象 typeof: Object, default: () => {} }, value: { // 物料數(shù)據(jù) typeof: Object, default: () => {} } }, methods: { // 獲取對(duì)應(yīng)類型的操作組件名,組件名定義為:schema-類型 // 例: input類型 -> schema-input getComponents(type){ return `schema-${type}` } }}</script>
細(xì)心的同學(xué)會(huì)發(fā)現(xiàn),屬性面板解析器也是遞歸嵌套組件。這是因?yàn)閷傩灶愋统嘶A(chǔ)類型外還存在復(fù)合類型,比如對(duì)象、對(duì)象數(shù)組等。復(fù)合類型會(huì)在下一節(jié)具體講解。
基礎(chǔ)類型操作組件
最后就是開發(fā)下圖的基礎(chǔ)類型操作組件,這塊開發(fā)比較簡單,我們?nèi)我?strong>舉個(gè)栗子
sting類型 -> SchemaString組件
<template> <config-item :label='label'> <!-- input組件 --> <el-input v-model="mValue" v-bind="mOptions" :placeholder='mOptions.placeholder' size='small' ></el-input> </config-item></template><script>import schemaMixin from "@/mixin/schemaMixin";export default { name: "SchemaString", // 使用mixin,混入公用代碼 mixins: [schemaMixin],};</script>
結(jié)尾
下一節(jié)預(yù)告
- 開發(fā)兼容物料屬性復(fù)雜類型
- 開發(fā)JsonSchema生成器,可視化生成物料屬性描述JSON