Vue broadcast example using store
by ktsn
HTML
<script src="https://npmcdn.com/vue/dist/vue.js"></script>
<div id="app">
<ul>
<item v-for="child in treeData"
:model="child">
</item>
</ul>
</div>
<script type="text/x-template" id="item-template">
<li>
<label>
<input type="checkbox" :checked="model.value" @change="onChange" />
{{model.label}}
</label>
<ul v-if="model.children">
<item v-for="child in model.children"
:model="child">
</item>
</ul>
</li>
</script>
Babel + JSX
const store = new Vue({
data: {
root: {
children: [
{
id: '1',
label:'A',value:false,
children:[
{
id: '1.1',
label:'A-1',value:false,
children:[
{id: '1.1.1', label:'A-1-1', value:false},
{id: '1.1.2', label:'A-1-2', value:false}
]
},
{id: '1.2', label:'A-2', value:false}
]
},
{
id: '2',
label:'B',value:false,
children:[
{id: '2.1', label:'B-1', value:false},
{id: '2.2', label:'B-2', value:false}
]
}
]
}
},
methods: {
// 再帰的に子孫に値を伝搬させる
walk: function(target, val) {
target.value = val
if (!target.children) return
target.children.forEach((child) => {
this.walk(child, val)
})
}
},
events: {
'change-at-parent': function(id, val) {
// 対象となる sub tree を探す
const path = id.split('.')
const target = path
.map(function(key) {
return Number(key) - 1
})
.reduce(function(data, key) {
return data.children[key]
}, this.root)
// 子孫にデータを伝搬させる
this.walk(target, val)
}
}
})
Vue.component('item', {
template: '#item-template',
props: {
model: Object
},
methods:{
onChange: function(event) {
store.$emit('change-at-parent', this.model.id, event.target.checked);
}
}
})
new Vue({
el: '#app',
data: {
treeData: store.root.children
}
})