vue3 -6 其他常见的组合式API尝试

141 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 29 天,点击查看活动详情

start

  • 今天学习一下 vue3 的 toRef api

toRef()

官方解释:

基于响应式对象上的一个属性,创建一个对应的 ref。这样创建的 ref 与其源属性保持同步:改变源属性的值将更新 ref 的值,反之亦然。

示例:

<script setup>
import { ref, toRef } from 'vue'

let obj1 = {
  name: '我是第一个测试数据',
}

let a = ref(obj1.name)

let obj2 = {
  name: '我是第二个对象',
}

let b = toRef(obj2, 'name')

a.value = '修改1'

b.value = '修改2'

console.log(a, b)

console.log(obj1, obj2)
// {name: '我是第一个测试数据'}
// {name: '修改2'}

obj1.name = '全新的数据111'
obj2.name = '全新的数据222'

console.log(a.value, b.value)
// 修改1
// 全新的数据222
</script>

由上述案例可得:

  • 使用 ref 去获取的响应式对象,接收到的是一个纯数值。上述示例的 obj1 和 a 无关联;

  • 使用 toRef 去获取的响应式对象,创建的 ref 和原属性保持同步。上述示例的 obj2b, b.value修改会影响obj2 ,obj2.name修改会影响b.value

toRefs()

官方解释:

将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。

示例:

<script setup>
import { toRefs } from 'vue'

let obj = {
  name: '我是一个对象',
  age: 18,
}

let b = toRefs(obj)

obj.name = '全新的数据'
console.log(obj.name, b.name.value)
// 全新的数据
// 全新的数据

b.name.age = 250
console.log(obj.age, b.age.value)
// 18 18
</script>

由上述案例可得:

  • toRefs 作用其实和 toRef 类似,只不过 toRef 是对一个个属性手动赋值,而 toRefs 是自动解构赋值。

shallowReactive()

官方解释:

reactive() 的浅层作用形式。

示例:

<template>
  <div>
    <!-- 第一层的是响应式的 -->
    {{ state.foo }}
    <input v-model="state.foo" type="text" />

    <br />

    <!-- 深层次的不是是响应式的 -->
    {{ state.nested.bar }}
    <input v-model="state.nested.bar" type="text" />
  </div>
</template>

<script setup>
import { shallowReactive, isReactive } from 'vue'

const state = shallowReactive({
  foo: 1,
  nested: {
    bar: 2,
  },
})

console.log(isReactive(state)) // true
console.log(isReactive(state.nested)) // false
</script>

结论:

  • shallow 英文释义 浅的;
  • shallowReactive() 是 reactive() 的浅层作用形式;

readonly()

官方解释:

接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理。

示例:

<script setup>
import { readonly } from 'vue'

var obj = {
  name: '你好番茄',
  hobby: {
    game: 'CSGO',
  },
}

var b = readonly(obj)

b.name = '通过只读修改'
//  Set operation on key "name" failed: target is readonly. {name: '你好番茄', hobby: {…}}
/* 浅层无法修改 */

b.hobby.game = '不玩游戏了'
// Set operation on key "game" failed: target is readonly. {game: 'CSGO'}
/* 深层无法修改 */
</script>

结论:

  • readonly 英文释义 只读;
  • 返回一个只读代理,深层也无法修改

shallowReadonly()

官方解释:

readonly 的浅层作用形式

示例:

<script setup>
import { shallowReadonly } from 'vue'

var obj = {
  name: '你好番茄',
  hobby: {
    game: 'CSGO',
  },
}

var b = shallowReadonly(obj)

b.name = '通过只读修改'
//  Set operation on key "name" failed: target is readonly. {name: '你好番茄', hobby: {…}}
/* 浅层无法修改 */

b.hobby.game = '不玩游戏了'
/* 深层可以修改 */

console.log(obj, b.hobby.game)
// {name: '你好番茄', hobby: {…}}
// '不玩游戏了'
</script>

结论:

  • shallowReadonly 是 readonly 的浅层作用形式

toRaw()

官方解释:

  • 根据一个 Vue 创建的代理返回其原始对象。
  • toRaw() 可以返回由 reactive()、readonly()、shallowReactive() 或者 shallowReadonly() 创建的代理对应的原始对象。

示例:

<script setup>
import { ref, reactive, toRaw } from 'vue'

var obj = {
  age: 18,
}
var a = reactive(obj)
console.log(toRaw(a), toRaw(a) === obj)
// {age: 18}
// true

var obj2 = {
  name: '222',
}
var b = ref(obj2)
console.log(toRaw(b), toRaw(b) === obj2)
// RefImpl {name: "222"}
// false
</script>

总结:

  • toRaw() 返回的是原始对象;
  • 原本的代理对象不受影响;

markRaw

官方解释:

将一个对象标记为不可被转为代理。返回该对象本身

示例:

<script setup>
import { reactive, markRaw, isReactive } from 'vue'

var obj = {
  age: '213',
  other: {
    age: 1,
  },
}

var foo = markRaw(obj)

// 1. 原本的对象无法代理
console.log(isReactive(reactive(obj))) // false

// 2. markRaw返回的对象也无法代理
console.log(isReactive(reactive(foo))) // false

// 3.拦截的对象的属性是可以代理的
console.log(isReactive(reactive(foo.other))) // true
</script>

总结:

  • markRaw标记的对象,无法代理;
  • markRaw的返回值为原本对象;
  • markRaw标记的对象内部,可以代理;

end

简单总结一下,

  • 主要是针对一些其他的常见 api做了初步体验,以及基本功能有了一个熟悉的过程;
  • 其主要逻辑就是弥补 ref 和 reactive的不足;
  • 深入对这些方法的使用,后期再做补充;