vue3组件常用的通信方式

一,父组件传值 子组件接受

1 props

父组件

<template>
    <div class="home">
        <child :list="list"></child>
        <div>
            <input v-model="value" type="text" placeholder="输入"/>
            <button @click="handleAdd" type="button">添加</button>
        </div>
    </div>
</template>

<script setup lang="ts">
    import child from "./homr/index.vue"
    import { ref} from "vue";
    const list = ref (['JavaScript', 'HTML', 'CSS'])
    const msg=ref('父组件的值');
    const handleAdd = () =>{
        list.value.push(msg.value)
    }
</script>

子组件接收父组件的值进行渲染

<template>
        <div >
            <div v-for="a in props.list" :key="a">{{ a }}</div>
        </div>
</template>
    
<script setup lang='ts'>
    import { defineProps} from 'vue'
    const props =defineProps({
        list:{
            type :Array,
            default :()=>[]
        }
    })
</script>

二,子组件传值 父组件接受

1 emit 

子组件

<template>
        <div>
            <input v-model="value" type="text" placeholder="输入"/>
            <button @click="handleSubmit" type="button">添加</button>
        </div>
</template>
    
<script setup lang='ts'>
    import {ref, defineEmits} from 'vue'
    const a=ref('1')
    const emits=defineEmits(['add'])
    const handleSubmit=()=>{
        emits('add',a.value)
        a.value=''
    } 
</script>

父组件 只需要监听子组件自定义的事件 

<template>
    <div>
        <div v-for="a in list" :key="a">{{ a }}</div>
        <indexMy @add="handleAdd"></indexMy>
    </div>
</template>
<script setup lang="ts">
    import {ref} from "vue"
    import indexMy from './my/My.vue'
    const list = ref(['JavaScript','HTML','CSS'])
    const handleAdd=value =>{
        list.value.push(value)
    }
</script>

三,v-model

v-model是vue 中出色的语法糖

<component v-model:title="page"></component>

子组件

<template>
        <div>
            <input v-model="value" type="text" placeholder="输入"/>
            <button @click="handleAdd" type="button">添加</button>
        </div>
</template>
    
<script setup lang='ts'>
    import {ref, defineEmits ,defineProps} from 'vue'
    const value=ref('')
    const props = defineProps({
        list:{
            type :Array,
            default :()=>[]
        }
    })
    const emits=defineEmits(['update:list'])
    const handleAdd=()=>{
        const arr=props.list
        arr.push(value.value)
        emits('update:list',arr)
        value.value=''
    } 
</script>

在子组件中我们首先定义props和emits,然后添加完成之后emit指定事件。

注:update:*是Vue中的固定写法,*表示props中的某个属性名。

<template>
    <div>
        <div v-for="a in list" :key="a">{{ a }}</div>
        <indexMy v-model:list="list"></indexMy>
    </div>
</template>
<script setup lang="ts">
    import {ref} from "vue"
    import indexMy from './my/My.vue'
    const list = ref(['JavaScript','HTML','CSS'])
</script>

四,refs

在使用选项式API时,我们可以通过this.$refs.name的方式获取指定元素或者组件,但是组合式API中就无法使用哪种方式获取。如果我们想要通过ref的方式获取组件或者元素,需要定义一个同名的Ref对象,在组件挂载后就可以访问了。

<template>
    <div>
        <div v-for="a in childRefs?.list" :key="a">{{ a }}</div>
        <indexMy ref="childRefs"></indexMy>
    </div>
</template>
<script setup lang="ts">
    import {ref} from "vue"
    import indexMy from './my/My.vue'
    const childRefs  = ref(null)
</script>

子组件

setup组件默认是关闭的,也即通过模板ref获取到的组件的公开实例,不会暴露任何在**

<template>
        <div>
            <input v-model="value" type="text" placeholder="输入"/>
            <button @click="handleAdd" type="button">添加</button>
        </div>
</template>
    
