我正在参加「掘金·启航计划」
在开发中大型项目时,很多场景得通过组件传值来解决,vue3相对于vue2组件间通信的方式还是有很大变化的。文中只列举最基础的一些方法,具体多种用法可以通过vue官网查看。
父子组件通信
在vue2中,可以通过$attrs / $listeners
来进行通信,这种方式在vue3已经移除了
props/emits
父-->子
<!--父-->
<template>
<child :name="name"/>
</template>
<script lang='ts' setup>
import Child from './child.vue'
const name = 'nexusfeng'
</script>
<!--子-->
<template>
{{name}}
</template>
<script lang='ts' setup>
const props = defineProps([
'name'
])
</script>
子-->父
<!--父-->
<template>
<child @update-name="updateName"/>
</template>
<script lang='ts' setup>
import Child from './child.vue'
const updateName = (args) => {
//...
}
</script>
<!--子-->
<template>
...
</template>
<script lang='ts' setup>
const emit = defineEmits(['updateName'])
emit('updateName', 'Feng')
</script>
v-model/emits
父-->子
<!--父-->
<template>
<child
v-model:name="name"
v-model:sex="sex"
/>
</template>
<script lang='ts' setup>
import Child from './child.vue'
</script>
<!--子-->
<template>
...
</template>
<script lang='ts' setup>
const props = defineProps([
'name',
'sex'
])
</script>
子-->父
<!--父-->
<template>
{{name}}
<child v-model:name='name'/>
</template>
<script lang='ts' setup>
import {ref} from 'vue'
import Child from './child.vue'
const name = ref('')
</script>
<!--子-->
<template>
...
</template>
<script lang='ts' setup>
const emit = defineEmits(['update:name'])
emit('update:name', 'Feng')
</script>
ref/emits
父组件可以通过子组件的ref
属性操作子组件的数据或者调用子组件方法
<!--父-->
<template>
<child ref="child"/>
</template>
<script lang='ts' setup>
import Child from './child.vue'
const child = ref<HTMLElement>(null)
child.value.onLoad()
child.value.name = 'child'
</script>
<!--子-->
<template>
{{name}}
</template>
<script lang='ts' setup>
const name = ref('Tom')
const onLoad = () => {
console.log('father')
}
</script>
爷孙组件通信
provide/inject
A通过provide
向A.A.A传值,A.A.A通过inject
触发A的事件,provide
并不是响应式的,如果想要响应式,得传入响应式数据
<!--A-->
<script lang='ts' setup>
import { provide } from 'vue'
// 传入响应式数据
// const name = ref('nexusfeng')
const name = 'nexusfeng'
// 基础数据类型也能响应,改变值时需要重新provide
provide('name', ():string => name)
</script>
<!--A.A.A-->
<script lang='ts' setup>
import { inject } from 'vue'
// 响应式数据
// const name = inject('name') || ''
const name = inject('name')
name()
</script>
注意基础数据类型的写法,如果要响应,得重新provide
全局组件通信(兄弟组件通信推荐此方法)
BUS
vue3移除了$on
、$off
、$once
,可以使用第三方库来实现mitt、tiny-emitter
Vuex
vuex的用法与vue2中的并无太大差别
import { createApp } from 'vue'
import { createStore } from 'vuex'
const store = createStore({
state:{
return {
name: 'feng'
}
},
mutations: {},
actions:{},
modules:{}
})
<!--组件中使用-->
<template>
{{store.state.name}}
</template>
<script lang='ts' setup>
import { useStore } from 'vuex'
const store = useStore()
</script>
Pinia
Pinia相对于vuex,去除了mutations
,也就是没有了同步操作和异步操作的区分,方便很多,对ts的支持也很好
//main.ts
import {createApp} from 'vue'
import {createPinna} from 'pinia'
import App from '@/App.vue'
createApp(App)
.use(createPinia())
.mount('#app')
// src/stores/index.ts
import {defineStore} from 'pinia'
export const useStore = defineStore('main', {
state: () => ({
name: 'feng'
})
})
<!--组件中使用-->
<template>
{{store.name}}
</template>
<script lang='ts' setup>
import { useStore } from '@/store'
const store = useStore()
</script>