vue3-响应式基础之ref

声明响应式状态

ref()

在组合式 API 中,推荐使用 ref() 函数来声明响应式状态: ref() 接收参数,并将其包裹在一个带有 .value 属性的 ref 对象中返回:

import { ref } from 'vue'
const count = ref(0)

console.log(count) // { value: 0 }
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

形式1 setup() 函数

  1. 要在组件模板中访问 ref,请从组件的 setup() 函数中声明并返回它们:

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

export default {
    setup() {
        const count = ref(0)

        function increment() {
            // 在 JavaScript 中需要 .value
            count.value++
        }

        // 不要忘记同时暴露 increment 函数
        return {
            count,
            increment
        }
    }
}
</script>

<template>
    <div class="container">
        <div>{{ count }}</div>
        <button @click="count++">
            {{ count }}
        </button>
    </div>
</template>

<style  scoped>
.container {}
</style>
  1. 注意,在模板中使用 ref 时,我们不需要附加 .value。为了方便起见,当在模板中使用时,ref 会自动解包 (有一些注意事项)。

在模板渲染上下文中,只有顶级的 ref 属性才会被解包。

在下面的例子中,count 和 object 是顶级属性,但 object.id 不是:

const count = ref(0)
const object = { id: ref(1) }

//模版正常渲染执行
{{ count + 1 }} 

//模版不会正常渲染非顶级不会被解包仍然是一个ref
{{ object.id + 1 }}  对象


//我们可以将 id 解构为一个顶级属性
const { id } = object
{{ id + 1 }}   //模版正常渲染并执行

//模版自动解包
{{ object.id }}
该特性仅仅是文本插值的一个便利特性,等价于 {{ object.id.value }}

形式2 <script setup>

  • 在 setup() 函数中手动暴露大量的状态和方法非常繁琐。

  • 幸运的是,我们可以通过使用单文件组件 (SFC) 来避免这种情况。我们可以使用 <script setup> 来大幅度地简化代码:

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

const count = ref(0)

function increment() {
    count.value++
}
</script>

<template>
    <button @click="increment">
        {{ count }}
    </button>
</template>

深层响应性

  • Ref 可以持有任何类型的值,包括深层嵌套的对象、数组或者 JavaScript 内置的数据结构,比如 Map。

  • Ref 会使它的值具有深层响应性。这意味着即使改变嵌套对象或数组时,变化也会被检测到:

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

const count = ref(0)
const obj = ref({
    nested: { count: 0 },
    arr: ['foo', 'bar']
})

function mutateDeeply() {
    // 以下都会按照期望工作
    obj.value.nested.count++
    obj.value.arr.push('baz')
}


function increment() {
    count.value++
}
</script>

<template>
    {{ obj.arr }}
    <button @click="mutateDeeply">
        {{ obj.nested.count + 1 }}
    </button>
</template>

shallow ref

可以通过 shallow ref 来放弃深层响应性

  1. 减少大型不可变数据的响应性开销

  2. 与外部状态系统集成

DOM 更新时机

  • 当你修改了响应式状态时,DOM 会被自动更新。但是需要注意的是,DOM 更新不是同步的。

  • Vue 会在“next tick”更新周期中缓冲所有状态的修改,以确保不管你进行了多少次状态修改,每个组件都只会被更新一次。

要等待 DOM 更新完成后再执行额外的代码,可以使用 nextTick() 全局 API:

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

const count = ref(0)

async function increment() {
    count.value++

    console.log(document.querySelector('button')?.textContent);
    // 这里会立即打印 '0'
    await nextTick()
    // 现在 DOM 已经更新了
    console.log(document.querySelector('button')?.textContent);
    // 这里会立即打印 '1'
}
</script>

<template>
    <button @click="increment">
        {{ count }}
    </button>
</template>
  • 31
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值