uniapp - props、 ref、$emit、$parent、$child、$on、$set

博客提供了一个参考网址https://www.cnblogs.com/cisum/p/12195515.html ,但未提及网址具体内容。
<template> <view class="mindmap-container"> <view class="canvas"> <MindNode :node="rootNode" :selectedId="selectedId" @node-toggle="toggleNode" @add-child="addChildNode" @edit-text="editNodeText"/> </view> </view> </template> <script> import MindNode from '@/components/MindNode/MindNode.vue'; export default { components: { MindNode }, data() { return { rootNode: null, selectedId: 'root', }; }, created() { this.initRootNode(); }, methods: { initRootNode() { this.rootNode = { id: 'root', content: '中心主题', expanded: true, level: 0, position: { x: 0, y: 5 }, children: [] }; }, addChildNode(parent) { // 层级限制:最多10层(根节点为0级)[^3] if (parent.level >= 9) { uni.showToast({ title: '已达到最大层级(10层)', icon: 'none' }); return; } const childCount = parent.children.length; const newNode = { id: `node-${Date.now()}`, content: '新节点', expanded: true, level: parent.level + 1, position: { x: 180, y: parent.position.y + (childCount * 60) }, children: [] }; parent.children.push(newNode); this.selectedId = newNode.id; }, toggleNode(node) { node.expanded = !node.expanded; this.$forceUpdate(); }, // 编辑节点文本 editNodeText({ node, newText }) { node.content = newText; this.$forceUpdate(); } } }; </script> <style scoped> .mindmap-container { position: relative; width: 100vw; height: 100vh; overflow: auto; background: #f8f9fa; } .canvas { position: relative; padding: 100px; min-height: 100vh; min-width: 100vw; } </style> <template> <view class="node-container" :style="{ left: `${node.position.x}px`, top: `${node.position.y}px`, zIndex: 1000 - node.level }"> <!-- 节点主体 --> <view class="node-card" :class="['level-' + node.level, { 'node-selected': node.id === selectedId }]"> <!-- 文本编辑区域 --> <view v-if="isEditing" class="edit-container"> <input v-model="editText" class="edit-input" auto-focus @blur="saveEdit" @keyup.enter="saveEdit" /> <view class="edit-btns"> <view class="btn-confirm" @click="saveEdit">✓</view> <view class="btn-cancel" @click="cancelEdit">✕</view> </view> </view> <!-- 显示文本区域 --> <view v-else class="content-container" @click="startEdit"> <text class="node-content">{{ node.content }}</text> </view> <!-- 操作按钮 --> <view class="node-actions"> <!-- 添加子节点按钮(层级限制) --> <view v-if="node.level < 9" class="action-btn" @click.stop="$emit('add-child', node)"> ➕ </view> <!-- 折叠/展开按钮 --> <view v-if="node.children.length" class="action-btn" @click.stop="$emit('node-toggle', node)"> {{ node.expanded ? '−' : '+' }} </view> </view> </view> <!-- 连接线 --> <view v-if="node.expanded" v-for="child in node.children" :key="child.id" class="connection"> <svg class="connector-svg"> <path :d="connectorPath(node, child)" stroke="#bbc3cc" stroke-width="1.5" fill="none"/> </svg> </view> <!-- 递归渲染子节点 --> <MindNode v-for="child in node.children" v-show="node.expanded" :key="child.id" :node="child" :selectedId="selectedId" @node-toggle="$emit('node-toggle', $event)" @add-child="$emit('add-child', $event)" @edit-text="$emit('edit-text', $event)"/> </view> </template> <script> export default { props: { node: Object, selectedId: String }, data() { return { isEditing: false, editText: '' }; }, methods: { connectorPath(parent, child) { const startX = 120; const startY = 24; const endX = child.position.x - parent.position.x; const endY = child.position.y - parent.position.y + 24; const controlX1 = startX + (endX - startX) * 0.5; return `M${startX},${startY} C${controlX1},${startY} ${controlX1},${endY} ${endX},${endY}`; }, // 启动文本编辑 startEdit() { this.editText = this.node.content; this.isEditing = true; }, // 保存编辑 saveEdit() { if (this.editText.trim()) { this.$emit('edit-text', { node: this.node, newText: this.editText }); } this.isEditing = false; }, // 取消编辑 cancelEdit() { this.isEditing = false; } } }; </script> <style scoped> .node-container { position: absolute; transition: all 0.3s; } .node-card { position: relative; display: flex; align-items: center; min-width: 120px; height: 48px; padding: 0 12px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); background: white; z-index: 1; } .content-container { flex: 1; padding: 5px 0; } .node-content { font-size: 14px; line-height: 1.4; } .edit-container { flex: 1; display: flex; flex-direction: column; } .edit-input { flex: 1; border: 1px solid #409eff; border-radius: 4px; padding: 4px 8px; font-size: 14px; } .edit-btns { display: flex; justify-content: flex-end; margin-top: 4px; } .btn-confirm, .btn-cancel { width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-left: 6px; font-weight: bold; cursor: pointer; } .btn-confirm { background: #4CAF50; color: white; } .btn-cancel { background: #f56c6c; color: white; } .node-actions { display: flex; margin-left: 8px; } .action-btn { width: 24px; height: 24px; border-radius: 50%; background: #f0f0f0; display: flex; align-items: center; justify-content: center; margin-left: 6px; font-weight: bold; cursor: pointer; } .action-btn:hover { background: #e0e0e0; } .connection { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; } .connector-svg { position: absolute; width: 100%; height: 100%; overflow: visible; } .level-0 .node-card { background: #ffeb3b; border: 2px solid #ffc107; } </style> 根据我给出的代码做出更改,将根节点的置于水平方向的中央且生成的子节点跟随移动,给子节点添加自动避让
10-01
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值