vue3学习记录-ref

vue3学习记录-ref

  • [1.未包裹ref 或则 rective 的变量不是响应式的](#1.未包裹ref 或则 rective 的变量不是响应式的)
  • [2.ref, Ref, isRef](#2.ref, Ref, isRef)
  • 3.shallowRef
  • 4.triggerRef
  • 5.customRef
    • [5.1 防抖 ref](#5.1 防抖 ref)
    • [5.2 节流ref](#5.2 节流ref)
    • [5.3 与本地存储同步的响应式变量](#5.3 与本地存储同步的响应式变量)

1.未包裹ref 或则 rective 的变量不是响应式的

javascript 复制代码
<script setup lang="ts">
//未包裹ref 或则 rective 的变量不是响应式的
let message: string = 'Hello Vite + Vue 3 + TypeScript!'
const changeMsg = () => {
  message = 'Hello Vite + Vue 3 '
  console.log(message)
}
</script>

<template>
<el-button @click="changeMsg">改变</el-button>
<span>message:{{ message }}</span>
</template>

<style scoped>

</style>

2.ref, Ref, isRef

javascript 复制代码
<script setup lang="ts">
//isRef
import { ref, Ref, isRef } from 'vue'
const msg: Ref<string> = ref('Hello Vite + Vue 3 + TypeScript!')
const notref: number = 999
const demo = ref<String>('Hello Vite')
const changeMsg2 = () => {
  msg.value = 'Hello Vite + Vue 3 '
  console.log(msg.value)
  console.log('demo', demo)
  console.log(isRef(msg))
  console.log(isRef(notref))
}
</script>

<template>
  <el-button @click="changeMsg2">isRef</el-button>
  <span>msg:{{ msg }}</span>
</template>

<style scoped></style>

3.shallowRef

shallowRef 是 Vue 3 中的一个响应式 API,用于创建一个浅层响应式引用。它的主要作用是只让引用的值本身变为响应式,而不会递归地使其内部属性变为响应式。这在处理大型对象或需要优化性能时特别有用。

javascript 复制代码
<template>
  <div>
    <p>名字: {{ user.name }}</p>
    <p>年龄: {{ user.age }}</p>
    <button @click="updateName">更新名字</button>
    <button @click="updateAge">更新年龄</button>
  </div>
</template>

<script setup lang="ts">
import { shallowRef,Ref } from 'vue'
type Obj = {
  name:string,
  age:number
}

const user:Ref<Obj> = shallowRef({
  name: '张三',
  age: 25
})

function updateName() {
  user.value.name = '李四'  // 这不会触发视图更新
  console.log('名字已更新,但视图不会立即反应',user)
}

function updateAge() {
  user.value = { ...user.value, age: 26 }  // 这会触发视图更新
  console.log('年龄已更新,视图会更新',user)
}
</script>

让我们考虑一个场景,我们需要处理一个包含大量数据的用户配置文件。

javascript 复制代码
<template>
  <div>
    <h1>用户配置文件</h1>
    <p>用户名: {{ userProfile.username }}</p>
    <p>邮箱: {{ userProfile.email }}</p>
    <button @click="updateEmail">更新邮箱</button>
    <button @click="refreshProfile">刷新整个配置文件</button>
    
    <!-- 假设这是一个很大的列表 -->
    <h2>用户偏好</h2>
    <ul>
      <li v-for="(value, key) in userProfile.preferences" :key="key">
        {{ key }}: {{ value }}
      </li>
    </ul>
  </div>
</template>

<script setup>
import { shallowRef } from 'vue'

// 模拟一个大型用户配置文件对象
const userProfile = shallowRef({
  username: '张三',
  email: 'zhangsan@example.com',
  preferences: {
    theme: 'dark',
    fontSize: 'medium',
    language: 'zh-CN',
    notifications: true,
    // ... 假设这里有成百上千的偏好设置
  },
  friends: [
    // ... 假设这里有一个很长的朋友列表
  ],
  posts: [
    // ... 假设这里有用户的所有帖子
  ],
  // ... 其他大量数据
})

function updateEmail() {
  // 这不会触发整个对象的响应式更新
  userProfile.value.email = 'newemail@example.com'
  console.log('邮箱已更新,但视图不会立即反应')
}

function refreshProfile() {
  // 这会触发整个对象的响应式更新
  userProfile.value = {
    ...userProfile.value,
    email: 'refreshed@example.com',
    // 在实际应用中,这里可能是从服务器获取的新数据
  }
  console.log('整个配置文件已刷新,视图会更新')
}
</script>

在这个例子中:

  1. 性能优化:使用 shallowRef 创建 userProfile,避免了对整个大型对象进行深层响应式转换。这对性能有显著影响,特别是当对象包含大量嵌套数据时。
  2. 选择性更新:updateEmail 函数演示了如何更新单个属性而不触发整个对象的响应式更新。这在频繁更新小部分数据时非常有用,可以避免不必要的渲染。
  3. 完整刷新:refreshProfile 函数展示了如何在需要时更新整个对象。这适用于从服务器获取新的完整配置文件数据的情况。
  4. 大型数据处理:用户偏好、朋友列表和帖子等大型数据集合被包含在对象中,但不会被递归地转换为响应式。这大大减少了内存使用和初始化时间。
  5. 视图更新控制:只有当整个 userProfile 对象被替换时(如在 refreshProfile 中),视图才会完全更新。这给了开发者更多控制,可以选择何时触发大规模的视图更新。

这种方法的优势:

初始化速度更快:对于大型对象,避免深层响应式转换可以显著减少初始化时间。 内存使用更少:不会为每个嵌套属性创建响应式包装器。

更好的性能:减少了不必要的响应式更新和重新渲染。 更精确的控制:开发者可以决定何时更新整个对象,从而触发视图更新。

在实际应用中,这种方法特别适用于处理大型配置对象、复杂的数据模型或需要频繁更新的大型数据集。它允许您在保持响应式能力的同时,最小化性能开销。

4.triggerRef

主要用于手动触发 shallowRef 或 customRef 的更新。它的作用是强制触发依赖于该 ref 的副作用(如计算属性或监听器)重新运行,并更新相关的视图。

javascript 复制代码
<template>
  <div>
    <h2>用户信息</h2>
    <p>名字: {{ user.name }}</p>
    <p>年龄: {{ user.age }}</p>
    <p>计算属性 - 成年: {{ isAdult }}</p>
    <button @click="updateAge">更新年龄</button>
    <button @click="forceUpdate">强制更新</button>
  </div>
</template>

<script setup lang="ts">
import { shallowRef, computed, triggerRef,Ref } from 'vue'
type Obj ={
  name: string,
  age: number
}
const user:Ref<Obj>  = shallowRef({
  name: '张三',
  age: 17
})

const isAdult = computed(() => {
  console.log('计算属性被重新计算')
  return user.value.age >= 18
})

function updateAge() {
  user.value.age = 18
  console.log('年龄已更新,但视图和计算属性不会自动更新')
}

function forceUpdate() {
  triggerRef(user)
  console.log('强制更新触发,视图和计算属性将更新')
}
</script>

使得原本的shallowRe不能更新视图的写法能强制更新视图了。

5.customRef

customRef 是 Vue 3 中的一个高级响应式 API,它允许你创建一个自定义的响应式引用,完全控制其依赖追踪和更新触发行为。这个 API 提供了极大的灵活性,使你能够实现复杂的响应式逻辑。

5.1 防抖 ref

创建一个防抖 ref,即只在最近一次 set 调用后的一段固定间隔后再调用

javascript 复制代码
<template>
  <div>
    <input v-model="searchQuery" placeholder="输入搜索词" />
  </div>
</template>

<script setup>
import { customRef } from 'vue'

function useDebouncedRef(value, delay = 500) {
  let timeout
  return customRef((track, trigger) => {
    return {
      get() {
        track()
        return value
      },
      set(newValue) {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          console.log('触发了set')
          value = newValue
          trigger()
        }, delay)
      }
    }
  })
}
const searchQuery = useDebouncedRef('search')
</script>

5.2 节流ref

javascript 复制代码
function throttlingCustomRef(value,delay = 200){
  let lastCall = 0
  return customRef((track,trigger)=>{
    return {
      get(){
        track()
        return value
      },
      set(newValue){
        const now = Date.now()
        if(now - lastCall >= delay){
          value = newValue
          lastCall = now
          trigger()
        }
      }
    }
  })
}

5.3 与本地存储同步的响应式变量

创建一个自动与 localStorage 同步的响应式引用。

javascript 复制代码
import { customRef } from 'vue'

function useLocalStorageRef(key, defaultValue) {
  return customRef((track, trigger) => ({
    get() {
      track()
      const value = localStorage.getItem(key)
      return value !== null ? JSON.parse(value) : defaultValue
    },
    set(newValue) {
      localStorage.setItem(key, JSON.stringify(newValue))
      trigger()
    }
  }))
}

// 使用示例
const username = useLocalStorageRef('username', '')

还有很多很多的自定义ref

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