Skip to content

Vue3-基础

1. 认识 ref 全家桶

1.1 ref

typescript
function ref<T>(value: T): Ref<UnwrapRef<T>>

interface Ref<T> {
  value: T
}

接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。

⚠️ 如果将一个对象赋值给 ref,那么这个对象将通过 reactive() 转为具有深层次响应式的对象。这也意味着如果对象中包含了嵌套的 ref,它们将被深层地解包。若要避免这种深层次的转换,请使用 shallowRef() 来替代。

无响应式数据,不能发生变化:

vue
<script setup lang="ts">
import { ref, reactive } from 'vue'

let msg = '我是App.vue'
const changeMsg = () => {
  msg = '我被改变了'
}
</script>

<template>
  <button @click="changeMsg">change</button>
  <div>{{ msg }}</div>
</template>

我们这样操作是无法改变 message  的值 应为 message 不是响应式的无法被 vue 跟踪要改成 ref

改为 ref

vue
<script setup lang="ts">
import { ref, reactive } from 'vue'

let msg = ref('我是App.vue')
const changeMsg = () => {
  msg.value = '我被改变了'
}
</script>

<template>
  <button @click="changeMsg">change</button>
  <div>{{ msg }}</div>
</template>

注意:被 ref 包装之后需要.value 来进行赋值

👉 调试技巧:

打开浏览器控制台 → 点击齿轮设置 → 在首选项中 → 勾选"启用自定义格式化程序"

未设置之前查看 ref 信息

设置之后查看信息

2. 认识 reactive 全家桶

2.1 reactive

用来绑定复杂的数据类型 例如 对象 数组 Map Set 等

为什么 reactive 只能绑定引用类型数据?

因为在源码中约束了数据类型

reactive 的基础用法

2.2 readOnly

拷贝一份 proxy 对象将其设置为只读

3. toRef, toRefs, toRaw

3.1 toRef

特点:

  • toRef 只能修改响应式对象的值, 非响应式对象无法修改.
  • 只能接受引用类型数据, 不能接受基本类型数据
  • 创建的 ref 与其源属性保持同步: 改变源属性的值将更新 ref 的值, 反之亦然。

toRef 一般用在把一个 prop 的 ref 传递给一个组合式函数, 即使源属性当前不存在,toRef() 也会返回一个可用的 ref。这让它在处理可选 props 的时候格外实用,相比之下 toRefs 就不会为可选 props 创建对应的 refs。

javascript
const useDemo = toRef(man, 'gender')

3.2 toRefs

描述: 将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。

特点:

  • 当从组合式函数中返回响应式对象时, toRefs 相当有用。使用它, 消费者组件可以解构/展开返回的对象而不会失去响应性;
  • toRefs 在调用时只会为源对象上可以枚举的属性创建 ref。如果要为可能还不存在的属性创建 ref, 请改用 toRef。

3.3 toRaw

描述:toRaw将一个响应式对象转换为其原始对象, 会丢失响应性。

特点:是一个可以用于临时读取而不引起代理访问/跟踪开销, 或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用, 请谨慎使用。

4. 组合式函数_hooks

“组合式函数”(Composables) 是一个利用 Vue 的组合式 API 来封装和复用有状态逻辑的函数。

一个鼠标坐标显示案例,如果我们要直接在组件中使用组合式 API 实现鼠标跟踪功能,它会是这样的:

vue
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const x = ref(0)
const y = ref(0)

function update(event) {
  x.value = event.pageX
  y.value = event.pageY
}

onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

但是,如果我们想在多个组件中复用这个相同的逻辑呢?我们可以把这个逻辑以一个组合式函数的形式提取到外部文件中:

ts
// mouse.ts
import { ref, onMounted, onUnmounted } from 'vue'

// 按照惯例,组合式函数名以“use”开头
export function useMouse() {
  // 被组合式函数封装和管理的状态
  const x = ref(0)
  const y = ref(0)

  // 组合式函数可以随时更改其状态。
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  // 一个组合式函数也可以挂靠在所属组件的生命周期上
  // 来启动和卸载副作用
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // 通过返回值暴露所管理的状态
  return { x, y }
}

下面是它在组件中使用的方式:

vue
<script setup>
import { useMouse } from './mouse.js'

const { x, y } = useMouse()
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>
Mouse position is at: 0, 0

更多的 demo 可查阅官网:https://cn.vuejs.org/guide/reusability/composables.html