vue-draggable实现模板自定义编辑器
一、效果
这封装成一个组件,在需要使用的地方引入即可,完整代码上传到git上面了,地址:https://github.com/zxc1989092...
二、基本配置(左边公共组件)
如果您对vue-draggable的基本用法还不熟悉可以看看我之前写的一篇文章,讲的是vue-dragagble的基本配置和用法
https://segmentfault.com/a/11...
定义json数据
sceneWidgets: [
{
type: 'text',
classify: 'text', // 文字、数字、email、phone等
icon: '',
label: '单行节点',
placeholder: '请输入文本',
text: '',
required: false
},
{
type: 'textarea',
icon: '',
label: '多行节点',
placeholder: '请输入文本',
text: ''
},
{
type: 'radio',
icon: '',
label: '单选',
placeholder: '',
text: '',
style: false,
radioList: [
{
value: 1,
label: 'Mac'
},
{
value: 2,
label: 'Ipad'
}
]
},
{
type: 'checkbox',
icon: '',
label: '多选',
placeholder: '',
text: [],
checkboxList: [
{
value: 1,
label: 'Mac'
},
{
value: 2,
label: 'Ipad'
}
]
},
{
type: 'select',
icon: '',
label: '下拉选项',
placeholder: '',
text: '',
selectList: [
{
value: 1,
label: '测试'
}
]
},
{
type: 'date',
icon: '',
label: '日期时间',
placeholder: '',
text: ''
},
{
type: 'link',
icon: 'ios-link',
label: '链接地址',
placeholder: '',
text: 'http://www.baidu.com',
title: '百度一下'
},
{
type: 'place',
icon: '',
label: '省市区县',
placeholder: '',
text: ''
}
]
html代码
<div class="pullList">
<div class="pullBaseTag">
基础节点
</div>
<!-- 公共节点 -->
<draggable
:group="{name: 'scene', pull: 'clone'}"
:sort="false"
v-model="sceneWidgets"
dragClass="pullDragClass"
chosenClass="pullChosenClass"
ghostClass="pullGhostClass"
>
<div v-for="(item, index) in sceneWidgets" :key="index" class="pullRow">
<div class="pullItem" :style="{'margin-left': index % 2 === 1 ? '5px' : 0}">
<div class="pullItemIcon">
<img :src="require('@/assets/images/help-icon.png')" />
</div>
<div class="pullItemText">{{item.label}}</div>
</div>
</div>
</draggable>
</div>
三、中间编辑区域拖拽配置
html代码
<!-- 编辑场景 -->
<draggable
:group="{name: 'scene', put: true}"
:put='true'
handle='.moveHandle'
v-model="sceneEditor"
@change="changeItem"
@choose="chooseItem"
class="putList"
@add="addItem"
>
<div v-for="(item, index) in sceneEditor" :key="(index + 1) * 1000" class="putItem" :class="{'active': index === putAcitveIndex}" v-if="sceneEditor.length > 0" @click="putItemClick (item, index)">
<div class="editSceneLable">
<span class="moveHandle"></span>{{index}} <span>{{item.label}}</span>:
</div>
<div class="editSceneInput">
<!-- 单行文本 -->
<Input type="text" :name="item.type + index" :value="item.text" v-if="item.type === 'text'" @on-change="inputChange($event, item, index)" />
<!-- 多行文本 -->
<Input type="textarea" :name="item.type + index" :value="item.text" v-if="item.type === 'textarea'" @on-change="inputChange($event, item, index)" />
<!-- 单选 -->
<RadioGroup :value="item.text" :vertical="item.style" v-if="item.type === 'radio'" @on-change="inputChange($event, item, index)">
<Radio v-for="(val, i) in item.radioList" :label="val.value" :key="i">{{val.label}}</Radio>
</RadioGroup>
<!-- 多选 -->
<CheckboxGroup :value="item.text" v-if="item.type === 'checkbox'" @on-change="inputChange($event, item, index)">
<Checkbox v-for="(val, i) in item.checkboxList" :label="val.value" :key="i">{{val.label}}</Checkbox>
</CheckboxGroup>
<!-- 下拉选项 -->
<Select :name="item.type + index" v-if="item.type === 'select'" @on-change="inputChange($event, item, index)">
<Option v-for="(val, i) in item.selectList" :value="val.value" :key="i">{{item.label}}</Option>
</Select>
<!-- 日期组件 -->
<DatePicker :type="item.type" :name="item.type + index" :placeholder="item.placeholder" :value="item.text" v-if="item.type === 'date'" @on-change="inputChange($event, item, index)" ></DatePicker>
<!-- 链接地址 -->
<div style="position: relative">
<Input type="text" prefix="ios-link" :name="item.type + index" :placeholder="item.placeholder" :value="item.text" v-if="item.type === 'link'" @on-change="inputChange($event, item, index)" />
<div>{{item.title}}</div>
</div>
<linkage @getLawyerListInfo="inputChange($event, item, index)" v-if="item.type === 'place'"></linkage>
</div>
</div>
<!-- <div class="noTag" v-if="sceneEditor.length === 0">
<div>从左侧拖拽节点</div>
</div> -->
</draggable>
四、右边设置中间编辑器选中的数据,对中间组价进行修改。
不同的组件修改的项目不同,这根据业务需求进行设置,我在这里只做了单选框的设置
html代码
<div class="editItemInfo">
<div v-if="inputItemObj.type === 'text'">
<div class="editTag">
<span class="editTagLabel">节点名称</span>
<span class="editTagNumber">4/10</span>
</div>
<div class="editTag">
<Input type="text" v-model="inputItemObj.label" :maxlength="10" />
</div>
<div class="editTag">
<span class="editTagLabel">格式</span>
</div>
<div class="editTag">
<Select v-model="inputItemObj.classify">
<Option value='text'>文本</Option>
<Option value='number'>数字</Option>
<Option value='phone'>电话号码</Option>
<Option value='email'>邮箱</Option>
</Select>
</div>
<div class="editTag">
<span class="editTagLabel">校验</span>
</div>
<div class="editTag">
<Checkbox v-model="inputItemObj.required" @on-change="requireStateChange">设为必填项</Checkbox>
</div>
</div>
</div>
</div>
五、组件sceneEdit.vue完整代码
<template>
<div class="content">
<div class="sceneEditor">
<div class="pullList">
<div class="pullBaseTag">
基础节点
</div>
<!-- 公共节点 -->
<draggable
:group="{name: 'scene', pull: 'clone'}"
:sort="false"
v-model="sceneWidgets"
dragClass="pullDragClass"
chosenClass="pullChosenClass"
ghostClass="pullGhostClass"
>
<div v-for="(item, index) in sceneWidgets" :key="index" class="pullRow">
<div class="pullItem" :style="{'margin-left': index % 2 === 1 ? '5px' : 0}">
<div class="pullItemIcon">
<img :src="require('@/assets/images/help-icon.png')" />
</div>
<div class="pullItemText">{{item.label}}</div>
</div>
</div>
</draggable>