主要记录以下api:ref()、isRef()、unref()、 shallowRef()、triggerRef()、customRef()
1、ref() 定义
接受一个内部值,返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value,.value属性用于追踪并且存储响应式数据的值(包括对象),当响应式对象变化时会自动追踪更新视图;
 如果将一个对象类型赋值给 ref(),那么这个对象将通过 reactive() 转为具有深层次响应式的对象。这也意味着如果对象中包含了嵌套的 ref,它们将被深层地解包
 如图:
 
2、ref使用
ref() 接收的数据,在js中使用需要.value作为唯一的键引用,而在模板中使用只需要直接使用即可,不需要再.value,因vue模板会自动解析ref类型数据;
 如图:
<template>
	 年龄:{{ age }}
	 <br>
	 姓名:{{ name }}
</template>
<script setup>
	import { ref,  reactive, computed, onMounted, onActivated, unref } from 'vue'
	const age = ref(0)
	const name = ref('Andy')
	onMounted(() => {
	  console.log('==age==', age.value)
	  console.log('==name==', name.value)
	})
</script>
3、ref() 接收对象类型时
ref() 接收的对象类型若要里面的属性保持响应式,需要使用.value的方式进行单个属性赋值,如果将声明对象整体赋值,则会导致响应式失效,如:unNormalMan
  unNormalMan{{ JSON.stringify(unNormalMan) }}
  <br>
  <button @click="handleChangeNormal">unNormalMan</button>
  // 声明为响应式对象
let unNormalMan = ref({
  job: '不知道',
  love: '猜猜'
})
// 整体赋值后变成普通对象,视图不会更新
const handleChangeNormal = () => {
  unNormalMan = {
    a: '111',
    b: '222'
  }
  console.log('=handleChangeNormal==unNomalMan', unNormalMan)
  console.log('=change=unRef', unref(unNormalMan))
}

// .value 形式单个赋值可以保持响应式
const person = ref({
  job: '搬砖',
  love: '象棋'
})
const handleChangeJOb = () => {
  person.value.job = person.value.job + '$'
  const { job } = person.value
  console.log('===job=', job) // 搬砖$ 同样页面视图也会更新
}

4、ref() 优缺点
响应式数据:ref函数可以让我们轻松地创建响应式数据,无需使用Vue2中的data选项或this关键字。
 支持所有类型:与Vue2的data选项不同,ref函数可以用于创建任何类型的响应式数据,包括对象和数组。
 逻辑复用灵活:通过使用ref函数,我们可以更容易地在不同的组件和逻辑块之间共享和复用状态。
 注意:
 使用 ref 函数创建的响应式数据,在修改值时,必须通过 .value 属性来访问和修改。
 ref 函数返回的响应式引用对象是不可变的,即你不能将新的值赋给整个引用对象,而只能通过 .value 属性来修改内部的值。
 ref 函数可以用于创建任何类型的响应式数据,包括基本类型、对象、数组等。
5、ref其他属性 isRef unRef shallowRef triggerRef customRef ,toRef toRefs 下节结合reactive 介绍
5.1、isRef() 判断一个对象或者值是否为ref类型,返回一个布尔值
const personMen = ref('优秀的')
console.log(isRef(personMen)) // true
const norefObj = {a:'333'}
console.log(isRef(norefObj)) // false
5.2、unref() 传入的对象如果是ref() 值或对象,则会返回 person.vue d的代理对象proxy;相反,如果是普通的对象或值,则会原样返回
 如图:
let unNormalMan = ref({
  job: '不知道',
  love: '猜猜'
})
console.log('=000=unRef', unref(unNormalMan))
// Proxy:{...}
const per = '测试'
console.log(unref(per)) // 测试
5.3、shallowRef()
 浅层的响应式声明,只针对.value进行响应式,而不会进行深层次的递归,即.value.xxx 不是响应式的,主要针对的是复杂类型的数据结构,
 如:
const pet = shallowRef({
  job: '专业搬砖'
})
pet.value = { job: '躺平梦想'} // 会触发视图更新,响应式的
pet.value.job = '响应不了' // 不是响应式的,
5.4、triggerRef
 强制触发依赖于浅层的Ref副作用,triggerRef() 会使浅层的响应式突变为深层的响应式,强制更新视图,比如使用shallowRef 处理的对象,响应式只能是浅层的,如果想要值更改时候也发生变化,则需要如下
const perObj = shallowRef({
  job: '测试'
})
const handleChangePerObj = () => {
  perObj.value.job = '搬砖的'
  triggerRef(perObj) // 这样在模板中使用的 {{ perObj.job }} 会更新为 “搬砖的”,如果不使用 triggerRef() 则不会更新视图
}
5.5、customRef
 创建一个工厂函数,显示的声明对其依赖追踪触发的控制条件;
 即:创建的工厂函数中返回 set() get() 方法对象,通过set()自主控制触发时机,比如防抖
 防抖代码:
import { customRef } from 'vue'
export function useDebouncedRef(value, delay = 500) {
  let timeout
  return customRef((track, trigger) => {
    return {
      get() {
        track()
        return value
      },
      set(newValue) {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          value = newValue
          trigger()
        }, delay)
      }
    }
  })
}
// 使用如下:
<script setup>
import { useDebouncedRef } from './debouncedRef'
const myRefVal = useDebouncedRef('测试防抖')
</script>
<template>
  <input v-model="myRefVal" />
</template>















![[Java、Android面试]_01_多线程: 重要参数、状态、优雅停止线程等](https://img-blog.csdnimg.cn/direct/0fdb6b6755854f9faea737c8cb81b87c.png)



