2019-12-03 04:22:04 +08:00
|
|
|
<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>
|
2020-01-24 04:05:38 +08:00
|
|
|
const treeData = {
|
|
|
|
name: 'My Tree',
|
|
|
|
children: [
|
|
|
|
{ name: 'hello' },
|
|
|
|
{ name: 'wat' },
|
|
|
|
{
|
|
|
|
name: 'child folder',
|
2019-12-03 04:22:04 +08:00
|
|
|
children: [
|
2020-01-24 04:05:38 +08:00
|
|
|
{
|
|
|
|
name: 'child folder',
|
|
|
|
children: [
|
|
|
|
{ name: 'hello' },
|
|
|
|
{ name: 'wat' }
|
|
|
|
]
|
|
|
|
},
|
2019-12-03 04:22:04 +08:00
|
|
|
{ name: 'hello' },
|
|
|
|
{ name: 'wat' },
|
|
|
|
{
|
|
|
|
name: 'child folder',
|
|
|
|
children: [
|
|
|
|
{ name: 'hello' },
|
2020-01-24 04:05:38 +08:00
|
|
|
{ name: 'wat' }
|
2019-12-03 04:22:04 +08:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
2020-01-24 04:05:38 +08:00
|
|
|
]
|
2019-12-03 04:22:04 +08:00
|
|
|
}
|
|
|
|
|
2020-01-24 04:05:38 +08:00
|
|
|
Vue.createApp({
|
|
|
|
components: {
|
|
|
|
TreeItem
|
|
|
|
},
|
|
|
|
data: () => ({
|
|
|
|
treeData
|
|
|
|
})
|
|
|
|
}).mount('#demo')
|
2019-12-03 04:22:04 +08:00
|
|
|
</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>
|