起因
我在月初開源的商城零代碼可視化搭建平臺Mall-Cook受到大家喜愛,使我深受鼓勵,謝謝大佬們的支持。本著授人以魚不如授人以漁思想,決定在項(xiàng)目新建shelf分支,從零開發(fā)一個"干凈"的可視化搭建平臺,帶大家開發(fā)一個自己的可視化搭建平臺。
可視化搭建核心
架構(gòu)
先看一下我理解的無代碼可視化搭建平臺架構(gòu),可視化搭建平臺主要有兩塊:
- 項(xiàng)目拖拽搭建平臺的構(gòu)建
- 物料接入平臺流水線的構(gòu)建
核心
可視化搭建的核心是什么?
開發(fā)搭建平臺使我們搭起了可視化構(gòu)建的架子,接下來只需要根據(jù)實(shí)際使用場景更新物料庫"運(yùn)營"平臺。 而在更新物料庫時(shí)(老物料的迭代與新物料的開發(fā)),我們也需要同步修改平臺來兼容物料庫。那怎么解決這個問題呢?
我的解決辦法是,利用Json Schema協(xié)議規(guī)范Json的作用,用規(guī)范的Json來描述物料,然后用物料屬性解析器來解析、構(gòu)造物料的屬性面板,我們更新物料庫時(shí)只需要修改對應(yīng)Json即可。最后提供Schema生成器可視化生成Json,避免用戶手動修改Json,完成一整條物料接入平臺流水線的構(gòu)建。
這時(shí)我們再回到問題,我認(rèn)為可視化搭建的核心是一套規(guī)范!
在平臺中我們利用Schema協(xié)議定義了物料屬性規(guī)范,然后遵循規(guī)范構(gòu)建一條標(biāo)準(zhǔn)接入的流水線。我們在開發(fā)同理可以定義其他規(guī)范,完成組件交互、頁面生命周期、遠(yuǎn)程接口調(diào)用等標(biāo)準(zhǔn)流水線(此平臺為無代碼平臺,開發(fā)低代碼平臺需要上述功能)。
畫虎畫皮難畫骨,我認(rèn)為這才是可視化搭建的難點(diǎn)!
開發(fā)拖拽搭建面板
我們使用的拖拽插件是vuedraggable,主要邏輯為拖拽模板物料到頁面面板,深拷貝物料配置數(shù)據(jù)到頁面配置中。
核心代碼
<!-- 物料模板列表 --> <draggable v-model="widgets" // 拖拽列表數(shù)據(jù)源 :options="{ group:{ name: 'itxst', // 可拖拽列組,相同表名可相互推拽 pull: 'clone' // 拖拽模板物料,復(fù)制到目標(biāo)列表 }, sort: false // 是否可推拽排序 }" :clone="handleClone" // 復(fù)制模板物料執(zhí)行方法 animation="300" // 動畫延遲 > <div v-for="(item, index) in widgets" :key="index" class="control-widgets-item" > <i class="iconfont" :class="item.icon"></i> <span class="f13">{{ item.label }}</span> </div> </draggable>
<!-- 頁面面板 --> <draggable v-model="mList" // 拖拽列表數(shù)據(jù)源 group="itxst" // 可拖拽列組,相同表名可相互推拽 ghostClass="ghost" // 拖動元素的占位樣式class chosenClass="chosen" // 選中目標(biāo)的樣式class selector="selector" :animation="500" // 動畫延遲 :sort="true" // 是否可推拽排序 class="panel" > <component v-for="item in mList" :key="item.id" :is="item.component" v-bind="item" ></component> </draggable>
// 拷貝物料模板 handleClone(cmp) { return { ...this.$cloneDeep(model), // 深拷貝物料模板 id: this.$getRandomCode(8), // 生成物料id },
開發(fā)可嵌套物料
想要實(shí)現(xiàn)可嵌套物料主要有三點(diǎn):
- 物料中包含slot,已供子物料存放
- 物料配置中增加children屬性,用于存放子物料配置
- 遞歸渲染物料實(shí)現(xiàn)無限層級嵌套
核心代碼
<!-- 遞歸可嵌套組件 --> <draggable v-model="list" group="itxst" ghostClass="ghost" chosenClass="chosen" selector="selector" :animation="500" :sort="true" :class="[isWidget ? 'nest-child' : 'nest-area']" > <component v-for="item in list" :key="item.id" :is="item.component" v-bind="item" > // 包含slot的組件才能進(jìn)行嵌套渲染 <ControlNestWidget :widgets.sync="item.children" // 子物料列表 :isWidget="true" // 是否為子物料 ></ControlNestWidget> </component> </draggable>
開發(fā)物料容器
接下來我們?yōu)轫撁娴奈锪霞右粋€保姆工具欄,使用容器組件可以解耦代碼功能,功能如下所示
<!-- 物料操作容器 --> <div class="shape" @click.stop="setcurComponent(widget)" ref="shape"> <!-- 選中組件高亮 --> <div v-if="isCurComponent(widget.id)" class="shape-solid event-none"></div> <!-- 組件工具欄 --> <div v-if="show" class="shape-tab" :style="{ right: getRightStyle() }"> <!-- 選中顯示刪除按鈕 --> <template v-if="isCurComponent(widget.id)"> <i class="iconfont icon-shanchu tab-icon f16" @click.stop="delComponent(chontrol.widgets, widget.id)" ></i> </template> <!-- 未選擇顯示物料名 --> <span v-else>{{ widget.label }}</span> </div> <!-- 插槽 --> <slot></slot> </div>
<!-- 使用物料容器 --> <widget-shape v-for="item in list" :key="item.id" :widget="item"> <component :is="item.component" v-bind="item" ></component> </widget-shape>
因?yàn)橛星短捉M件,所以刪除物料時(shí)應(yīng)遞歸遍歷刪除
// 刪除物料 delComponent(list, id) { // 遍歷查找目標(biāo)下標(biāo) let index = list.reduce((pre, cur, i) => { return cur.id == id ? i : pre; }, -1); // 找到目標(biāo),刪除物料 if (index >= 0) { list.splice(index, 1); } else { // 遞歸子物料 list .filter((c) => c.children) .forEach((c) => { this.delComponent(c.children, id); }); } }
下一節(jié)預(yù)告
我們已經(jīng)開發(fā)了可視化搭建的架子,下一節(jié)會講述:
- 使用json描述物料
- 開發(fā)物料屬性解析器,解析生成屬性面板
- 開發(fā)屬性面板基礎(chǔ)類型組件(string、number等
版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。