为什么普通常量仍然可以在Composition APIVue 3中使用?

问题描述

如官方documentation所述,在新的合成api setup方法中定义“ data”变量时,我们必须使用refreactive才能让Vue跟踪该特定变量的任何变化。

我正在试验反应性,但发现了奇怪的行为。 将此组件作为该组件的参考:

App.vue

<template>
  <div id="app">
    <p>{{ awesomeState.txt }}</p>
    <p>{{ myConst }}</p>
    <button @click="operate">Test it</button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import awesomeStore from "@/AwesomeStore";

export default defineComponent({
  setup() {
    const awesomeState = awesomeStore.getState();
    const myConst = "I'm a const"; // This should be const `myConst = ref('...');`
    return {
      awesomeState,myConst
    };
  },name: "App",methods: {
    operate() {
      this.myConst = 'Why this updates?';
      awesomeStore.changeText("yess!");
    }
  }
});
</script>

AwesomeStore.ts

import { reactive,readonly,watch } from "vue";

export abstract class Store<T extends Record<string,any>> {
  protected state: T;

  constructor() {
    const data = this.data();
    this.state = reactive(data) as T;
    watch(() => this.state,(value) => {
      console.log(value); debugger;
    },{deep: true});
  }

  protected abstract data(): T;

  public getState(): T {
    return readonly(this.state) as T;
  }
}

interface Test extends Object {
  txt: string;
}

class AwesomeClass extends Store<Test> {
  protected data(): Test {
    return {
      txt: "init"
    };
  }
  public changeText(msg: string) {
    this.state.txt = msg;
  }
}

export default new AwesomeClass();

当我单击按钮时,属性myConst被更新。 除了我不应该在setup()的范围之外定义方法之外,我不明白为什么会这样。

有人可以得到提示吗?

预先感谢

更新

我忘了提及,仅当我尝试使用awesomeStore.changeText方法修改常量时,暴露的行为才会发生:

operate() {
      this.myConst = 'Why this updates?';
      //awesomeStore.changeText("yess!"); <-- If commented,myConst do not update.
    }

解决方法

有两件事使它起作用

1)您使用的是方法而不是传递函数

您可以使用标准的Vue API from或composition API,例如:data:,methods:,etc...

您的示例同时使用了两者。 AFAIK,可以这样做,但是请注意setup()setup传递的方法的行为会有所不同。在一种方法中,您可以访问methods可变的this对象

myConst

如果您要使用此示例(如下),则更新 methods: { operate() { this.myConst = 'Why this updates?'; // <=== access to mutable variable in `this` awesomeStore.changeText("yess!"); } } 无效

myConst

2)您正在更新ref和static

另一个问题是您要更新静态值,然后再更新引用。更改ref将重新触发渲染,此时静态值将发生变化

因此,如果您通过存储删除更新,则应该不会再看到更新发生

setup(){
  const myConst = "I'm a const"; // This should be const `myConst = ref('...');`
  // ...stuff...
  return {
    awesomeState,myConst,operate: ()=>{
      this.myConst = 'Why this updates?'; // <=== nope
      myConst = 'Why this updates?';      // <=== also nope
      awesomeStore.changeText("yess!");
    }
  }
}

这是一个测试我的“理论”的游乐场

  methods: {
    operate() {
      this.myConst = 'Why this updates?';
      // awesomeStore.changeText("yess!"); // <== no ref change,no update
    }
  }
const {
  createApp,ref,} = Vue

createApp({
  el: '#app',setup() {
    let mystatic = 1
    const myref = ref(1)
    return {
      mystatic,myref,updateStatic: () => {
        mystatic++
      },updateRef: () => {
        myref.value++
      }
    }

  },methods: {
    updateStaticMethod() {
      this.mystatic++
    }
  }
}).mount('#app')

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...