为什么非反应变量在 Vue3 中表现得很奇怪?

Why does non-reactive variable behave strange in Vue3?

提问人:James 提问时间:11/3/2023 最后编辑:VLAZJames 更新时间:11/10/2023 访问量:71

问:

代码如下

<template>
  <input type="button" value="click" @click="clickBtn"/>
  <div id="reactiveDiv">{{ reactiveVariable }}</div>
  <div id="noneReactiveDiv">{{ noneReactiveVariable }}</div>
</template>

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

const reactiveVariable = ref('reactive')

let noneReactiveVariable = 'non reactive '

function clickBtn(){
  reactiveVariable.value = (new Date().getTime()).toString()
  noneReactiveVariable = (new Date().getTime()).toString()

  nextTick(()=>{
    console.log('next tick')
  })
}

</script>

我有两个变量:reactiveVariable 是反应式的,noneReactiveVariable 不是。

我的问题是:

  1. 当我单击该按钮时,模板中的两个变量都会更改。我认为不应该更改 noneReactiveVariable,因为它是在没有 ref 或反应式关键字的情况下定义的。我的猜测是反应变量 reactiveVariable 的值更改导致模板更新,也导致模板中的 noneReactiveVariable 更改。我不确定。

  2. 如果我像这样更改模板:

<template>
  <input type="button" value="click" @click="clickBtn"/>
  <div id="noneReactiveDiv">{{ noneReactiveVariable }}</div>
</template>

在这种情况下,当我单击该按钮时,模板中的 noneReactiveVariable 不会更改。现在看来还不错。但是我在函数clickBtn中有一个nextTick,当我单击按钮时,我可以看到控制台中的登录,这意味着UI或模板已更新。我认为如果模板已经更新,为什么模板中的noneReactiveVariable没有像以前一样改变,reactiveVariable的变化导致了noneReactiveVariable的变化?

更新: 我稍微更改了代码。现在,noneReactiveVariable 在 reactiveVariable 以外的另一个函数中发生了变化。但是 noneReactiveVariable 仍在更改,并在单击按钮时更新为 DOM。

<template>
    <input type="button" value="click" @click="clickBtn"/>
    <div id="reactiveDiv">{{ reactiveVariable }}</div>
    <div id="noneReactiveDiv">{{ noneReactiveVariable }}</div>
</template>

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

const reactiveVariable = ref('reactive')

let noneReactiveVariable = 'non reactive '

onMounted(()=>{
    setInterval(()=>{
        noneReactiveVariable = (new Date().getTime()).toString()
    },1000)
})

function clickBtn(){
    reactiveVariable.value = (new Date().getTime()).toString()

    nextTick(()=>{
        console.log('next tick')
    })
}

</script>

JavaScript vue.js vuejs3 反应式

评论


答:

2赞 Adi 11/3/2023 #1

所以我最近才开始使用 VueJs,但据我了解,当你使用“ref”或“reactive”创建的反应式变量时,Vue 会在内部跟踪它的依赖关系,允许它在反应式变量发生变化时自动更新模板。Vue 的反应式系统足够智能,可以检测反应变量的变化并触发模板的重新渲染。

在第一段代码中,reactiveVariable 和 noneReactiveVariable 都在模板中呈现。当 reactiveVariable 发生变化时,Vue 会检测到这种变化并更新模板的相应部分。

在第二段代码中,仅呈现 noneReactiveVariable。当 reactiveVariable 发生变化时,Vue 不依赖于 noneReactiveVariable,因此它不会触发模板中 noneReactiveVariable 的更新。

关于你的最后一个问题,我不确定功能,但据我通过阅读文档 https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick 了解。它用于等到下一个 DOM 更新周期后再执行提供的回调。即使调用了 nextTick,也不意味着模板会立即更新。它只是确保在更新 DOM 以响应当前状态更改后执行回调。因此,在您的情况下,console.log('next tick')将在DOM更新后执行,但由于noneReactiveVariable不是第二段代码中的反应式依赖项,因此它不会在更改时触发模板更新。nextTick

希望这有助于回答您的问题。

评论

0赞 James 11/3/2023
关于这个:在第一段代码中,reactiveVariable 和 noneReactiveVariable 都在模板中呈现。当 reactiveVariable 发生变化时,Vue 会检测到这种变化并更新模板的相应部分。noneReactiveVariable 不是反应式的,因此即使它是用反应式渲染的,也不应该改变它。
0赞 James 11/3/2023
你说,“console.log('next tick')将在DOM更新后执行,但是noneReactiveVariable不是你的第二段代码中的反应式依赖项,它不会在更改时触发模板更新。在第一段代码中,Dom 也已更新。有什么不同?如果一个非反应变量与其他反应变量在一起,它可以改为反应变量吗?
0赞 Adi 11/3/2023
因此,当您单击该按钮时,将调用 clickBtn 方法,并且在此方法中,您将同时更新 reactiveVariable 和 noneReactiveVariable。即使 noneReactiveVariable 不是反应式的,它也会在更新反应式变量的方法中被访问。因此,Vue.js 会触发一个反应性循环,导致模板重新渲染并显示更新的值 noneReactiveVariable。reactiveVariable
0赞 James 11/3/2023
因此,如果以不同的方法更改了 noneReactiveVariable,它就不会被更改,对吧?
1赞 Adi 11/3/2023
哦,我明白了,所以我想 noneReactiveVariable 似乎在 DOM 中更改和更新是因为 setInterval 函数每秒都在不断更新其值。但我相信 noneReactiveVariable 的值会发生变化,它不会导致模板中的反应性更新,因为它不是反应式变量