Vue3+X6流程图实现数据双向绑定详解

 更新时间:2024年03月12日 08:43:25   作者:阿赛工作室  
这篇文章主要为大家详细介绍了Vue3如何结合X6流程图实现数据双向绑定,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

代码很简单,看看就可以了,不用多说。

定义组件:实现html节点与数据初始化、更新

<script setup lang="ts">
import { Graph, Shape } from "@antv/x6";
import { onMounted, reactive, ref, watch } from "vue";
import useFlowModel from "./useFlowModel";
import flowdata from "./flowdata";

const container: any = ref(null);

Shape.HTML.register({
  shape: "custom-html",
  effect: ["data"],
  html(cell: any) {
    const { bgcolor, label } = cell.getData();
    return `<div style="background:${bgcolor};width:100%;height:100%;">${label}</div>`;
  },
});

const flowModel: any = reactive({
  graph: null,

  datatype: 0,
  modeldata: flowdata,
});
const { graphToModelData, modelDataToGraph, addNode, addNodeData } =
  useFlowModel(flowModel);

onMounted(() => {
  flowModel.graph = new Graph({
    container: container.value,
    // 设置画布背景颜色
    background: {
      color: "#F2F7FA",
    },
    height: 300,
    width: 600,
    grid: {
      visible: true,
      type: "doubleMesh",
      args: [
        {
          color: "#eee", // 主网格线颜色
          thickness: 1, // 主网格线宽度
        },
        {
          color: "#ddd", // 次网格线颜色
          thickness: 1, // 次网格线宽度
          factor: 4, // 主次网格线间隔
        },
      ],
    },
  });

  flowModel.graph.fromJSON(flowModel.modeldata); // 渲染元素
  flowModel.graph.centerContent(); // 居中显示

  flowModel.graph.on("cell:changed", (val: any) => {
    graphToModelData(val);
  });

  watch(
    () => flowModel.modeldata.cells.map((el: any) => JSON.stringify(el.data)),
    (newVal, oldVal) => {
      modelDataToGraph(newVal, oldVal);
    },
    { deep: true }
  );
});
</script>

<template>
  <template
    v-if="flowModel.modeldata?.cells && flowModel.modeldata?.cells[0]?.position"
  >
    <input type="number" v-model="flowModel.modeldata.cells[0].position.x" />
    <input type="text" v-model="flowModel.modeldata.cells[0].data.label" />
    <input type="text" v-model="flowModel.modeldata.cells[0].data.bgcolor" />
  </template>
  【{{ flowModel.modeldata?.cells && flowModel.modeldata?.cells[0].position }}】

  <button @click="addNode()">加G</button>
  <button @click="addNodeData()">加A</button>
  <button
    @click="console.log(666.1001, flowModel.modeldata.cells[0].x, flowModel)"
  >
    实时
  </button>
  <div id="container" ref="container"></div>
  <div class="as-show-model">{{ flowModel.modeldata }}</div>
</template>

<style scoped>
html,
body {
  margin: 0;
  padding: 0;
}
.as-show-model {
  display: inline-block;
  white-space: pre-wrap;
  overflow: auto;
  height: 300px;
  width: 300px;
}
.custom-html {
  outline: 1px dashed bisque;
}
#container {
  display: inline-block;
  background-color: rgb(248, 255, 240);
  margin-right: 8px;
  margin-left: 8px;
  border-radius: 5px;
  box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
</style>

基本函数处理

export default (flowModel: any) => {
  function modelDataToGraph(newVal: any, oldVal: any) {
    // console.log(666.333, oldVal, newVal);
    if (flowModel.datatype) {
      flowModel.datatype = 0;
    } else if (
      !oldVal?.length ||
      !newVal?.length ||
      oldVal?.length !== newVal?.length
    ) {
      flowModel.graph.fromJSON(flowModel.modeldata);
    } else {
      const nowCells: any = flowModel.graph.getCells();
      newVal.forEach((el: any, index: number) => {
        if (!oldVal.includes(el)) {
          flowModel.datatype = 2;
          nowCells[index].setProp({
            data: JSON.parse(el),
          });
        }
      });
    }
  }

  function graphToModelData(val: any) {
    // const { cell, options } = val;
    if (flowModel.datatype) {
      flowModel.datatype = 0;
    } else {
      flowModel.datatype = 1;
      flowModel.modeldata = flowModel.graph.toJSON();
    }
  }

  function addNodeData() {
    flowModel.modeldata.cells.push({
      position: {
        x: 30,
        y: 40,
      },
      size: {
        width: 100,
        height: 40,
      },
      data: {
        bgcolor: "#8f8f8f",
        label: "我是节点",
        color: "#333232",
        a: { B: 1 },
      },
      attrs: {
        text: {
          text: "我是节点",
        },
        body: {
          stroke: "#8f8f8f",
          strokeWidth: 1,
          fill: "#fff",
          rx: 6,
          ry: 6,
        },
      },
      visible: true,
      shape: "custom-html",
      id: "node1" + Date.now(),
      zIndex: 1,
    });
  }
  function addNode() {
    flowModel.graph.addNode({
      shape: "custom-html",
      x: 60,
      y: 100,
      width: 80,
      height: 40,
      data: {
        bgcolor: "#8f8f8f",
        label: "我是节点",
      },
    });
  }

  return { graphToModelData, modelDataToGraph, addNode, addNodeData };
};

