vue3中使用antv-X6实现关系图

news2024/11/24 8:43:16

先看效果图:

1、安装 npm install@antv/x6 --save

这里使用的X6中自定义节点的方式实现的,项目目录如下,hooks里面存放一些函数和变量

nodes里面是自定义节点的页面,最外围的index.vue就是主渲染页面

2、testSh/index.vue

注意:

(1)代码如下,里面有个useMouse()函数,追踪鼠标位置,这个需要项目中安装vueuse,可以查看下面文章去自行安装,Vueuse中文文档详解_笔记大全_设计学院

<template>
  <div class="w-full h-full">
    <div class="centerPart w-full h90%">
      <div id="container" ref="containerRef"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  messageWarning,
} from "@/utils/element-utils/notification-common";
import { Graph } from "@antv/x6";
import { register } from "@antv/x6-vue-shape";
import { DagreLayout } from "@antv/layout";
import type { Edge } from "@antv/x6";
import { edgeStyle, setEdge, ILink, Data } from "./hooks/comGraph";
import GraphNode from "./nodes/index.vue";

const graph = ref<Graph>(); //graph实例
const containerRef = ref(); //graph容器ref实例
let nodes: any = ref([]);
let edges: any = ref([]);
const myLinks = ref<any>([]); //保存我的所有边

onMounted(() => {
  getNodeList();
});
// 获取节点和边
const getNodeList = async () => {
  let { tables, links } = Data;
  nodes.value = tables;
  links.forEach((aa: any, i: any) => {
    aa.modelId = aa.modelId + i;
  });
  edges.value = links;
  myLinks.value = links;
  init();
};
// 放大缩小zoom
const resizeGraph = (val: string) => {
  val == "add" ? graph.value?.zoom(0.1) : graph.value?.zoom(-0.1);
};
// graph初始化
const init = () => {
  const data: any = {
    nodes: [],
    edges: [],
  };
  register({
    shape: "custom-node",
    width: 250,
    height: 150,
    component: GraphNode,
  });
  // 添加节点
  nodes.value.forEach((item: any, i: string) => {
    data.nodes!.push({
      id: item?.path,
      shape: "custom-node",
      label: item?.name,
      data: {
        ...item,
        toolClickEvent: nodeClickCallback, //结点操作回调事件
      }, //向节点组件传递数据或者方法
    });
  });
  // 添加边
  edges.value.forEach((item: any, i: string) => {
    data.edges!.push({
      source: item.sourcePath,
      target: item.targetPath,
      ...edgeStyle,
    });
  });
  // 初始化实例
  graph.value = new Graph({
    container: document.getElementById("container")!,
    //对画布进行缩放
    mousewheel: {
      enabled: true, //是否开启滚轮缩放交互
      maxScale: 2, //缩放的倍数
      minScale: 0.1, //缩放的最小倍数
    },
    autoResize: true, //设置撑开屏幕
    panning: true,
    background: {
      color: "#F7FAFD",
    },
    onEdgeLabelRendered: (args) => {
      const { selectors, edge } = args as any
      console.log(selectors, edge, '------------');
    },
  });
  // 基本布局,从左向右
  const dagreLayout = new DagreLayout({
    type: "dagre",
    rankdir: "LR",
    align: "UL",
    ranksep: 150,
    nodesep: 100,
  });
  const model: any = dagreLayout.layout(data);

  graph.value.fromJSON(model);
  // 监听节点的点击事件,点击进行连线
  graph.value.on("node:click", ({ node }) => {
    node.toFront();
    // 创建连线终点通过点击节点确定
    // 当起点存在时,表明创建终点
    if (tempSourceID) {
      createLink(node);
    }
  });
};
// 节点的tool工具函数,编辑关联和删除
const nodeClickCallback = (type: string, node: any) => {
  switch (type) {
    case "edit":
      changeEdit(node);
      break;
    case "remove":
      changeRemove(node);
      break;
    case "link":
      createLink(node);
      break;
  }
};
// 节点编辑
const changeEdit = (node: any) => { };
// 节点删除
const changeRemove = (node: any) => { };
//---------------------------------创建关联线--------------------------------------
// 创建关联
let tempSourceID: string = ""; //关联线起点暂存id
let tempSourceData: any; //关联线起点暂存数据
let tempEdge: Edge; //暂存edge实例
const { x, y } = useMouse();
// 鼠标动作追踪
const handleMouseMove = () => {
  if (!tempSourceID) {
    return;
  }
  let local = graph.value!.pageToLocal(x.value, y.value);
  // 链接到边,减的数字是坐标终点距离鼠标小手的位置,减值越大,离的越远
  // setTarget获取链接到画布的终止点
  tempEdge.setTarget({ x: local.x - 15, y: local.y - 15 });
};

