一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第四天,点击查看活动详情。
这篇文章主要记录vue3的基础知识点,提供给需要从vue2过渡到vue3的朋友,因为我也是需要从vue2过渡到vue3,所以在此记录学习过程,vue3知识点文章将会持续更新
祝愿看到文章的朋友身体健康;如果可以麻烦一键三连
计算属性和侦听属性
computed
语法和vue2.x相差不大
import {computed,reactive} from 'vue'
setup(){
let person = reactive({
firstName:'张',
lastName:'三'
})
//计算属性——简写
let fullName = computed(()=>{
return person.firstName + '-' + person.lastName
})
//计算属性——完整
let fullName = computed({
get(){
return person.firstName + '-' + person.lastName
},
set(value){
const nameArr = value.split('-')
person.firstName = nameArr[0]
person.lastName = nameArr[1]
}
})
}
watch
语法和vue2.x相差不大,但是有一点小不同
-
监视reactive定义的响应式数据时
1.1. oldValue无法正确获取
1.2 强制开启了深度监视(deep配置为false也没有用)
-
监视reactive定义的响应式数据中的某个属性时
2.1 如果该属性是基本数据类型,oldValue获取的值是正确的,但是深度监听无效,设置为false也可以监听
2.2 如果该属性是引用数据类型,oldValue获取的值不正确和newValue一样,深度监听有效,设置为false不会被监听
2.3 如果监听数据中的多个属性,只要属性中有引用类型和基本类型,只有基本数据类型的oldValue正确,并且deep为false也可以监听(深度监听无效)
2.4 如果监听数据中的多个属性,全为引用类型或者全为基本类型和第一个第二个规则一样
监听ref所定义的响应式数据
<template>
<button ref="btn" @click="clickBtn">点击</button>
</template>
<script>
import {ref,watch} from "vue"
export default {
name: 'App',
setup() {
let msg = ref('这里是组件的双向绑定')
let msg1 = ref('这里是组件的双向绑定1')
// 监听一个ref所定义的响应式数据
watch(msg,(newValue,oldValue)=>{
console.log('msg变化了',newValue,oldValue)
},{immediate:true})
// 监听多个个ref所定义的响应式数据;newValue和oldValue都是数组
watch([msg1,msg],(newValue,oldValue)=>{
console.log('msg1或msg变化了',newValue,oldValue)
})
// 点击按钮以改变
function clickBtn() {
msg.value = '这里是组件的双向绑定1';
msg1.value = '这里是组件的双向绑定这里是组件的双向绑定11';
}
return {msg,msg1,clickBtn}
}
}
</script>
监听reactive所定义的响应式数据
<template>
<button ref="btn" @click="clickBtn">点击</button>
</template>
<script>
import {reactive,watch} from "vue"
export default {
name: 'App',
setup() {
const obj = reactive({
a:1,
b:{
a:2,
b:{
a:3
}
},
c:2
})
// 监听reactive所定义的响应式数据
//此处的deep配置没有用,并且oldValue获取的值是newValue的值
// watch(obj,(newValue,oldValue)=>{
// console.log('obj变化了',newValue,oldValue)
// },{immediate:true,deep:false})
//监视reactive定义的响应式数据中的引用类型属性
// 这里的oldValue依然获取的是newValue的值
// 因为obj.b也是引用类型设置deep为false改变obj的b不会被监听,只有设置为true才会被监听
// watch(()=>obj.b,(newValue,oldValue)=>{
// console.log('obj的b变化了',newValue,oldValue)
// },{immediate:true,deep:false})
//监视reactive定义的响应式数据中的基本类型属性
// 这里的oldValue正确,设置deep无效,设置为false也会被监听
// watch(()=>obj.a,(newValue,oldValue)=>{
// console.log('obj的a变化了',newValue,oldValue)
// },{immediate:true,deep:false})
//监视reactive定义的响应式数据中的某些属性
// 这里的oldValue值中的a是对的,b是不对的,b的值和newValue一样
// 这里a是基本数据类型,b是对象,将deep设置为false如果只改变a也可以监听
watch([()=>obj.a,()=>obj.b],(newValue,oldValue)=>{
console.log('obj的a或者b变化了',newValue,oldValue)
},{immediate:true,deep:false})
// 点击按钮以改变
function clickBtn() {
obj.a = 4;
}
return {obj,clickBtn}
}
}
</script>
watchEffect函数
watch需要指定监听的值和监听回调
watchEffect不需要指定监听的属性,回调中用到哪个属性就是监听的哪个属性,和computed有点像
watchEffect和computed的比较
computed注重返回值(计算出来的值),必须有返回值
watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值
<template>
<button ref="btn" @click="clickBtn">点击{{msg}}</button>
</template>
<script>
import {reactive,watchEffect,ref} from "vue"
export default {
name: 'App',
setup() {
const obj = reactive({
a:1,
b:{
a:2,
b:{
a:3
}
},
c:2,
d:{
a:2
}
})
let msg = ref(10)
watchEffect(()=>{
msg.value = obj.a;
console.log('watchEffect被执行了')
})
// 点击按钮以改变
function clickBtn() {
obj.a = 4;
}
return {obj,clickBtn,msg}
}
}
</script>
生命周期钩子
beforeCreate -> 使用 setup()
created -> 使用 setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
errorCaptured -> onErrorCaptured
vue3.x中的mixin
vue3.x中的自定义hook函数,类似于vue2.x中的mixin
可以在任意你想抽离复用代码的地方创建一个js文件(一般我们把自定义的hook函数都放到src下面的hooks文件夹中)
hooks/hook1.js
import { ref } from "vue"
export default function(){
let title = ref('这里是hook函数的')
function clickBtn() {
title.value+='1'
}
return {title,clickBtn}
}
组件useHook
<template>
<div class="hello">{{title}}</div>
<button @click="clickBtn">点击title加1</button>
</template>
<script>
import hook1 from "./hooks/hook1"
export default {
name: 'useHook',
setup() {
const hook = hook1()
// 因为hook1.js返回的是对象,所以需要解构
return {
...hook
}
}
}
</script>
toRef和toRefs函数
根据名字可以看出是创建ref对象
toRef:
当我们定义一个数据不是响应式的时候,可以使用toRef将其变成响应式的数据;比如我们将一个响应式对象中的某个属性赋值给一个变量时,这时这个变量就不是响应式的,可以使用toRef让其变为响应式,语法为toRef(对象,'属性')
<template>
<div>{{numA}}</div>
<button @click="clickBtn">点击按钮</button>
</template>
<script>
import { reactive } from "vue"
export default {
name: 'HelloWorld',
setup() {
const obj = reactive({
a:1,
b:{
a:1
}
})
// 点击按钮改变numA,但是页面不会更新因为numA不是响应式的
let numA = obj.b.a;
function clickBtn() {
numA = 5
}
// 点击按钮改变numA,页面会更新因为numA是响应式的
let numA = toRef(obj.b,'a');
// 点击按钮改变a
function clickBtn() {
numA.value = 5
}
return {numA,clickBtn}
}
}
</script>
toRefs:
和toRef的功能一样,只是可以创建多个ref对象;用的最多就是解构返回的对象;我们直接解构定义的响应式对象之后就不再是响应式的了,利用toRefs函数就可以避免这个问题(如果不解构的话在模板中就要写{{obj.a}})
<template>
<div>{{a}}</div>
<button @click="clickBtn">点击按钮</button>
</template>
<script>
import { reactive,toRefs } from "vue"
export default {
name: 'HelloWorld',
setup() {
const obj = reactive({
a:1,
b:{
a:1
}
})
function clickBtn() {
obj.a++;
}
// 直接解构点击按钮页面也不会改变
// return {...obj,clickBtn}
return {...toRefs(obj),clickBtn}
}
}
</script>