文章目录
- Vue3学习笔记(下)
- 组合式API下的父子通信
- 父传子
- 子传父
- 模板引用
- defineExpose()
- provide和inject
- vue3新特性 - defineOptions
- vue3新特性 - defineModel
- Pinia
- Pinia异步写法
Vue3学习笔记(下)
组合式API下的父子通信
父传子
基本思想:
- 父组件中给子组件绑定属性
- 子组件内部通过props选项接收
注意:由于写了setup,所以无法直接配置props选项,所以,此处需要借助“编译器宏”函数接收子组件传递的数据。
defineProps原理:就是编译阶段的一个标识,实际编译器解析时,遇到后会进行编译转换
子传父
基本思想:
- 父组件中给子组件标签通过@绑定事件
- 子组件内部通过emit方法触发事件
模板引用
概念:通过ref标识获取真实的dom对象或者组件实例对象(可以获取dom,也可以获取组件)
- 调用ref函数,生成一个ref对象
- 通过ref标识,进行绑定
- 通过ref对象.value即可访问到绑定的元素(必须渲染完后才能拿到)
defineExpose()
默认情况下在<script setup>
语法糖下组件内部的属性和方法是不开放给父组件访问的,但可以通过defineExppose编译宏指定哪些属性和方法允许访问。
<script setup>
import { ref } from 'vue'
const testMsg = ref('this is msg')
defineExpose({testMsg
})
</script>
provide和inject
作用和场景:顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信。
跨层传递普通数据:
- 顶层组件通过provide函数提供数据 ——
provide('words', 'abc')
- 底层组件通过inject函数获取数据 ——
const word = inject('words')
跨层传递响应式数据:
const count = ref(100)
provide('count', count)
const count = ('count')
跨层级传递函数:
底层组件如何修改顶层组件的数据:顶层组件给子孙后代传递可以修改数据的方法,底层组件调用。
-
provide('changeCount', (newValue) => {count.value = newvalue })
-
const changeCount = inject('changeCount')
vue3新特性 - defineOptions
背景:有<script setup>
之前,如果要定义props,emits可以轻而易举地添加一个与setup平级的属性。但是用了<script setup>
后,相当于script中所有的代码都写在setup函数里,无法添加与其平级的属性。
为了解决这一问题,引入了defineProps与defineEmits这两个宏,但这只解决了props与emits这两个属性。如果我们要定义组件的name或者其他自定义的属性,还得回到最原始的用法——再添加一个普通的<script>
标签。
defineOptions主要是用来定义Options API的选项。可以用defineOptions定义任何选项,props,emits,expose,slots除外(因为这些可以使用defineXXX来做到。
<script setup>
defineOptions({name: 'LoginIndex',inheritAttrs: false,// ...更多自定义属性
})
</script>
vue3新特性 - defineModel
在vue3中,自定义组件上使用v-model,相当于传递一个modelValue属性,同时触发update:modelValue
事件。
<script setup>
import sonCom from '@/components/son-com.vue'
import { ref } from 'vue'
const txt = ref('aaabbb')
</script><template><sonCom v-model="txt"></sonCom><div>{{ txt }}</div>
</template><style scoped>
</style>
<script setup>
defineProps({modelValue: String
})
const emit = defineEmits(['update:modelValue'])
</script><template>
<div><input type="text":value="modelValue"@input="e => emit('update:modelValue', e.target.value)">
</div>
</template><style>
</style>
Pinia
Pinia是Vue的最新状态管理工具,是Vuex的替代品。
- 提供更加简单的API(去掉了mutation)
- 提供符合组合式风格的API(和Vue3新语法统一)
- 去掉了modules的概念,每一个store都是一个独立的模块
- 配合TypeScript更加友好,提供可靠的类型推断
import { defineStore } from "pinia"
import { ref } from 'vue'
import axios from 'axios'
export const storeModel = defineStore('store', () => {const count = ref(10)const sub = () => { count.value-- }const add = () => { count.value++ } return {count,sub,add}
})
<script setup>
import { storeModel } from '@/store/index'
const store = storeModel() // 此处不能直接解构const { count } = store,会丢失数据的响应式
</script><template><div><h3>Son1组件 - {{ store.count }}</h3><button @click="store.add()">+</button></div>
</template><style scoped></style>
Pinia异步写法
import { defineStore } from "pinia"
import { ref } from 'vue'
import axios from 'axios'
export const storeModel = defineStore('store', () => {const list = ref([])const getlist = async () => {const res = await axios.get('http://geek.itheima.net/v1_0/channels')list.value = res}return {getlist,list}
})
<script setup>
import { storeModel } from '@/store/index'
const store = storeModel()
store.getlist()
</script>
<template><div>{{ store.list }}</div>
</template>
<style scoped>
</style>
注意:
store
是一个用reactive
包装的对象,这意味着不需要在 getters 后面写.value
。就像setup
中的props
一样,我们不能对它进行解构为了从 store 中提取属性时保持其响应性,需要使用
storeToRefs()
。它将为每一个响应式属性创建引用。<script setup> import { storeModel } from '@/store/index' import { storeToRefs } from 'pinia'; const store = storeModel() const { count } = storeToRefs(store) </script><template><div><h3>Son1组件 - {{ count }}</h3><button @click="store.add()">+</button></div> </template><style scoped></style>
注意,我们可以直接从 store 中解构 action,因为它们也被绑定到 store 上。