飞道的博客

手把手教学,带你升级vue3.0(三)setup,ref,reactive,customRef,readOnly

418人阅读  评论(0)

setup

特点:

  • 它是一个组合api,只能是一个同步函数
  • 生命周期位于beforeCreate和created之间,因此也意味着,在它里面无法访问到data和mounted,
  • this = undefined;
  • 需要返回一个对象 (在setup函数中定义的变量和方法需要 return 出去的 不然无法再template中使用)
  • setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新。但是,因为 props 是响应式的,你不能使用 ES6 解构,因为它会消除 prop 的响应性。
props:['test']
setup(props,context){
   
//const {test} = props //错
const {
   test} = toRefs(props) //对
const {
    attrs, slots, emit }= context //对
  return {
   
    test
  }
}

reactive

用来实现响应式更新ui页面,它的参数是{}/[],
如果是其他对象(new Date)之类的,则需要给它重新赋值,才会响应式更新

// state.time = newTime;

实现

原理其实就是对每一层的object进行递归监听

function reactive(obj) {
   
  if(typeof obj === 'object'){
   
    if(obj instanceof Array){
   
      obj.forEach((item,index)=>{
   
        if(typeof item === 'object'){
   
          obj[index] = reactive(item)
        }
      })
    }else{
   
      for (let key in obj){
   
        let item = obj[key]
        if(typeof item === 'object'){
   
          obj[key] = reactive(item)
        }
      }
    }
    return new Proxy(obj,{
   
      get(obj,key){
   
        return obj[key]
      },
      set(obj,key,value){
   
        obj[key] = value;
        return true//如果obj是数组的的话,它会改变两次,一次是value,一次是length ,不然会报错
      }
    })
  }else{
   
    console.warn(`${
     obj} must be object`)
  }
}

ref

一般用于创建基本类型的数据,它的本质其实也是reactive

所以在setup中要使用num的时候,需要通过.value修改,

const num = ref(0);  // const num = reactive({value:0})
num.value = 2;

<template>标签中使用,则不需要,vue会自动添加上.value,解析之前,会判断是否为ref类型,通过当前数据的__v_isref属性是否为true判断

import {
   onMounted,ref} from 'vue'
<div ref="box"></div>
setup(){
   
  let box = ref(null)
  onMounted(()=>{
   
    console.log(box.value); //获取到dom值 <div ref="box"></div>
  })
  return {
   box}
}

实现

function ref(val) {
   
  reactive({
   value:val})
}

递归监听

把每一层都包装成proxy对象,当数据量很大的时候,很耗性能

非递归监听(只有在监听数据量比较大的时候 )

shallowReactive只会监听第一层,如果第一层没变,则不会更新UI界面,

shallowRef 本质也是shallowReactive({value:}),所以value也是他的第一层

shallowReactive实现

function shallowReactive(obj){
   
  return new Proxy(obj,{
   
    get(obj,key){
   
      return obj[key]
    },
    set(obj,key,value){
   
      obj[key] = value
      console.log('更新UI界面');
      return true //如果obj是数组的的话,它会改变两次,一次是value,一次是length ,不然会报错
    }
  })
}

shallowRef的实现

function shallowRef(val) {
   
  shallowReactive({
   value:val})
}

所以需要改变它第一层value的数据,才会更新页面,或者是通过triggerRef主动触发,只提供triggerRef,没提供triggerReactive

state.value.a.b = 1
triggerRef(state),

只有通过ref或者reactive包装之后的对象修改才会更新UI

1.通过原始数据的不会

let obj = {
   a:1}
let state = reactive(obj)
obj.a = 2
//state.a = 2  obj.a = 2

虽然数据改了,但是ui界面不会同步更新

2.或者通过toRaw获取到的原始数据修改也不会更新UI

let state = ref(2)//ref本质是reactive({value:})
let state1 = toRaw(state.value)
state1.a = 3

3.通过markRaw(),不让数据被追踪,所以之后修改了数据,UI也不会更新

let obj = {
   a:1}
 obj = markRaw(obj)
let state = reactive(obj)

应用场景:

当UI界面不需要更新的时候,因为每次修改UI界面更新其实是挺消耗性能的,这样可以减少重绘回流的次数

ref和toRef的区别

ref

let obj = {
   a:1}
let state = ref(obj.a)
state.value.a = 3
//state变了,原始obj不变,UI变

toRef

let obj = {
   a:1}
let state = toRef(obj,'a')
state.value.a = 3
//state变,原始obj变,ui不变

ref => 它的本质是复制,修改不会影响以前的数据,UI会变
toRef => 它的本质是引用,修改会影响到以前的数据,但是,UI不会改变

toRefs => 跟toRef一样,只是接收参数不一样

let obj = {
   a:1,b:2}
let state = toRefs(obj,'a','b') //等于 let state = toRefs(obj)
state.a.value = 3
state.b.value = 3

应用场景: 如果想让响应式数据和原始数据关联起来,并且更新之后不想更新到UI,则可以使用

customRef

返回一个ref对象,可以显式的控制依赖追踪和触发相应

function myRef(value) {
   
  return customRef((track,trigger)=>{
   
    return {
   
      get(){
   
        track();//告诉VUE 这里的数据是需要追踪的
        return value
      },
      set(newValue){
   
        value = newValue
        trigger()//告诉vue触发页面更新
      }
    }
  })
}

readOnly

用于创建一个只读的数据,它是递归只读

let state = readOnly({
   age:1,attr:{
   age:1}})

const与readOnly的区别

const 赋值保护,不能给变量重新赋值
readOnly 属性保护,不能给属性重新赋值

readOnly实现

function readOnly(obj) {
   
  return new Proxy(obj,{
   
    get(obj,key){
   
      return obj[key]
    },
    set(){
   


    }
  })
}

shallowReadOnly

用于创建一个只读的数据,不过只是第一层只读,第二层还是可以更改的,但UI不会更新

isReadOnly 是否是readOnly/shallowReadOnly


转载:https://blog.csdn.net/weixin_44730897/article/details/117028838
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场