<script setup lang='ts'>
    import {ref, defineExpose} from 'vue'
    const list=ref(['JavaScript', 'HTML', 'CSS'])
    const a=ref('')
    const handleAdd=()=>{
        list.value.push(a.value)
        a.value=''
    } 
    defineExpose({ list })
</script>

五,provide/inject

provide和inject是Vue中提供的一对API,该API可以实现父组件向子组件传递数据,无论层级有多深,都可以通过这对API实现

父组件

<template>
    <div class="home">
        <child></child>
        <div>
            <input v-model="value" type="text" placeholder="输入"/>
            <button @click="handleAdd" type="button">添加</button>
        </div>
    </div>
</template>

<script setup lang="ts">
    import child from "./homr/index.vue"
    import { ref, provide} from "vue";
    const list = ref (['JavaScript', 'HTML', 'CSS'])
    const msg=ref('父组件的值');
    provide('list',list.value)
    const handleAdd = () =>{
        list.value.push(msg.value)
        msg.value=''
    }
</script>

子组件

使用provide进行数据传递时,尽量readonly进行数据包装,避免子组件修改父级传递过去的数据

<template>
        <div >
            <div v-for="a in props" :key="a">{{ a }}</div>
        </div>
</template>
    
<script setup lang='ts'>
    import { inject } from 'vue'
    const props =inject('list')
</script>

六,mitt

mitt.js  原理是EventBus 跨组件通信,

先安装 npm i mitt -S

然后在封装一下

//mitt.js
import mitt from 'mitt'
const mitt = mitt()
export default mitt
// 组件 A
<script setup>
import mitt from './mitt'
const handleClick = () => {
    mitt.emit('handleChange')
}
</script>

// 组件 B
<script setup>
import mitt from './mitt'
import { onUnmounted } from 'vue'
const someMethed = () => { ... }
mitt.on('handleChange',someMethed)
onUnmounted(()=>{
    mitt.off('handleChange',someMethed)
})
</script>

七,pinia

pinia 和 vuex 具有相同的功效, 是 Vue 的存储库,它允许您跨组件/页面共享状态。
设计使用的是 Composition api,更符合vue3的设计思维。
Pinia 对 Vue 2 和 Vue 3 都有效,并且不需要您使用组合 API。

1.pinia 符合直觉,易于学习。
2.pinia 是轻量级状态管理工具,大小只有1KB.
3.pinia 模块化设计,方便拆分。
4.pinia 没有 mutations,直接在 actions 中操作 state,通过 this.xxx 访问响应的状态,尽管可 以直接操作 state,但是还是推荐在 actions 中操作,保证状态不被意外的改变。
5.store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或者是 MapAction 辅助函数,这是在 Vuex 中很常见的。
6.支持多个 store。
7.支持 Vue devtools、SSR、webpack 代码拆分。

安装npm包

npm install pinia --save         

在main.js中 导入

import { createPinia } from 'pinia'

app.use(createPinia())

使用

//在src目录下,像vuex一样创建store文件夹,文件夹下面创建index.js
import { defineStore } from 'pinia'
//这个函数的第一个参数为他的id,这个id必须是唯一的
export const useMainStore = defineStore('main', {
    state: () => {
        return{
            count:0
        }
    },
    getters: {},
    actions: {
        increment() {
            this.count++
        }
    }
})

<template>
 	{{mainStore.count}}
	<button @click="mainFn">13</button>
</template>
<script setup>
import {useMainStore} from '@/pinia-store/index'
const mainStore = useMainStore()
//改变count的值
const mainFn = ()=>{
    //第一种方式
    mainStore.count++
    //第二种方式
    mainStore.increment()
    //第三种方式
    mainStore.$patch({
    	count : mainStore.count + 1
 	})
    //第四种方式
    mainStore.$patch( state =>{
   		state.count++
  	})
}
//重置状态
mainStore.$reset()
mainStore.$state = {
   count : 0
}
</script>

               

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值