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>
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于