Vue2.x组件通信
1、父子组件通信
- props - 子组件接收到数据后,不能直接修改父组件的数据。(父组件重新渲染时,数据会被覆盖);推荐使用 computed。
//父组件
<template>
<child :msg="msg"></child>
</temolate>
//子组件
export default{
// 写法一:数组接收
props:['msg']
// 写法二:用对象接收,可以限定接收的数据类型,设置默认值、验证等
props:{
msg:{
type:String,
default:'这是默认数据'
}
},
mounted(){
console.log(this.msg)
}
}
- $emit / v-on - 子组件通过派发事件的方式给父组件数据,或者触发父组件更新等操作。
// 子组件 派发
export default {
data(){
return { msg: "这是发给父组件的信息" }
},
methods: {
handleClick(){
this.$emit("sendMsg",this.msg)
}
},
}
// 父组件 响应
<template>
<child v-on:sendMsg="getChildMsg"></child>
// 或 简写
<child @sendMsg="getChildMsg"></child>
</template>
export default {
methods:{
getChildMsg(msg){
console.log(msg) // 这是父组件接收到的消息
}
}
}
- ref - ref 如果在普通的DOM元素上,引用指向的就是该DOM元素;如果在子组件上,引用的指向就是子组件实例,然后父组件就可以通过 ref 主动获取子组件的属性或者调用子组件的方法。
//子组件
export default {
data(){
return {
name:"沐华"
}
},
methods:{
someMethod(msg){
console.log(msg)
}
}
}
//父组件
<template>
<child ref="child"></child>
</template>
<script>
export default {
mounted(){
const child = this.$refs.child
console.log(child.name) // 沐华
child.someMethod("调用了子组件的方法")
}
}
</script>
- .syns - 可以实现父组件向子组件传递的数据的双向绑定,所以子组件接收到数据后,可直接修改,并且会同时修改父组件的数据。
//父组件
<template>
<child :page.sync="page"></child>
</temolate>
export default{
data(){
return {
page:1
}
}
}
//子组件
export default{
props:["page"],
computed(){
// 在子组件里修改 currentPage 时,父组件的 page 也会随之改变
currentPage{
get(){
return this.page
},
set(newVal){
this.$emit("update:page", newVal)
}
}
}
}
- v-model - 和 .sync 类似,可以实现将父组件传给子组件的数据为双向绑定,子组件通过 $emit 修改父组件的数据
// 父组件
<template>
<child v-model="value"></child>
</template>
<script>
export default {
data(){
return {
value:1
}
}
}
// 子组件
<template>
<input :value="value" @input="handlerChange">
</template>
export default {
props:["value"],
// 可以修改事件名,默认为 input
model:{
event:"updateValue"
},
methods:{
handlerChange(e){
this.$emit("input", e.target.value)
// 如果有上面的重命名就是这样
this.$emit("updateValue", e.target.value)
}
}
}
</script>
- $$children / $parent
2、兄弟组件通信
- EventBus - EventBus 是中央事件总线,不管是父子组件,兄弟组件,跨层级组件等都可以使用它完成通信操作。
// 方法一
// 抽离成一个单独的 js 文件 Bus.js ,然后在需要的地方引入
// Bus.js
import Vue from "vue"
export default new Vue()
// 方法二 直接挂载到全局
// main.js
import Vue from "vue"
Vue.prototype.$bus = new Vue()
// 方法三 注入到 Vue 根对象上
// main.js
import Vue from "vue"
new Vue({
el:"#app",
data:{
Bus: new Vue()
}
})
- Vuex - Vuex 是状态管理器,集中式存储管理所有组件的状态。
//目录层级
store
|-state.js
|-actions.js
|-getter.js
|-muations.js
|-moeules
// index.js封装
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import actions from './actions'
import mutations from './mutations'
import state from './state'
import user from './modules/user'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
user
},
getters,
actions,
mutations,
state
})
export default store
// 在需要的组件里面使用
import {mapGetters,mapMutations} from "vuex",
export default{
computed:{
//方式一:通过this.属性名就可以用
...mapGetters({"引入getters.js里属性1","属性2"})
//方式二:
...mapGetters("user",["user模块里的属性1","属性2"])
},
methods:{
//方式一:通过this.属性名就可以用
...mapMustaions(["引入mutations.js里的方法1","方法2"])
//方式二:
...mapMuations("user",["引入user模块里的方法1","方法2"])
}
}
Vue3.x组件通信
defineProps ----> [用来接收父组件传来的 props]:
- 父组件代码:
<template> <Child @getChili="getChili" :title="msg" /> </template> <script setup> import {ref} from 'vue' import Child from './child.vue' //把值传递给子组件 --> :title="msg" cosnt msg = ref('父组件的值') </script> - 子组件代码:
<template> <div style="color: red">{{props.title}}</div> </template> <script setup> import {defineProps} from 'vue' //接收父组件 传过来的值! const props = defineProps({ title: { type: String } }); //打印一下 接收父组件的值 console.log(props.title) //父的值 </script>
defineEmit ----> [子组件向父组件事件传递] :
- 子组件代码:
<temolate> <button @click="toEmits">点击传值到父组件</button> </temolate> <script setup> import {defineEmits,ref} from 'vue' //先定义一下,在发送值 const emits = defineEmits(['getChili']) const toEmits = () => { emits('getChili','子组件的值') } </script> - 父组件代码:
<template> <div>{{data}}</div> <Child @getChili="getChili" :title="msg" /> </template> <script setup> import {ref} from 'vue' import Child from './child.vue' //空值接收 子组件的传值 const data = ref(null) const getChili = (e) => { console.log(e) //子组件的值 data.value = e } </script>
在标准组件写法里,子组件的数据都是默认隐式暴露给父组件的,但在script-setup模式下,所有数据只是默认return给template 使用,不会暴露到组件外,所以父组件是无法直接通过挂载ref 变量获取子组件的数据。如果要调用子组件的数据,需要先在子组件显示的暴露出来,才能够正确的拿到,这个操作,就是由defineExpose来完成。
defineExpose ----> [组件暴露出自己的属性] :
- 子组件代码:
<template> <div>{{user.name}}</div> </template> <script setup> import {ref, defineExpose, reactive} from 'vue' const user = reactive({ name:'张三', age:20 }) const userNew = ref('小张三') console.log(userNew) defineExpose({ user, userNew }) </script> - 父组件代码:
<template> <button @click="shiEmots">获取暴露</button> <Child ref="shield"/> </template> <script setup> import Child from './child.vue' import {defineEmits,defineProps,ref} from 'vue' const shield = ref() const shiEmots = () =>{ //子组件接收暴露出来得值 console.log('接收reactive暴漏出来的值',shield.value.xiaoZhi) console.log('接收ref暴漏出来的值',shield.value.xiaoXiaoZhi) } </script>