vue3 响应式对象的 api ,你全用过了吗?

Ⅰ. ref、reactive ( 递归监听 )

1
2
3
4
5
6
7
8
9
import {<!-- -->ref,reactive} from 'vue';
setup() {<!-- -->
const num = ref(123);
num.value = 456;

const obj = reactive({<!-- -->num:123});
obj.value = 456;
}

  • ref 对象 在 html 模板中会 自动添加 value ( ref 对象中__v_isRef:true 进行判断的 )
  • ref 对象 => reactive( { value:0 } ) 底层自动转换为 reactive
  • 最终 基本数据 类型采用 => (Object.defineProperty) ,引用数据 类型采用 => ( proxy 代理 )

    2. isRef、isReactive ( 判断 )

1
2
3
4
5
6
import {<!-- -->isRef,isReactive} from 'vue';
setup() {<!-- -->
const num = ref(123)
console.log(isRef(num)) // =&gt; true
}

  • 用于判断是否是 Ref 和 Reactive 创建的响应对象
  • 使用场景较少

    3. toRef 和 toRefs ( 解构 )

toRef (一个属性)

1
2
3
4
5
6
7
8
9
10
import {<!-- --> toRef , reactive } from 'vue';
setup() {<!-- -->
const obj = reactive({<!-- --> width:10, height:20 })
const width = toRef(obj,'width')

return {<!-- -->
width
}
}

  • 将一个响应对象的属性,当作 响应对象 单独拿出来 。
    toRefs ( 所有 )
1
2
3
4
5
6
7
8
9
10
import {<!-- --> toRefs , reactive } from 'vue';
setup() {<!-- -->
const obj = reactive({<!-- --> width:10, height:20 })
const {<!-- --> width, height }= toRefs(obj)

return {<!-- -->
width, height
}
}

  • 将多个或所有属性,拿出来 且还是响应对象,
  • 一般在返回的时候一次性全部导出 👇
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import {<!-- --> toRefs , reactive } from 'vue';
    setup() {<!-- -->
    const obj = reactive({<!-- --> width:10, height:20 })

    return {<!-- -->
    ...toRefs(obj)
    }
    }

4. toRaw 、 markRaw ( 解除代理)

toRaw ( 不影响本身 )

1
2
3
4
5
6
7
import {<!-- -->toRaw} from 'vue';
setup(){<!-- -->
const num1 = ref(123)
const num2 = toRaw(num1)
console.log(num2 === 123) //=&gt;true
}

  • 不影响原数据 ,相当于拷贝当前的值
  • 拷贝的值,不在是响应式对象

markRaw ( 添加 非响应对象 属性 )

1
2
3
4
5
6
7
8
9
10
11
12
13
import {<!-- --> markRaw, reactive } from "vue";
setup(){<!-- -->
const obj = reactive({<!-- --> num:1 }); //让数据无法被追踪
obj.noUpdate = markRaw({<!-- -->num:1});

function add() {<!-- -->
obj.num++; // 页面数据 会更新

obj.noUpdate.num++; //页面数据 不会更新
}
return {<!-- --> obj , add }
}

  • 通过 markRaw 添加的值 => 其中的属性变化,页面不会监听的到-
  • 用于添加搞定的参数,不会发生不会的 ( 从而节约资源 )

    5. unref ( 拷贝 )

1
2
3
const aaa = ref('abc');
const bbb = unref(aaa);

  • 相当于 bbb = isRef(aaa) ? aaa.value : aaa 的语法糖- 可以用于拷贝

    6. shallowRef 、shallowReactive( 非递归监听 )

shallowRef 、shallowReactive(非递归监听)

1
2
3
4
5
6
7
8
9
10
import {<!-- -->shallowRef,shallowReactive} from 'vue';
setup(){<!-- -->
const obj1 = shallowRef({<!-- -->a:1,b:{<!-- -->c:2})
const obj2 = shallowReactive({<!-- -->a:1,b:{<!-- -->c:2})

obj1.value.a = 2 //页面未更新

obj2.b.c = 3 //页面未更新
}

  • obj1 (shallowRef)=> 只监听第一层( value 的值,不监听a、b、c、d 的值)
  • obj2 (shallowReactive)=> 只监听第一层( a、b 的值,不监听 c 的值)

    7. triggerRef (强制更新)

1
2
3
4
5
6
7
import {<!-- -->triggerRef, shallowRef} from 'vue';
setup(){<!-- -->
const obj1 = shallowRef({<!-- -->a:1,b:{<!-- -->c:2})
obj1.value.a = 2 //页面没有发生更新,因为只监听value第一层

triggerRef(obj1); // 强制更新

  • 非递归监听,只监听首层 ,消耗的资源小;
  • 配合 triggerRef 强制更新 => 性能要大于 > 直接使用 (ref 和 reactive)