vue-draggable实现模板自定义编辑器

一、效果

image
image.png
这封装成一个组件,在需要使用的地方引入即可,完整代码上传到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>
posted @ 2020-08-20 17:11  风吹麦浪打  阅读(186)  评论(0编辑  收藏  举报