背景:

1、首页模板由多个子组件组成,如图表、新闻、公告、轮播图等,一般都由前端引入子组件,写在固定的位置上,最终形成一个固定的首页模板;

2、像这样直接在代码中写死的首页没有灵活性,不同用户想展示出来的首页模板千篇一律;

3、若是首页模板可以根据用户自己的需求拖拽生成,首页模板的灵活性与交互性将会两者兼备。

描述:

1、通过使用draggable拖拽插件可实现自由拖拽子组件;

【拖拽插件 draggable 详解及意见 - 掘金】

2、draggable可实现左右拖拽,若想完全根据用户的意愿上下左右都可拖拽,在这里我使用的是grid网格布局实现相应功能。

【CSS Grid 网格布局教程 - 阮一峰的网络日志】

测试案例展示:

1)左边为子组件列表,暂时使用色块代表可组成首页的所有组件;

2)右边为拖拽区域,拖拽区域由grid网格布局作为背景板,子组件可根据手动设置的网格布局的大小进行放置;

3)拖拽后的子组件提供了编辑、删除、拖拽三项功能,编辑可控制该子组件的宽高比例,删除后则回到左部组件列表中,拖拽可实现各个子组件之间的位置交换。

代码展示:

一、子组件列表

循环dataList拿到子组件对象数组,鼠标放置时增加遮罩层,显示该子组件的宽高比例、名称;draggable是可拖拽的子组件列表区域,通过dragOptions1进行对拖拽区域内容的控制。

:data-width="item.width"

:data-height="item.height"

:class="[

'item',

'item_width_' + item.width,

'item_height_' + item.height,

'item_' + item.component

]"

v-for="(item, index) in dataList"

:key="index"

>

{{ item.title }}{{ item.width }}×{{ item.height }}

dragOptions1() {

return {

animation: 300,

group: {

name:'group',//名称相同的分组可以相互拖拽

pull:true, //是否允许拖出当前组

put:true //是否允许拖入当前组

},

chosenClass: "sortable-btn",

forceFallback: true,

handle: ".item" // 只有按住拖动手柄才能使列表单元进行拖动

}

},

二、拖拽区域展示

dataList2存放从dataList中拖拽出来的子组件数据信息,同样增加遮罩层moveDialog,展示子组件的功能按钮:编辑、删除。

:class="[

'item',

'item_width_' + item.width,

'item_height_' + item.height,

]"

v-for="(item, index) in dataList2"

:key="index"

>

dragOptions2() {

return {

animation: 300,

group: {

name:'group',

pull:false,

put:true

},

ghostClass: 'ghost',

forceFallback: true,

handle: ".moveDialog"

}

}

三、编辑、删除功能

编辑在这里只写了控制子组件的宽高比例、删除则会将已经拖拽的组件撤回到子组件列表中,具体代码实现如下:

v-model="editModal"

class="edit-modal"

:transfer='false'

:title="`编辑组件信息`"

@on-ok="submitFormEdit"

@on-cancel="handleCancelEdit"

:mask-closable="false">

*(推荐宽度比例:4、8、12、16。)

*(建议高度比例:大于等于当前默认高度。)

*(提示:以上给出的是较为合适的宽高比例,可酌情调整,不建议暴力调整比例。)

// 编辑按钮

edit(row) {

this.editModal = true

this.formValidate = JSON.parse(JSON.stringify(row))

},

// 删除按钮

del(data){

let dataList2 = JSON.parse(JSON.stringify(this.dataList2))

this.dataList2 = dataList2.filter(item => item.chartId !== data.chartId)

this.dataList.push(data)

},

// 编辑弹窗确定按钮

submitFormEdit: function () {

this.$refs['formValidate'].validate((valid) => {

if (valid) {

this.dataList2.map(item => {

if(item.chartId === this.formValidate.chartId){

item.width = this.formValidate.width

item.height = this.formValidate.height

}

return item

})

this.handleCancelEdit()

this.$Message.success('编辑成功!')

} else {

console.log('检验不通过!');

}

})

},

// 编辑弹窗取消按钮

handleCancelEdit() {

this.editModal = false

this.$refs.formValidate.resetFields()

this.formValidate = {

width: 4,

height: 1

}

}

四、拖拽插件的引入、使用及网格布局的使用

(在这里就不过多解释啦~,参考下面提示的文章了解draggable的使用和grid的相关概念)

【拖拽插件 draggable 详解及意见 - 掘金】 【CSS Grid 网格布局教程 - 阮一峰的网络日志】

全部代码实现:

(该案例使用vue2框架书写,实现效果请观看视频https://live.csdn.net/v/284266)

前端小白积累经验篇~~