快乐星球持证驾驶员 冲冲冲!!
一 main.js 区别 vue2 vs vue3
vue3引入的再也不是Vue构造函数
了,引入的为一个名为createApp的工厂函数
二 template
vue3中的template不需要根元素
三 setup
-
setup 中的 this 为
undefined
。 -
组件中所用到的:数据、方法等等,均要配置在setup中。
-
setup 会在 beforeCreate 之前执行一次。
-
setup为一个函数,需要 return 。
-
setup函数中有
两种返回值
5.1 返回一个对象,对象中的属性、方法可以直接在模板中使用。
5.2 返回一个函数(渲染函数) 但是需要单独引入 h 函数。 -
setup 可以和2.x的语法一起用 但是
不建议
一起使用
6.1 vue2.x的配置(data、methos、···) 可以访问到setup的属性和方法。setup最后抛出到this中,methos等方法可以直接 this.xxx 引用
6.2 但在setup中不能访问到 vue2.0 配置。
setup 访问不到this console.log(this) // undefined
6.3 如果有重名 setup
优先
-
setup的参数
7.1 props:值为响应式对象(proxy),组件外部传递过来。
7.2 context: 上下文对象attrs:类似于vue2的this.$attrs
slots: 类似于vue2的this.$slots
emit: 类型与vue2的this.$emit
export default {
props: ['hello'],
emits: ['fn'], // 应该是为了更加的规范 不加这个会有警告
setup(props: any, context: any) {
console.log(props) // Proxy {hello: '你好'}
console.log(context)
context.emit('fn')
},
}
四 ref (Refimpl = 引用对象类型)
作用:定义一个基本类型的响应式数据
-
此ref为一个加工函数,并不是
<buttom ref='but' />
这个ref,两者互不影响。 -
ref 本身是一个加工函数,通过 ref 加工后的
基本数据类型的数据
为Refimpl
引用对象类型。
2.1 通过 ref 加工后的 Refimpl 对象后,需要.value
来进行获取或者修改。
2.2 在 template 中是不需要用.value
来进行获取对应的值,因为 template 可以自动识当前的数据是否为 Refimpl 类型, 是的话会自动并且隐式的加上.value
官方叫 解包。 -
当 ref 中的数据为
引用数据类型
时,ref 会求助3.x中的新方法 — reactivereactive 会把当前对象转化为 Proxy 对象
-
无论是基本类型还是引用类型,
ref
的响应式机制始终基于对象封装和getter
/setter
- 所有
ref
值都会被包装为一个对象,结构为{ value: ... }
。 - 通过
RefImpl
类的get value()
和set value()
方法实现依赖收集和更新触发
- 所有
-
对基本类型和引用类型的处理差异
-
基本类型 | 直接存储原始值,通过
getter
/setter
监听.value
的读写操作。 -
引用类型 | 将值传递给
reactive()
,生成Proxy
代理对象,再存储到.value
中。vue官方文档介绍:如果将对象分配为ref值,则通过 reactive 函数使该对象具有高度的响应式
-
五 reactive ( proxy对象类型 )
作用:当数据是复杂对象或数组且不需要替换整个引用时,`reactive` 更直观。
-
reactive 不支持基本数据类型,会有
警告
。 -
在处理对象的时候,vue3使用的Es6的
proxy
,不再是以前的defineProperty方法。 vue2中响应式原理
const data ={
count:10
}
object。defineProperty(data,'count',{
get() {
}
set(){
}
})
扩展 Reflect
Reflect与object相同,尽管两者之间存在某些微乎其微的的差别 主要是用于框架开发
let of = Reflect.defineProperty(obj,'c',{
get(){
}
set(){
}
})
consolg.log(of) // Boolean
vue3中响应式原理
const obj = {
name:"张三",
age:'18'
}
const pobj = new proxy(obj,{
// 当读取 pobj 某属性时会被调用
get(target,propName){
return target[propName]
},
// 当针对于 pobj 修改或者添加 时会被调用
set(target,propName,value){
target[propName] = value
},
// 当删除 pobj 某属性时会被调用
deleteProperty(target,propName){
return delete target[propName]
}
})
差异
Object.defineProperty 是对 对象属性 的劫持
Proxy 是对整个对象劫持
Object.defineProperty 无法监听新增和删除 页面不会响应式更新
添加:$set 可以添加
删除:#delete 可以删除
Object.defineProperty 无法监听数组部分方法需要重写
Object.defineProperty 性能不好要对深层对象劫持要一次性递归 性能不好
Object.defineProperty 直接通过数组的下标修改数据 页面不会响应式
Proxy 能正确监听数组方法
Proxy 能正确监听对象新增删除属性
Proxy 只在 getter 时才进行对象下一层属性的劫持 性能优化
Proxy 兼容性不好
Object.defineProperty 和 Proxy
在 getter 时进行添加依赖 `dep.addSub(watcher)` 比如 绑定 view 层,在函数中使用
在 setter 时触发依赖通知 `dep.notify()` 比如 修改属性
Object.defineProperty 是对所有对象属性的劫持,如访问obj.o, 所有属性,包括深层的都是响应式,浪费性能
Proxy 是对访问到哪个属性,那个属性就是响应式,如访问obj.o,属性o才是响应式, 访问obj.o.b,
b才是响应式,访问到那个属性,那个属性才是响应式,不需一次性遍历