总结-vue2组件通信

lxf2023-05-11 01:31:02

组件通信

1. 父子组件

a. 通过发送和接受消息

父组件

例如

通过v-bind或:实现把父组件的数据传给子组件
通过v-on或@,实现监听子组件事件和接收数据
<son :uname="uname" @update-uname="uname = $event"></son>

子组件

例如

export default {
	//通过props接收父组件传过来的数据
	props: ['uname'],
	methods: {
		handle(){
			//通过$emit触发事件,发送数据给父组件
			this.$emit('update-uname','ls')
		}
	}
}

语法

v-model

父组件

<son v-model="uname"></son>

子组件

export default {
	props: ['value'],
	methods: {
		handle(){
			this.$emit('input','ls')
		}
	}
}
.sync

父组件

<son :uname.sync="uname"></son>

子组件

export default {
	props: ['uname'],
	methods: {
		handle(){
			this.$emit('update:uname','ls')
		}
	}
}

b.通过组件实例直接通信

父->子

通过ref和$refs

<template>
	<son ref="sonRef"></son>
</template>
<script>
export default = {
	methods: {
		handle(){
			this.$refs.sonRef.uname //访问数据
			this.$refs.sonRef.updateUname('ls')//访问方法
		}
	}
}
</script>

子->父

通过$parent

export default {
	methods: {
		handle(){
			this.$parent.uname //访问数据
			this.$parent.upateUname('ls') //访问方法
		}
	}
}

2. 兄弟组件

a通过事件中心

事件中心

例如

import Vue from 'vue'
const eventBus = new Vue()
export funtion on(eventName, fn){
	eventBus.$on(eventName, fn)
}
export funtion emit(eventName, data){
	eventBus.$emit(eventName, data)
}

兄弟A

例如

import {emit} from '@/utils/eventBus.js'
export default {
  methods: {
     handle(){
        //发消息
        emit('add-success', 4)
     }
  }
}

兄弟B

例如

import {on} from '@/utils/eventBus.js'
export default {
  data(){
    return {
        list: [1,2,3]
    }  
  },
  mounted(){
    //接受消息
  	on('add-success', function(data){
  		this.list.push(data)
  	})
  }
}

b.通过父组件通信(通过消息和直接通信)

父组件

例如

<template>
    <son-a @add-success="handle"><son-a>
    <son-b ref="sonbRef"><son-b>
</template>
<script>
export defalut {
	methods: {
		handle(data){
			//父组件之间操作子组件实例实现通信
			this.$refs.sonbRef.list.push(data)
		}
	}
}
</script>

兄弟A

例如

export default {
  methods: {
     handle(){
        //发消息
        this.$emit('add-success', 4)
     }
  }
}

兄弟B

例如

export default {
  data(){
    return {
        list: [1,2,3]
    }  
  }
}

c.通过父组件通信(通过消息)

父组件

例如

<template>
    <son-a @add-success="handle"><son-a>
    <son-b :list="list"><son-b>
</template>
<script>
export defalut {
    data(){
    	list: []
    },
	methods: {
		handle(data){
			//父子组件通过数据绑定实现通信
			this.list.push(data)
		}
	}
}
</script>

兄弟A

例如

export default {
  methods: {
     handle(){
        //发消息
        this.$emit('add-success', 4)
     }
  }
}

兄弟B

例如

export default {
  props: {
  	//通过props接收父组件传过来的数据
  	list: {
  		type: Array,
  		default: ()=>[]
  	}
  }
}

d.通过插槽

父组件

<template>
    <son-a><button @click="handle(4)">add</button><son-a>
    <son-b :list="list"><son-b>
</template>
<script>
export defalut {
    data(){
      return {
          list: [1,2,3]
      }  
    },
	methods: {
		handle(data){
			//父组件之间操作子组件实例实现通信
			this.list.push(data)
		}
	}
}
</script>

兄弟A

例如

<template>
	<div class="son-a">
		<slot></slot>
	</div>
</template>

兄弟B

例如

export default {
  props: {
  	//通过props接收父组件传过来的数据
  	list: {
  		type: Array,
  		default: ()=>[]
  	}
  }
}

3. 爷孙组件

a.通过父子通信

<body>
    <div id="app">
        <grand-father></grand-father>
    </div>
</body>
<script>
// 爷爷组件
Vue.component('grand-father', {
    data() {
        return {
            money: 1000
        }
    },
    template: `
        <div>
            <div>爷爷</div>
            <father :money="money" @pay="money-=$event"/>
        </div>
    `
})
// 父亲组件
Vue.component('father', {
    props: ['money'],
    template: `
        <div>
            <div>父亲</div>
            <son :money="money" @pay="$emit('pay',$event)"/>
        </div>
    `
})
// 孙子组件
Vue.component('son', {
    props: ['money'],
    template: `
        <div>
            <div>孙子-{{money}}</div>
            <button @click="$emit('pay', 100)">-100</button>
        </div>
    `
})
var vm = new Vue({
    el: '#app',
    data: {
    },
    methods: {
    },
    mounted() {
    },
})

b.通过$parent

<body>
    <div id="app">
        <grand-father></grand-father>
    </div>
