当前位置:   article > 正文

【Vue入门实践】Element-UI 树形组件el-tree的组件封装 =>实现组织机构树Tree => 使用vue-content-menu定制可编辑树结构editableTree

el-tree

文章资源连接(如果需要付费,联系我修改即可):https://download.csdn.net/download/Sabrina_cc/87607289

好吧吐槽一下,公司决定之后的技术栈都是vue了,我又从React转战回来了。干巴爹

好的生活方式,是和一群志同道合的人,一起奔跑在理想的路上!回头有一路的故事,低头有坚定的脚步,抬头有清晰的远方。

 首先了解Element-UI中定义的基础Tree树组件Element - The world's most popular Vue UI framework

目录

一、页面效果预览

二、Tree组件的设计

1.修改elementUI的tree结构

2.绑定属性解释

3. 渲染Tree组件数据

(1) 对照后端接口

​(2)调接口获取组织机构树信息

(3) 组织机构效果图

三、使用Tree组件实现组织机构树查询列表功能

 1. 搭建主页面核心框架

2.显示主页面列表数据

(1)在data中定义查询参数

(2)调接口显示列表数据

3.组件传值显示数据

 四、实现右键新增删除的组织机构树

1.安装vue-context-menu

(1) 安装vue-context-menu

(2)在main.js中引用

2.使用vue-context-menu

3.修改组织机构树

(1) el-tree添加鼠标右击事件

(2) 编辑右键菜单函数

(3) 实现菜单按钮功能


一、页面效果预览

   页面解释:页面左边包含组织机构树,点击机构后,右侧列表显示对应公司的人员信息列表,点击即发生页面效果变化,在tree中可以对组织进行搜索,同时右侧可以对人员账户进行查询,并进一步进行新建、编辑和删除操作。

二、Tree组件的设计

1.修改elementUI的tree结构

  1. <template>
  2. <div class="content">
  3. <div>组织列表</div>
  4. <el-input
  5. class="searchInput"
  6. placeholder="输入关键字进行过滤"
  7. v-model="filterText"
  8. suffix-icon="el-icon-search"
  9. >
  10. </el-input>
  11. <div class="treeDiv">
  12. <el-tree
  13. :data="treeData"
  14. :props="defaultProps"
  15. ref="tree"
  16. highlight-current
  17. default-expand-all
  18. :expand-on-click-node="false"
  19. @node-click="handleNodeClick"
  20. node-key="id"
  21. :current-node-key="currentNodeKey"
  22. :filter-node-method="filterNode"
  23. ></el-tree>
  24. </div>
  25. </div>
  26. </template>
  1. <script>
  2. import { getOrgTreeData } from "@/api/people/people";
  3. export default {
  4. data() {
  5. return {
  6. filterText: "",
  7. treeData: [],
  8. defaultProps: {
  9. children: "children",
  10. label: "name",
  11. },
  12. currentNodeKey: "",
  13. };
  14. },
  15. watch: {
  16. filterText(val) {
  17. this.$refs.tree.filter(val);
  18. },
  19. },
  20. created() {},
  21. mounted() {
  22. getOrgTreeData().then((res) => {
  23. this.treeData = res.data;
  24. this.currentNodeKey = res.data[0].id;
  25. this.$nextTick(() => {
  26. this.$refs.tree.setCurrentKey(res.data[0].id);
  27. });
  28. this.$emit("getTreeData", res.data[0]);
  29. });
  30. },
  31. methods: {
  32. filterNode(value, data) {
  33. if (!value) return true;
  34. return data.name.indexOf(value) !== -1;
  35. },
  36. handleNodeClick(data) {
  37. this.$emit("getTreeData", data);
  38. },
  39. },
  40. };
  41. </script>

2.绑定属性解释

(1) :data="treeData" 绑定树结构对应的数据,需要在data中定义treeData数组。

  1. data() {
  2. return {
  3. filterText: "",
  4. treeData: [],
  5. defaultProps: {
  6. children: "children",
  7. label: "name",
  8. },
  9. currentNodeKey: "",
  10. };
  11. },

(2):props="defaultProps" 配置treeData数据中对应的属性名称,方便前后端统一属性名以及二级属性名

(3) node-key="id"   对于获取和设置选中节点。获取和设置各有两种方式:通过 node 或通过 key。如果需要通过 key 来获取或设置,则必须设置node-key

(4)ref="tree"

(5)highlight-current  是否高亮当前选中节点,默认值是 false。

(6)default-expand-all  是否默认展开所有节点  默认值是 false。

(7):expand-on-click-node="false"  是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。

(8)@node-click="handleNodeClick"  节点点击时的回调

(9):current-node-key="currentNodeKey"   当前选中的节点,绑定data中自定义的数据,方便后续操作

(10):filter-node-method="filterNode"   对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏。

  在需要对节点进行过滤时,调用 Tree 实例的filter方法,参数为关键字。需要注意的是,此时需要设置filter-node-method,值为过滤函数。

3. 渲染Tree组件数据