const createLink = (node: any) => {
  if (!tempSourceID) {
    //起始点为空,就创建起始点
    // 设置初始点id
    tempSourceID = node.id;
    tempSourceData = node.data;
    if (graph.value) {
      let local = graph.value.pageToLocal(x.value, y.value);
      // 添加edge
      tempEdge = graph.value?.addEdge({
        source: { cell: tempSourceID },
        target: { x: local.x, y: local.y },
        ...edgeStyle,
      });
    }
    // 监听鼠标移动事件
    document.addEventListener("mousemove", handleMouseMove);
  } else {
    //否则存在起点的话就创建终点
    cancleLink();
    if (tempSourceID === node.id) {
      messageWarning("不可与自身创建关联!");
    } else {
      // some数组中至少存在一个元素满足指定条件
      // 判断节点的起点和终点都对应上才返回true
      const isExist = myLinks.value.some((e: any) => {
        return (
          (e["sourcePath"] == tempSourceID && e["targetPath"] == node.id) ||
          (e["sourcePath"] == node.id && e["targetPath"] == tempSourceID)
        );
      });
      if (isExist) {
        messageWarning("已存在关系");
      } else {
        // 创建节点
        if (graph.value) {
          console.log(12121, "------------");
          tempEdge = graph.value.addEdge(setEdge(tempSourceID, node.id, true));
          const newLink: ILink = {
            sourceModelId: tempSourceData.modelId,
            targetModelId: node.data.modelId,
            mainField: "",
            type: "1",
            unionType: "inner",
            sourceField: "",
            targetField: "",
            sourcePath: tempSourceData["path"],
            targetPath: node.data["path"],
            sourceTable: tempSourceData.code,
            targetTable: node.data.code,
          };
          myLinks.value.push(newLink);
        }
      }
      // 重置暂存标志位
      tempSourceID = "";
    }
  }
};

// 取消连线
const cancleLink = (edge: Edge = tempEdge) => {
  console.log(edge, "------------");
  if (!edge) return;
  graph.value?.removeEdge(edge.id);
  // 监听鼠标移动事件移除
  document.removeEventListener("mousemove", handleMouseMove);
};
const saveModel = () => {
  // 拿到所有的线条关系
  console.log(myLinks.value, "------------");
};
</script>

<style scoped lang="scss">
#container {
  height: 100%;
  position: relative;

  .footTool {
    position: absolute;
    bottom: 0;
    background-color: #f6f9fc;
    height: 10%;
  }
}
</style>

3、node/index.vue

这个是自定义节点页面,定义好之后,在主页面中进行引入