</body>
<script>
// 爷爷组件
Vue.component('grand-father', {
    data() {
        return {
            money: 1000
        }
    },
    template: `
        <div>
            <div>爷爷</div>
            <father ref="father"/>
        </div>
    `,
    methods: {
        pay(num){
            if(this.money>num){
                this.money -= num
            }
        }
    }
})
// 父亲组件
Vue.component('father', {
    template: `
        <div>
            <div>父亲</div>
            <son/>
        </div>
    `
})
// 孙子组件
Vue.component('son', {
    template: `
        <div>
            <div>孙子-{{$parent.$parent.money}}</div>
            <!--可以,但是不要做-->
            <!--<button @click="$parent.$parent.money-=100">-100</button>-->
            <button @click="$parent.$parent.pay(100)">-100</button>
        </div>
    `
})
var vm = new Vue({
    el: '#app',
    data: {
    },
    methods: {
    },
    mounted() {
    },
})
</script>

c.通过provide和inject

<body>
    <div id="app">
        <grand-father></grand-father>
    </div>
</body>
<script>
// 爷爷组件
Vue.component('grand-father', {
    data() {
        return {
            money: 1000
        }
    },
    provide(){
        return {
            grandFather: this
        }
    },
    template: `
        <div>
            <div>爷爷</div>
            <father/>
        </div>
    `,
    methods: {
        pay(num){
            if(this.money>num){
                this.money -= num
            }
        }
    }
})
// 父亲组件
Vue.component('father', {
    template: `
        <div>
            <div>父亲</div>
            <son/>
        </div>
    `
})
// 孙子组件
Vue.component('son', {
    inject: ['grandFather'],
    mounted() {
    },
    template: `
        <div>
            <div>孙子-{{grandFather.money}}</div>
            <button @click="grandFather.pay(100)">-100</button>
        </div>
    `
})
var vm = new Vue({
    el: '#app',
    data: {
    },
    methods: {
    },
    mounted() {
    },
})
</script>

4. 没关系组件

通过vuex

定义store

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  // 定义数据
  state: {
    count: 0
  },
  // 同步代码
  mutations: {
    addCount (state) {
      state.count++
    },
    //接受参数
    addCountN (state, payload) {
      state.count += payload
    }
  },
  // 异步代码
  actions: {
    addCountSync (context) {
      setTimeout(() => {
        context.commit('addCount')
      }, 1000)
    },
    // 接受参数
    addCountNSync (context, payload) {
      setTimeout(() => {
        context.commit('addCountN', payload)
      }, 1000)
    }
  },
  // 计算属性
  getters: {
    showCount (state) {
      return `当前的count值=${state.count}`
    },
    // 简化模块中state的获取
    token (state) {
      return state.user.token
    }
  },
  // 模块化
  modules: {
    user: {
      // 命名空间
      namespaced: true,
      state: {
        token: 'abc'
      },
      mutations: {
        updateToken () {
          console.log('2')
        }
      }
    }
  }
})

访问state

标准写法

<div>{{$store.state.count}}</div>

简化写法

<template>
	<div>{{count}}</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
  computed: {
    ...mapState(['count'])
  }   
}
</script>

访问mutations

标准写法

<button @click="$store.commit('addCount')">+1</button>
<button @click="$store.commit('addCountN', 3)">+N</button>

简化写法

<template>
    <div>
        <button @click="addCount">+1</button>
        <button @click="addCountN(3)">+N</button>        
    </div>
</template>
<script>
import {mapMutations} from 'vuex'
export default {
  methods: {
    ...mapMutations(['addCount', 'addCountN'])
  } 
}
</script>

访问actions

标准写法

<button @click="$store.dispatch('addCountSync')">+1 sync</button>
<button @click="$store.dispatch('addCountNSync', 3)">+N sync</button>

简化写法

<template>
    <div>
        <button @click="addCountSync">+1 sync</button>
        <button @click="addCountNSync(3)">+N sync</button>        
    </div>
</template>
<script>
import {mapActions} from 'vuex'
export default {
  methods: {
    ...mapActions(['addCountSync', 'addCountNSync']),
  } 
}
</script>

访问getters

标准写法

<div>{{$store.getters.showCount}}</div>

简化写法

<template>
    <div>{{showCount}}</div>
</template>
<script>
import {mapActions} from 'vuex'
export default {
  computed: {
    ...mapGetters(['showCount'])
  },
}
</script>

访问模块state

标准写法

<div>token={{$store.state.user.token}}</div>

简化写法

<template>
    <div>{{token}}</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
  computed: {
    ...mapGetters(['token'])
  }
}
</script>

访问模块mutations

标准写法

<button @click="$store.commit('user/updateToken')">updateToken</button>

简化写法

通过mapMutations('命令空间名/mutations名')
<template>
    <button @click="()=>this['user/updateToken']()">updateToken</button>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
  methods: {
    ...mapMutations(['user/updateToken'])
  }
}
</script>
通过mapMutations('命令空间名',['mutations名'])
<template>
    <button @click="updateToken">updateToken</button>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
  methods: {
    ...mapMutations('user', ['updateToken']),
  }
}
</script>
通过createNamespacedHelpers
<template>
    <button @click="updateToken">updateToken</button>
</template>
<script>
import { createNamespacedHelpers } from 'vuex'
const { mapMutations } = createNamespacedHelpers('user')
export default {
  methods: {
    ...mapMutations(['updateToken'])
  }
}
</script>
本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!