父子通信:
1、父传子:在父组件的子组件标签绑定一个自定义属性,子组件通过props获取父组件传递的数据。
//父
<child :data="list" @del="idx => list.splice(idx, 1)" ref="child" :isShow.sync="isShow" />
//子props: {data: {type: Array,required: true},value: { // 固定的名字(v-model)type: Boolean,default: false},isShow: {type: Boolean,default: false}},
vue3通过defineProps接受props数据
//vue3获取父组件数据defineProps({goods: {type: Array}
})
2、子传父:在父组件的子组件的标签上绑定一个自定义方法,子组件通过$emit触发父组件传递的方法从而传递数据给父组件。
//父
<child :data="list" @del="idx => list.splice(idx, 1)" ref="child" :isShow.sync="isShow" />
//子<li v-for="(item, index) in data" :key="item">{{ item }}<button @click="$emit('del', index)">删除</button></li>
vue3中通过defineEmits接受父组件的方法
const emit = defineEmits(['del', 'add'])const del = (id) => {emit('del', id)
}
const add = () => {emit('add')
}
vue3以上代码都是在setup语法糖中写的
3、ref:通过给子组件标签定义ref属性,通过this.$refs.ref属性名或租子组件的实例
//父
<child :data="list" @del="idx => list.splice(idx, 1)" ref="child" :isShow.sync="isShow" />
//子methods: {clickMe() {console.log(this.$refs.child.msg)}}
4、$parent:通过this.$parent获取父节点
//子methods: {clickMe() {console.log(this.$parent)}}
5、$root:获取根节点
//子methods: {clickMe() {console.log(this.$root)}}
6、v-model:通过双向数据绑定实现数据传递
//父
<child :data="list" @del="idx => list.splice(idx, 1)" ref="child" v-model="isShow" />
//子<div v-if="value"><h3>我是子组件</h3><ul><li v-for="(item, index) in data" :key="item">{{ item }}<button @click="$emit('del', index)">删除</button></li></ul><hr /><button @click="send">发送数据</button><button @click="$emit('input', false)">关闭</button></div>//props获取父组件通过v-model传递的值,值只能是value,通过value判断数据显隐props: {data: {type: Array,required: true},value: { // 固定的名字(v-model)type: Boolean,default: false},isShow: {type: Boolean,default: false}},
v-model缺点:只能使用一次,因为父组件传递的值在子组件中只能通过props获取并且值为value,不能触发多次
7、.sync修饰符:
//父
<child :data="list" @del="idx => list.splice(idx, 1)" ref="child" :isShow.sync="isShow" />
//子
<div v-if="isShow"><h3>我是子组件</h3><ul><li v-for="(item, index) in data" :key="item">{{ item }}<button @click="$emit('del', index)">删除</button></li></ul><hr /><button @click="send">发送数据</button><button @click="$emit('update:isShow', false)">关闭</button><hr /><div>{{ title }}</div></div></div>props: {data: {type: Array,required: true},value: { // 固定的名字(v-model)type: Boolean,default: false},isShow: {type: Boolean,default: false}},
通过父组件传递属性的时候加上.sync修饰符,子组件通过$emit接受到传递的属性通过update:属性名可进行修改
兄弟通信:
8、全局事件总线(事件搭桥):
main.js文件中创建一个实例对象,通过this.bus.$emit('方法名',传递的数据)发送数据
兄弟组件可以通过this.bus.$on('方法名',回调)接受数据
//main.js
// 创建一个空的vue实例对象
Vue.prototype.bus = new Vue()//html中button按钮
<button @click="send">发送数据</button>//方法(发送数据)methods: {send() {this.bus.$emit('send', this.msg)// console.log(this.$root);console.log(this.$parent.list);}}//方法(接受数据)mounted() {this.bus.$on('send', val => {// console.log(val);this.msg = val;})}
vue3中使用全局事件总线需要通过mitt插件从而实现。
下载插件以后在main.js文件引入mitt,并且创建一个新的实例,通过创建的实例进行兄弟通讯
//main.js
import mitt from 'mitt'
app.config.globalProperties.mittBus = new mitt()//传递数据组件 通过getCurrentInstance的proxy获取我们的全局属性mittBus
import { getCurrentInstance, provide, reactive, toRefs } from 'vue'const { proxy } = getCurrentInstance()//方法传递数据
const ShowData = () => {proxy.mittBus.emit('openData', name.value)proxy.mittBus.emit('openIsShow', true)console.log('展示');
}//接受数据的组件 通过getCurrentInstance的proxy获取我们的全局属性mittBus
import { getCurrentInstance, provide, reactive, toRefs } from 'vue'
const { proxy } = getCurrentInstance()
//通过on方法接受回调,从而进行逻辑操作
onMounted(() => {proxy.mittBus.on('openData', (data) => {fatherData.value = data})proxy.mittBus.on('openIsShow', (data) => {isShow.value = data})
})
9、vuex:
通过集中式管理工具,从而获取数据进行获取修改等
vue3和vue2相似,vue3可以通过useStore引入直接获取数据或者dispatch调用方法等操作
vue2通过this.$store.dispatch/state获取数据以及获取dispatch调用方法等操作
这里展示vue3的
//store/index.js
import { createStore } from 'vuex'export default createStore({state: {vuexNum: 10},getters: {},mutations: {handleChangeNum(state, payload) {console.log(payload, 'payload');state.vuexNum += payload}},actions: {},modules: {}
})
import { useStore } from 'vuex';
const store = useStore()const handleVuexNum = () => {store.commit('handleChangeNum', 10)//调用actions的方法
}
10、pinia:类似于vuex的集中式管理工具
需要下载pinia插件main.js全局引入
import { createPinia } from 'pinia'
const pinia = createPinia()
app.config.globalProperties.sname = '刘展通'
app.use(plugin).use(router).use(store).use(pinia).mount('#app')
使用:目录创建文件store或者什么都可以 目录下创建pinia.js
import { defineStore } from 'pinia'const userStore = defineStore('user', {state: () => {return {count: 1,paw2: 1,paw3: 1}},getters: {doubleCount: (state) => state.count * 2,handleDoubleCount() {return this.doubleCount + 1}},actions: {inc() {this.count++},randomNum() {this.count = Math.random(100 + Math.random()).toFixed(2)}}
})
export default userStore;
//代码使用
<template><div>数值:{{ data.count }},双倍数值:{{ data.doubleCount }},双倍数值+1:{{ data.handleDoubleCount }},平方:{{ data.paw2 }}三次方:{{data.paw3 }}<button @click="store.count--">-</button><button @click="handleCount">+</button><button @click="store.$reset()">重置</button><button @click="store.randomNum()">随机数</button></div>
</template><script setup>
import userStore from '../storage/pinia'
import { storeToRefs } from 'pinia'
const store = userStore()
// console.log(store, 'store');
const data = storeToRefs(store)
console.log(data);
const handleCount = () => {store.$patch({count: store.count + 1,paw2: Math.pow(store.count + 1, 2),paw3: Math.pow(store.count + 1, 3)})
}
</script><style lang="scss" scoped></style>
pina通过引入我们store下pinia.js中抛出的defineStore可以获取数据以及调用方法
通过pinia中引入storeToRefs可以获取我们pinia仓库中的所有数据
store为我们pinia抛出的方法 通过赋值方法 store = useStore()使store拥有pinia的属性和方法
通过store.$patch可以批量调用我们的方法实现更新效果。
通过$store.reset()可以实现重置功能,重置为我们最初值。
通过store也可以直接给按钮绑定方法直接store.方法名直接调用。
跨组件通信:
11、provide/inject:
通过provide发布数据 inject接受数据
//传递者 provide也可以是个对象
provide('provideSendData', num.value)
//接收者 inject也可以是个数组
const provideData = inject('provideSendData')
12、插槽(slot):
分为匿名插槽、具名插槽、作用域插槽
专门一篇文章进行讲解
13、消息订阅与发布
下载pubsub-js插件
引入pubsub在需要发送和接受的组件
pubsub.publish发布数据
publish.subscribe接受数据 通过回调获取数据类似于事件总线on接受方法以后获取数据那样