vue3.0新特性归纳记录
背景
关于vue3.0已经出来很久了,但是一直没有尝鲜,最近时间充裕一点,就开始梳理下相关新特性,也当作是一个学习历程。
1. globalProperties
公共变量或者方法得定义
// main.js
const app = createApp(App)
app.config.globalProperties.heimayu = 'hi heimayu you are prefect!'
app.mount('#app')
// vue
<template>
<h1>{{helloword}}</h1>
</template>
<script>
import { getCurrentInstance } from 'vue'
export default {
setup () {
const { proxy } = getCurrentInstance();
const helloword = proxy.heimayu;
return {
helloword
}
}
}
</script>
2 ref 和 reactive
ref
作用:定义一个响应式数据
使用:JS中操作数据:xxx.value=xxx; 模板中使用直接{{xxx}}
reactive
作用:定义一个响应式对象
使用:JS中操作数据和模板中都直接使用
<template>
<h1>{{nameRef}}</h1>
<h1>{{student.nameForm.nameReactive}}</h1>
<button @click="changeName">修改</button>
</template>
<script setup>
import { reactive, ref } from 'vue'
let nameRef = ref('hi, heimayu!')
let student = reactive({
nameForm: {
nameReactive: 'hi yaoyao!'
}
})
const changeName = () => {
nameRef.value = 'hi, heimayu!' + new Date().getTime();
student.nameForm.nameReactive = 'hi yaoyao!' + new Date().getTime();
}
</script>
3 watch与watchEffect
watch
还是上面的例子,会发现监视reactive的数据时候,是无法获取oldValue的,即2个value下的属性是一样!
watch(student, (newValue, oldValue) => {
console.log("student", newValue.nameForm.nameReactive, oldValue.nameForm.nameReactive);
}, {
deep: true
});
如果按下面的方式写,可以获取
watch([() => student.nameForm.nameReactive], (newValue, oldValue) => {
console.log(newValue, oldValue);
});
watchEffect
watchEffect有点像computed,而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。只要引用的变量做了变化,则执行函数。
watchEffect(() => { console.log('你点击更改了!', student.nameForm.nameReactive ) })
4 生命周期
onBeforeMount(() => {
console.log('实例创建完成,即将挂载')
})
onMounted(() => {
console.log('实例挂载完成')
})
onBeforeUpdate(() => {
console.log('组件dom即将更新')
})
onUpdated(() => {
console.log('组件dom已经更新完毕')
})
// 对应vue2 beforeDestroy
onBeforeUnmount(() => {
console.log('实例即将解除挂载')
})
// 对应vue2 destroyed
onUnmounted(() => {
console.log('实例已经解除挂载')
})
onErrorCaptured(() => {
console.log('捕获到一个子孙组件的错误')
})
onActivated(() => {
console.log('被keep-alive缓存的组件激活')
})
onDeactivated(() => {
console.log('被keep-alive缓存的组件停用')
})
// 两个新钩子,可以精确地追踪到一个组件发生重渲染的触发时机和完成时机及其原因
onRenderTracked(() => {
console.log('跟踪虚拟dom重新渲染时')
})
onRenderTriggered(() => {
console.log('当虚拟dom被触发重新渲染时')
})
5、Proxy + Reflect
vue3使用Proxy + Reflect代替了Object.defineProperty,是因为在使用Object.defineProperty的时候,我们遇到的问题有:
1 一次只能对一个属性进行监听,需要遍历来对所有属性监听
2 如果监听的对象是嵌套的深层对象,需要递归监听。
3 对于对象的新增属性,需要手动监听
4 对于数组的增删改,只能使用固定的几个方法才能实现监听
proxy是用来操作对象并且扩展对象能力的,而Object.defineProperty只是单纯地操作对象的属性,用proxy来拦截对象,不管是对对象执行任何操作,都会先通过proxy的处理逻辑
使用Reflect.set 和 Reflect.get 是为了让数据的指向始终指向当前的proxy
let arr = [1, 2, 3];
let proxy = new Proxy(arr, {
get (target, key, receiver) {
console.log('get', key);
return Reflect.get(target, key, receiver)
},
set (target, key, value, receiver) {
console.log('set', key, value)
return Reflect.set(target, key, value, receiver)
}
})
proxy.push(4)
let obj = {
info: {
name: 'heimayu',
age: ['webpack', 'element', 'vue3']
}
}
let handler = {
get (target, key, receiver) {
console.log('get', key)
// 递归创建并返回
if (typeof target[key] === 'object' && target[key] !== null) {
return new Proxy(target[key], handler)
}
return Reflect.get(target, key, receiver)
},
set (target, key, value, receiver) {
console.log('set', key, value)
return Reflect.set(target, key, value, receiver)
}
}
let proxy2 = new Proxy(obj, handler)
proxy2.info.name = 'new heimayu';
proxy2.info.age.push("proxy")