vue兄弟组件通信

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
}
View Code

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的地方都会随之改变

 

posted @ 2021-08-02 16:38  吴小明-  阅读(813)  评论(0编辑  收藏  举报