Vue Ref全家桶具体用法详解
作者:剑九 发布时间:2024-04-27 15:49:06
1. ref
在Vue3中,ref
成为了一个全家桶,除了用于创建响应式数据之外,还可以用于引用DOM元素、组件实例和其他对象。以下是ref
的具体用法:
1.1. 创建响应式数据
我们可以使用ref
函数来创建响应式数据,例如:
<template>
<div>{{ count }}</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
console.log(count.value) // 输出 0
count.value += 1
console.log(count.value) // 输出 1
</script>
<style scoped>
</style>
注意被ref包装之后需要.value 来进行赋值
在这个例子中,我们使用ref
函数来创建一个响应式数据count
,初始值为0
。我们可以使用count.value
来访问和修改这个值。
1.2. 引用DOM元素
我们可以使用ref
函数来引用DOM元素,例如:
<template>
<div ref="container"></div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const container = ref(null) // 注意:此处的变量名必须和标签上的属性名一致
onMounted(() => {
console.log(container.value) // 输出 <div></div>
})
</script>
<style scoped>
</style>
在这个例子中,我们使用ref
函数来创建一个container
引用,然后在模板中使用ref="container"
来将这个引用绑定到一个<div>
元素上。在setup
函数中,我们使用onMounted
钩子来访问这个引用的值。
1.3. 引用组件实例
我们可以使用ref
函数来引用组件实例,例如:
<template>
<Child ref="child" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Child from './Child.vue'
const child = ref(null)
</script>
<style scoped>
</style>
在这个例子中,我们使用ref
函数来创建一个child
引用,然后将这个引用绑定到一个<Child>
组件上。在script
中,我们将这个引用暴露出去,以便在其他地方使用。
1.4. 引用其他对象
除了DOM元素和组件实例之外,我们还可以使用ref
函数来引用其他对象,例如:
<template>
<Child ref="child" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
const data = { name: 'John' }
const obj = ref(data)
console.log(obj.value.name) // 输出 'John'
obj.value.name = 'Mary'
console.log(data.name) // 输出 'Mary'
<script>
<style scoped>
</style>
在这个例子中,我们使用ref
函数来引用一个对象data
,然后将这个引用赋值给一个obj
变量。我们可以使用obj.value
来访问和修改这个对象。在这个例子中,我们将obj.value.name
修改为Mary
,然后发现data.name
也被修改了。
1.5. ref源码
在Vue3中,ref函数的源码如下:
import { isObject } from '@vue/shared'
import { ReactiveFlags, reactive } from './reactive'
export function ref(value) {
// 如果value已经是一个ref对象,直接返回它
if (isRef(value)) {
return value
}
// 创建一个响应式对象
let valueIsObject = isObject(value)
const ref = {
// 标记这个对象是一个ref对象
[ReactiveFlags.IS_REF]: true,
// 获取ref的值
get value() {
// 如果value是一个对象,则返回一个响应式对象
if (valueIsObject) {
return reactive(value)
}
return value
},
// 设置ref的值
set value(newVal) {
if (valueIsObject) {
value = newVal
valueIsObject = isObject(newVal)
return
}
// 如果value是一个基本类型的值,则直接修改它
value = newVal
}
}
return ref
}
在这个源码中,ref
函数首先会判断传入的值是否已经是一个ref
对象,如果是则直接返回它,否则会创建一个响应式对象来作为ref
对象的值。然后ref
函数会返回一个拥有value
属性的对象,当读取这个属性时,如果它的值是一个对象,则会返回一个响应式对象,否则直接返回它的值;当修改这个属性时,如果它的值是一个对象,则会将新值转化为响应式对象,否则直接修改它的值。
2. isRef
在Vue3中,isRef
函数用于判断一个对象是否为ref
对象,它通过判断这个对象是否拥有一个特殊的属性IS_REF
来进行判断。这个特殊属性的值为true
,表示这个对象是一个ref
对象。
2.1. isRef的使用
<template>
<div class="wrapper"></div>
</template>
<script setup lang="ts">
import { isRef, ref } from 'vue';
const name: string = '张三';
console.log(isRef(name)); // false
const age = ref(10);
console.log(isRef(age)); // true
</script>
<style scoped>
</style>
2.2. isRef源码
// 判断一个对象是否为ref对象
export function isRef(r) {
return Boolean(r && r[ReactiveFlags.IS_REF])
}
3. shallowRef
在Vue3中shallowRef
函数,用于创建一个“浅层”的响应式对象。
与ref
函数不同的是,shallowRef
函数不会将其值转化为响应式对象,而是直接将其作为普通的对象或数组来处理。这意味着,当修改shallowRef
对象的属性或数组的元素时,Vue3将不会追踪这些变化。这种“浅层”的响应式对象对于一些不需要完全响应式的场景非常有用,例如缓存一些数据或跟踪某些状态。
3.1. shallowRef的使用
下面是一个使用shallowRef
函数的示例:
<template>
<div>{{ obj.name }}</div>
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
const obj = { name: 'John', age: 30 }
const ref = shallowRef(obj)
console.log(ref.value.name) // 输出 'John'
ref.value.name = 'Mary'
console.log(obj.name) // 输出 'Mary'
</script>
<style scoped>
</style>
在这个示例中,我们使用shallowRef
函数来创建一个“浅层”
的响应式对象ref
,并将其值设置为obj
对象。当我们修改ref.value.name
属性的值时,obj.name
属性的值也发生了改变。这是因为obj
对象和ref
对象共享同一个引用。
3.2. shallowRef的源码
在Vue3中,shallowRef
函数的源码如下:
import { isObject, toRawType } from '@vue/shared'
import { track, trigger } from './effect'
import { ReactiveFlags } from './reactive'
const shallowGet = (value) => value
const shallowSet = () => {
console.warn(
`Value assigned to a shallow ref ${String(value)} is not reactive, ` +
`expecting explicitly passing deep: true in ref() options`
)
}
class ShallowRefImpl {
public readonly __v_isRef = true
public readonly [ReactiveFlags.IS_SHALLOW] = true
constructor(public _value) {}
get value() {
track(this, 'get', 'value')
return this._value
}
set value(newValue) {
if (newValue !== this._value) {
this._value = newValue
trigger(this, 'set', 'value', newValue)
}
}
}
export function shallowRef(value) {
return new ShallowRefImpl(value)
}
export function isShallowRef(value) {
return !!value[ReactiveFlags.IS_SHALLOW]
}
shallowRef
函数会创建一个ShallowRefImpl
对象,并将传入的值作为其内部的_value
属性的值。ShallowRefImpl
对象是一个带有get
和set
方法的普通对象,当读取value
属性时,get
方法会返回_value
属性的值;当修改value
属性时,set
方法会将新值赋值给_value
属性,并触发相应的依赖。
4.triggerRef
强制更新DOM
4.1. triggerRef的使用
triggerRef
的使用非常简单,只需要传递一个Ref
对象作为参数即可。例如:
import { ref, triggerRef } from 'vue'
const count = ref(0)
// 在某些情况下需要手动更新count,可以使用triggerRef
triggerRef(count)
在这个例子中,我们使用ref
函数创建了一个名为count
的响应式引用,它的初始值为0
。然后我们在某些情况下需要手动更新count,这时我们可以使用triggerRef
函数来触发它的更新。
需要注意的是,当使用triggerRef
函数触发更新时,它只会更新Ref
对象本身,而不会更新与之相关联的组件。因此,我们应该在明确知道需要手动更新时使用triggerRef
函数,而在普通情况下使用Vue
自身的响应式系统来自动更新相关组件。
4.2. triggerRef的源码实现
在Vue3中,triggerRef
函数用于触发一个ref
对象的依赖更新。其源码如下:
import { effect } from './effect'
import { track, trigger } from './operations'
export function triggerRef(ref) {
if (ref.__v_isRef) {
const value = ref.value
if (isTracking()) {
track(ref, 'set', 'value')
}
ref.value = value
trigger(ref, 'set', 'value', value)
} else {
console.warn(`triggerRef() expects a ref object passed as its argument.`)
}
}
在这个源码中,首先判断传入的对象是否为ref
对象,如果是则获取它的值,并使用track
函数追踪这个ref
对象的依赖。然后将这个ref
对象的值赋值给它自己的value
属性,并使用trigger
函数触发这个ref
对象的依赖更新。如果传入的对象不是ref
对象,则会输出一个警告信息。
5. customRef
在 Vue 3 中,提供了一个 customRef
函数,用于创建一个自定义的、可响应的引用对象。与 ref
和 shallowRef
不同的是,customRef
可以自定义 get
和 set
方法的实现逻辑,从而实现更加灵活的响应式行为。
使用 customRef
函数创建的引用对象与 ref
对象类似,也具有 value
属性,当读取这个属性时,会触发 get
方法的执行;当修改这个属性时,会触发 set
方法的执行,并且会触发相应的依赖更新。与 ref
对象不同的是,customRef
函数本身并不会对传入的初始值进行处理,而是将其直接作为 get
方法的返回值,需要自己手动处理。
下面是 customRef
函数的使用示例:
5.1. customRef使用
import { customRef } from 'vue'
const myRef = customRef((track, trigger) => ({
value: 0,
get() {
track()
return this.value
},
set(newValue) {
this.value = newValue
trigger()
}
}))
console.log(myRef.value) // 输出 0
myRef.value = 1
console.log(myRef.value) // 输出 1
在这个示例中,使用 customRef
函数创建了一个自定义的引用对象 myRef
,它的 get
方法用于追踪依赖,返回 value
属性的值;set
方法用于修改 value
属性的值,并触发相应的依赖更新。当读取和修改 myRef
对象的 value
属性时,会分别触发它的 get
和 set
方法。
注意:customRef
函数的参数是一个函数,这个函数接收两个参数,分别是 track
和 trigger
函数,它们用于追踪依赖和触发依赖更新。
5.2. customRef 函数的源代码
import { track, trigger } from './effect'
export function customRef(factory) {
const ref = {
__v_isRef: true,
get value() {
return factory().get()
},
set value(newValue) {
factory().set(newValue)
}
}
return ref
}
export function triggerRef(ref) {
trigger(ref, 'set', 'value', ref.value)
}
在这个源码中,定义了一个 customRef
函数,它接收一个工厂函数作为参数,用于创建一个自定义的引用对象。在函数内部,创建了一个普通的对象 ref
,它有一个只读的 __v_isRef
属性,用于标识它是一个 ref
对象;还有一个名为 value
的属性,用于存储引用对象的值,并且在读取和修改时会触发工厂函数的 get
和 set
方法。在 customRef
函数的最后,返回这个 ref
对象。
总结:这篇文章介绍了Vue3中的ref
函数、isRef
函数、shallowRef
函数和customRef
函数。ref
函数主要用于创建响应式对象,引用DOM
实例,引用组件实例等。isRef
函数主要用于判断传入的数据是不是响应式对象。shallowRef
函数创建一个“浅层”的响应式对象,只追踪值的属性变化,而不追踪对象内部属性的变化。customRef
函数可以创建自定义的引用对象,可以自定义get
和set
方法的实现逻辑。此外,文章还介绍了triggerRef
函数,用于触发ref
对象的依赖更新。
来源:https://blog.csdn.net/to_the_Future/article/details/129233894
猜你喜欢
- 项目需求近日需要实现用户推荐相关的功能,也就是说向用户推荐他可能喜欢的东西。我们的数据分析工程师会将用户以及用户可能喜欢的东西整理成文档给我
- SQL Server推荐使用 SET 而不是 SELECT 对变量进行赋值。当表达式返回一个值并对一个变量进行赋值时,推荐使用 SET 方法
- 第一步: 1:磁盘寻道能力,以高速硬盘(7200转/秒),理论上每秒寻道7200次.这是没有办法改变的,优化的方法是----用多个硬盘,或者
- API的设计是一个艺术活。往往需要其简单、易懂、整洁、不累赘。很多时候,我们在底层封装一个方法给高层用,而其它的方法只是为了辅助这个方法的。
- 去掉数据重复 增加两个字段 alter TABLE T_Employee Add FSubCompany VARchar(20); ALTE
- 你还没用 jQuery 写过导航菜单? 相信看到这些出色的jQuery导航菜单后,一定会为此而后悔没早点把 jQuery 应用到自己的Web
- 如下所示:import matplotlib.pyplot as pltimport numpy as npimport mathdef g
- 50个常用sql语句 Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(
- 我们知道 Golang 切片(slice) 在容量不足的情况下会进行扩容,扩容的原理是怎样的呢?是不是每次扩一倍?下面我们结合源码来告诉你答
- 做 Web 开发少不了要与模板引擎打交道。我陆续也接触了 Python 的不少模板引擎,感觉可以总结一下了。一、首先按照我的熟悉程度列一下:
- 描述Python 字典(Dictionary) copy() 函数返回一个字典的浅复制。语法copy()方法语法:dict.copy()返回
- 在接触公司一个系统时,公司使用的是SQL Server 2008数据库,里面涉及到了多个数据库之间的查询,而且数据库是分布式的,数据库分布在
- js 读取csv内容拼接成jsonformdata对象上传了csv文件,读取文件内容拼接成json对象var form = new Form
- Pandas提供了duplicated、Index.duplicated、drop_duplicates函数来标记及删除重复记录duplic
- 在开发国际化网站的时候,难免会与时区打交道,通用CMS更是如此,毕竟其 * 户可能是来自于全球各地的。Django在时区这个问题上下了不少功
- class和id的命名,如果合理,可以使得文档具有清晰的结构我们现在解决办法就是使用现有的元素,通过给他们id或class而得到额外的信息。
- Wake-On-LAN简称WOL,是一种电源管理功能;如果存在网络活动,则允许设备将操作系统从待机或休眠模式中唤醒。许多主板厂商支持IBM提
- 前言简单介绍下python的几个自动求导工具,tangent、autograd、sympy;在各种机器学习、深度学习框架中都包含了自动微分,
- PyQt5 Qt Designer (Qt设计师)PyQt5是对Qt所有类进行封装, Qt能开发的东西, PyQt都能开发.Qt是强大的GU
- 简介EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False。EXISTS 指定一个