一、响应式的数据
- 1.1 reactive API 用于创建响应式的对象或者数组,实际上该方法的内部是基于ES6的proxy实现的。
reactive基本用法如下:
<template>
<h3>信息展示组件:</h3>
<ul>
<li>姓名: {{ data.name }}</li>
<li>年龄: {{ data.age }}</li>
</ul>
</template>
<script setup>
import { reactive } from 'vue'
// 创建响应式对象
const data = reactive({
name: 'pony',
age: 18
})
</script>
Vue3还提供了一个isReactive API用户检测是否是reactive创建的响应式代理。
- 1.2 ref 我们使用reactive只能对Object或者Array类型的数据进行劫持, 如果我们想要对普通数据类型进行劫持, 可以使用refAPI, 例如以下代码:
<template>
<h3>信息展示组件:</h3>
<ul>
<li>姓名: {{ name }}</li>
<li>年龄: {{ age }}</li>
</ul>
</template>
<script setup>
import { ref } from 'vue'
// 创建响应式对象
const name = ref('pony')
const age = ref(18)
const handleEditName = () => {
// 通过ref创建的是一个响应式的对象, 我们需要通过ref定义的变量.value方式来访问或者修改
name.value = '777'
}
const handleEditAge = () => {
age.value = 20
}
</script>
- 1.3 readonly有时候我们希望传递给其他组件的数据时, 往往希望其他组件使用我们传递的内容, 但是不允许它们修改, 这个时候我们需要使用readonly API,该API可以创建一个不可修改的对象。
示例代码如下:
import { ref, readonly } from 'vue'
const name = ref('UK')
const age = ref(20)
const readonlyName = readonly(name)
const handleEditName = () => {
name.value = 'USA'
}
const handleEditAGe = () => {
age.value = 30
}
当name修改的时候, readonly的值也会随着进行而改变, 但是直接修改readonlyName并不会生效。
- 1.4toRefs和toRef 用于将reactive创建的响应式代码结构成响应式的数据; 如果直接使用ES6的语法进行解构的话,解构出来的数据就不是响应式的。
例如下面这段代码:
import { toRefs, reactive } from 'vue'
const user = reactive({ name: 'pony', age: 18 })
// user下的属性通过toRefs与解构后的数据建立了链接, 任何一个修改都会引起另一个的变化,不管是user里面的name或者解构的name变化了两边都能捕捉到。
const { name, age } = toRefs(user) // toRefs解构整个对象
const handleEditName = () => {
name.value = '777'
}
const handleEditAge = () => {
age.value = 19
}
如果想解构单个数据可以使用toRef,整个对象里面解构用toRefs,示例代码如下:
const name = toRef(user, 'name')
const age = toRef(user, 'age') // 解构的对象加名称
二、计算属性
2.1 computed: 在Composition API中定义计算属性通过computed方法实现, 它可以接受两种参数, 一个是getter函数, 另一个是包含get和set函数的对象: computed返回一个ref对象。
如下代码展示接收getter函数时, 计算属性用法:
import { ref, computed } from 'vue'
const name = ref('pony')
const age = ref(19)
// 定义计算属性
const user = computed(() => {
return `姓名: ${ name.value }\n年龄:${ age.value }`
})
上面的代码当中name或者age发生变化时, user也会进行变化。 computed方法接受对象参数时, 常见的场景就是组件实现v-model的功能, 实例代码如下所示:
<template>
<input type="text" v-model:value="myName"/>
</template>
<script setup>
// 引入方法
import { defineProps, defineEmits, computed } from 'vue'
// 定义props
const props = defineProps({
name: String
})
// v-model 规定写法 update:name name -> 需要v-model的名称
const emit = defineEmits(['update:name'])
// 计算属性
const myName = computed({
get() {
return props.name
},
set(val) {
emit('update:name', val)
}
})
</script>
三、监听器
-
3.1 watch : Vue3的composition API中提供了两个用于监听数据变化的API, 分别是watchEffect (vue3.2中新增了watchEffect和watchsyncEffect API,这两个都是watchEffect的别名)和 watch, 这两者的区别如下:
- watchEffect用于自动收集响应数据的依赖;
- watch 需要手动去监听的数据源;
四、生命周期
- 4.1 生命周期 Vue3的composition API没有生命周期钩子选项, 但是提供了 onBeforeMount、onMounted 等函数来注册声明周期钩子, 提供的声明周期函数如下表示:
选项式API | Hook inside setup | 触发时机 |
---|---|---|
beforeMount | onBeforeMount | 组件挂载之前触发 |
mounte | onMounted | 组件挂载后触发 |
beforeUpdate | onBeforeUpdate | 组件更新前触发 |
updated | onUpdated | 组件更新后触发 |
beforeUnmount | onBeforeUnmount | 组件卸载之前触发 |
unmounted | onUnmounted | 组件卸载后触发 |
如下代码展示了部分API的用法:
import { onMounted, onUpdated, onUmounted } from 'vue'
onMounted(() => {
console.log('onMounted')
})
onUpdated(() => {
console.log('onUnmounted')
})
五、模板ref($refs的替代品)
-
5.1 由于Vue3的composition API无法使用this, 所以说this.$refs并不可以用, 那我们怎么获取元素或者组件呢?其实很简单, 我们需要定义个 ref 对象, 名称与模板中ref属性的名称一致即可。
示例代码如下:
<template> <h4 ref="nameRef">加油逍遥子</h4> </template> <script setup> import { ref, onMounted } from 'vue' const nameRef = ref(null) onMounted(() => { console.log(nameRef.value) // <h4>加油逍遥子</h4> }) </script>
-
5.2 补充知识 如果希望像Vue2一样, 直接通过this.$refs['XXX'], Vue3 的子组件需要通过内置的 defineExpose 把需要用到的变量和方法全暴露给父组件。示例代码如下:
// 子组件
<template>
<h1>我是子组件</h1>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
defineExpose({
count
})
</script>
// 父组件
<template>
<div>
login
<child ref="newChild"/>
<h2 ref="myChild">2222</h2>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import child from '@/components/HelloWorld.vue'
const myChild = ref(null)
const newChild = ref(null)
onMounted(() => {
console.log(myChild.value)
console.log(newChild.value.count, 'newChild')
})
</script>
- 效果图如下: