Vue3.0新特性

Vue3.0新特性

响应式原理vue2的defineProperty变为Proxy

概述:
对象:会递归得去循环vue得每一个属性,(这也是浪费性能的地方)会给每个属性增加getter和setter,当属性发生变化的时候会更新视图。
数组:重写了数组的方法,当调用数组方法时会触发更新,也会对数组中的每一项进行监控。

Object.defineProperty的缺陷

  • 对象只监控自带的属性,新增的属性不监控,也就不生效。若是后续需要这个自带属性,就要再初始化的时候给它一个undefined值(data里面初始化),后续再改这个值
  • 数组的索引发生变化或者数组的长度发生变化不会触发实体更新。可以监控引用数组中引用类型值,若是一个普通值并不会监控,例如:[1, 2, {a: 3}] ,只能监控a

Object.defineProperty

  • Vue 将遍历 data 里的所有 property ,使用 Object.defineProperty 把这些 property
    全部转为 getter/setter。
  • getter/setter在内部让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。
  • 每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 “属性” 记录为依赖。之后当依赖项的setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
    在这里插入图片描述
  • 由于 JavaScript 的限制,Vue 不能检测数组的变化。
当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
  • 为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue相同的效果,同时也将在响应式系统内触发状态更新:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
//使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名
vm.$set(vm.items, indexOfItem, newValue)
  • 为了解决第二类问题,你可以使用 splice:
vm.items.splice(newLength)
  • vue使用装饰者模式,对数组的方法进行扩展;
		// 从数组原型中获取这7个方法,并覆盖为可以发送更新通知的函数实现
 		// 提取vue的原型链
        var arrProto = Array.prototype;   //因为要调用老方法
        // 拷贝
        var arrayMethods = Object.create(arrProto);
        //会改变原数组的方法7个
        var arr = ['push', 'pop', 'shift', 'unshift', 'splice', 'reverse', 'sort']; 
        arr.forEach((method)=>{
            arrayMethods[method]=function(){
                var original=arrProto[method];  //拿出老方法
                var result = original.apply(this,args);  //调用老方法
                dep.notify();  //新方法:调用视图更新
                return result;
            }
        })

Proxy

Proxy消除了之前 Vue2.x 中基于 Object.defineProperty 的实现所存在的这些限制:无法监听 属性的添加和删除、数组索引和长度的变更,并可以支持 Map、Set、WeakMap 和 WeakSet!

详细看这篇文章
初探 Vue3.0 中的一大亮点——Proxy !

new Vue()与createApp()

Vue3 之前使用 new Vue() 来构建应用根组件,现在改为 createApp() ,调用 $mount 方法进行挂载

let app = new Vue() => 
let app = createApp(App);
app.mount("#app")

Vue3 之前使用 Vue.use() 注册api,现在是挂到具体实例对象上

 Vue.use => 实例对象.use()

composition API 与 options api的区别

options

  • 包含了data,methods,watch,props等描述组件的选项
  • Vue 是通过 Options (选项) 的方式对外提供接口,通过已经指定好的不同的 Option 来完成指定的功能
  • 调用时机:创建组件实例,然后初始化 props ,紧接着就调用setup 函数。从生命周期钩子的视角来看,它会在 beforeCreate 钩子之前被调用
  • 原来视图中可使用的数据来源很多: data,props,computed,methods,inject
    这种做法数据来源太多,容易造成混乱
    使用mixin复用代码会导致命名冲突

composition API

  • 基于函数的api

setup函数

  • setup()函数是Vue3.0中,专门为组件提供的新属性。它为基于Composition API的新特性提供了统一的入口。
  • 在Vue3中,定义methods、watch、computed、data数据都放在了setup()函数中
  • 执行时机:setup()函数会在created()生命周期之前执行。
    参数:两个参数,第一个为props(组件接收的props数据可以在setup()函数内访问到)、第二个是context,它是一个上下文对象,可以通过context 来访问Vue的实例 this

响应式数据

  • ref
  • reactive
  • computed
  • watchEffect
  • watch

