当前位置:   article > 正文

vue 树形目录结构

vue文件夹树形结构

 原先使用的是Ztree,后来因为更多的定制化要求,还是手写一个算了

  1. <template>
  2. <div>
  3. <menu-tree :nodes="nodes" :selected="currentCameraId"></menu-tree>
  4. </div>
  5. </template>
  6. <script>
  7. import EventBus from "@/utils/EventBus";
  8. import MenuTree from "@/views/HomePage2D/components/MenuTree";
  9. import dh_config from "static/config/dh-camera";
  10. export default {
  11. name: "zoneDeviceDir",
  12. components: {MenuTree},
  13. data() {
  14. return {
  15. nodes: [],
  16. allNodes: [],
  17. currentCameraId: ''
  18. }
  19. },
  20. watch: {},
  21. computed: {},
  22. methods: {
  23. //选中
  24. cameraClick(item) {
  25. this.currentCameraId = this.currentCameraId === item.id ? '' : item.id;
  26. if (this.currentCameraId !== '') {
  27. EventBus.$emit('showThisVideo',item)
  28. }
  29. },
  30. //全部展开或折叠
  31. allNoExpand(flag) {
  32. this.nodes.forEach(node => {
  33. this.noExpand(node, flag)
  34. })
  35. },
  36. noExpand(node, flag) {
  37. node.expand = flag;
  38. if (node.children && node.children.length > 0) {
  39. node.children.forEach(childNode => {
  40. this.noExpand(childNode, flag)
  41. })
  42. }
  43. },
  44. //反向定位
  45. reverseCamera(id) {
  46. this.currentCameraId = id;
  47. this.allNoExpand(false);
  48. this.nodes = this.allNodes;
  49. this.cameraSelect(this.nodes, id);
  50. },
  51. cameraSelect(nodes, queryData) {
  52. for (let i = 0; i < nodes.length; i++) {
  53. let node = nodes[i];
  54. if (node.children === null && this.corCamera(node, queryData)) {
  55. node.expand = true;
  56. } else {
  57. let deepQuery = this.corCamera(node, queryData);
  58. if (deepQuery) {
  59. node.expand = true;
  60. if (node.children) {
  61. this.cameraSelect(node.children, queryData);
  62. }
  63. }
  64. }
  65. }
  66. },
  67. corCamera(node, queryData) {
  68. if (node.children === null) {
  69. if (node.id === queryData) {
  70. return true;
  71. } else {
  72. return false;
  73. }
  74. }
  75. for (let i = 0; i < node.children.length; i++) {
  76. if (this.corCamera(node.children[i], queryData)) {
  77. return true;
  78. }
  79. }
  80. return false;
  81. },
  82. //查找
  83. search(queryData) {
  84. let array = this.treeSelect(this.allNodes, queryData);
  85. this.nodes = array;
  86. this.allNoExpand(true);
  87. },
  88. treeSelect(nodes, queryData) {
  89. let newArray = [];
  90. for (let i = 0; i < nodes.length; i++) {
  91. let node = nodes[i];
  92. if (node.children === null && this.treeDeepQuery(node, queryData)) {
  93. newArray.push(node);
  94. } else {
  95. let deepQuery = this.treeDeepQuery(node, queryData);
  96. if (deepQuery) {
  97. let newNode = JSON.parse(JSON.stringify(node));
  98. if (node.children) {
  99. newNode.children = this.treeSelect(node.children, queryData);
  100. }
  101. newArray.push(newNode)
  102. }
  103. }
  104. }
  105. return newArray;
  106. },
  107. treeDeepQuery(node, queryData) {
  108. if (node.children === null) {
  109. if (node.name.indexOf(queryData) !== -1) {
  110. return true;
  111. } else {
  112. return false;
  113. }
  114. }
  115. for (let i = 0; i < node.children.length; i++) {
  116. if (this.treeDeepQuery(node.children[i], queryData)) {
  117. return true;
  118. }
  119. }
  120. return false;
  121. }
  122. },
  123. mounted() {
  124. EventBus.$on("item-click", this.cameraClick)
  125. EventBus.$on('ReversePositioning',this.reverseCamera)
  126. let T = this
  127. this.$axios.get(`/camera/menu/list?&time=${new Date().getTime()}`).then(res => {
  128. if (res.data.code !== 200) {
  129. this.$Message.error(res.data.msg)
  130. } else {
  131. T.nodes = res.data.data
  132. T.allNodes = res.data.data
  133. }
  134. })
  135. },
  136. beforeDestroy() {
  137. }
  138. }
  139. </script>
  140. <style lang="scss" scoped>
  141. </style>

