elementUI 树自定义增删改的功能
-
需求:
-
基于 vue 和 elementui 组件的 el-tree 写一个树的样式;
-
可以添加和删除当前节点;
-
添加点击后出现弹窗,进行添加的编辑;如图所示:
-
根据当前节点的情况确定是否需要显示删除和添加的图标;例如:如果是根节点,则只能添加不能删除;
-
准备
-
新增节点思路:
- 点击新增按钮之后,出现弹出框;
- 读取用户输入的信息传递给后台,并且请求数据(节点 id、节点名称、节点是否可新增、节点是否可删除等);
- 将请求回来的数据在树形组件上进行渲染;
-
删除节点思路:
- 点击当前要删除的节点,获取当前 id;
- 根据当前节点 id,遍历其所有的 children,在 list 中进行删除;
项目使用中的注意
- 该树形组件是基于 vue 和 webspack 的,而 elementUI 中在树的节点区添加按钮或图标等内容,需要使用 render-content 指定渲染函数;
- 首先需要下载依赖包,此处主要讲需要使用的 jsx 部分,需要下载以下安装包:
npm install babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx babel-helper-vue-jsx-merge-props babel-preset-env --save-dev
- 然后需要配置.babelrc(此处配置很重要), 如下:
{ "presets": [ ["env", { "modules": false, "targets": { "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] } }], "stage-2" ], "plugins": ["transform-runtime","transform-vue-jsx"], "env": { "test": { "presets": ["env", "stage-2"], "plugins": ["transform-vue-jsx","istanbul"] } } }
源码
- html
<!--树形控件--> <el-aside width="300px" style="padding: 15px;"> <el-tree ref="eventCategoryTree" :data="eventCategoryTree" :props="defaultProps" node-key="id" highlight-current default-expand-all :render-content="renderContent" :expand-on-click-node="false"> </el-tree> </el-aside> <!--新增事件节点分类弹窗--> <el-dialog title="新增事件分类" width="25%" class="add-event-dialog" :visible.sync="addEventdialogVisible" size="tiny"> <el-form ref="addEventForm" :model="addEventForm" :rules="addEventNodeRules"> <el-form-item label="分类名称" prop="categoryName" > <el-input v-model="addEventForm.categoryName"></el-input> </el-form-item> <el-form-item label="分类标识" prop="categoryFlag"> <el-input v-model="addEventForm.categoryFlag"></el-input> </el-form-item> </el-form> <span slot="footer" class="dialog-footer" > <el-button @click="addEventFormCancleBtn('addEventForm')">取 消</el-button> <el-button type="primary" @click="addEventFormSubmitBtn('addEventForm')">确 定</el-button> </span> </el-dialog>
- data
//树组件的数据 eventCategoryTree: [ { id: 1, label: '一级 1', addAble: true, //根据后台给的是否可添加节点,也可以根据当前的node节点自行判断 delAble: false, //根据后台给的是否可删除节点,也可以根据当前的node节点自行判断 parentId: '', children: [{ id: 4, label: '二级 1-1', addAble: false, delAble: true, parentId: '1', },{ id: 5, label: '二级 2-1', addAble: false, delAble: true, parentId: '1', }, { id: 6, label: '二级 2-2', addAble: false, delAble: true, parentId: '1', },] }], defaultProps: { children: 'children', label: 'label' }, /*触发的当前的节点,放到全局,方便调用*/ triggerCurrenNodeData:{}, /*触发的当前节点*/ triggerCurrenNode:{}, /*新增事件弹窗的输入框数据*/ addEventdialogVisible: false, addEventForm:{ categoryName: '', categoryFlag: '', },
- 引入自定义的树:将该组件放置在同一个文件夹下以供调用;
import TreeRender from './tree_render.vue';
- methods:
/*渲染函数*/ renderContent(h, { node, data, store }) { let that = this;//指向vue return h(TreeRender,{ props:{ NODE: node, DATA: data, STORE: store, }, on:{ //新增 Append: ((s,d,n) => that.appendEvent(s,d,n)), //删除节点 Delete: ((s,d,n) => that.removeEvent(s,d,n)), //查看 WatchInfo: ((s,d,n)=> that.changeMainRegion(s,d,n)) } } ); }, /*树形控件添加节点,添加弹窗出现*/ appendEvent(s,d,n) { this.addEventdialogVisible = true; this.triggerCurrenNodeData = d; this.triggerCurrenNode = n; }, /*树形控件删除节点*/ removeEvent(s,d,n) { const parent = n.parent; const children = parent.data.children || parent.data; const index = children.findIndex(data => data.id === d.id); console.log(index,'索引') this.$confirm('确定要删除该节点吗?', '温馨提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.$http('delete', `/url/****/****/${d.id}`,{queryParams: null}) .then((res) => { if (res.statusCode === 200) { children.splice(index, 1); this.$message({ message: res.messages[0], type: 'success' }); } }); }).catch(() => { this.$message({ type: 'info', message: '已取消删除' }); }); }, /*节点新增,新增树形菜单事件分类弹窗,提交按钮*/ addEventFormSubmitBtn(formname){ this.$refs[formname].validate((valid) => { if (valid) { console.log('验证成功') /*获取当前input上输入的文字*/ let dataPost={ label: this.addEventForm.categoryName.trim(), id: this.addEventForm.categoryFlag.trim(), parentId: this.triggerCurrenNodeData.id, //当前节点id depth: this.triggerCurrenNode.level, //当前节点层级 } this.$http('post', '/api/***/****', {queryParams: dataPost}) .then((res) => { console.log('请求成功'); if (res.statusCode === 200) { let result = res.data; /*点击弹窗的确定按钮可以得到输入的数据,作为新的节点名称插入*/ /*如果没有子节点,就创建一个子节点插入*/ if (!this.triggerCurrenNodeData.children) { this.$set(this.triggerCurrenNodeData, 'children', []); }; //如果已有子节点,就把返回的数据push进去,插入到树形数据中 this.triggerCurrenNodeData.children.push(result); /*关闭弹窗,重置输入框*/ this.addEventdialogVisible = false; this.$refs[formname].resetFields(); /*刷新树形菜单*/ //this.getDictionarytTree(); } }) .catch((e) => { console.log('请求失败',e) }) } else { console.log('验证未通过'); return false; } }); },
- 引入的自定义的树组件:
<template> <span style="flex: 1; display: flex; align-items: center; font-size: 14px; padding-right: 8px;"> <span @click="WatchInfo(STORE,DATA,NODE)" style="width: 80%"> <span>{{DATA.label}}</span> </span> <span class="span_icon"> <el-button style="font-size: 12px;" type="text" v-if="DATA.addAble" @click="Append(STORE,DATA,NODE)"> <i class="el-icon-plus"></i> </el-button> <el-button style="font-size: 12px;" type="text" v-if="DATA.delAble" @click="Delete(STORE,DATA,NODE)"> <i class="el-icon-delete"></i> </el-button> </span> </span> </template> <script> export default { name: '', data() { return {} }, props: ['NODE', 'DATA', 'STORE'], methods:{ Append(s,d,n){ //添加节点事件 this.$emit('Append',s,d,n) }, Delete(s,d,n){ this.$emit('Delete',s,d,n) }, WatchInfo(s,d,n){ this.$emit('WatchInfo',s,d,n) } } } </script> <style></style>
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于