当前位置: 首页 > article >正文

【Vue3 入门到实战】13. 常用 API

目录

1. shallowRef 与 shallowReactive

1.1 shallowRef演示

1.2 shallowReactive演示

 1.3 小结

2. readonly 与 shallowReadonly 

2.1 readonly

​编辑

2.2 shallowReadonly 

3. toRaw 与 markRaw

3.1 toRaw 

3.2  markRaw

4. customRef 自定义ref

5. 总结


1. shallowRef 与 shallowReactive

1.1 shallowRef演示

shallowRef:ref 的浅层作用形式。只会对顶层的值进行响应式转换,而不会深入嵌套的对象或数组内部进行响应式处理。

效果演示 ↓ ↓ ↓

当我们使用 ref 定义时

代码如下

<template>
    <div>
        <h3>姓名:{{ obj.name }}</h3>
        <h3>年龄:{{ obj.age }}</h3>
        <h3>地址:{{ obj.address.city }}</h3>

        <button @click="changename">修改姓名</button>
        <button @click="changeage">修改年龄</button>
        <button @click="changeaddress">修改地址</button>
        <button @click="changeobj">修改整体</button>
    </div>
</template>
<script setup>
import { ref, reactive, shallowRef, shallowReactive } from 'vue'

let obj = ref({
    name: 'zhangsan', age: 18,
    address: {
        city: '北京',
    }
})
function changename() {
    obj.value.name = 'lisi'
}
function changeage() {
    obj.value.age = 19
}
function changeaddress() {
    obj.value.address.city = '上海'
}
function changeobj() {
    obj.value = {
        name: 'wangwu', age: 20, address: {
            city: '深圳',
        }
    }
}
</script>

顶层和嵌套的内部数据都是响应式的。 

 

当我将 ref 换成 shallowRef 定义时

只有顶层才是响应式。

 

1.2 shallowReactive演示

shallowReactive:reactive 的浅层作用形式。只会对对象的第一层属性进行响应式转换,而不会递归地将嵌套对象转换为响应式对象。

演示效果 ↓ ↓ ↓

当我们使用 reactive 定义时

代码如下

<template>
    <div>
        <h3>姓名:{{ obj.name }}</h3>
        <h3>年龄:{{ obj.age }}</h3>
        <h3>地址:{{ obj.address.city }}</h3>

        <button @click="changename">修改姓名</button>
        <button @click="changeage">修改年龄</button>
        <button @click="changeaddress">修改地址</button>
        <button @click="changeobj">修改整体</button>
    </div>
</template>
<script setup>
import { ref, reactive, shallowRef, shallowReactive } from 'vue'

let obj = reactive({
    name: 'zhangsan', age: 18,
    address: {
        city: '北京',
    }
})
function changename() {
    obj.name = 'lisi'
}
function changeage() {
    obj.age = 19
}
function changeaddress() {
    obj.address.city = '上海'
}
function changeobj() {
    Object.assign(obj,{
        name: 'wangwu',
        age: 20,
        address: {
            city: '深圳'
        }
    })
}
</script>

 注意:reactive 无法直接修改整体,可以通过 Object.assign() 来修改。

可以看到顶层和嵌套的都具有响应式。

 

当我将 reactive 换成 shallowReactive 时。

只有对对象的顶层和第一层进行响应式转换,而不会递归地将嵌套对象转换为响应式对象。

 

 1.3 小结

通过使用 shallowRef shallowReactive 来绕开深度响应。浅层式API创建的状态只在其顶层是响应式的,对所有深层的对象不会做任何处理,避免了对每一个对象内部属性做响应式所带来的性能成本,这使得属性的访问变得更快,可提升性能。

2. readonly 与 shallowReadonly 

2.1 readonly

用于创建一个对象的深只读副本。包括所有嵌套对象都是只读。

特点:

(1) 对象的所有嵌套属性都将变为只读。

(2) 任何尝试修改这个对象的操作都会被阻止(在开发模式下,还会在控制台中发出警告)。

演示效果 ↓ ↓ ↓

代码如下

<template>
    <div>
        <h2> sum求和为:{{ sum }}</h2>
        <h2> sum2求和为:{{ sum2 }}</h2>

        <button @click="sum++">sum加</button>
        <button @click="sum2++">sum2加</button>
    </div>
</template>

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

let sum = ref(1);
let sum2 = readonly(sum);

</script>

当我修改sum2时,控制台会弹出提示,无法修改。

2.2 shallowReadonly 

与 readonly 类似,但只作用于对象的顶层属性。确保顶层属性不被修改,允许嵌套对象内部变化。

代码如下

<template>
    <div>
        <h2> sum名字:{{ sum.name }}</h2>
        <h2> sum年龄:{{ sum.age }}</h2>
        <h2> sum地址:{{ sum.address.city }}</h2>
        <h2> sum2为:{{ sum2 }}</h2>

        <button @click="changename">sum2修改name</button>
        <button @click="changeage">sum2修改age</button>
        <button @click="changeaddress">sum2修改address</button>
        <button @click="changeall">sum2修改整个</button>

    </div>
</template>

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

let sum = ref({
    name: 'hhh',
    age:20,
    address:{
        city:'北京'
    }
});
let sum2 = shallowReadonly(sum);
function changename(){
    sum2.value.name = 'hhh2';
}
function changeage(){
    sum2.value.age = 21;
}
function changeaddress(){
    sum2.value.address.city = '上海';
}

function changeall(){
    sum2.value = {
    name: 'hh',
    age:2,
    address:{
        city:'京'
    }
}
}
</script>

下图可以看到,除了最顶层(这里是整个sum2)设置为只读外,其他都没有设置只读。