树组件

  1. <template>
  2. <div class="menu-tree" :class="{'menu-tree-top' : top}">
  3. <div v-for="item in nodes" :key="item.id">
  4. <!--菜单-->
  5. <div class="menu-item" @click="folderClick(item)" v-show="item.children !== null && item.num > 0">
  6. <div style="position: absolute;top: 0;left: 20px;width: calc(100% - 20px);height: 100%"></div>
  7. <i class="iconfont iconjia" v-show="!item.expand" style="color: #0ABBE5"></i>
  8. <i class="iconfont iconjian" v-show="item.expand"></i>
  9. {{item.name}}<span v-show="item.num > 0">({{item.num}})</span>
  10. </div>
  11. <!--摄像头-->
  12. <div class="menu-item" @click="itemClick(item)" v-show="item.children === null" :class="{'menu-item-selected-parent':item.id === selected}">
  13. <div style="position: absolute;top: 0;left: 20px;width: calc(100% - 20px);height: 100%" :class="{'menu-item-selected':item.id === selected}"></div>
  14. <i class="iconfont iconshexiangtou" :class="[{'online': item.statusName === '在线'},{'offline': item.statusName !== '在线'}]"></i>
  15. <span>({{item.resource}})&nbsp;</span>{{item.name}}
  16. </div>
  17. <!--子菜单递归-->
  18. <div v-show="item.children && item.children.length > 0 && item.expand" class="child-menu">
  19. <menu-tree :nodes="item.children" :selected="selected" :top="false"></menu-tree>
  20. </div>
  21. </div>
  22. </div>
  23. </template>
  24. <script>
  25. import EventBus from "@/utils/EventBus";
  26. export default {
  27. props: {
  28. nodes: Array,
  29. selected: String,
  30. top: {
  31. required: false,
  32. default: true
  33. }
  34. },
  35. name: "MenuTree",
  36. data() {
  37. return {}
  38. },
  39. mounted() {
  40. },
  41. methods: {
  42. itemClick(item) {
  43. EventBus.$emit('item-click', item);
  44. },
  45. folderClick(item) {
  46. this.nodes.forEach(node => {
  47. if (node.id === item.id) {
  48. node.expand = !node.expand;
  49. }
  50. })
  51. }
  52. }
  53. }
  54. </script>
  55. <style lang="scss">
  56. .menu-tree {
  57. color: #333;
  58. font-size: 17px;
  59. position: relative;
  60. .menu-item {
  61. position: relative;
  62. padding-left: 25px;
  63. height: 40px;
  64. line-height: 40px;
  65. overflow: hidden;
  66. text-overflow: ellipsis;
  67. white-space: nowrap;
  68. .online {
  69. color: #1686D8;
  70. }
  71. .offline {
  72. color: #B7C3CE;
  73. }
  74. .menu-item-selected {
  75. border: 1px solid #1686D8;
  76. background: rgba(22, 134, 216, 0.1);
  77. }
  78. &:hover {
  79. cursor: pointer;
  80. > div {
  81. &:first-child {
  82. border: 1px solid #1686D8;
  83. background: rgba(22, 134, 216, 0.1);
  84. }
  85. }
  86. }
  87. &:after {
  88. content: "";
  89. width: 11px;
  90. height: 20px;
  91. position: absolute;
  92. left: 12px;
  93. top: 19px;
  94. border-width: 1px;
  95. border-top: 1px dashed #52627C;
  96. }
  97. }
  98. .menu-item-selected-parent {
  99. font-weight: bold;
  100. }
  101. .menu-item-camera {
  102. width: 100%;
  103. }
  104. .child-menu {
  105. margin-left: 20px;
  106. position: relative;
  107. &:before {
  108. content: "";
  109. height: calc(100% - 11px);
  110. width: 1px;
  111. position: absolute;
  112. left: 12px;
  113. top: -11px;
  114. border-width: 1px;
  115. border-left: 1px dashed #52627C;
  116. }
  117. }
  118. }
  119. .menu-tree-top > div > .menu-item {
  120. /*padding-left: 0;*/
  121. &:before {
  122. border-left: none;
  123. }
  124. &:after {
  125. border-top: none;
  126. }
  127. }
  128. </style>
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签