tree.html 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <script src="../../dist/vue.global.js"></script>
  2. <!-- item template -->
  3. <script type="text/x-template" id="item-template">
  4. <li>
  5. <div
  6. :class="{bold: isFolder}"
  7. @click="toggle"
  8. @dblclick="changeType">
  9. {{model.name}}
  10. <span v-if="isFolder">[{{open ? '-' : '+'}}]</span>
  11. </div>
  12. <ul v-if="isFolder" v-show="open">
  13. <tree-item
  14. class="item"
  15. v-for="model in model.children"
  16. :model="model">
  17. </tree-item>
  18. <li class="add" @click="addChild">+</li>
  19. </ul>
  20. </li>
  21. </script>
  22. <!-- item script -->
  23. <script>
  24. const { reactive, computed, toRefs } = Vue
  25. const TreeItem = {
  26. name: 'TreeItem', // necessary for self-reference
  27. template: '#item-template',
  28. props: {
  29. model: Object
  30. },
  31. setup(props) {
  32. const state = reactive({
  33. open: false,
  34. isFolder: computed(() => {
  35. return props.model.children && props.model.children.length
  36. })
  37. })
  38. function toggle() {
  39. state.open = !state.open
  40. }
  41. function changeType() {
  42. if (!state.isFolder) {
  43. props.model.children = []
  44. addChild()
  45. state.open = true
  46. }
  47. }
  48. function addChild() {
  49. props.model.children.push({ name: 'new stuff' })
  50. }
  51. return {
  52. ...toRefs(state),
  53. toggle,
  54. changeType,
  55. addChild
  56. }
  57. }
  58. }
  59. </script>
  60. <p>(You can double click on an item to turn it into a folder.)</p>
  61. <!-- the app root element -->
  62. <ul id="demo">
  63. <tree-item class="item" :model="treeData"></tree-item>
  64. </ul>
  65. <script>
  66. const treeData = {
  67. name: 'My Tree',
  68. children: [
  69. { name: 'hello' },
  70. { name: 'wat' },
  71. {
  72. name: 'child folder',
  73. children: [
  74. {
  75. name: 'child folder',
  76. children: [
  77. { name: 'hello' },
  78. { name: 'wat' }
  79. ]
  80. },
  81. { name: 'hello' },
  82. { name: 'wat' },
  83. {
  84. name: 'child folder',
  85. children: [
  86. { name: 'hello' },
  87. { name: 'wat' }
  88. ]
  89. }
  90. ]
  91. }
  92. ]
  93. }
  94. Vue.createApp({
  95. components: {
  96. TreeItem
  97. },
  98. data: () => ({
  99. treeData
  100. })
  101. }).mount('#demo')
  102. </script>
  103. <style>
  104. body {
  105. font-family: Menlo, Consolas, monospace;
  106. color: #444;
  107. }
  108. .item {
  109. cursor: pointer;
  110. }
  111. .bold {
  112. font-weight: bold;
  113. }
  114. ul {
  115. padding-left: 1em;
  116. line-height: 1.5em;
  117. list-style-type: dot;
  118. }
  119. </style>