vue3.0+TS+antdesgin 选择树(tree)的增删改查(简单封装)

vue3.0+TS+antdesgin 选择树(tree)的增删改查(简单封装)

效果图:
在这里插入图片描述
父组件代码:

<div class="tree-box">
	<type-tree @onSelect="onSelect" :action="true"/>
</div>

子组件代码:

<template>
  <div class="tree">
    <a-tree
      show-line
      :treeData="treeData"
      :defaultExpandAll="true"
      @select.self="onSelect"
      v-if="treeData.length"
      :replaceFields="replaceFields"
      v-model:selectedKeys="selectedKeys"
    >
      <!-- @click.prevent="((e)=>{e.stopPropagation()})" :阻止默认事件向后传播 -->
      <template v-slot:title="nodeData">
        <a-input
          style="width: 100px"
          :ref="childId === nodeData.len ? 'inputVal' : 'inputTest'"
          @click.prevent="
            (e) => {
              e.stopPropagation();
            }
          "
          @blur="addSumbit(nodeData)"
          v-if="nodeData.isEdit"
          v-model:value="inputTypeName"
        />
        <span v-if="!nodeData.isEdit">{{ nodeData.typeName }}</span>
        <a-button-group class="editBox" v-if="action">
          <a-button type="link" size="small" @click.stop="slotAdd(nodeData)" title="添加">
            <template #icon><PlusOutlined /></template>
          </a-button>
          <a-button type="link" size="small" @click.stop="slotEdit(nodeData)" title="修改">
            <template #icon><EditOutlined /></template>
          </a-button>
          <a-button type="link" size="small" @click.stop="slotDelete(nodeData)" title="删除">
            <template #icon><DeleteTwoTone twoToneColor="#eb2f96" /></template>
          </a-button>
        </a-button-group>
      </template>
    </a-tree>
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref, reactive, nextTick, createVNode } from 'vue';
import { SelectEvent } from 'ant-design-vue/es/tree/Tree';
import { adminApi, treeEdit } from '/@/api/index';
import { message, Modal } from 'ant-design-vue';
import {
  PlusOutlined,
  EditOutlined,
  DeleteTwoTone,
  ExclamationCircleOutlined,
} from '@ant-design/icons-vue';

