Tree Component With Vue & Vuex
by huang shiyu
HTML
<script src="https://cdn.bootcss.com/vuex/2.4.0/vuex.js"></script>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
<div id="app">
{{ all | JSON }}
<group :content.sync="all"></group>
</div>
CSS
.item {
margin-left: 1rem;
margin-top: 1rem;
}
.group {
padding: 1rem 0 0 1rem;
}
JavaScript
const deepClone = obj => JSON.parse(JSON.stringify(obj))
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
all: {
name: '0',
list: [
{ name: '0-0', content: 'some text' }
]
},
formData: {
group: {
name: '',
list: []
},
item: {
name: '',
content: ''
}
}
},
mutations: {
add(state, { content, type }) {
const newItem = deepClone(state.formData[type])
const list = content.list
newItem.name = content.name + '-' + (list.length > 0 ? list[list.length - 1].name.match(/\d+/g).pop() - (-1) : '0')
content.list.push(newItem)
},
remove(state, { item, parent }) {
let index = parent.list.findIndex(_item => item.name === _item.name)
if (index >= 0) {
parent.list.splice(index, 1)
}
}
},
getters: {
all: state => state.all
}
})
const item = Vue.extend({
props: ['content'],
methods: {
remove() {
this.$emit('remove', this.content)
}
},
template:
`<div class="item">
<span>{{ content.name }}</span>
<input v-model="content.content" />
<button @click="remove">Delete Item</button>
</div>
`
})
const group = Vue.extend({
name: 'group',
props: ['content'],
components: { item },
methods: {
add(content, type) {
this.$store.commit('add', { content, type })
},
remove(item) {
this.$store.commit('remove', { item, parent: this.content })
},
componentType(item) {
return item.list ? 'group' : 'item'
},
},
template:
`<div class="group">
<span>{{ content.name }}</span>
<button @click="add(content, 'item')">Add Item</button>
<button @click="add(content, 'group')">Add Group</button>
<button @click="$emit('remove', content)">Delete Group</button>
<component :is="componentType(item)" v-for="item in content.list" :content.sync="item" @remove="remove">
</div>`,
})
const app = new Vue({
el: '#app',
store,
computed: {
...