经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
vue-tree-chart树形组件的实现(含鼠标右击事件)
来源:jb51  时间:2022/2/28 11:23:51  对本文有异议

基于 vue-tree-chart,生成项目效果预览,包含鼠标右击事件;

在这里插入图片描述

vue-tree-chart:https://github.com/tower1229/Vue-Tree-Chart

大家可以直接安装使用(具体事例可以查看官网)

但是个人建议最好是下载整个项目,封装成组件调用

基于官网初始代码,封装组件:

  1. <template>
  2. <table v-if="treeData.name">
  3. <tr>
  4. <td :colspan="Array.isArray(treeData.children) ? treeData.children.length * 2 : 1"
  5. :class="{parentLevel: Array.isArray(treeData.children) && treeData.children.length, extend: Array.isArray(treeData.children) && treeData.children.length && treeData.extend}"
  6. >
  7. <div :class="{node: true, hasMate: treeData.mate}">
  8. <div class="person"
  9. :class="Array.isArray(treeData.class) ? treeData.class : []"
  10. >
  11. <div class="avat">
  12. <img :src="treeData.image_url" @contextmenu="$emit('click-node', treeData)"/>
  13. </div>
  14. <!-- <div class="name">{{treeData.name}}</div> -->
  15. </div>
  16. <div class="paeson_name">{{treeData.name}}</div>
  17. <template v-if="Array.isArray(treeData.mate) && treeData.mate.length">
  18. <div class="person" v-for="(mate, mateIndex) in treeData.mate" :key="treeData.name+mateIndex"
  19. :class="Array.isArray(mate.class) ? mate.class : []"
  20. @click="$emit('click-node', mate)"
  21. >
  22. <div class="avat">
  23. <img :src="mate.image_url" />
  24. </div>
  25. <!-- <div class="name">{{mate.name}}</div> -->
  26. </div>
  27. <div class="paeson_name">{{treeData.name}}</div>
  28. </template>
  29. </div>
  30. <div class="extend_handle" v-if="Array.isArray(treeData.children) && treeData.children.length" @click="toggleExtend(treeData)"></div>
  31. </td>
  32. </tr>
  33. <tr v-if="Array.isArray(treeData.children) && treeData.children.length && treeData.extend">
  34. <td v-for="(children, index) in treeData.children" :key="index" colspan="2" class="childLevel">
  35. <TreeChart :json="children" @click-node="$emit('click-node', $event)"/>
  36. </td>
  37. </tr>
  38. </table>
  39. </template>
  40.  
  41. <script>
  42. export default {
  43. name: "TreeChart",
  44. props: ["json"],
  45. data() {
  46. return {
  47. treeData: {}
  48. }
  49. },
  50. watch: {
  51. json: {
  52. handler: function(Props){
  53. let extendKey = function(jsonData){
  54. jsonData.extend = (jsonData.extend===void 0 ? true: !!jsonData.extend);
  55. if(Array.isArray(jsonData.children)){
  56. jsonData.children.forEach(c => {
  57. extendKey(c)
  58. })
  59. }
  60. return jsonData;
  61. }
  62. if(Props){
  63. this.treeData = extendKey(Props);
  64. }
  65. },
  66. immediate: true
  67. }
  68. },
  69. methods: {
  70. toggleExtend: function(treeData){
  71. treeData.extend = !treeData.extend;
  72. this.$forceUpdate();
  73. }
  74. }
  75. }
  76. </script>
  77.  
  78. <style scoped>
  79. table{border-collapse: separate!important;border-spacing: 0!important;}
  80. td{position: relative; vertical-align: top;padding:0 0 50px 0;text-align: center; }
  81. .extend_handle{position: absolute;left:50%;bottom:30px; width:10px;height: 10px;padding:10px;transform: translate3d(-15px,0,0);cursor: pointer;}
  82. .extend_handle:before{content:""; display: block; width:100%;height: 100%;box-sizing: border-box; border:2px solid;border-color:#ccc #ccc transparent transparent;
  83. transform: rotateZ(135deg);transform-origin: 50% 50% 0;transition: transform ease 300ms;}
  84. .extend_handle:hover:before{border-color:#333 #333 transparent transparent;}
  85. /* .extend .extend_handle:before{transform: rotateZ(-45deg);} */
  86. .extend::after{content: "";position: absolute;left:50%;bottom:15px;height:15px;border-left:2px solid #ccc;transform: translate3d(-1px,0,0)}
  87. .childLevel::before{content: "";position: absolute;left:50%;bottom:100%;height:15px;border-left:2px solid #ccc;transform: translate3d(-1px,0,0)}
  88. .childLevel::after{content: "";position: absolute;left:0;right:0;top:-15px;border-top:2px solid #ccc;}
  89. .childLevel:first-child:before, .childLevel:last-child:before{display: none;}
  90. .childLevel:first-child:after{left:50%;height:15px; border:2px solid;border-color:#ccc transparent transparent #ccc;border-radius: 6px 0 0 0;transform: translate3d(1px,0,0)}
  91. .childLevel:last-child:after{right:50%;height:15px; border:2px solid;border-color:#ccc #ccc transparent transparent;border-radius: 0 6px 0 0;transform: translate3d(-1px,0,0)}
  92. .childLevel:first-child.childLevel:last-child::after{left:auto;border-radius: 0;border-color:transparent #ccc transparent transparent;transform: translate3d(1px,0,0)}
  93. .node{position: relative; display: inline-block;margin: 0 1em;box-sizing: border-box; text-align: center;}
  94. .node:hover{color: #2d8cf0;cursor: pointer;}
  95. .node .person{position: relative; display: inline-block;z-index: 2;width:6em; overflow: hidden;}
  96. .node .person .avat{display: block;width:4em;height: 4em;margin:auto;overflow:hidden; background:#fff;border:1px solid #ccc;box-sizing: border-box;}
  97. .node .person .avat:hover{ border: 1px solid #2d8cf0;}
  98. .node .person .avat img{width:100%;height: 100%;}
  99. .node .person .name{height:2em;line-height: 2em;overflow: hidden;width:100%;}
  100. .node.hasMate::after{content: "";position: absolute;left:2em;right:2em;top:2em;border-top:2px solid #ccc;z-index: 1;}
  101. .node .paeson_name{transform: rotate(90deg);position: absolute; top: 68px;right: 39px;width: 88px;text-align: center;text-overflow: ellipsis; overflow: hidden; white-space: nowrap;}
  102.  
  103.  
  104. .landscape{transform:translate(-100%,0) rotate(-90deg);transform-origin: 100% 0;}
  105. .landscape .node{text-align: left;height: 8em;width:8em;right: 18px;}
  106. .landscape .person{position: absolute; transform: rotate(90deg);height: 4em;top:4em;left: 2.5em;}
  107. .landscape .person .avat{position: absolute;left: 0;border-radius: 2em;border-width:2px;}
  108. .landscape .person .name{height: 4em; line-height: 4em;}
  109. .landscape .hasMate{position: relative;}
  110. .landscape .hasMate .person{position: absolute; }
  111. .landscape .hasMate .person:first-child{left:auto; right:-4em;}
  112. .landscape .hasMate .person:last-child{left: -4em;margin-left:0;}
  113. </style>

新建一个组件,调用组件并增加鼠标右击事件:

  1. <template>
  2. <div id="app">
  3. <TreeChart :json="data" :class="{landscape: 1}" @click-node="clickNode" />
  4.  
  5. <div class="gl_prs_ctn" :style='[contextstyle]'>
  6. <ul class='gl_prs_li'>
  7. <li >添加</li>
  8. <li >详情</li>
  9. <li >编辑</li>
  10. <li >删除</li>
  11. </ul>
  12. </div>
  13.  
  14. </div>
  15. </template>
  16.  
  17. <script>
  18. import TreeChart from "./treechar";
  19. export default {
  20. name: 'app',
  21. components: {
  22. TreeChart
  23. },
  24. data() {
  25. return {
  26. data: {
  27. name: 'root',
  28. image_url: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3689173839,956040439&fm=26&gp=0.jpg",
  29. class: ["rootNode"],
  30. children: [
  31. {
  32. name: 'children1',
  33. image_url: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3689173839,956040439&fm=26&gp=0.jpg"
  34. },
  35. {
  36. name: 'children2',
  37. image_url: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3689173839,956040439&fm=26&gp=0.jpg",
  38. children: [
  39. {
  40. name: 'grandchild',
  41. image_url: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3689173839,956040439&fm=26&gp=0.jpg"
  42. },
  43. {
  44. name: 'grandchild2',
  45. image_url: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3689173839,956040439&fm=26&gp=0.jpg"
  46. },
  47. {
  48. name: 'grandchild3',
  49. image_url: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3689173839,956040439&fm=26&gp=0.jpg"
  50. }
  51. ]
  52. }
  53. ]
  54. },
  55. contextstyle: {
  56. display: 'none',
  57. right: '0px',
  58. top: '0px',
  59. left: '0px',
  60. bottom: '0px',
  61. },
  62. }
  63. },
  64. created(){
  65. document.oncontextmenu = ()=>{return false}
  66. document.addEventListener("click", (event) => {
  67. if(this.contextstyle.display == 'block'){
  68. this.contextstyle.display = 'none'
  69. }
  70. })
  71. },
  72. methods: {
  73. clickNode(node){
  74. if(window.event.x + 188 > document.documentElement.clientWidth){
  75. this.contextstyle.left = 'unset';
  76. this.contextstyle.right = document.documentElement.clientWidth - window.event.x + 'px';
  77. }else{
  78. this.contextstyle.left = window.event.x + 'px';
  79. }
  80. if(window.event.y + 166 > document.documentElement.clientHeight){
  81. this.contextstyle.top = 'unset';
  82. this.contextstyle.bottom = document.documentElement.clientHeight - window.event.y + 'px';
  83. }else{
  84. this.contextstyle.top = window.event.y + 'px';
  85. }
  86. this.contextstyle.display = 'block';
  87. },
  88. }
  89. }
  90. </script>
  91.  
  92. <style>
  93. #app {
  94. font-family: 'Avenir', Helvetica, Arial, sans-serif;
  95. -webkit-font-smoothing: antialiased;
  96. -moz-osx-font-smoothing: grayscale;
  97. text-align: center;
  98. color: #2c3e50;
  99. margin-top: 60px;
  100. }
  101. .gl_prs_ctn{
  102. width: 188px;
  103. background: rgb(255, 255, 255);
  104. box-shadow: rgba(0, 0, 0, 0.075) 0px 1px 1px inset, rgba(102, 175, 233, 0.6) 0px 0px 8px;
  105. z-index: 99999;
  106. position: fixed;
  107. padding: 10px;
  108. box-sizing: content-box;
  109. height: 142px;
  110. }
  111. .gl_prs_li{padding: unset;margin: unset;}
  112. .gl_prs_li>li{
  113. cursor: pointer;
  114. list-style: none;
  115. border-bottom: 1px solid #efefef;
  116. padding: 7px 10px;
  117. }
  118. li:last-child { border: unset }
  119. li:hover{
  120. background: #ccc;
  121. color: #fff;
  122. }
  123. </style>

到此这篇关于vue-tree-chart树形组件的实现(含鼠标右击事件)的文章就介绍到这了,更多相关vue-tree-chart 树形组件内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号