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

相关推荐
栈老师不回家6 分钟前
Vue 计算属性和监听器
前端·javascript·vue.js
芊寻(嵌入式)7 分钟前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
前端啊龙12 分钟前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
一颗松鼠16 分钟前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
小远yyds36 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
hong16168844 分钟前
跨模态对齐与跨领域学习
学习
程序媛小果1 小时前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
小光学长1 小时前
基于vue框架的的流浪宠物救助系统25128(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
数据库·vue.js·宠物
阿伟来咯~1 小时前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端2 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js