vue3 toRow与markRaw、customRef

1,208 阅读1分钟

这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

toRaw:

作用:将生成的响应式数据转为普通数据

使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新

markRaw:

作用:标记一个对象,使其永远不会再成为响应式对象

应用场景:

1:有些值不应该被设为响应式的,比如复杂的第三方库等
2:当渲染具有不可变数据的大列表时,跳过响应式转换可以提高性能

toRaw:

import {reactive, toRaw,ref} from 'vue'
export default {
  setup(){
    let b = ref({name:'liudan'})
    let c = ref(0)
    let a = reactive({
      name:'liudan',
      age:18,
      job:{
        salary:70
      }
    })
    //将响应式数据转换为不具备响应式的普通数据
    console.log(toRaw(a))
    console.log(toRaw(b.value))
    console.log(toRaw(c.value))
    return {
      a,b,c
    }
  }
}

image.png

控制台可以看到,经过toRaw之后的返回的是一个普通的没有响应式的对象和数字

markRaw:

<template>
  <h1>{{a}}</h1>
  <button @click="adda">a++</button>
</template>

<script>
import {markRaw, reactive,ref, toRaw} from 'vue'
export default {
  setup(){
    let a = reactive({
      name:'liudan',
      age:18,
      job:{
        salary:70
      }
    })
    let sub = {
      salary:30
    }
    a.job = markRaw(sub)
    function adda(){
      a.job.salary++
      console.log(a)
    }
    return {
      a,
      adda
    }
  }
}

image.png 可以看到,原本用reactive定义的响应式对象,但是经过markRawAPI覆盖的属性,已经不再具备响应式了,但是数据还是能修改,这个和readonly连数据都不能更改的效果还是有一定区别。

customRef

作用:创建一个自定义的ref,并对其依赖跟踪和更新触发进行显示控制

<template>
  <input type="text" v-model="keyWord">
  <h1>{{keyWord}}</h1>
</template>

<script>
import {ref,customRef} from 'vue'
export default {
  setup(){
    //自定义ref————myRef
    function myRef(val){
     return x = customRef((track,trigger)=>{//track:追踪  trigger:有触发器的意思
       return {//语法要求要返回一个对象
        get(){
          track()//通知vue追踪val的变化,提前和get商量一下,让他认为val是有用的(视图更新需要)
          return val//读取
        },
        set(newVal){
          val = newVal
          trigger()//通知vue去重新解析模板
        }
       } 
     })
    }
    let keyWord = myRef('hello')
    return {
      keyWord
    }
  }
}
</script>

实现防抖效果:(加个定时器,每隔一定时间再去调用trigger方法)

//自定义ref————myRef
function myRef(val,delay){
    let timer
    return x = customRef((track,trigger)=>{//track:追踪  trigger:有触发器的意思
    return {//语法要求要返回一个对象
        get(){
            track()//通知vue追踪val的变化,提前和get商量一下,让他认为val是有用的(视图更新需要)
            return val//读取
        },
        set(newVal){
            clearTimeout(timer)
            timer = setTimeout(() => {
                val = newVal
                trigger()//通知vue去重新解析模板
            }, delay);
        }
    } 
 })
}
let keyWord = myRef('hello',500)