(1)对照后端接口

 (2)调接口获取组织机构树信息

  1. mounted() {
  2. getOrgTreeData().then((res) => {
  3. this.treeData = res.data;
  4. this.currentNodeKey = res.data[0].id;
  5. this.$nextTick(() => {
  6. this.$refs.tree.setCurrentKey(res.data[0].id);
  7. });
  8. this.$emit("getTreeData", res.data[0]);
  9. });
  10. },
  1. // 组织机构树
  2. export function getOrgTreeData() {
  3. return request({
  4. url: "/api/sys/organization/tree",
  5. method: "get",
  6. });
  7. }

 (3)组织机构效果图

三、使用Tree组件实现组织机构树查询列表功能

效果图

 1. 搭建主页面核心框架

  1. <div class="content-panel">
  2. <el-col :span="6">
  3. <Tree @getTreeData="getTreeData"></Tree>
  4. </el-col>
  5. <el-col :span="18">
  6. <div class="options-panel f-r-b-c">
  7. <div>
  8. <el-input
  9. v-model="params.username"
  10. placeholder="请输入用户名"
  11. clearable
  12. style="margin-right: 30px; width: 150px"
  13. ></el-input>
  14. <el-button
  15. type="primary"
  16. size="mini"
  17. style="margin: 34px"
  18. @click="searchInfoChange"
  19. >搜索</el-button
  20. >
  21. <el-button size="mini" @click="reset">重置</el-button>
  22. </div>
  23. </div>
  24. <div class="buttonDiv">
  25. <el-button type="primary" @click="createDialog">新增</el-button>
  26. </div>
  27. <div class="tableSpan">
  28. <el-table
  29. ref="singleTable"
  30. :data="AccountData"
  31. style="width: 100%"
  32. stripe
  33. fit
  34. highlight-current-row
  35. @row-click="handleClickRow"
  36. >
  37. <el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
  38. <el-table-column
  39. prop="orgName" label="公司名称" width="200" align="center"></el-table-column>
  40. <el-table-column prop="username" label="用户名" width="100" align="center"></el-table-column>
  41. <el-table-column prop="roleIds" label="权限角色" width="150" align="center" > </el-table-column>
  42. <el-table-column prop="status" label="状态" width="100" align="center">
  43. <template slot-scope="scope">
  44. <p v-if="scope.row.status == 1" type="success">启用</p>
  45. <p v-if="scope.row.status == 0" type="warning">禁用</p>
  46. </template>
  47. </el-table-column>
  48. <el-table-column prop="jobDuty" label="备注" width="100" align="center">
  49. </el-table-column>
  50. <el-table-column prop="" label="操作" align="center">
  51. <template slot-scope="scope">
  52. <el-button
  53. type="text"
  54. @click="handleManageRow(scope.row.id)"
  55. >编辑</el-button
  56. >
  57. <el-button
  58. @click="handleDeleteRow(scope.row.id)"
  59. type="text"
  60. >删除</el-button
  61. >
  62. </template>
  63. </el-table-column>
  64. </el-table>
  65. <el-pagination
  66. background
  67. class="pagelist"
  68. :current-page.sync="params.pageNum"
  69. :page-size="params.pageSize"
  70. layout="total, prev, pager, next"
  71. :total="params.total"
  72. @current-change="handlePageChange"
  73. />
  74. </div>
  75. </el-col>
  76. </div>

注意: table绑定的数据是:data="AccountData"

2.显示主页面列表数据

(1)在data中定义查询参数

  1. params: {
  2. username: "", // 用户名
  3. orgId: "", // 组织机构id
  4. status: "", // 状态,0:禁用,1:启用
  5. pageNum: 1, // 当前第几页
  6. pageSize: 10, // 每页数量
  7. total: 0, // 总记录数
  8. },

 (2)调接口显示列表数据

 查看接口文档可以看出,需要根据Tree中点击的orgaId进行查询

  1. // 获取人员账户列表
  2. getAccount() {
  3. let req = { ...this.params };
  4. delete req.total;
  5. getAccountList(req).then((res) => {
  6. this.AccountData = res.data.list;
  7. this.orgName = res.data.list[0].orgName; // 记录新建时回显的公司全部名称
  8. this.params.total = res.data.totalCount;
  9. });
  10. },
  1. // account.js
  2. // 账户详情
  3. export function getAccountList(data) {
  4. return request({
  5. url: "api/sys/user/list",
  6. method: "post",
  7. data: data,
  8. });
  9. }

3.组件传值显示数据

由于切换机构名称的操作在Tree组件中,但是查询方法getAccount()在父组件中,因此在子组件中切换orgId就需要出发父组件中的方法@getTreedata.

  1. <!--父组件中引用子组件,并把方法传入子组件中-->
  2. <Tree @getTreeData="getTreeData"></Tree>
  1. // Tree子组件中
  2. mounted() {
  3. getOrgTreeData().then((res) => {
  4. this.treeData = res.data;
  5. this.currentNodeKey = res.data[0].id;
  6. this.$nextTick(() => {
  7. this.$refs.tree.setCurrentKey(res.data[0].id);
  8. });
  9. this.$emit("getTreeData", res.data[0]);
  10. });
  11. },
  12. methods: {
  13. filterNode(value, data) {
  14. if (!value) return true;
  15. return data.name.indexOf(value) !== -1;
  16. },
  17. handleNodeClick(data) {
  18. this.$emit("getTreeData", data);
  19. },
  20. },

