一,父组件传值 子组件接受
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>