响应式api工具

  • toRef 可以用来为一个 reactive 对象的属性创建一个 ref。这个 ref 可以被传递并且能够保持响应性
  • 第一个参数是哪个对象,第二个参数是对象的哪个属性
  setup(){
    let obj = {name : 'alice', age : 12};
    let newObj= toRef(obj, 'name');
    function change(){
      newObj.value = 'Tom';
      console.log(obj,newObj)
    }
    return {newObj,change}

toRefs

  • 当想要从一个组合逻辑函数中返回响应式对象时,用 toRefs 是很有效的,该 API 让消费组件可以 解构 / 扩展返回的对象,并不会丢失响应性

  • 可以使用该对象将props属性解构出来并把每一项变为响应式的

  • 以此来控制percentage属性响应式的传递给底层组件

  • 我们知道ref可以用于创建一个响应式数据,而toRef也可以创建一个响应式数据,那他们之间有什么区别呢?
    事实上,如果利用ref函数将某个对象中的属性变成响应式数据,修改响应式数据是不会影响到原始数据

    toRef与ref的区别

setup(props, ctx) {
    const {percentage} = toRefs(props);
}

ref本质是拷贝,修改响应式数据不会影响原始数据;toRef的本质是引用关系,修改响应式数据会影响原始数据 
ref数据发生改变,界面会自动更新;toRef当数据发生改变是,界面不会自动更新 
toRef传参与ref不同;toRef接收两个参数,第一个参数是哪个对象,第二个参数是对象的哪个属性 

setup() {
  const user = reactive({ age: 1 });
  const age = toRef(user, "age");

  age.value++;
  console.log(user.age); // 2

  user.age++;
  console.log(age.value); // 3
}

watch与watchEffect的区别

watch

监听ref

let a = ref(0)
let b = ref(1)
watch(() => {
  console.log('watch a+b', a.value + b.value)
})
watch(a, () => {
  console.log('watch a', a.value + b.value)
})
setTimeout(
  () => {
    a.value++
  }, 1000
)
setTimeout(
  () => {
    b.value++
  }, 2000
)

监听reactive

let a = reactive({count: 1})
let b = reactive({count: 2})
watch(() => {
  console.log('a+b', a.count + b.count)
})
watch(() => a.count, () => {
  console.log('a.count', a.count + b.count)
})
watch(() => a, () => {
  console.log('a', a.count + b.count)
})
setTimeout(() => {
  a.count++
}, 1000)
setTimeout(() => {
  b.count++
}, 2000)

回调函数停止监听

let a = ref(0)
let stop = watch(() => {
  console.log('a', a.value)
})
setTimeout(() => {
  a.value++
  console.log('change')
  stop()
  console.log('stop')
}, 1000)

watchEffect

// watchEffect
setup () {
    const age = ref(0)
    watchEffect(() => console.log(age))
    setTimeout(() => {
      age.value = 1
    }, 1000)

    return {
      age
    }
 }

总结watch与watchEffec

watch特性:

1.具有一定的惰性,第一次页面展示的时候不会执行,只有数据变化的时候才会执行

2.参数可以拿到当前值和原始值

3.可以侦听多个数据的变化,用一个侦听起承载

4.watch也可以变为非惰性的 立即执行的 添加第三个参数 immediate: true

watchEffect特性:

1.没有过多的参数 只有一个回调函数

2.自动检测内部代码,代码中有依赖 便会执行

3.不需要传递要侦听的内容 会自动感知代码依赖,不需要传递很多参数,只要传递一个回调函数

4.不能获取之前数据的值 只能获取当前值

6.立即执行,没有惰性,页面的首次加载就会执行。

组件

Fragment

  • vue3不会再像vue2一样需要手动添加一个根结点
  • vue3会自动使用fragment包裹组件结点

teleport
teleport组件能帮我们将组件渲染在页面指定的仍和地方

  • 比如modal组件,vue2中可以通过指令来实现modal组件挂载到body上去,但是比较麻烦
  • vue3可以直接使用teleport组件实现这一需求
<teleport to="body" class="modal" v-if="">
  ...
</teleport>
<teleport to="#modals" class="modal" v-if="">
  ...
</teleport>

源码层面

重写了虚拟DOM

传统vdom的性能瓶颈:

  • 虽然 Vue 能够保证触发更新的组件最小化,但在单个组件内部依然需要遍历该组件的整个 vdom 树。
  • 传统 vdom的性能跟模版大小正相关,跟动态节点的数量无关。在一些组件整个模版内只有少量动态节点的情况下,这些遍历都是性能的浪费。
  • JSX 和手写的 render function 是完全动态的,过度的灵活性导致运行时可以用于优化的信息不足

diff算法

  • vue3标记和提升了所有静态根节点,diff时只比较动态节点

静态提升

  • patch flag,patch算法的时候跳过静态节点,缓存事件处理函数

静态树提升(Static Tree Hoisting)

  • 使用静态树提升,这意味着 Vue 3 的编译器将能够检测到什么是静态的,然后将其提升,从而降低了渲 染成本。
  • 跳过修补整棵树,从而降低渲染成本,即使多次出现也能正常工作

静态属性提升

使用静态属性提升,Vue3打补丁时将跳过这些属性不会改变的节点

改进的TypeScript支持,编辑器能提供强有力的类型检查和错误及警告

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值