低代碼開發(fā)之vue.draggable的使用(進階:組件化拖拽生成功能頁面)

效果展示:

20240126-161933.gif

前言:隨著各公司定制化需求的不斷攀升烤送,公司對低代碼、組態(tài)化的開發(fā)需求日漸迫切糠悯。也許是研發(fā)任務節(jié)點將至帮坚,也許是為順應時代潮流,我也是去學習并實踐了一番互艾。如圖所示調(diào)研后是正式上線的一期組態(tài)化版本试和,主要應對不同甲方的多站概覽頁面的定制化需求,此處為了脫敏纫普,已將相關(guān)logo去掉阅悍,只保留了功能頁面。

功能簡介:

左側(cè)組件區(qū)域特意做了選中態(tài)昨稼,小眼睛預覽浮框態(tài)等交互节视,右側(cè)內(nèi)容區(qū)域支持增加、刪除假栓、退出寻行、重置、預覽 匾荆、保存拌蜘、應用等操作,以及組態(tài)化最重要的功能點--隨意拖拽換位牙丽,后期考慮增加屬性面板支持對拖拽進來的組件進行寬高简卧、顏色等的二次編輯修飾。

具體實現(xiàn):

1烤芦、實現(xiàn)流程依據(jù)

通過json實現(xiàn)贞滨,預先定義好描述組件的json,json包含了當前組件數(shù)據(jù)和當前組件的樣式屬性數(shù)據(jù)等拍棕,并通過組件生成器將將描述組件的json結(jié)合起來渲染出實際組件晓铆,當修改樣式屬性時,組件樣式同步更新绰播;

示例json:

json:{
  fieldid:"",
  name:"Input",
  label:"單行文本",
  icon:"input01",
  placeholder:"請輸入",
  value:"",
  rules:{},
  style:{},//組件的樣式
  setting:{},//組件的其他屬性骄噪,比如:row:2

實現(xiàn)原理思維導圖:


image.png
2、實現(xiàn)詳情介紹

此需求基于開源的vue.draggable ^2.24.3蠢箩,Vue項目首先需要去npm i -S vuedraggable下載vue.draggable相關(guān)依賴链蕊,并導入注冊draggable組件事甜。如果是原生js直接CDN形式引用vuedraggable壓縮文件即可。建議沒看過我初階版本博客的小伙伴去看一下上篇文章再來滔韵,沿襲上篇代碼還是分組件區(qū)跟內(nèi)容區(qū)兩個group逻谦,group要名稱一致才可以建立拖拽關(guān)系,那么假設我們內(nèi)容區(qū)域group起名module陪蜻,那么組件內(nèi)區(qū)域應該也命module邦马,結(jié)合展開面板組件使用那么json結(jié)構(gòu)如下:

componentsList:[
    {
        key: "1",
        name: "頂部指標欄",
        group: { name: "module", pull: "clone", put: false },
        child: [
            {
                id: 1,
                type: 0,
                col: 24,
                name: "默認樣式",
                imgSrc: "TopIndicator",
                componentName: "TopIndicator",
                activeKey: true
            },
            {
                id: 2,
                type: 1,
                col: 24,
                name: "樣式一",
                imgSrc: "TopIndicatorOne",
                componentName: "TopIndicator",
                activeKey: false
            },
            {
                id: 3,
                type: 2,
                col: 24,
                name: "樣式二",
                imgSrc: "TopIndicatorTwo",
                componentName: "TopIndicator",
                activeKey: false
            }
        ]
    },
    ......
]

組件區(qū)域代碼

<div class="left-components beautify-scroll">
                    <a-collapse v-model="activeKey">
                        <a-collapse-panel
                            :key="item.key"
                            :header="item.name"
                            v-for="item in componentsList"
                        >
                            <draggable
                                v-model="item.child"
                                draggable=".li"
                                v-bind="dragOptions"
                                :options="{ sort: false, group: item.group }"
                            >
                                <div
                                    v-for="d in item.child"
                                    :key="d.id + 'item'"
                                    :class="[
                                        'li',
                                        d.componentName,
                                        d.col == 12 ? 'w5' : null,
                                        d.activeKey ? 'active' : null
                                    ]"
                                >
                                    <div class="txt">{{ d.name }}</div>
                                    <img
                                        class="img"
                                        :src="
                                            require(`@/assets/images/configuration/${d.imgSrc}.png`)
                                        "
                                        alt=""
                                    />
                                    <div
                                        class="eyes"
                                        @mouseover="panelShow($event, d, item)"
                                        @mouseout="panelHide"
                                    ></div>
                                </div>
                                <div
                                    :class="[
                                        'amplifier-img-box',
                                        panelComponentName
                                    ]"
                                    :style="{ top: panelTop, left: panelLeft }"
                                    v-show="
                                        panelFlag && panelParentKey == item.key
                                    "
                                >
                                    <div class="panel-title">
                                        {{ panelName }}
                                    </div>
                                    <img
                                        class="panel-img"
                                        :src="panelImgSrc"
                                        alt=""
                                    />
                                </div>
                            </draggable>
                        </a-collapse-panel>
                    </a-collapse>
                </div>