<template>
  <div class="node">
    <div>
      <div class="flex topttitle pd-10">
        <svg width="20px" height="20px" viewBox="0 0 20 20" :style="{ 'margin-top': '5px' }">
          <g fill="#be49e7">
            <path
              d="M13.6149425,0 C14.5639836,0 15.3333333,0.769349769 15.3333333,1.7183908 L15.3333333,13.6149425 C15.3333333,14.5639836 14.5639836,15.3333333 13.6149425,15.3333333 L1.7183908,15.3333333 C0.769349769,15.3333333 0,14.5639836 0,13.6149425 L0,1.7183908 C0,0.769349769 0.769349769,0 1.7183908,0 L13.6149425,0 Z M6.4916986,8.2247765 L3.3584504,8.2247765 C3.01776901,8.2247765 2.74159217,8.50095334 2.74159217,8.84163474 L2.74159217,11.9748829 C2.74159217,12.3155643 3.01776901,12.5917412 3.3584504,12.5917412 L6.4916986,12.5917412 C6.83237999,12.5917412 7.10855683,12.3155643 7.10855683,11.9748829 L7.10855683,8.84163474 C7.10855683,8.50095334 6.83237999,8.2247765 6.4916986,8.2247765 Z M11.9748829,11.3580247 L8.84163474,11.3580247 C8.50095334,11.3580247 8.2247765,11.6342015 8.2247765,11.9748829 C8.2247765,12.3155643 8.50095334,12.5917412 8.84163474,12.5917412 L11.9748829,12.5917412 C12.3155643,12.5917412 12.5917412,12.3155643 12.5917412,11.9748829 C12.5917412,11.6342015 12.3155643,11.3580247 11.9748829,11.3580247 Z M11.9748829,8.61643252 L8.84163474,8.61643252 C8.50095334,8.61643252 8.2247765,8.89260936 8.2247765,9.23329076 C8.2247765,9.57397216 8.50095334,9.850149 8.84163474,9.850149 L11.9748829,9.850149 C12.3155643,9.850149 12.5917412,9.57397216 12.5917412,9.23329076 C12.5917412,8.89260936 12.3155643,8.61643252 11.9748829,8.61643252 Z M6.4916986,2.74159217 L3.3584504,2.74159217 C3.01776901,2.74159217 2.74159217,3.01776901 2.74159217,3.3584504 L2.74159217,6.4916986 C2.74159217,6.83237999 3.01776901,7.10855683 3.3584504,7.10855683 L6.4916986,7.10855683 C6.83237999,7.10855683 7.10855683,6.83237999 7.10855683,6.4916986 L7.10855683,3.3584504 C7.10855683,3.01776901 6.83237999,2.74159217 6.4916986,2.74159217 Z M11.9748829,5.48318433 L8.84163474,5.48318433 C8.50095334,5.48318433 8.2247765,5.75936117 8.2247765,6.10004257 C8.2247765,6.44072397 8.50095334,6.71690081 8.84163474,6.71690081 L11.9748829,6.71690081 C12.3155643,6.71690081 12.5917412,6.44072397 12.5917412,6.10004257 C12.5917412,5.75936117 12.3155643,5.48318433 11.9748829,5.48318433 Z M11.9748829,2.74159217 L8.84163474,2.74159217 C8.50095334,2.74159217 8.2247765,3.01776901 8.2247765,3.3584504 C8.2247765,3.6991318 8.50095334,3.97530864 8.84163474,3.97530864 L11.9748829,3.97530864 C12.3155643,3.97530864 12.5917412,3.6991318 12.5917412,3.3584504 C12.5917412,3.01776901 12.3155643,2.74159217 11.9748829,2.74159217 Z"
              id="形状结合"
            ></path>
          </g>
        </svg>
        <h1 class="head-name">{{ data.name }}</h1>
        <div class="head-tool">
          <ElDropdown trigger="click" :teleported="true">
            <BIcon size="20">
              <BSvg name="wenjianjiabeifen11" />
            </BIcon>
            <template #dropdown>
              <ElDropdownMenu>
                <ElDropdownItem @click="operateFunc('edit')">编辑</ElDropdownItem>
                <ElDropdownItem @click="operateFunc('link')">创建关联</ElDropdownItem>
                <ElDropdownItem @click="operateFunc('remove')">删除</ElDropdownItem>
              </ElDropdownMenu>
            </template>
          </ElDropdown>
        </div>
      </div>
      <h6 class="secondTitle">({{ data.path }})</h6>
    </div>
    <div class="content">
      <div class="flex field-item" v-for="(item, i) in data.fields" :key="i">
        <span>{{ i + 1 }}.{{ item.name }}</span>
        <span>{{ item.code }}</span>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
const getNode: any = inject("getNode");
const node: any = getNode(); //当前节点
let data = ref<any>(node.getData()); //当前节点数据

const operateFunc = (type: string) => {
  data.value.toolClickEvent(type, node);
  console.log(data.value, "------------");
};
onMounted(() => {});
</script>