注意: 如果将 ref 变为 reactive,那么第一层是只读,不会影响其他嵌套层。

3. toRaw 与 markRaw

3.1 toRaw 

用于获取一个响应式对象的原始对象, toRaw 返回的对象不再是响应式的,不会触发视图更新。

适用场景:在需要将响应式对象传递给非 `Vue` 的库或外部系统时,使用 toRaw 可以确保它们收到的是普通对象。

代码如下

<template>
    <div>

        <div>{{sum2.name}}</div>
        <button @click="changename">修改sum2的name</button>
    </div>
</template>

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

let sum = reactive({
    name: 'hhh',
    age:20,
    address:{
        city:'北京'
    }
});

let sum2 = toRaw(sum)


function changename(){
    sum2.name = 'hhh2'
    console.log(sum,sum2)
}

</script>

如下图所示,用 sum2 接收 toRaw 包裹的响应式对象,结果 sum2 失去了响应式 。

 

3.2  markRaw

标记一个对象,使其永远不会变成响应式的。

代码如下

<template>
    <div>
        <div>{{ sum2.name }}</div>
        <button @click="changename">修改sum2的name</button>
    </div>
</template>
<script setup>
import { reactive,markRaw } from 'vue'

let sum = markRaw({
    name: 'hhh',
    age: 20,
    address: {
        city: '北京'
    }
})
let sum2 = reactive(sum)
console.log(sum,sum2)
</script>

如下入所示,当 sum 对象被 markRaw 标记之后,就算被 reactive 包裹,也不会转成响应式对象。 

4. customRef 自定义ref

创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行逻辑控制。

下面我们使用自定义 ref 来实现一个防抖效果,用来熟悉这个 customRef。

代码如下

<template>
    <div>
        <h2>{{ msg }}</h2>
        <input type="text" v-model="msg">
    </div>
</template>
<script setup>
import { customRef } from 'vue'

let initValue = '你好'
let time
let msg = customRef((track,trigger)=>{
    return {
        // 当msg被读取时调用
        get(){
            track()  // 告诉Vue,这个msg数据很重要,你要对msg进行持续关注,一旦msg变化就去更新
            console.log('hhh,我被读取啦')
            return initValue
        },
        // 当msg被修改时调用
        set(value){
            clearTimeout(time)
          time = setTimeout(()=>{
            console.log('hhh,我被修改啦',value)
            initValue = value
            trigger() // 告诉Vue,这个msg数据发生了变化,去更新
          },1000)
        }
    }
})

</script>

效果如下 ↓ ↓ ↓ 

注意点:

(1) get 方法在数据读取时被调用。

(2) set 方法在数据修改时被调用。

(3) track 方法用于 告诉这个Vue,该数据很重要,要对这个数据进行持续关注。

(4) trigger 方法用于 告诉Vue,这个数据发生了变化,去更新。

为了提高代码的复用性,可以将这个自定义ref,封装成一个 hooks,每次使用直接引用既可。

创建一个hooks并暴露

useCustomRef.ts

import { customRef } from "vue";
export default function useCustomRef(value:string,delay:number){
    return customRef((track,trigger)=>{
        let timer:any = null
        return {
            get(){
                track();
                return value
            },
            set(newValue:string){
                clearTimeout(timer)
                timer = setTimeout(()=>{
                    value = newValue
                    trigger()
                },delay)
            }
        }
    })
}
 

在组件中直接引用

App.vue

<template>
    <div>
        <h2>{{ msg }}</h2>
        <input type="text" v-model="msg">
    </div>
</template>
<script setup>
import  useCustomRef  from "@/useCustomRef"

let msg = useCustomRef('hello',1000)

</script>

效果和上面是一样的。

5. 总结

上面主要介绍了Vue3常用的一些API,包括浅层API(shallowRef)、只读API(readonly)、toRaw、markRaw、自定义ref(customRef)等。

更多内容点击下方链接 ↓ ↓ ↓

Vue3入门到实战_借来一夜星光的博客-CSDN博客


http://www.kler.cn/a/543243.html

相关文章:

  • (一)Axure制作移动端登录页面
  • 内网ip网段记录
  • 使用C语言实现MySQL数据库的增删改查操作指南
  • Docker Compose介绍及安装使用MongoDB数据库详解
  • WPS计算机二级•文档的文本样式与编号
  • 文理医院预约挂号系统的设计与实现(代码+数据库+LW)
  • 探索技术新边界:让 HTML 电子凭证与二维码、PDF 完美融合
  • 网络安全 理清 安全 边界
  • 计算机毕业设计制造业MES生产管理平台 MES 生产制造源码+文档+运行视频+讲解视频)
  • 【前端】ES6新特性汇总
  • AI直播的未来:智能化、自动化与个性化并存
  • AI时代的前端开发:效率、协作与ScriptEcho
  • C++设计模式 —— 单例模式
  • TiDB Vector 本地部署的亲身体验与心得
  • Druid GetConnectionTimeoutException解决方案之一
  • 基础连接已经关闭: 服务器关闭了本应保持活动状态的连接
  • Cursor无法安装插件解决方法
  • 操作系统|ARM和X86的区别,存储,指令集
  • 在anaconda环境中构建flask项目的exe文件
  • 后端面试题
  • 1.2 快速搭建环境
  • npm运行Vue项目报错 error:0308010c:digital envelope routines::unsupported
  • Three.js编辑器百度搜索 Top 1
  • Python解决“数字字符串千分位转化”问题
  • 制造企业智慧物流架构解决方案
  • leetcode_深度搜索和广度搜索 116. 填充每个节点的下一个右侧节点指针