使用vue3 写法 拖拽节点成功后 配置当前节点自定义属性值

20 阅读3分钟

在 Vue3 中,当拖拽节点成功后配置自定义属性值,主要有两种方式:一种是在拖拽时通过 startDrag方法直接传入初始属性,另一种是在节点被添加到画布后通过事件监听来动态设置属性。下面是一个清晰的实现方案。

🛠️ 核心实现步骤

1. 拖拽时直接传入属性

在启动拖拽 (startDrag) 时,除了节点类型 (type) 和文本 (text),还可以通过 properties字段直接传入自定义的业务属性 。

// 可拖拽的节点列表定义
const nodeList = ref([
  {
    type: 'approval-node',
    text: '审批节点',
    // 在此处定义该类型节点的默认属性
    properties: {
      nodeName: '默认审批节点',
      assignee: '待指定', // 负责人
      status: 'pending',  // 状态:待处理
      priority: 'medium', // 优先级:中
      createTime: new Date().toLocaleDateString() // 创建时间
    }
  },
  // ... 其他节点类型
]);

// 处理拖拽开始事件
const onDragStart = (event, nodeConfig) => {
  if (!lf.value) return;

  lf.value.dnd.startDrag({
    type: nodeConfig.type,
    text: nodeConfig.text,
    // 关键:传入自定义属性,可以在此动态覆盖或添加属性
    properties: {
      ...nodeConfig.properties,
      createTime: new Date().toLocaleString() // 动态生成更精确的时间
    }
  });
  event.dataTransfer.setData('text/plain', nodeConfig.type);
};

2. 节点添加后动态设置属性

通过监听节点被添加到画布的事件 (node:add),可以获取到节点实例,然后为其设置或更新属性 。

// 在初始化LogicFlow后,设置事件监听
const setupEventListeners = () => {
  if (!lf.value) return;

  // 监听节点添加事件
  lf.value.on('node:add', ({ data }) => {
    // 获取新增节点的模型
    const nodeModel = lf.value.getNodeModelById(data.id);
    
    if (nodeModel) {
      // 使用 setProperties 方法批量更新属性
      nodeModel.setProperties({
        ...nodeModel.properties,
        // 确保关键属性存在,例如为节点设置一个唯一标识
        nodeId: data.id,
        // 或者根据业务逻辑设置状态
        status: nodeModel.properties.status || 'pending'
      });

      // 也可以根据属性值,动态更新节点的视觉样式
      updateNodeStyleByProperties(nodeModel);
    }
  });
};

// 根据属性更新节点样式(例如,根据不同状态显示不同颜色)
const updateNodeStyleByProperties = (nodeModel) => {
  const { status } = nodeModel.properties;

  if (status === 'approved') {
    nodeModel.stroke = '#52c41a';
    nodeModel.fill = '#f6ffed';
  } else if (status === 'rejected') {
    nodeModel.stroke = '#ff4d4f';
    nodeModel.fill = '#fff2f0';
  }
  // 触发视图更新
  nodeModel.updateAttributes({ style: { stroke: nodeModel.stroke, fill: nodeModel.fill } });
};

💡 在自定义节点模型中固化属性逻辑

为了更彻底地管理属性,可以在自定义节点的 Model 中重写 initNodeData方法,确保每个新节点都具备完整的默认属性 。

import { RectNodeModel } from '@logicflow/core';

class CustomNodeModel extends RectNodeModel {
  initNodeData(data) {
    // 调用父类方法初始化基础数据
    super.initNodeData(data);
    
    // 设置节点默认尺寸
    this.width = 120;
    this.height = 60;

    // 核心:合并及设置节点的自定义属性
    this.properties = {
      // 先设置该类型节点的默认属性
      ...this.getDefaultProperties(data.type),
      // 再合并拖拽时传入或数据中已有的属性
      ...data.properties
    };

    // 初始化后立即根据属性更新一次样式
    this.updateStyleByProperties();
  }

  // 定义不同类型节点的默认属性
  getDefaultProperties(nodeType) {
    const defaults = {
      'approval-node': {
        nodeName: '审批节点',
        assignee: '待指定',
        status: 'pending',
        priority: 'medium'
      },
      'start-node': {
        nodeName: '开始节点',
        initiator: 'system',
        autoStart: true
      }
    };
    return defaults[nodeType] || {}; // 返回对应类型的默认属性,若无则返回空对象
  }

  // 定义一个方法,用于在属性变化时更新节点样式
  updateStyleByProperties() {
    const { status, priority } = this.properties;
    // ... 根据 status 或 priority 等属性更新 this.stroke, this.fill 等样式逻辑
  }
}

⚠️ 注意事项

  1. 属性名避免冲突:自定义属性建议使用特定的命名空间,避免与 LogicFlow 节点模型内置属性(如 x, y, text)同名。
  2. 属性序列化:确保 properties中的值是可序列化的数据类型(如字符串、数字、布尔值、普通对象、数组),便于后续数据的保存和传输 。
  3. 事件监听时机:确保事件监听(如 node:add)在 LogicFlow 实例渲染 (lf.render()) 之前设置,否则初始渲染的节点可能无法被捕获。

通过上述方法,你可以灵活地为拖拽创建的节点配置丰富的自定义属性,并能根据这些属性控制节点的外观和行为,更好地满足业务需求。