在 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 等样式逻辑
}
}
⚠️ 注意事项
- 属性名避免冲突:自定义属性建议使用特定的命名空间,避免与 LogicFlow 节点模型内置属性(如
x,y,text)同名。 - 属性序列化:确保
properties中的值是可序列化的数据类型(如字符串、数字、布尔值、普通对象、数组),便于后续数据的保存和传输 。 - 事件监听时机:确保事件监听(如
node:add)在 LogicFlow 实例渲染 (lf.render()) 之前设置,否则初始渲染的节点可能无法被捕获。
通过上述方法,你可以灵活地为拖拽创建的节点配置丰富的自定义属性,并能根据这些属性控制节点的外观和行为,更好地满足业务需求。