Vue3.0系列(Composition API 的补充)

上一篇我们说了ref 和 reactive创建数据,下面来做一些补充

1…递归监听和非递归监听

1.1 递归监听

1. 默认情况下, 无论是通过ref还是reactive都是递归监听
每一层都监听

<template>
  <div>
      <p>{{state.a}}</p>
      <p>{{state.gf.b}}</p>
      <p>{{state.gf.f.c}}</p>
      <p>{{state.gf.f.s.d}}</p>
    <button @click="myFn">按钮</button>
  </div>
</template>

<script>

import {reactive} from 'vue';
  // import {ref} from 'vue';
export default {
  name: 'App',
  setup() {
    let state = reactive({
        a:'a',
        gf:{
            b:'b',
            f:{
                c:'c',
                s:{
                    d:'d'
                }
            }
        }
    });
    function myFn() {
        state.a = '1';
        state.gf.b = '2';
        state.gf.f.c = '3';
        state.gf.f.s.d = '4';
        
        console.log(state);
        console.log(state.gf);
        console.log(state.gf.f);
        console.log(state.gf.f.s);
    }
    return {state, myFn}
  }
}
</script>

2.递归监听存在的问题
如果数据量比较大, 非常消耗性能

打印后,发现每一层对象都被包装为了Proxy对象,
如果数据量比较大, 非常消耗性能
在这里插入图片描述

2.2 非递归监听

使用shallowReactiveshallowRef

shallowReactive:

<script>
 // 3.非递归监听
import {shallowReactive} from 'vue';

export default {
  name: 'App',
  setup() {
    let state = shallowReactive({
    // let state = ref({
        a:'a',
        gf:{
            b:'b',
            f:{
                c:'c',
                s:{
                    d:'d'
                }
            }
        }
    });
    function myFn() {
        state.a = '1';
        state.gf.b = '2';
        state.gf.f.c = '3';
        state.gf.f.s.d = '4';
        console.log(state);
        console.log(state.gf);
        console.log(state.gf.f);
        console.log(state.gf.f.s);
    }
    return {state, myFn}
  }
}
</script>

再次打印输出结果,发现只有第一层被封装为了Proxy对象
但是第2, 3,4层数据为什么也发生了变化呢?
因为修改了第一层,它就去修改UI了
在这里插入图片描述
shallowRef:

注意点:

  • 如果是通过shallowRef创建数据,
    那么Vue监听的是.value的变化, 并不是第一层的变化
  • Vue3只提供了triggerRef方法, 没有提供triggerReactive方法
  • 所以如果是reactive类型的数据, 是无法主动触发界面更新的
    triggerRef(state);

2.toRow 和 markRow

2.1 toRow
  • 从Reactive 或 Ref中得到原始数据
    let obj = {name:‘lnj’, age:18};
    let state = reactive(obj);
    let obj2 = toRaw(state);
  • toRaw作用 :做一些不想被监听的事情(提升性能)

例子:
ref/reactive数据类型的特点:

  1. 每次修改都会被追踪, 都会更新UI界面, 但是这样其实是非常消耗性能的
  2. 所以如果我们有一些操作不需要追踪, 不需要更新UI界面, 那么这个时候,
  3. 我们就可以通过toRaw方法拿到它的原始数据, 对原始数据进行修改, 这样就不会被追踪, 这样就不会更新UI界面, 这样性能就好了
import {reactive, toRaw} from 'vue';
export default {
  name: 'App',
  setup() {
      let obj = {name:'lnj', age:18};
      // state和obj的关系:
      // 引用关系, state的本质是一个Proxy对象, 在这个Proxy对象中引用了obj
      let state = reactive(obj);
      let obj2 = toRaw(state);
 
      function myFn() {
          // 如果直接修改obj, 那么是无法触发界面更新的
          // 只有通过包装之后的对象来修改, 才会触发界面的更新
          obj2.name = 'zs';
          console.log(obj2); // {name: "zs", age: 18}
          console.log(state); // {name: "zs", age: 18}
      }
    return {state, myFn}
  }
}

上面的例子是,toRow获取 Reactive类型的原始数据,
如果toRow要获取 ref类型的原始数据,

注意点:

  • ref本质: reactive
    ref(obj) -> reactive({value: obj})
  • 注意点: 如果想通过toRaw拿到ref类型的原始数据(创建时传入的那个数据)
    那么就必须明确的告诉toRaw方法, 要获取的是.value的值
    因为经过Vue处理之后, .value中保存的才是当初创建时传入的那个原始数据
  let obj = {name:'lnj', age:18};
  let state = ref(obj);
  let obj2 = toRaw(state.value);
2.2 markRow

markRaw
数据标记为永远不能追踪的数据
一般在编写自己的第三方库时使用

import {reactive, markRaw} from 'vue';
export default {
  name: 'App',
  setup() {
      let obj = {name: 'lnj', age: 18};
      obj = markRaw(obj);
      let state = reactive(obj);
      function myFn() {
          state.name = 'zs';
      }
    return {state, myFn}
  }
}

3. toRef 和 toRefs

  • toRef
    创建一个ref类型数据, 并和以前的数据关联
  • toRefs
    批量创建ref类型数据, 并和以前数据关联
  • toRef和ref区别
    ref创建出来的数据和以前无关(复制)
    toRef-创建出来的数据和以前的有关(引用)
    ref-数据变化会自动更新界面
    toRef-数据变化不会自动更新界面
<script>
  import {ref, toRef} from 'vue';
export default {
  name: 'App',
  setup() {
      let obj = {name:'lnj'};
      /*
      ref(obj.name) -> ref(lnj)
      -> reactive({value:lnj})
      * */
      // ref->复制
      // let state = ref(obj.name);
      // toRef->引用
      /*
      ref和toRef区别:
      ref->复制, 修改响应式数据不会影响以前的数据
      toRef->引用, 修改响应式数据会影响以前的数据
      ref->数据发生改变, 界面就会自动更新
      toRef->数据发生改变, 界面也不会自动更新

      toRef应用场景:
      如果想让响应式数据和以前的数据关联起来, 并且更新响应式数据之后还不想更新UI, 那么就可以使用toRef
      * */
      let state = toRef(obj, 'name');

      function myFn() {
          state.value = 'zs';
          console.log(obj);
          console.log(state);
      }
    return {state, myFn}
  }
}
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值