<style scoped lang="scss">
.node {
  width: 250px;
  height: 150px;
  background: #fff;
  display: flex;
  z-index: 1000 !important;
  flex-direction: column;
  box-shadow: rgb(233, 170, 255) 0px 0px 6px 0px;
  .topttitle {
    padding: 12px;
    padding-bottom: 0;
    height: 40px;
    position: relative;
    .head-tool {
      position: absolute;
      right: 0;
      z-index: 100;
      cursor: pointer;
    }
  }
  .head-name {
    color: #000000;
    font-size: 18px;
    line-height: 25px;
    font-weight: bold;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding-left: 10px;
  }
  .secondTitle {
    color: #999;
    font-size: 14px;
    line-height: 20px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding-left: 40px;
    padding-bottom: 10px;
    font-weight: normal;
    border-bottom: 1px solid #e0e7ed;
  }
  .content {
    flex: 1;
    overflow: auto;
    cursor: pointer;
  }
  .field-item {
    height: 27px;
    font-size: 14px;
    padding: 12px;
    display: flex;
    align-items: center;
    span:nth-child(1) {
      display: block;
      width: 50%;
    }
    span:nth-child(2) {
      color: #697a8f;
    }
  }
}
</style>

 4、hooks/comGraph.ts

存放一些静态变量

// 线的样式
export const edgeStyle = {
  attrs: {
    line: {
      stroke: "rgb(26, 97, 211)", //线条颜色
      strokeWidth: 1, //线条粗细
      targetMarker: null, //不设置箭头
    },
  },
  allowNode: true,
  snap: true,
  allowLoop: false,
  router: {
    // 路由类型 normal orth(正交路由)
    name: "manhattan", //智能正交,自动避开障碍
    args: {
      step: 70,
      padding: 50,
      offset: 24,
    },
  },
  allowMulti: true,
  connector: {
    name: "jumpover",
    args: {
      radius: 14,
    },
  },
};
// 设置线
export const setEdge = (source: string, target: string, showLable: boolean) => {
  return {
    shape: "double-edge",
    source: { cell: source },
    target: { cell: target },
    label: showLable ? [] : "",
    ...edgeStyle,
  };
};
//线和节点数据
export const Data = {
  "tables": [
    {
      "name": "产品线",
      "path": "productlines",
      "fields": [
        {
          "code": "productLine",
          "name": "主键",
        },
        {
          "code": "textDescription",
          "name": "纯文本描述",
        }
      ]
    },
    {
      "name": "客户表",
      "path": "customers",
      "fields": [
        {
          "code": "phone",
          "name": "联系电话",
        },
        {
          "code": "addressLine1",
          "name": "联系地址1",
        },
        {
          "code": "addressLine2",
          "name": "联系地址2",
        },
        {
          "code": "city",
          "name": "所在城市",
        },
        {
          "code": "state",
          "name": "州",
        },
      ]
    },
    {
      "name": "订单表",
      "path": "orders",
      "fields": [
        {
          "code": "orderDate",
          "name": "下单日期",
        },
        {
          "code": "requiredDate",
          "name": "需用日期",
        },
        {
          "code": "shippedDate",
          "name": "发货日期",
        },
        {
          "code": "status",
          "name": "状态",
        },
      ]
    },
    {
      "name": "订单明细表",
      "path": "orderdetails",
      "fields": [
        {
          "code": "orderNumber",
          "name": "订单编号",
        },
        {
          "code": "productCode",
          "name": "产品编号",
        },
      ]
    },
    {
      "name": "员工表",
      "path": "employees",
      "fields": [
        {
          "code": "employeeNumber",
          "name": "员工编号",
        },
        {
          "code": "lastName",
          "name": "姓",
        },
        {
          "code": "firstName",
          "name": "名",
        },
        {
          "code": "extension",
          "name": "分机号",
        },
        {
          "code": "email",
          "name": "电子邮件",
        },
      ]
    },
    {
      "name": "付款",
      "path": "payments",
      "fields": [
        {
          "code": "customerNumber",
          "name": "客户编号",
        },
        {
          "code": "checkNumber",
          "name": "检验数",
        },
        {
          "code": "paymentDate",
          "name": "付款日",
        },
        {
          "code": "amount",
          "name": "金额",
        }
      ]
    },
    {
      "name": "产品",
      "path": "products",
      "fields": [
        {
          "code": "productCode",
          "name": "产品编码",
        },
        {
          "code": "productName",
          "name": "产品名称",
        },
        {
          "code": "productLine",
          "name": "产品线",
        },
        {
          "code": "productScale",
          "name": "生产规模",
        }
      ]
    }
  ],
  "links": [
    {
      "sourcePath": "orders",
      "targetPath": "customers",
    },
    {
      "sourcePath": "payments",
      "targetPath": "customers",
    },
    {
      "sourcePath": "customers",
      "targetPath": "employees",
    },
    {
      "sourcePath": "orderdetails",
      "targetPath": "products",
    },
    {
      "sourcePath": "orderdetails",
      "targetPath": "orders",
    },
    {
      "sourcePath": "products",
      "targetPath": "productlines",
    }
  ]
}