內(nèi)容區(qū)json

contentList:[
    {
        id: 1,
        type: 0,
        col: 24,
        name: "默認樣式",
        imgSrc: "TopIndicator",
        componentName: "TopIndicator",
        activeKey: false
    },
    {
        id: 4,
        type: 0,
        col: 24,
        name: "默認樣式",
        imgSrc: "IncomeIndicators",
        componentName: "IncomeIndicators",
        activeKey: false
    },
  ......
]

內(nèi)容區(qū)代碼,實現(xiàn)思路是用:is="item.componentName"去對應組件名注冊寫好的組件宴卖,這樣就可以在draggable的渲染布局里面渲染具體組件

        <draggable
                    class="content beautify-scroll"
                    group="module"
                    v-bind="dragOptions"
                    :list="contentList"
                    @change="toChange"
                >
                    <div
                        v-for="(item, index) in contentList"
                        :key="'r' + index"
                        :class="[
                            'item',
                            item.componentName,
                            item.col == 12 ? 'w5' : null
                        ]"
                    >
                            <component
                                :key="'c' + item.componentName + item.type"
                                :is="item.componentName"
                                :isEdit="true"
                                :type="Number(item.type)"
                                @click.native="selectContentItem(item)"
                                :class="[
                                    item.id == contentActiveId ? 'active' : null
                                ]"
                            ></component>
                            <div
                                v-show="item.id == contentActiveId"
                                class="delbtn"
                                @click="del(item, index)"
                            ></div>
                    </div>
          </draggable>

小眼睛顯示預覽圖浮框不建議用hover去做滋将,因為這里樣式涉及overflow: hidden;如下圖用鼠標事件去做會更好。

methods:

// 鼠標移入顯示浮態(tài)框
        panelShow(e, d, item) {
            console.log(e, d, item);
            this.panelName = item.name + " - " + d.name;
            this.panelComponentName = d.componentName;
            this.panelImgSrc = require(`@/assets/images/configuration/${d.imgSrc}.png`);
            // 獲取窗口寬度
            let windowHeight =
                window.innerHeight ||
                document.documentElement.clientHeight ||
                document.body.clientHeight;
            // 判斷當前鼠標位置加上面板位置大于窗口寬度症昏,表示超出不足以顯示随闽,定位向上進行定位
            if (e.clientY + 276 > windowHeight) {
                this.panelTop = e.clientY - 296 + "px";
            } else {
                this.panelTop = e.clientY - 40 + "px";
            }

            this.panelLeft = e.clientX + 26 + "px";
            this.panelParentKey = item.key;
            this.panelFlag = true;
        },
        // 鼠標移出隱藏浮態(tài)框
        panelHide() {
            this.panelFlag = false;
            this.panelName = "";
            this.panelImgSrc = undefined;
        },

最后再補上一個組件的刪除函數(shù),因為內(nèi)容區(qū)刪除要聯(lián)動把組件區(qū)選中態(tài)去除肝谭,所以這里的刪除里面要多一些邏輯控制

    del(el, idx) {
            this.contentList.splice(idx, 1);
            // 刪除 取消框選態(tài)
            this.componentsList.map((item) => {
                item.child.map((i) => {
                    if (i.id == el.id) {
                        i.activeKey = false;
                    }
                });
            });
        },

創(chuàng)作不易掘宪,點贊支持!H林颉添诉!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市医寿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蘑斧,老刑警劉巖靖秩,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異竖瘾,居然都是意外死亡沟突,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門捕传,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惠拭,“玉大人,你說我怎么就攤上這事庸论≈案ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵聂示,是天一觀的道長域携。 經(jīng)常有香客問我,道長鱼喉,這世上最難降的妖魔是什么秀鞭? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任趋观,我火速辦了婚禮,結(jié)果婚禮上锋边,老公的妹妹穿的比我還像新娘皱坛。我一直安慰自己,他們只是感情好豆巨,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布剩辟。 她就那樣靜靜地躺著,像睡著了一般搀矫。 火紅的嫁衣襯著肌膚如雪抹沪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天瓤球,我揣著相機與錄音融欧,去河邊找鬼。 笑死卦羡,一個胖子當著我的面吹牛噪馏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播绿饵,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼欠肾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拟赊?” 一聲冷哼從身側(cè)響起刺桃,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吸祟,沒想到半個月后瑟慈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡屋匕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年葛碧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片过吻。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡进泼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纤虽,到底是詐尸還是另有隱情乳绕,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布逼纸,位于F島的核電站刷袍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏樊展。R本人自食惡果不足惜呻纹,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一堆生、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧雷酪,春花似錦淑仆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吩跋,卻和暖如春寞射,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锌钮。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工桥温, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人梁丘。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓侵浸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親氛谜。 傳聞我的和親對象是個殘疾皇子掏觉,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容