vue3 ts element-plus el-tree添加树节点 删除树节点 修改树节点

本文介绍了如何在Vue应用中使用el-tree组件,展示了如何实现节点的编辑、添加和删除功能,以及相关的状态管理方法。

                    <el-tree
                      ref="treeRef"
                      :data="data"
                      :expand-on-click-node="false"
                      :highlight-current="true"
                      :props="defaultProps"
                      class="menu-tree"
                      default-expand-all
                      draggable
                      node-key="id"
                      @node-click="handleNodeClick"
                    >

                      <template #default="{ node, data }">
                        <span class="custom-tree-node">
                           <template v-if="!isEditing || editingNodeId !== data.id">
                             {{ node.label }}
                           </template>
                           <template v-else>
                             <el-input
                               v-model="editingNodeLabel"
                               @blur="cancelEdit"
                               @keyup.enter="updateNodeLabel(data)"
                             ></el-input>
                           </template>
                          <span>
                            <a :style="{marginRight: '0.5rem'}" @click="append(data)">
                              <el-icon :style="{color:'#0000FF'}">
                                <Plus />
                              </el-icon>
                            </a>
                            <a :style="{marginRight: '0.5rem'}" @click="remove(node, data)">
                              <el-icon :style="{color:'#DA3434'}">
                                <Delete />
                              </el-icon>
                            </a>
                            <a :style="{marginRight: '0.5rem'}" @click="edit(node,data)">
                              <el-icon :style="{color:'#0000FF'}">
                                <Edit />
                              </el-icon>
                            </a>
                          </span>
                        </span>
                      </template>

                    </el-tree>




/** 树节点id */
let id = 1000;
/** 单击节点的数据 */
const nodeData = ref({});
/** 节点是否修改 */
const isEditing = ref(false);
/** 保存正在编辑的节点ID */
const editingNodeId = ref<number | null>(null);
/** 临时存储编辑中的节点名称 */
const editingNodeLabel = ref<string>("");
/** 树形结构数据 */
const defaultProps = {
  children: "children",
  label: "label"
};

/** 树形结构数据 */
interface Tree {
  [key: string]: any;
}

/** 树形结构数据 */
const data: Tree[] = [
  {
    id: 1,
    label: "基本"
  },
  {
    id: 2,
    label: "属性",
    data: [
      {
        id: 1,
        label: "电池电压"
      },
      {
        id: 2,
        label: "正在充电"
      },
      {
        id: 3,
        label: "固件版本"
      },
      {
        id: 4,
        label: "输入电压"
      },
      {
        id: 5,
        label: "信号质量"
      },
      {
        id: 6,
        label: "位置"
      },
      {
        id: 7,
        label: "服务器地址"
      },
      {
        id: 8,
        label: "服务器用户名"
      },
      {
        id: 9,
        label: "通讯协议"
      },
      {
        id: 11,
        label: "产品令牌"
      },
      {
        id: 12,
        label: "设备令牌"
      }
    ]
  },
  {
    id: 3,
    label: "功能"
  },
  {
    id: 4,
    label: "时间"
  },
  {
    id: 5,
    label: "授权"
  },
  {
    id: 6,
    label: "固件"
  },
  {
    id: 7,
    label: "警报"
  },
  {
    id: 8,
    label: "界面"
  },
  {
    id: 9,
    label: "影子"
  }
];

/** 修改树节点 */
const edit = (node: Node, data: Tree) => {
  isEditing.value = true;
  editingNodeId.value = data.id;
  editingNodeLabel.value = data.label;
};

/** 点击树节点 */
const handleNodeClick = (data: Tree) => {
  nodeData.value = data.data;
};

/** 添加树节点 */
const append = (data: Tree) => {
  const newChild = { id: id++, label: "testtest", children: [] };
  if (!data.children) {
    data.children = [];
  }
  data.children.push(newChild);
  data.value = [...data.value];
};

/** 删除树节点 */
const remove = (node: Node, data: Tree) => {
  const parent = node.parent;
  const children: Tree[] = parent.data.children || parent.data;
  const index = children.findIndex((d) => d.id === data.id);
  children.splice(index, 1);
  data.value = [...data.value];
};

