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没有视图的更新

相关推荐
GIS开发特训营1 分钟前
Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍
前端·vue.js·前端框架·gis开发·webgis·三维gis
Cachel wood27 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Code哈哈笑29 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
joan_8532 分钟前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
还是大剑师兰特1 小时前
什么是尾调用,使用尾调用有什么好处?
javascript·大剑师·尾调用
Watermelo6171 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
QQ同步助手1 小时前
如何正确使用人工智能:开启智慧学习与创新之旅
人工智能·学习·百度
流浪的小新1 小时前
【AI】人工智能、LLM学习资源汇总
人工智能·学习
A懿轩A2 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
一个处女座的程序猿O(∩_∩)O3 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js