有问题的可以评论区讨论~ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1289109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机视觉GPT时刻!UC伯克利三巨头祭出首个纯CV大模型,推理惊现AGI火花

计算机视觉的GPT时刻&#xff0c;来了&#xff01; 最近&#xff0c;来自UC伯克利的计算机视觉「三巨头」联手推出了第一个无自然语言的纯视觉大模型&#xff08;Large Vision Models&#xff09;&#xff0c;并且第一次证明了纯视觉模型本身也是可扩展的&#xff08;scalabil…

YOLOv8创新魔改教程(三)如何添加注意力机制注意力机制的用法与思考

注意力机制的用法与思考 好多同学问我加了CA注意力机制&#xff0c;CBAM注意力机制&#xff0c;都没有涨点&#xff0c;然后就在不停地换不同的注意力机制&#xff0c;其实并不是这样的。今天和大家讨论一下注意力机制的用法与思考。 &#xff08;一&#xff09;添加位置 大…

异常追踪与 JIRA 实现双向联动

前言 当应用程序或系统出现异常时&#xff0c;通常需要及时处理以保证系统的正常运行。通过异常追踪与 JIRA 双向联动&#xff0c;可以让企业内部相关人员快速了解、分析问题故障发生的原因、追溯并记录故障的处理过程&#xff0c;有效提高人员的沟通效率&#xff0c;极大降低…

使用 SVN 新建本地仓库和提交

在写代码的时候经常要看自己修改了什么或者临时备份一下&#xff0c;发现 SVN 比 Git 更好用&#xff0c;下面是使用 TortoiseSVN 在本地新建仓库和关联仓库的方法。 1. 新建文件夹&#xff0c;在文件夹里面右键选择 TortoiseSVN -> Create repository here 。 2. 选择建立…

C++红黑树封装set和map(很详细)

前言 在前面&#xff0c;我们学习了红黑树。&#xff08;没学过红黑树直接看会很吃力&#xff09;set和map的底层就是红黑树&#xff0c;现在我们要用这棵树来封装STL里面的容器&#xff1a;set和map。 下面是之前讲过的红黑树&#xff0c;他只是普通的“Key”模型,适合封装set…

排序:直接插入排序希尔排序

目录 排序&#xff1a; 概念&#xff1a; 直接插入排序&#xff1a; 代码的实现&#xff1a; 代码解析&#xff1a; 总结&#xff1a; 希尔排序&#xff1a; 代码实现&#xff1a; 预排序&#xff1a; 代码优化&#xff1a; gap 的 本质 &#xff1a; 直接…

千梦网创:设计一个100%回本赚钱的培训模式

互联网上搞培训&#xff0c;牌坊立的快&#xff0c;倒的也快。 你会的东西你教了才能赚钱&#xff0c;你想赚钱你就要教。 你只要教了&#xff0c;立马就有人模仿&#xff0c;立马就有人收费比你更低。 所以&#xff0c;你不会变&#xff0c;你没有核心的东西&#xff0c;就…

日本IT行业发展前景怎么样呢?

由于日本劳动力短缺&#xff0c;招聘外国IT工程师的公司越来越多&#xff0c;目前&#xff0c;日本IT行业有约28,000多名外国工程师&#xff0c;占所有日本IT工程师的3%。随着大量海外人才涌入日本&#xff0c;预计这一数字还会进一步增长&#xff0c;所以有不少人想要转行做赴…

