Vue3浅谈:(一)Vue3响应式基础

目录

一、Vue3响应式基础

1.声明响应式状态

2.DOM 更新时机

3.深层响应性和浅层响应性

4.响应式代理 vs. 原始对象

5.用 ref() 定义响应式变量


一、Vue3响应式基础

1.声明响应式状态

我们可以使用 reactive() 函数创建一个响应式对象或数组入过想要使用,可以在setup() 函数中定义并返回。

<script>
import { reactive } from "vue";
export default {
  // `setup` 是一个专门用于组合式 API 的特殊钩子函数
  setup() {
    let oneNumber = reactive({ count: 0 });
    function add() {
      oneNumber.count++;
    }
    // 暴露 state 到模板
    return {
      oneNumber,
      add,
    };
  },
};
</script>
<template>
  <button @click="add">
    {
    
    { oneNumber.count }}
  </button>
</template>
<style scoped></style>

在 setup() 函数中手动暴露大量的状态和方法非常繁琐,因此我们可以使用<script setup>来简化代码,如下:

<script setup>
import { reactive } from "vue";
let oneNumber = reactive({ count: 0 });
function add() {
  oneNumber.count++;
}
</script>

<template>
  <button @click="add">
    {
    
    { oneNumber.count }}
  </button>
</template>

2.DOM 更新时机

当更改响应式状态后,DOM 会自动更新。然而DOM 的更新并不是同步的。相反,Vue 将缓冲它们直到更新周期的 “下个时机” 以确保无论你进行了多少次状态更改,每个组件都只更新一次。若要等待一个状态改变后的 DOM 更新完成,可以使用 这个全局 API

<script setup>
import { reactive, nextTick } from "vue";
let oneNumber = reactive({ count: 0 });
function add() {
  oneNumber.count++;
  console.log(document.getElementById("addBtn").textContent);
  nextTick(() => {
    // 访问更新后的 DOM
    console.log(document.getElementById("addBtn").textContent);
  });
}
</script>

<template>
  <button @click="add" id="addBtn">
    {
    
    { oneNumber.count }}
  </button>
</template>

显而易见的是,当执行add时,访问dom的内容是操作count之前的值,在nextTick之后才为count更新后的值

3.深层响应性和浅层响应性

深层响应性:

在 Vue 中,状态都是默认深层响应式的。这意味着即使在更改深层次的对象或数组,改动也能被检测到。

<script setup>
import { reactive } from "vue";
let oneNumberObj = reactive({
  nested: { count: 0 },
  arr: ["hello", "vue3"],
});

function add() {
  oneNumberObj.nested.count++;
  oneNumberObj.arr[0] = "ts" + oneNumberObj.nested.count;
}
</script>

<template>
  <button @click="add" id="addBtn">
    {
   
   { oneNumberObj.nested.count }}--{
   
   { oneNumberObj.arr[0] }}
  </button>
</template>

显而易见的是,当执行add时,count和arr都可以做出相应

浅层响应性:

一个浅层响应式对象里只有根级别的属性是响应式的。

<script setup>
import { reactive,shallowReactive } from "vue";
let oneNumberObjShallow = shallowReactive({
  nested: { count: 0 },
  arr: ["hello", "vue3"],
});
function add() {
  oneNumberObjShallow.nested.count++;
  oneNumberObjShallow.arr[0] = "ts" + oneNumberObjShallow.nested.count;
}
</script>

<template>
  <button @click="add" id="addBtn">
    {
   
   { oneNumberObjShallow.nested.count }}--{
   
   { oneNumberObjShallow.arr[0] }}
  </button>
</template>

显而易见的是,当执行add时,count和arr不可以做出相应

4.响应式代理 vs. 原始对象

reactive() 返回的是一个原始对象的 Proxy,它和原始对象是不相等的。

只有代理对象是响应式的,更改原始对象不会触发更新。因此,使用 Vue 的响应式系统的最佳实践是 仅使用你声明对象的代理版本

对同一个原始对象调用 reactive() 会总是返回同样的代理对象,而对一个已存在的代理对象调用 reactive() 会返回其本身

如下:

<script setup>
import { reactive } from "vue";
let oneNumber = { count: 0 };
let proxy = reactive(oneNumber)
function addProxy() {
  proxy.count++;
  console.log(proxy === oneNumber) //false
  console.log(reactive(oneNumber) === proxy) //true
  console.log(reactive(proxy) === proxy) //true

}
</script>

<template>
  <button @click="addProxy">
    {
   
   { proxy.count }}
  </button>
</template>

5.用 ref() 定义响应式变量

reactive()仅对对象类型有效,因此我们可以使用ref() 来允许我们创建可以使用任何值类型的响应式 

ref() 将传入参数的值包装为一个带 .value 属性的 ref 对象

当 ref 在模板中作为顶层属性被访问时,它们会被自动“解包”,所以不需要使用 .value

跟响应式对象不同,当 ref 作为响应式数组或像 Map 这种原生集合类型的元素被访问时,不会进行解包。

如下:

<script setup>
import { ref,reactive } from 'vue'
const oneNumber = ref(0)
const oneStr = reactive([ref('Vue3')])
function add() {
  oneNumber.value++
}
</script>

<template>
  <button @click="add">
    {
   
   { oneNumber }} <!-- 无需 .value -->
  </button>
  <div>{
   
   { oneStr[0].value }}</div>

</template>

有问题可以在下面评论,我会为大家解答。

猜你喜欢

转载自blog.csdn.net/samxiaoguai/article/details/128472892
今日推荐