vue2中el-tree 增加、修改、删除节点

405 阅读2分钟

分析

  1. 增加(修改)根节点
  2. 增加(修改)叶子节点
  3. 懒加载叶子节点

DOM结构

<el-button
    icon="el-icon-refresh-left"
    size="mini"
    type="warning"
    @click="addRootTree()"
    >添加根节点
</el-button>
<el-tree
  ref="tree"
  :data="projectList"
  :expand-on-click-node="false"
  :load="loadProjectNode"
  :props="defaultProps"
  lazy
  node-key="id"
>
  <template v-slot="{ node, data }">
    <span class="custom-tree-node">
      <el-popover
        v-if="data.isShowSpan"
        placement="top-start"
        popper-class="poject-tree-el-popover"
        trigger="hover"
      >
        <el-button
          v-permission="permission.add"
          size="mini"
          type="text"
          @click="handleAdd(node,data)"
        >
          新增
        </el-button>
        <el-button
          v-permission="permission.edit"
          size="mini"
          type="text"
          @click="handleEdit(data)"
        >编辑
        </el-button>
        <el-popconfirm
          style="margin-left: 10px;"
          title="确定要删除这个目录吗?"
          @confirm="doDelete(node,data)"
        >
          <el-button
            slot="reference"
            v-permission="permission.del"
            size="mini"
            type="text"
          >
            删除
          </el-button>
        </el-popconfirm>
        <span slot="reference" class="node-label">{{ data.name }}</span>
      </el-popover>
      <template v-else>
        <el-input
          ref="inputValue"
          v-model="inputValue"
          class="node-input"
          placeholder="请输入内容"
          style="width: 150px; margin-right: 10px;"
          @keyup.enter.native="saveNewNode(node, data)"
        />
        <el-button
          circle
          icon="el-icon-check"
          size="mini"
          style="padding: 4px"
          type="success"
          @click="saveNewNode(node,data)"
        />
        <el-button
          v-if="!data.id"
          circle
          icon="el-icon-delete"
          size="mini"
          style="padding: 4px"
          type="danger"
          @click="deleteNewNode(node,data)"
        />
      </template>
    </span>
  </template>
</el-tree>

js实现

// data中的数据
projectList:[],
newChild: { 
    name: '',
    label: '',
    children: [],
    isShowSpan: false, // 为了区分是输入框状态还是span标签状态
    leaf: true,
    id: '',
    type: '' // 1:代表根节点 2:代表叶子节点 3:代表编辑
},
defaultProps: {
  isLeaf: 'leaf',
  children: 'children', // 子节点字段名
  label: 'label' // 节点文本字段名
}
editInfo: {},
inputValue: '',
// 功能函数---添加根节点
addRootTree() {
    const canAddNewNode = this.justShowInput();
    if (!canAddNewNode) {
      const newChild = { ...this.newChild, type: '1' };
      this.projectList.unshift(newChild)
      this.inputFocus();
    }
}
// 功能函数---添加叶子节点
handleAdd(node, data) {
  const canAddNewNode = this.justShowInput();
  if (!canAddNewNode) {
    this.$set(data, 'hasChildren', true);
    this.$set(data, 'noFistLoad', true);
    node.loaded = false;
    node.expand();
  }
}
// 功能函数---修改节点
handleEdit(data) {
  const canAddNewNode = this.justShowInput();
  if (!canAddNewNode) {
    data.type = '3'
    data.isShowSpan = false;
    this.inputValue = data.name
    this.editInfo = data;
    this.inputFocus();
  }
}
// 功能函数---删除没有id的节点
deleteNode(node, data) {
  this.showInput = false;
  this.inputValue = '';
  this.$refs.tree.remove(node)
}
// 功能函数---删除有id的节点
doDelete(node, data) {
    // 走自己的接口进行删除 然后进行以下操作
    this.updateNode(node)
}
// 功能函数---懒加载函数
loadProjectNode(node, resolve) {
  setTimeout(() => {
    getPmTreeSmall(params).then(res => {
      if (resolve) {
        const data = this.addIsShowSpan(res.content);
        if (node.data.noFistLoad) {
          const newChild = { ...this.newChild, type: '2', data: node.data };
          data.unshift(newChild)
          setTimeout(() => {
            this.inputFocus();
          }, 100)
        }
        resolve(data)
      } else {
        this.projectList = this.addIsShowSpan(res.content)
      }
    })
  }, 100)
},
// 功能函数---保存节点
saveNewNode(node, data) {
  // 走接口 保存或者编辑 成功之后 
  // 1. 接口没有返回值
  this.updateNode(node);
  // 2. 接口有返回值为res
  this.$set(data, 'isShowSpan', true);
  Object.keys(res).forEach(key => {
    this.$set(data, key, res[key]);
  });
  this.inputValue = '';
  this.showInput = false;
},
// 辅助函数---通过接口更新数据
updateNode() {
   this.inputValue = ''
   this.$set(node.parent.data, 'noFistLoad', false);
   node.parent.loaded = false;
   node.parent.expand();
}
// 辅助函数---获取到数据之后进行添加isShowSpan
addIsShowSpan(data) {
  return data.map(item => {
    item.isShowSpan = true;
    return item;
  });
}
// 辅助函数---输入框显示的时候立刻获取焦点
async inputFocus() {
  await this.$nextTick()
  const inputElement = this.$refs.inputValue
  inputElement.focus()
}
// 辅助函数---判断当前是否存在输入框
justShowInput() {
  if (this.showInput) {
    this.$notify({
      title: '还有未保存的目录',
      type: 'info',
      duration: 2500
    })
    return true; // 阻止添加新节点并触发通知
  } else {
    this.showInput = true;
    return false; // 允许添加新节点
  }
}

希望有所帮助!!!也希望掘友们能提出意见