1、通过改变父组件中的状态,从而改变兄弟组件的状态
Parent.vue:
<template> <div> <h1>父组件</h1> <p>{{name}}</p> <Child1 :name='name' @child1Click='name = $event' /> <Child2 :name='name' /> </div> </template> <script> import Child1 from './Child1' import Child2 from './Child2' export default { data() { return { name: '小明' } }, components: { Child1, Child2 } } </script>
Child1.vue:
<template> <div> <h3>子组件1</h3> <p>{{name}}</p> <button @click="handleClick">改变name</button> </div> </template> <script> export default { props: ['name'], methods: { handleClick() { this.$emit('child1Click', '小帅哥') } } } </script>
Child2.vue:
<template> <div> <h3>子组件2</h3> <p>{{name}}</p> </div> </template> <script> export default { props: ['name'] } </script>
这种方式只适合一种非父子组件(兄弟组件)传值,Child1组件改变父组件,Child2随之改变
2、eventBus
Parent.vue:
<template> <div> <h1>父组件</h1> <p>{{name}}</p> <Child1 :name='name' /> <Child2 :name='name' /> </div> </template> <script> import Child1 from './Child1' import Child2 from './Child2' export default { data() { return { name: '小明' } }, components: { Child1, Child2 } } </script>
Child1.vue:
<template> <div> <h3>子组件1</h3> <p>{{name}}</p> <button @click="handleClick">改变name</button> </div> </template> <script> import { eventBus } from '@/main' export default { props: ['name'], methods: { handleClick() { eventBus.$emit('change', '小帅哥') } } } </script>
Child2.vue:
<template> <div> <h3>子组件2</h3> <p>{{myName}}</p> </div> </template> <script> import { eventBus } from '@/main' export default { props: ['name'], data() { return { myName: this.name } }, created() { eventBus.$on('change', (val) => { this.myName = val }) }, beforeDestroy() { eventBus.$off('change') } } </script>
main.js:
export const eventBus = new Vue()
eventBus是一个vue实例对象,拥有$emit和$on方法
3、observer
src/utils/observer.js:
const eventList = {} const $on = function (eventName, callback) { if (!eventList[eventName]) { eventList[eventName] = [] } eventList[eventName].push(callback) } const $emit = function (eventName, params) { if (eventList[eventName]) { let arr = eventList[eventName] arr.forEach((cb) => { cb(params) }) } } const $off = function (eventName, callback) { if (eventList[eventName]) { if (callback) { let index = eventList[eventName].indexOf(callback) eventList[eventName].splice(index, 1) } else { eventList[eventName].length = 0 } } } export default { $on, $emit, $off }
main.js:
import observer from '@/utils/observer'
Vue.prototype.$observer = observer
Parent.vue:
<template> <div> <h1>父组件</h1> <p>{{name}}</p> <Child1 :name='name' /> <Child2 :name='name' /> </div> </template> <script> import Child1 from './Child1' import Child2 from './Child2' export default { data() { return { name: '小明' } }, components: { Child1, Child2 } } </script>
Child1.vue:
<template> <div> <h3>子组件1</h3> <p>{{name}}</p> <button @click="handleClick">改变name</button> </div> </template> <script> export default { props: ['name'], methods: { handleClick() { this.$observer.$emit('change', '小帅哥') } } } </script>
Child2.vue:
<template> <div> <h3>子组件2</h3> <p>{{myName}}</p> </div> </template> <script> export default { props: ['name'], data() { return { myName: this.name } }, created() { this.$observer.$on('change', (val) => { this.myName = val }) }, beforeDestroy() { this.$observer.$off('change') } } </script>
和eventBus原理一样
4、vuex
src/store/index.js:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { name: '小明' }, mutations: { changeName(state, name) { console.log(name) state.name = name } } })
main.js:
import store from './store' const vm = new Vue({ router, store, render: (h) => h(App) })
Parent.vue:
<template> <div> <h1>父组件</h1> <p>{{$store.state.name}}</p> <Child1 /> <Child2 /> </div> </template> <script> import Child1 from './Child1' import Child2 from './Child2' export default { components: { Child1, Child2 } } </script>
Child1.vue:
<template> <div> <h3>子组件1</h3> <p>{{name}}</p> <button @click="changeName('小帅哥')">改变name</button> </div> </template> <script> import { mapState, mapMutations } from 'vuex' export default { computed: { ...mapState({ name: (state) => state.name }) }, methods: { ...mapMutations({ changeName: 'changeName' }) } } </script>
Child2.vue:
<template> <div> <h3>子组件2</h3> <p>{{$store.state.name}}</p> </div> </template>
改变vuex中的状态,项目中所有使用name的地方都会随之改变