vue: 从组件通讯到vuex (上)
关于vue之间的组件通讯
1: prop,refs 父组件 => 子组件
1) prop
// app.vue <template> <div id="app"> <childTest1 :msg="msg"/> </div> </template> <script> import childTest1 from './components/childTest1' export default { name: 'App', data () { return { msg: 'data from parent' } }, methods: { }, components: { childTest1 } } </script>
// childTest1.vue <template> <div class="hello"> {{msg}} </div> </template> <script> export default { name: 'childTest1', props: ['msg'], data () { return { msgTest2: null } }, methods: { } } </script>
2) refs
// app.vue <template> <div id="app"> <childTest1 :msg="msg" ref="childTest1"/> </div> </template> <script> import childTest1 from './components/childTest1' export default { name: 'App', data () { return { msg: 'data from parent' } }, created () { // 无效 this.$refs.childTest1.setMsgTest2('refs set msg test') }, mounted () { this.$refs.childTest1.setMsgTest2('refs set msg test') }, methods: { }, components: { childTest1 } } </script>
// childTest1.vue <template> <div class="hello"> <p>{{msg}}</p> <p style="color: #f80000">{{msgTest2}}</p> </div> </template> <script> export default { name: 'childTest1', props: ['msg'], data () { return { msgTest2: null } }, methods: { setMsgTest2 (val) { this.msgTest2 = val } } } </script>
2 : $emit 子组件 => 父组件
// App.vue <template> <div id="app"> <childTest1 :msg="msg" ref="childTest1" @changeMsg="setMsg"/> </div> </template> <script> import childTest1 from './components/childTest1' export default { name: 'App', data () { return { msg: 'data from parent' } }, created () { // 无效 this.$refs.childTest1.setMsgTest2('refs set msg test') }, mounted () { this.$refs.childTest1.setMsgTest2('refs set msg test') }, methods: { setMsg (val) { this.msg = val } }, components: { childTest1 } } </script>
// childTest1.vue <template> <div class="hello"> <p>{{msg}}</p> <p style="color: #f80000">{{msgTest2}}</p> <button @click="changeMsg">changeMsg</button> </div> </template> <script> export default { name: 'childTest1', props: ['msg'], data () { return { msgTest2: null } }, methods: { setMsgTest2 (val) { this.msgTest2 = val }, changeMsg () { this.$emit('changeMsg', 'child change test msg') } } } </script>
上面是简单的组件通讯,简单的父子组件传递可以使用上述形式,当比较复杂的情况下, 或者组件是相互独立,而且中间一个发生变化另一个变化的时候可以使用vue bus。
3: vue bus 独立组件 => 独立组件 (父 => 子 子 => 父)
// app.Vue <template> <div id="app"> {{parentMsg}} <childTest1 :msg="msg" ref="childTest1" @changeMsg="setMsg"/> <ChildTest2 /> </div> </template> <script> import ChildTest1 from './components/ChildTest1' import ChildTest2 from './components/ChildTest2' import ChildTestBus from './bus/ChildTest' export default { name: 'App', data () { return { parentMsg: 'parent init msg', msg: 'data from parent' } }, created () { ChildTestBus.$on('changeMsg', val => this.setParentMsg(val)) // 无效 this.$refs.childTest1.setMsgTest2('refs set msg test') }, mounted () { this.$refs.childTest1.setMsgTest2('refs set msg test') }, destrory () { ChildTestBus.$off('changeMsg') }, methods: { setParentMsg (val) { this.parentMsg = val }, setMsg (val) { this.msg = val } }, components: { ChildTest1, ChildTest2 } } </script>
// ChildTest1.vue <template> <div class="hello"> <p>{{msg}}</p> <p style="color: #f80000">{{msgTest2}}</p> <button @click="changeMsg">changeMsg</button> <button @click="changeParentMsg" style="background: #ddd">changeMsgFromTest1</button> </div> </template> <script> import ChildTestBus from '../bus/ChildTest' export default { name: 'ChildTest1', props: ['msg'], data () { return { msgTest2: null } }, methods: { setMsgTest2 (val) { this.msgTest2 = val }, changeMsg () { this.$emit('changeMsg', 'child change test msg') }, changeParentMsg () { ChildTestBus.$emit('changeMsg', 'change msg from childTest1') } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>
// ChildTest2.vue <template> <div class="hello"> <p style="color: blue">{{msgTest2}}</p> <button @click="changeMsg">changeMsgFromTest2</button> </div> </template> <script> import ChildTestBus from '../bus/ChildTest' export default { name: 'ChildTest2', props: ['msg'], data () { return { msgTest2: 'msg in childTest2' } }, methods: { changeMsg () { ChildTestBus.$emit('changeMsg', 'change msg from childTest2') } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>
// ChildTest.js import Vue from 'Vue' export default new Vue()
上述就可以实现复杂点的组件通讯了,这里有着注意点,当你使用bus时,通过$on事件获取消失时,得在组件注销时解除监听。
这个的缺点时当你的应用比较大时,这个触发和监听信息的代码需要在多处使用,这样我们就需要统一管理了,既便于维护,也方便理解
这个时候就可以用到vuex ,详情下级分解