tree.html 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <script src="../../dist/vue.min.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. Vue.set(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: [{ name: 'hello' }, { name: 'wat' }]
  77. },
  78. { name: 'hello' },
  79. { name: 'wat' },
  80. {
  81. name: 'child folder',
  82. children: [{ name: 'hello' }, { name: 'wat' }]
  83. }
  84. ]
  85. }
  86. ]
  87. }
  88. new Vue({
  89. components: {
  90. TreeItem
  91. },
  92. data: () => ({
  93. treeData
  94. })
  95. }).$mount('#demo')
  96. </script>
  97. <style>
  98. body {
  99. font-family: Menlo, Consolas, monospace;
  100. color: #444;
  101. }
  102. .item {
  103. cursor: pointer;
  104. }
  105. .bold {
  106. font-weight: bold;
  107. }
  108. ul {
  109. padding-left: 1em;
  110. line-height: 1.5em;
  111. list-style-type: dot;
  112. }
  113. </style>