首页 > 解决方案 > 类中的vue3反应性

问题描述

我试图在一个类中拥有一个反应属性,所以这就是我所做的:

Class B{
  index = ref(-1);

  canUndo: ComputedRef<boolean>;

  canRedo: ComputedRef<boolean>;

  constructor(private max: number) {
    this.canUndo = computed(() => {
      return this.index.value > -1;
    });
    this.canRedo = computed(() => {
      const { length } = this.items;
      return length > 0 && this.index.value < length - 1;
    });
  }

  undo() {
    console.log(this.canUndo); // -> true
    console.log(this.canUndo.value); // -> undefined
    if (!this.canUndo.value) return false;

    console.log(this.index); // -> 1
    this.index.value -= 1;
    return this.items.slice(0, this.index.value + 1);
  }
  
}

// this is how I use it
class A{
  b:B;

  undo(){ this.b.undo() }
}

export default defineComponent({
  setup(){
    const a= ref<A>();

    function initA() {
      a.value = new A();
    }

    return { a };
  }
});
<BaseButton
        :disabled="!a.b.canUndo"
        color="light" size="sm" @click="a.undo()"
        start-icon="undo"></BaseButton>

我原以为这会起作用,但我看到了一个奇怪的行为!
this.canUndoboolean我期望的地方ComputedRef<boolean>,因此this.canUndo.valueundefined

也一样this.index?!?

为什么?难道我做错了什么?这是一个错误吗?

更新基于@tony19 的回答:组件实际上是这样的:

export default defineComponent({
  setup(){
    const elRef = ref<HTMLElement>();
    const a = ref<A>();

    function initA() {
      a.value = new A(elRef);
    }

    onMounted(initA);

    return { a };
  }
});

我不能做任何建议的解决方法因为我需要一个元素 ref 来实际启动类,所以它需要在onMounted钩子中启动。

标签: javascripttypescriptvue.jsvuejs3vue-reactivity

解决方案


我认为这与refs 如何在模板中自动展开有关,setup()docs中所述。这似乎包括ref在类的方法中展开 s 。

一种解决方法是将原始实例公开给模板。它不需要是 a ref,除非您计划更改它的值(例如,更改为 的新实例A):

export default defineComponent({
  setup() {
    //const a = ref<A>(new A())
    const a = new A()

    return { a }
  }
})

如果您确实需要保留 a ref,则可以将aref与原始文件一起公开:

export default defineComponent({
  setup() {
    const rawA = new A()
    const a = ref<A>(rawA)

    return { a, rawA }
  }
})

然后在您的模板中,将原始用于任何具有refs 的方法:

<BaseButton @click="rawA.undo()">

推荐阅读