vue3学习(二)--- ref和reactive

文章目录

  • ref
    • [1.1 ref将基础类型和对象类型数据转为响应式](#1.1 ref将基础类型和对象类型数据转为响应式)
    • [1.2 ref()获取id元素](#1.2 ref()获取id元素)
    • [1.3 isRef](#1.3 isRef)
  • reactive
    • [1.1 reactive()将引用类型数据转为响应式数据,基本类型无效](#1.1 reactive()将引用类型数据转为响应式数据,基本类型无效)
    • [1.2 ref和reactive的联系](#1.2 ref和reactive的联系)
  • [toRef 和 toRefs](#toRef 和 toRefs)
    • [1.1 如果原始对象是非响应式的就不会更新视图 数据是会变的](#1.1 如果原始对象是非响应式的就不会更新视图 数据是会变的)

ref

1.1 ref将基础类型和对象类型数据转为响应式

接受一个内部值,返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value。

vue3中定义数据默认不是响应式的数据,需要手动将数据转化为响应式的,这里就用到了ref()

javascript 复制代码
let num1 = 20  //非响应式的

import {ref} from 'vue'v
let num1 = ref(20) // 响应式的
  1. ref()可以将数据转为响应式数据
  2. 获取ref(xx)的值需要使用.value的形式,html模板中使用不需要.value因为html中默认就是通过.value来获取值的

1.2 ref()获取id元素

javascript 复制代码
<p ref="demo">获取ref的元素</p>

import {ref,onmounted} from 'bue'

onMounted(()=>{
	let demo= ref()  这样就获取了id=demo的元素
	console.log(demo.value)
})

注意!声明的变量名要跟dom元素的id一致才可以, ref不传任何参数。记得在dom挂载之后再获取

1.3 isRef

判断是不是一个ref对象

c 复制代码
import { ref, Ref,isRef } from 'vue'
let message: Ref<string | number> = ref("我是message")
let notRef:number = 123
const changeMsg = () => {
  message.value = "change msg"
  console.log(isRef(message)); //true
  console.log(isRef(notRef)); //false
  
}

reactive

1.1 reactive()将引用类型数据转为响应式数据,基本类型无效

javascript 复制代码
let _obj = {
      num: 20,
    }

let objRef = ref(_obj)
 console.log('ref  obj', objRef.value.num)

let obj = reactive(_obj)
console.log('reactive  obj', obj.num) 


其实ref().value内部是跟reactive()一样的,所以说ref内部是通过reactive实现的。

  1. ref()----用于基本数据类型和引用类型
  2. reactive()----用于引用类型

1.2 ref和reactive的联系

reactive针对引用类型,内部通过new Proxy实现,因为new proxy可以直接拦截引用类型,无法直接在基础类型进行拦截。

ref针对基础类型和引用类型,内部会生成一个对象添加value属性指向数据类型,然后再通过reactivenew proxy)对生成的对象进行拦截。达到响应式的效果。

所以为什么ref的值需要用.value来获取,因为内部生成一个新的带有value属性的对象,只有对象的形式才能使用new proxy进行拦截


toRef 和 toRefs

作用:

在解构 reactive()得到对象的时候,将解构的数据变成响应式ref()类型.

当然解构出来的数据依旧需要通过.value的形式来操作.

常用于es6的解构赋值操作,因为在对一个响应式对象直接解构时解构后的数据将不再有响应式,而使用toRefs和toRef 可以方便解决这一问题。

c 复制代码
 let _obj = {
      num: 20,
    }
let obj = reactive(_obj)

//toRef 
let num = toRef(obj,'num') 

//toRefs
let { num } = toRefs(obj)
const handleClick = () => {
    // obj.num++
    // toRefs()模式
    num.value++
  }

toRef针对对象的单个属性,toRefs直接针对对象,记得需要用.value来获取值

1.1 如果原始对象是非响应式的就不会更新视图 数据是会变的

c 复制代码
const obj = {
   foo: 1,
   bar: 1
}
const state = toRef(obj, 'bar')
// bar 转化为响应式对象
const state = toRefs(obj)
// obj 转化为响应式对象

obj对象是非响应式的 ,toRef/toRefs可以将obj转为响应式对象,但视图的更新方法在ref reactive中有实现,toRef/toRefs并没有更新视图的功能

toRef/toRefs实现的大体思路是:判断是不是响应式对象,如果是直接返回,如果不是通过ObjectRefImpl()将数据变成响应式

js 复制代码
export function toRef<T extends object, K extends keyof T>(
  object: T,
  key: K,
  defaultValue?: T[K]
): ToRef<T[K]> {
  const val = object[key]
  return isRef(val)
    ? val
    : (new ObjectRefImpl(object, key, defaultValue) as any)
}

 ObjectRefImpl的实现

class ObjectRefImpl<T extends object, K extends keyof T> {
  public readonly __v_isRef = true
 
  constructor(
    private readonly _object: T,
    private readonly _key: K,
    private readonly _defaultValue?: T[K]
  ) {}
 
  get value() {
  	这里没有监听视图变化
    const val = this._object[this._key]
    return val === undefined ? (this._defaultValue as T[K]) : val
  }
 
  set value(newVal) {
 	 这里没有监听视图变化
    this._object[this._key] = newVal
  }
}

下面是ref的源码实现,明显的区别在于toRef没有视图的更新

相关推荐
南宫生16 分钟前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode
技术小齐36 分钟前
网络运维学习笔记 016网工初级(HCIA-Datacom与CCNA-EI)PPP点对点协议和PPPoE以太网上的点对点协议(此处只讲华为)
运维·网络·学习
竹言笙熙44 分钟前
代码审计初探
学习·web安全
日记成书1 小时前
物联网智能项目
物联网·学习
dorabighead1 小时前
JavaScript 高级程序设计 读书笔记(第三章)
开发语言·javascript·ecmascript
虾球xz1 小时前
游戏引擎学习第118天
学习·游戏引擎
gz927cool2 小时前
大模型做导师之开源项目学习(lightRAG)
学习·开源·mfc
林的快手3 小时前
CSS列表属性
前端·javascript·css·ajax·firefox·html5·safari
世事如云有卷舒3 小时前
FreeRTOS学习笔记
笔记·学习
bug总结3 小时前
新学一个JavaScript 的 classList API
开发语言·javascript·ecmascript