export default defineComponent({
  props: {
    action: {
      type: Boolean,
      required: false,
    },
  },
  components: {
    PlusOutlined,
    EditOutlined,
    DeleteTwoTone,
  },
  setup(props, { emit }) {
    // 替换 treeNode 中 title,key,children 字段为 treeData 中对应的字段
    let replaceFields: object = reactive({
      title: 'typeName',
      key: 'id',
    });
    // 用于点击添加时总是让第一个输入框获取焦点
    let childId = ref(0);
    // tree的数据
    let treeData = ref([]);
    // 定义ref值
    let inputVal = ref<any>(null);
    let inputTest = ref<any>('inoputTest');
    // 输入框内容
    let inputTypeName = ref<string>('新建类型');
    // 刷新组件
    let flag = ref<boolean>(true);
    // 用于判断是点击添加还是编辑
    let editOperation = ref<string>('');
    onMounted(() => {
      getTreeData();
    });
    function onSelect(selectedKeys: string[], event: SelectEvent) {
      emit('onSelect', selectedKeys);
    }
    // 获取树列表
    async function getTreeData() {
      let tree: Array<object> = [];
      let tree1: Array<object> = [];
      let tree2: Array<object> = [];
      let res = await adminApi.TreeDataApi();
      res.obj.forEach((item: any) => {
        if (item.parentId === '0') {
          item.children = [];
          tree.push(item);
        }
        for (let node of tree) {
          getChildren(node, res.obj);
        }
      });
      tree.forEach((item: any) => {
        // 给数组里的每一个对象都添加一个isEdit属性
        item.isEdit = false;
        for (let i of item.children) {
          i.isEdit = false;
          tree1.push(i);
        }
        tree2.push(item);
        onSelect(item.id);
      });
      treeData.value = tree2;
    }
    function getChildren(node: any, dataList: any) {
      for (let item of dataList) {
        if (!item.children) {
          item.children = [];
        }
        if (item.parentId === node.id) {
          node.children.push(item);
        }
      }
      if (node.children === []) {
        return;
      }
      for (let child of node.children) {
        getChildren(child, dataList);
      }
    }
    // 点击添加按钮
    function slotAdd(nodeItem: any) {
      editOperation.value = 'add';
      let len = nodeItem.children.length || 0;
      childId.value = len;
      //  上面这里你看下
      nodeItem.children.unshift({
        len,
        id: null,
        isEdit: true,
        key: new Date().getTime(),
        parentId: nodeItem.id,
        children: [],
      });
      // 点击添加让新增的输入框获取焦点
      nextTick(() => {
        inputVal.value.focus();
      });
    }

    // 新增、编辑时input框失去焦点触发事件
    async function addSumbit(nodeItem: any) {
      let params = {
        id: nodeItem.id || null,
        parentId: nodeItem.parentId,
        typeName: inputTypeName.value,
      };
      let res =
        editOperation.value === 'add'
          ? await treeEdit.insertType(params)
          : await treeEdit.updateType(params);
      if (res.success) {
        nodeItem.isEdit = false;
        getTreeData();
        message.success(res.msg);
      } else {
        message.error(res.msg);
      }
    }
    // 点击编辑
    async function slotEdit(nodeItem: any) {
      editOperation.value = 'edit';
      treeData.value.forEach((item: any) => {
        if (item.id === nodeItem.id) {
          item.isEdit = true;
          inputTypeName.value = nodeItem.typeName;
        }
        for (let i of item.children) {
          if (i.id === nodeItem.id) {
            i.isEdit = true;
            inputTypeName.value = nodeItem.typeName;
          }
        }
        // 点击编辑时让输入框获取焦点
        nextTick(() => {
          inputTest.value.focus();
        });
      });
      console.log('nodeItem', nodeItem); //这是传点那个树的分支 传过来的树的属性
    }
    // 点击删除
    function slotDelete(nodeItem: any) {
      let params = {
        id: nodeItem.id,
      };
      Modal.confirm({
        title: '删除',
        icon: createVNode(ExclamationCircleOutlined),
        content: '你确定要删除吗?',
        okText: 'Yes',
        okType: 'danger',
        cancelText: 'No',
        async onOk() {
          const res = await treeEdit.deleteType(params);
          if (res.success) {
            getTreeData();
            message.success(res.msg);
          } else {
            message.error(res.msg);
          }
        },
      });
    }
    return {
      onSelect,
      treeData,
      replaceFields,
      slotAdd,
      slotEdit,
      slotDelete,
      childId,
      inputVal,
      inputTest,
      inputTypeName,
      addSumbit,
      flag,
      editOperation,
    };
  },
});
</script>
<style lang="scss" scoped>
.editBox {
  margin-left: 7px;
}
</style>

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue 3.0是一个非常流行的JavaScript框架,不仅易于学习和使用,而且可以与许多UI框架集成。ElementUI是一种流行的UI框架,提供了许多易于使用的UI组件和效果。在Vue 3.0中,可以使用TypeScriptTS)编写代码,提供了更好的类型安全和代码可读性。下面是在Vue 3.0中引用ElementUI的步骤: 1. 安装ElementUI:可以使用npm或yarn命令安装ElementUI ``` npm i element-plus -S ``` 2. 使用TypeScript的话需要安装依赖 `ts` 和 `webpack`(如果没有的话) ``` npm i webpack webpack-cli webpack-dev-server typescript ts-loader -D ``` 3. 在Vue项目中引入ElementUI样式和组件: 3.1 引入样式(会自动挂载到全局样式表上) ```scss // main.ts import 'element-plus/dist/index.css' ``` 3.2 引入组件 ```js // main.ts or other entry file import { createApp } from 'vue' import App from './App.vue' import ElementPlus from 'element-plus' import 'element-plus/styles/index.css' // 引入组件样式 const app = createApp(App) app.use(ElementPlus) // 注册全局组件 app.mount('#app') ``` 这样就可以通过引入ElementPlus来使用ElementUI组件了。例如,在Vue 3.0中使用一个按钮组件: ```vue <template> <el-button type="primary">click me</el-button> </template> <script lang="ts"> import { defineComponent } from 'vue' import { ElButton } from 'element-plus' export default defineComponent({ name: 'MyButton', components: { ElButton } // 局部注册组件 }) </script> ``` 总的来说,引用ElementUI到Vue 3.0中相对比较简单,只需要安装依赖与组件后进行注册即可正常使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值