Vue.js
发布3.0版本,代号:One Piece
(海贼王)proxy
代替defineProperty
实现响应式Tree-Shaking
Vue3
可以更好的支持TSComposition API
(组合API)
setup
配置ref
与reactive
watch
与watchEffect
provide
与inject
Fragment
Teleport
Suspense
拉开序幕的setup
setup
是所有Composition API
(组合API)的表演舞台。setup
函数的两种返回值。
Vue2
配置(data
、methods
、computed
…)中可以访问setup
的属性、方法setup
中不能访问到Vue2配置的(data
、methods
、computed
…)setup
优先。setup
不能是一个async
函数,因为返回值不再是return
的对象,而是promise
,模板看不到return
对象中的属性。(后期也可以返回一个promise
实例,但需要Suspense
和异步组件配合)ref函数
const xxx = ref(initValue)
xxx.value
.value
,直接: {{ xxx }}
Object.definePeoperty()
的get
与set
完成的。Vue3
中的一个新函数———— reactive
函数。reactive函数
const 代理对象 = reactive(源对象)
接收一个对象(或数组),返回一个代理对象(Proxy
的实例对象)reactive
定义的响应式数据是“深层次的”。ES6
的Proxy
实现,通过代理对象操作源对象内部数据进行操作。Vue3的响应式
原理实现:
Proxy
(代理):拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等等。Reflect
(反射):对源对象的属性进行操作。new Proxy(data, {
// 拦截读取属性值
get (target, prop) {
return Reflect.get(target, prop)
},
// 拦截设置属性值或添加新属性
set (target, prop, value) {
return Reflect.set(target, prop, value)
},
// 拦截删除属性
deleteProperty (target, prop) {
return Reflect.deleteProperty(target, prop)
}
})
reactive对比ref
从定义数据角度对比:
ref
用于定义:基本数据类型reactive
用于定义:对象(或数组)类型数据注意:ref
也可以用来定义对象(或数组)类型数据,它内部会自动通过reactive
转为代理对象。
从原理调度对比
Object.defineProperty()
的get
与set
来实现响应式(数据劫持)reactive
通过使用Proxy
来实现响应式(数据劫持),并通过Reflect
操作源对象内部的数据。从使用角度对比
ref
定义的数据:操作数据需要.value
,读取数据时模板中直接读取不需要.value
。reactive
定义的数据:操作数据与读取数据:均不需要.value
setup的两个注意点
beforeCreate
之前执行一次,this是undefined
props
:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。context
:上下文对象
attrs
:值为对象,包含:组件外部传递过来,但没有在props
配置中声明的属性,相当于this.$attrs
slots
收到的插槽内容,相当于this.$slots
emit
:分发自定义事件的函数,相当于this.$emit
计算属性与监视
import {computed} from 'vue'
setup(){
...
//计算属性——简写
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]
}
})
}
监视
与Vue2中watch配置功能一致
两个小坑
reactive
定义的响应数据时:oldValue
无法正确获取、强制开启了深度监视(deep配置失效)reactive
定义的响应数据中某个属性(属性为对象)时:deep配置有效。//情况一:监视ref定义的响应式数据
watch(sum,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue)
},{immediate:true})
//情况二:监视多个ref定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{
console.log('sum或msg变化了',newValue,oldValue)
})
/* 情况三:监视reactive定义的响应式数据 */
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{immediate:true,deep:false}) //此处的deep配置不再奏效
//情况四:监视reactive定义的响应式数据中的某个属性
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
//情况五:监视reactive定义的响应式数据中的某些属性
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
//特殊情况
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效
WatchEffect函数
watch
的套路是:既要指明监视的属性,也要指明监视的回调。
watchEffect
的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
watchEffect
有点像computed
computed
注重的计算出来的值(回调函数的返回值),所以必须要写返回值。watchEffect
更注重的是过程(回调函数的函数体),所以不用写返回值。watchEffect(() => {
const x1 = sum.value;
const x2 = person.age;
console.log('watchEffect配置的回调执行了');
})
vue3声明周期
beforeDestroy
改名为beforeUnmount
destroyed
改名为unmounted
Composition API
形式的生命周期钩子,与Vue2中钩子对应关系如下
beforeCreate
===>setup()
created
=======>setup()
beforeMount
===>onBeforeMount
mounted
=======>onMounted
beforeUpdate
===>onBeforeUpdate
updated
=======>onUpdated
beforeUnmount
==>onBeforeUnmount
unmounted
=====>onUnmounted
自定义hook函数
Composittion API
进行了封装。toRef
value
值指向另一个对象中的某个属性。const name = toRef(person, 'name')
toRefs
与toRef
功能一致,但可以批量创建多个ref
对象。语法:toRefs(person)