vue3-响应式基础之ref

发布时间:2024年01月12日

声明响应式状态

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>
文章来源:https://blog.csdn.net/wdk996/article/details/135541350
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。