演示数据

export default {
  cells: [
    {
      position: {
        x: 30,
        y: 40,
      },
      size: {
        width: 120,
        height: 40,
      },
      data: {
        bgcolor: "#8f8f8f",
        label: "我是节点",
        color: "#333232",
        a: { B: 1 },
      },
      attrs: {},
      visible: true,
      shape: "custom-html",
      id: "node1",
      zIndex: 1,
    },
    {
      position: {
        x: 160,
        y: 180,
      },
      size: {
        width: 111,
        height: 40,
      },
      attrs: {
        text: { text: "世界你好" },
        body: {
          stroke: "#8f8f8f",
          strokeWidth: 1,
          fill: "#fff",
          rx: 6,
          ry: 6,
        },
      },
      visible: true,
      shape: "rect",
      id: "node2",
      zIndex: 1,
    },
    {
      position: {
        x: 190,
        y: 100,
      },
      size: {
        width: 160,
        height: 40,
      },
      data: {
        bgcolor: "#8f8f8f",
        label: "my test",
        color: "#333232",
        a: { B: 1 },
      },
      attrs: {},
      visible: true,
      shape: "custom-html",
      id: "node3",
      zIndex: 1,
    },
    {
      shape: "edge",
      attrs: {
        label: {
          text: "x6",
        },
        line: {
          stroke: "#8f8f8f",
          strokeWidth: 1,
        },
      },
      id: "0d9f0031-f018-413c-9631-1cd21d2f8c1f",
      source: {
        cell: "node1",
      },
      target: {
        cell: "node2",
      },
      labels: [
        {
          attrs: {
            label: {
              text: "x6",
            },
          },
        },
      ],
      zIndex: 1,
    },
  ],
};

以上就是Vue3+X6流程图实现数据双向绑定详解的详细内容,更多关于Vue3数据双向绑定的资料请关注脚本之家其它相关文章!

相关文章

  • Vue3中Teleport的用法小结

    Vue3中Teleport的用法小结

    Teleport是一个内置组件,它可以将一个组件内部的一部分模板传送到该组件的 DOM 结构外层的位置去,本文主要介绍了Vue3中Teleport用法小结,感兴趣的可以了解一下
    2025-04-04
  • vue如何动态绑定img的src属性(v-bind)

    vue如何动态绑定img的src属性(v-bind)

    这篇文章主要介绍了vue如何动态绑定img的src属性(v-bind),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • vue+element+Java实现批量删除功能

    vue+element+Java实现批量删除功能

    这篇文章主要介绍了vue+element+Java实现批量删除功能,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-04-04
  • ElementUI表单验证validate和validateField的使用及区别

    ElementUI表单验证validate和validateField的使用及区别

    Element-UI作为前端框架,最常使用到的就是表单验证,下面这篇文章主要给大家介绍了关于ElementUI表单验证validate和validateField的使用及区别,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • vue+highcharts实现3D饼图效果

    vue+highcharts实现3D饼图效果

    这篇文章主要为大家详细介绍了vue+highcharts实现3D饼图效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Vue实现简单计算器

    Vue实现简单计算器

    这篇文章主要为大家详细介绍了Vue实现简单计算器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01
  • 如何使用el-table实现纯前端导出(适用于el-table任意表格)

    如何使用el-table实现纯前端导出(适用于el-table任意表格)

    我们日常做项目,特别是后台管理系统,常常需要导出excel文件,这篇文章主要给大家介绍了关于如何使用el-table实现纯前端导出的相关资料,本文适用于el-table任意表格,需要的朋友可以参考下
    2024-03-03
  • vue中$router.back()和$router.go()的用法

    vue中$router.back()和$router.go()的用法

    这篇文章主要介绍了vue中$router.back()和$router.go()的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • vue3+koa实现文件上传功能的全过程记录

    vue3+koa实现文件上传功能的全过程记录

    开发项目的时候,用到文件上传的功能很常见,包括单文件上传和多文件上传,下面这篇文章主要给大家介绍了关于vue3+koa实现文件上传功能的相关资料,需要的朋友可以参考下
    2023-01-01
  • Vue 组件上的v-model双向绑定原理解析

    Vue 组件上的v-model双向绑定原理解析

    这篇文章主要介绍了Vue 组件上的v-model双向绑定原理,从本文的学习可以知道组件上v-model指令的本质也是生成了value属性和input事件,具体实例代码跟随小编一起看看吧
    2022-05-05

最新评论