BREAKING CHANGE: `createApp` API has been adjusted.
  - `createApp()` now accepts the root component, and optionally a props
  object to pass to the root component.
  - `app.mount()` now accepts a single argument (the root container)
  - `app.unmount()` no longer requires arguments.
  New behavior looks like the following:
  ``` js
  const app = createApp(RootComponent)
  app.mount('#app')
  app.unmount()
  ```
		
	
			
		
			
				
	
	
		
			131 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <script src="../../dist/vue.global.js"></script>
 | |
| 
 | |
| <!-- item template -->
 | |
| <script type="text/x-template" id="item-template">
 | |
|   <li>
 | |
|     <div
 | |
|       :class="{bold: isFolder}"
 | |
|       @click="toggle"
 | |
|       @dblclick="changeType">
 | |
|       {{model.name}}
 | |
|       <span v-if="isFolder">[{{open ? '-' : '+'}}]</span>
 | |
|     </div>
 | |
|     <ul v-if="isFolder" v-show="open">
 | |
|       <tree-item
 | |
|         class="item"
 | |
|         v-for="model in model.children"
 | |
|         :model="model">
 | |
|       </tree-item>
 | |
|       <li class="add" @click="addChild">+</li>
 | |
|     </ul>
 | |
|   </li>
 | |
| </script>
 | |
| <!-- item script -->
 | |
| <script>
 | |
| const { reactive, computed, toRefs } = Vue
 | |
| 
 | |
| const TreeItem = {
 | |
|   name: 'TreeItem', // necessary for self-reference
 | |
|   template: '#item-template',
 | |
|   props: {
 | |
|     model: Object
 | |
|   },
 | |
|   setup(props) {
 | |
|     const state = reactive({
 | |
|       open: false,
 | |
|       isFolder: computed(() => {
 | |
|         return props.model.children && props.model.children.length
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     function toggle() {
 | |
|       state.open = !state.open
 | |
|     }
 | |
| 
 | |
|     function changeType() {
 | |
|       if (!state.isFolder) {
 | |
|         props.model.children = []
 | |
|         addChild()
 | |
|         state.open = true
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     function addChild() {
 | |
|       props.model.children.push({ name: 'new stuff' })
 | |
|     }
 | |
| 
 | |
|     return {
 | |
|       ...toRefs(state),
 | |
|       toggle,
 | |
|       changeType,
 | |
|       addChild
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <p>(You can double click on an item to turn it into a folder.)</p>
 | |
| 
 | |
| <!-- the app root element -->
 | |
| <ul id="demo">
 | |
|   <tree-item class="item" :model="treeData"></tree-item>
 | |
| </ul>
 | |
| 
 | |
| <script>
 | |
| const treeData = {
 | |
|   name: 'My Tree',
 | |
|   children: [
 | |
|     { name: 'hello' },
 | |
|     { name: 'wat' },
 | |
|     {
 | |
|       name: 'child folder',
 | |
|       children: [
 | |
|         {
 | |
|           name: 'child folder',
 | |
|           children: [
 | |
|             { name: 'hello' },
 | |
|             { name: 'wat' }
 | |
|           ]
 | |
|         },
 | |
|         { name: 'hello' },
 | |
|         { name: 'wat' },
 | |
|         {
 | |
|           name: 'child folder',
 | |
|           children: [
 | |
|             { name: 'hello' },
 | |
|             { name: 'wat' }
 | |
|           ]
 | |
|         }
 | |
|       ]
 | |
|     }
 | |
|   ]
 | |
| }
 | |
| 
 | |
| Vue.createApp({
 | |
|   components: {
 | |
|     TreeItem
 | |
|   },
 | |
|   data: () => ({
 | |
|     treeData
 | |
|   })
 | |
| }).mount('#demo')
 | |
| </script>
 | |
| 
 | |
| <style>
 | |
|   body {
 | |
|     font-family: Menlo, Consolas, monospace;
 | |
|     color: #444;
 | |
|   }
 | |
|   .item {
 | |
|     cursor: pointer;
 | |
|   }
 | |
|   .bold {
 | |
|     font-weight: bold;
 | |
|   }
 | |
|   ul {
 | |
|     padding-left: 1em;
 | |
|     line-height: 1.5em;
 | |
|     list-style-type: dot;
 | |
|   }
 | |
| </style>
 |