低代码平台拖拽实现逻辑

330 阅读1分钟

页面分为左中右三栏,左边物料栏定义key,中间是定制的div,右边是设置属性

image.png 代码目录

image.png 最外层的div

<template>
  <div class="dragList">
    <Widgets class="widgets"></Widgets>
    <Panel class="panel" :list='list' v-model:json='json' @changeJson='changeJson'></Panel>
    <Config class="config" :config='state.config'></Config>
  </div>
</template>

<script lang='ts' setup>
import { ref, reactive } from "vue";
import Widgets from "./control/material/index.vue";
import Panel from "./control/components/index.vue";
import Config from "./control/setting/index.vue";

const state = reactive({
  config: {},
});
const list = reactive([]);
const changeJson = (e) => {
  state.config = e;
};
</script>

<style lang="scss"  scoped>
.dragList {
  width: 100%;
  height: 100%;
  padding: 20px;
  display: flex;
  justify-content: space-between;
}
.widgets {
  width: 200px;
  border: 1px solid #000;
  height: 100%;
}
.panel {
  width: 375px;
  box-shadow: 0 0 0.37333333rem 0 rgb(0 0 0 / 10%);
  margin: 70px auto 200px auto;
  background-color: #fff;
}
.config {
  width: 400px;
  height: 100%;
  border: #000 1px solid;
}
</style>

点击切换json进行设置元素的背景色,这里使用的是import Draggable from "vuedraggable";进行拖拽

左边物料区的代码 关键的代码是clone,深拷贝json

<template>
  <div class="dragList-list1">
    <h3 style="text-align:center">标签选择</h3>
    <Draggable :list="componentsJson" item-key="id" :group="{ name: 'TpFormGroup', pull: 'clone', put: false }" :clone="clone" :sort="false" animation="300" @end="end1" class="dragArea1">
      <template #item="{ element }">
        <div>{{element.name}}</div>
      </template>
    </Draggable>
  </div>
</template>

<script lang='ts' setup>
import Draggable from "vuedraggable";
import { componentsJson } from "../components/index";
import _ from "lodash";

const props = withDefaults(
  defineProps<{
    list: any[];
  }>(),
  {
    list: () => [],
  }
);
const clone = (obj) => {
  const newObj = Object.assign(_.cloneDeep(obj), {
    fieldId: `${obj.name}_${new Date().getTime()}`,
  });
  return newObj;
};
</script>
<style lang='scss' scoped>
.dragArea1 {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  padding: 5px;
}
</style>

中间的内容代码 关键代码changeJson(element),将其json传给父组件,双向绑定到右边的设置区域修改

<template>
  <div class="dragList-list2">
    <div class="content-header">拖动至此处</div>
    <Draggable :list="list" item-key="id" group="TpFormGroup" :disabled="false" @start="start2" @end="end2" class="dragArea">
      <template #item="{ element }">
        <div>
          <component :is="element.com" :options='element' @click="changeJson(element)"></component>
        </div>
      </template>
    </Draggable>
    <div class="tabbar" @click="getCompenent">tabbar</div>
  </div>
</template>

<script lang='ts' setup>
import { ref, reactive } from "vue";
import Draggable from "vuedraggable";
import cloneDeep from "lodash/cloneDeep";
import header1 from "@/views/build/control/components/header";
import { componentsJson } from "./index";
console.log("componentsJson", componentsJson);
// import header1 from "./header.vue";
const props = withDefaults(
  defineProps<{
    list: any[];
  }>(),
  {
    list: () => [{}],
  }
);
// const name = ref(header1);
console.log("props.list", props.list, name);
const getCompenent = () => {
  console.log("2", 2);
};
const emits = defineEmits([]);
const changeJson = (element) => {
  emits("changeJson", element);
  console.log("element", element);
};
</script>
<style lang='scss' scoped>
.dragList-list2 {
  display: flex;
  flex-direction: column;
  height: 750px;
  overflow-y: hidden;
}
.dragArea {
  height: calc(100% - 65px);
  flex: 1;
  overflow-x: hidden;
  overflow-y: auto;
}
.dragArea::-webkit-scrollbar {
  width: 0;
}
.list-complete-item-handle {
  height: 300px;
}
.content-header {
  width: 100%;
  height: 88px;
}
.tabbar {
  height: 80px;
  background-color: gray;
}
</style>

在里面定义json

import Header1 from './header.vue'

const componentsJson = [
  {
    name: 'header1',
    label: 'header1',
    com: Header1,
    style: {
      background: 'gray',
      marginTop: '10px',
      marginBottom: '10px',
      borderRadius: '10px',
      // font: '',
    },
    icon: {},
    img: {},
  },
  {
    name: 'header2',
    label: 'header2',
    com: Header1,
    style: {
      background: '#000',
      marginTop: '10px',
      marginBottom: '10px',
      borderRadius: '10px',
      // font: '',
    },
    icon: {},
    img: {},
  },
]
export { componentsJson }

总结:

1.先划分区域,理清代码目录,左中右三栏

2.左边区域拖拽时进行深拷贝,没有就会导致一修改就会全部改到,以及改到json的数据

3.根据需求定义样式的json

4.使用component的:is进行组件渲染,:options进行子组件传值,父组件@click进行传值

5.右边的设置div进行修改样式设置