注意:在mounted中获取组织树对象后需要默认初始化展示第一个元素的列表信息,所以调用了父组件的方法.

在handleNodeClick()中,控制切换点击组织树,获取组织机构值后,调用父组件的方法查询并展示数据

  1. getTreeData(data) {
  2. this.params.orgId = data.id; // 获取选中的组织树的机构id
  3. this.treeNodeData = data;
  4. this.getAccount();
  5. }
  6. },

 四、实现右键新增删除的组织机构树

1.安装vue-context-menu

参考链接:vue-context-menu鼠标右键事件_poplargg的博客-CSDN博客_vue-context-menu

(1) 安装vue-context-menu

npm install vue-contextmenu --save

(2)在main.js中引用

  1. import VueContextMenu from 'vue-contextmenu'
  2. Vue.use(VueContextMenu)

2.使用vue-context-menu

  1. <div class="treeDiv">
  2. <el-tree
  3. :data="treeData"
  4. :props="defaultProps"
  5. ref="tree"
  6. highlight-current
  7. default-expand-all
  8. :expand-on-click-node="false"
  9. @node-click="handleNodeClick"
  10. node-key="id"
  11. :current-node-key="currentNodeKey"
  12. :filter-node-method="filterNode"
  13. @node-contextmenu="showMenu"
  14. ></el-tree>
  15. <vue-context-menu
  16. :contextMenuData="contextMenuData"
  17. @handleNew="handleNew"
  18. @handleDelete="handleDelete"
  19. ></vue-context-menu>
  20. </div>

在data中绑定添加contentMenuData. menuName-菜单名,axis-位置坐标,menulist-菜单选项(对应的方法)为固定写法.

  1. data() {
  2. return {
  3. filterText: "",
  4. treeData: [],
  5. defaultProps: {
  6. children: "children",
  7. label: "name",
  8. },
  9. currentNodeKey: "",
  10. currentNodeNode: {},
  11. // 菜单数据
  12. contextMenuData: {
  13. menuName: "demo",
  14. //菜单显示的位置
  15. axis: {
  16. x: null,
  17. y: null,
  18. },
  19. //菜单选项
  20. menulists: [
  21. {
  22. fnHandler: "handleNew", //绑定事件
  23. btnName: "新增", //菜单名称
  24. },
  25. {
  26. fnHandler: "handleDelete",
  27. btnName: "删除",
  28. },
  29. ],
  30. },
  31. dialogFormVisible: false,
  32. form: {
  33. type: 1,
  34. name: "",
  35. creditCode: "",
  36. contactName: "",
  37. contactPhone: "",
  38. },
  39. formLabelWidth: "100px",
  40. };
  41. },

3.修改组织机构树

(1) el-tree添加鼠标右击事件

其中,@node-contextmenu="showMenu"   当某一节点被鼠标右键点击时会触发该事件  

  1. showMenu(event, data) {
  2. console.log(data);
  3. this.currentNodeNode = data;
  4. this.$refs.tree.setCurrentKey(data.id);
  5. this.currentNodeKey = data.id;
  6. event.preventDefault();
  7. var x = event.clientX;
  8. var y = event.clientY;
  9. // Get the current location
  10. this.contextMenuData.axis = {
  11. x,
  12. y,
  13. };
  14. },

其主要目的就是在鼠标右击的位置显示菜单,并获取到点击的组织机构树信息。

(2)编辑右键菜单函数

右键菜单包含两个函数【新建】【删除】分别对应handleNew和handleDelete,这部分的内容在contextMenuData中的menulists菜单选项中定义。

  1. <vue-context-menu
  2. :contextMenuData="contextMenuData"
  3. @handleNew="handleNew"
  4. @handleDelete="handleDelete"
  5. ></vue-context-menu>
  1. //菜单选项
  2. menulists: [
  3. {
  4. fnHandler: "handleNew", //绑定事件
  5. btnName: "新增", //菜单名称
  6. },
  7. {
  8. fnHandler: "handleDelete",
  9. btnName: "删除",
  10. },
  11. ],

(3)实现菜单按钮功能

新建:显示弹框

  1. // 新建 - 弹框
  2. handleNew() {
  3. this.dialogFormVisible = true;
  4. },

删除:调用接口删除组织机构树中的节点

  1. handleDelete() {
  2. this.$confirm("此操作将永久删除该组织, 是否继续?", "提示", {
  3. confirmButtonText: "确定",
  4. cancelButtonText: "取消",
  5. type: "warning",
  6. })
  7. .then(() => {
  8. deleteOrg(this.currentNodeKey).then((res) => {
  9. if (res.code === 200 && res.success === true) {
  10. this.$message.success(res.message);
  11. this.getTreeData();
  12. }
  13. });
  14. })
  15. .catch(() => {
  16. this.$message({
  17. type: "info",
  18. message: "已取消删除",
  19. });
  20. });
  21. },

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/119222
推荐阅读
相关标签
  

闽ICP备14008679号