/** 更新节点名称 */
const updateNodeLabel = (data: Tree) => {
  if (editingNodeId.value === data.id) {
    data.label = editingNodeLabel.value;
    isEditing.value = false;
    editingNodeId.value = null;
  }
};

/** 取消节点编辑 */
const cancelEdit = () => {
  isEditing.value = false;
  editingNodeId.value = null;
};

<think>在Vue3中使用Element Plusel-tree组件实现单独修改每个树节点的label,可以通过自定义节点内容(使用插槽)来实现。这样,每个节点都可以被自定义渲染,从而允许我们为每个节点添加独立的操作(如编辑按钮)来修改其label。 主要思路: 1. 使用el-tree组件的`scoped-slot`(在Vue3中为`v-slot`)来自定义节点内容。 2. 在自定义节点内容中,根据节点的状态(是否处于编辑模式)来切换显示文本或输入框。 3.节点添加编辑按钮(或其他触发方式),点击后进入编辑模式,修改完成后保存。 步骤: a. 定义树节点数据,每个节点对象可以包含一个属性(如`isEdit`)来控制该节点是否处于编辑状态。 b. 使用el-tree的`data`属性绑定树节点数据,并设置`node-key`(唯一标识)。 c.el-tree中使用`v-slot:default="{ node, data }"`来获取当前节点和作用域插槽的数据。 d. 在插槽内部,根据`data.isEdit`的值来决定显示文本还是输入框。同时,可以添加编辑按钮和保存按钮(或使用其他交互方式)。 示例代码: 首先,确保安装了Element Plus,并正确引入el-tree组件。 模板部分: ```html <template> <el-tree :data="treeData" node-key="id" default-expand-all > <template #default="{ node, data }"> <span class="custom-tree-node"> <!-- 非编辑状态显示标签和编辑按钮 --> <span v-if="!data.isEdit"> {{ node.label }} <el-button type="text" size="mini" @click="startEdit(data)"> 编辑 </el-button> </span> <!-- 编辑状态显示输入框和保存按钮 --> <span v-else> <el-input v-model="data.label" size="mini" autofocus @blur="saveEdit(data)" @keyup.enter="saveEdit(data)" /> <el-button type="text" size="mini" @click="saveEdit(data)"> 保存 </el-button> </span> </span> </template> </el-tree> </template> ``` 脚本部分: ```javascript <script setup> import { ref } from &#39;vue&#39;; // 树节点数据 const treeData = ref([ { id: 1, label: &#39;一级 1&#39;, children: [ { id: 4, label: &#39;二级 1-1&#39;, children: [ { id: 9, label: &#39;三级 1-1-1&#39; }, { id: 10, label: &#39;三级 1-1-2&#39; } ] } ] }, { id: 2, label: &#39;一级 2&#39;, children: [ { id: 5, label: &#39;二级 2-1&#39; }, { id: 6, label: &#39;二级 2-2&#39; } ] }, { id: 3, label: &#39;一级 3&#39;, children: [ { id: 7, label: &#39;二级 3-1&#39; }, { id: 8, label: &#39;二级 3-2&#39; } ] } ]); // 开始编辑 const startEdit = (data) => { data.isEdit = true; }; // 保存编辑 const saveEdit = (data) => { data.isEdit = false; // 这里可以添加保存到后端等操作 }; </script> ``` 说明: - 每个节点数据对象中,我们没有预先定义`isEdit`属性,但在编辑时动态添加。为了避免响应式问题,我们使用`ref`创建响应式数据。 - 在编辑状态下,输入框自动获取焦点(`autofocus`),并且支持按回车键保存(`@keyup.enter`)和失去焦点保存(`@blur`)。 - 编辑按钮和保存按钮使用`el-button`并设置`type="text"`,使其看起来像文本链接。 注意:由于树节点数据是响应式的,修改`data.label`会直接更新树节点的显示。如果需要在保存时进行其他操作(如验证或提交到后端),可以在`saveEdit`方法中处理。 这种方法实现了每个树节点可以单独进入编辑模式并修改其标签。 相关问题: 1. 如何避免在树节点数据中动态添加属性带来的响应式问题? 2. 如何实现树节点的异步加载和编辑? 3. 在编辑树节点时,如何避免同时编辑多个节点?</think>在 Vue3 中使用 Element Plus 的 `el-tree` 组件实现单独修改每个树节点的 label,可以通过自定义节点内容(使用作用域插槽)和动态数据绑定来实现。以下是具体实现方案: ### 解决方案步骤 1. **使用作用域插槽自定义节点内容** ```html <el-tree :data="treeData" node-key="id" default-expand-all> <template #default="{ node, data }"> <span class="custom-tree-node"> <!-- 可编辑状态显示输入框 --> <el-input v-if="data.isEditing" v-model="data.label" size="mini" autofocus @blur="saveEdit(data)" @keyup.enter="saveEdit(data)" /> <!-- 非编辑状态显示标签和编辑按钮 --> <span v-else> {{ node.label }} <el-button type="text" size="mini" @click="startEdit(data)"> 编辑 </el-button> </span> </span> </template> </el-tree> ``` 2. **定义树形数据并添加编辑状态控制** ```typescript import { ref } from &#39;vue&#39;; const treeData = ref([ { id: 1, label: &#39;父节点1&#39;, isEditing: false, // 控制编辑状态 children: [ { id: 2, label: &#39;子节点1&#39;, isEditing: false }, { id: 3, label: &#39;子节点2&#39;, isEditing: false } ] } ]); ``` 3. **实现编辑状态切换方法** ```typescript const startEdit = (nodeData) => { // 重置所有节点的编辑状态 treeData.value.forEach(traverseNodes); // 设置当前节点为编辑状态 nodeData.isEditing = true; }; const saveEdit = (nodeData) => { nodeData.isEditing = false; // 这里可添加保存到后端的逻辑 }; // 递归遍历所有节点 const traverseNodes = (node) => { node.isEditing = false; if (node.children) { node.children.forEach(traverseNodes); } }; ``` ### 关键点说明 1. **作用域插槽**:通过 `#default="{ node, data }` 获取当前节点数据和节点对象 2. **编辑状态控制**:每个节点通过 `isEditing` 属性独立控制编辑状态 3. **自动聚焦优化**:使用 `autofocus` 确保输入框自动获得焦点 4. **退出编辑方式**: - 按回车键 (`@keyup.enter`) - 输入框失焦 (`@blur`) 5. **数据响应式**:使用 `ref` 确保数据修改自动更新视图 ### 完整示例代码 ```html <template> <el-tree :data="treeData" node-key="id" default-expand-all> <template #default="{ node, data }"> <span class="custom-tree-node"> <el-input v-if="data.isEditing" v-model="data.label" size="mini" autofocus @blur="saveEdit(data)" @keyup.enter="saveEdit(data)" /> <span v-else> {{ node.label }} <el-button type="text" size="mini" @click="startEdit(data)"> 编辑 </el-button> </span> </span> </template> </el-tree> </template> <script setup lang="ts"> import { ref } from &#39;vue&#39;; const treeData = ref([ { id: 1, label: &#39;一级菜单&#39;, isEditing: false, children: [ { id: 2, label: &#39;子项1&#39;, isEditing: false }, { id: 3, label: &#39;子项2&#39;, isEditing: false } ] } ]); const startEdit = (nodeData: any) => { // 关闭所有编辑状态 const resetEditState = (nodes: any[]) => { nodes.forEach(node => { node.isEditing = false; if (node.children) resetEditState(node.children); }); }; resetEditState(treeData.value); // 开启当前节点编辑 nodeData.isEditing = true; }; const saveEdit = (nodeData: any) => { nodeData.isEditing = false; console.log(&#39;保存修改:&#39;, nodeData.label); // 实际项目这里调用API保存修改 }; </script> ``` ### 效果说明 1. 每个节点右侧显示"编辑"按钮 2. 点击按钮后,该节点变为输入框(其他节点自动退出编辑状态) 3. 修改后按回车或点击其他地方自动保存 4. 使用 Vue3 的响应式系统,数据变更自动更新视图 ### 相关问题 1. 如何实现树节点的异步加载和编辑? [^1] 2. 在编辑树节点时如何添加输入验证? [^2] 3. 如何优化大型树结构的编辑性能? [^3] 4. 如何将修改后的树数据保存到后端? [^1] [^1]: 引用[1]: Vue 13v-for循环对象.html [^2]: 引用[2]: Vue v-model指令的学习 [^3]: 引用[3]: Vue 14v-for迭代数字
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值