RHCE作业

目录 1、搭建一个通过网址https://www.openlab.com/money访问的缴费网站&#xff0c;网站内容为money 2、配置DNS的正向解析 1、搭建一个通过网址https://www.openlab.com/money访问的缴费网站&#xff0c;网站内容为money 首先查看自己是不是有nginx的包没有的话装一个 首…

ModStartCMS v7.7.0 集成内容区块,文件选择顺序

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议&#xff0c;免费且不限制商业使用。 功能特性 丰富的模块市…

智能优化算法应用:基于鼠群算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于鼠群算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于鼠群算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.鼠群算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

mapbox系列:常见功能使用总结

前言 最近在写一个大屏的时候使用mapbox&#xff0c;将开发过程进行总结如下&#xff1a; 功能1&#xff1a;mapbox logo显示与隐藏 使用mapbox时地图上会有mapbox的logo&#xff0c;如下&#xff1a; 设置地图全局样式设置 :deep(.mapboxgl-ctrl) {display: none !import…

第十五届蓝桥杯模拟赛B组(第二期)C++

前言&#xff1a; 第一次做蓝桥模拟赛的博客记录&#xff0c;可能有很多不足的地方&#xff0c;现在将第十五届蓝桥杯模拟赛B组&#xff08;第二期&#xff09;的题目与代码与大家进行分享&#xff0c;我是用C做的&#xff0c;有好几道算法题当时自己做的也是一脸懵&#xff0c…

R语言学习

Part1阶段1&#xff1a;入门基础 1安装R和RStudio&#xff1a; 下载并安装R&#xff1a;https://cran.r-project.org/ 下载并安装RStudio&#xff1a;https://www.rstudio.com/products/rstudio/download/ 2Hello World&#xff1a; 学习如何在R中输出"Hello, World!"…

苹果OS X系统介绍(Mac OS --> Mac OS X --> OS X --> macOS)

文章目录 OS X系统介绍历史与版本架构内核与低级系统图形&#xff0c;媒体和用户界面应用程序和服务 特性用户友好强大的命令行安全性集成与互操作性 总结 OS X系统介绍 OS X是由苹果公司为Macintosh计算机系列设计的基于UNIX的操作系统。其界面友好&#xff0c;易于使用&…

论文阅读:Distributed Initialization for VIRO with Position-Unknown UWB Network

前言 Distributed Initialization for Visual-Inertial-Ranging Odometry with Position-Unknown UWB Network这篇论文是发表在ICRA 2023上的一篇文章&#xff0c;本文提出了一种基于位置未知UWB网络的一致性视觉惯性紧耦合优化测距算法( DC-VIRO )的分布式初始化方法。 对于…

【从删库到跑路 | MySQL数据库总结篇】JDBC编程

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】&#x1f388; 本专栏旨在分享学习MySQL的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、前言…

【Linux】信号的保存和捕捉

文章目录 一、信号的保存——信号的三个表——block表&#xff0c;pending表&#xff0c;handler表sigset_t信号集操作函数——用户层sigprocmask和sigpending——内核层 二、信号的捕捉重谈进程地址空间&#xff08;第三次&#xff09;用户态和内核态sigaction可重入函数volat…

技术博客:Vue中各种混淆用法汇总

​ 摘要 本文主要介绍了在Vue中使用的一些常见混淆用法&#xff0c;包括new Vue()、export default {}、createApp()、Vue.component、Vue3注册全局组件、Vue.use()等&#xff0c;以及如何使用混淆器对代码进行加固&#xff0c;保护应用安全。 引言 在Vue开发中&#xff0c;…

java小工具util系列3:JSON转实体类对象工具

文章目录 准备工作1.JSONObject获取所有的key2.集合中实体对象转换 list中Enrey转Dto3.字符串转List<BusyTimeIndicatorAlarmThreshold>4.json字符串转JSONObject5.list根据ids数组过滤list6.json字符串转JavaBean对象7.json对象转javabean8.jsonObject转map9.List\<U…