展开类中声明的ref变量-vue 3

zpgglvta  于 2023-11-21  发布在  Vue.js
关注(0)|答案(1)|浏览(187)

在Vue 3中,我创建了几个类,其中包含ref和computed值,例如:

class BaseBlock {
  id = "XXXXX"

  run = ref(false)
  disabled = ref(false)
  alarm = ref(false)
  ready = ref(false)
  energySaving = ref(false)
  resetNeed = ref(false)
  activeCycle = ref(false)

  n0 = {
    status: ref(false),
    sigla: "XXX",
    title: "Alarm 0",
    description: "Alarm 0 is active",
    action: "Contact Saiet Engineering Customer Care",
    color: COLORS.red,
  }
  n1 = {
    status: ref(false),
    sigla: "XXX",
    title: "Alarm 1",
    description: "Alarm 1 is active",
    action: "Contact Saiet Engineering Customer Care",
    color: COLORS.red,
  }
  constructor(id) {
    this.id = id
    this.runText = `The element ${id} is running as expected`
    this.disabledText = `The element ${id} is currently DISABLED`

    // activeAlarms is a computed array that keeps all currently active alarms in priority order
    this.activeAlarms = computed(() => {
      let activeArray = [];
      for (let alarmId of this.alarmPriority) {
        if (this[alarmId].status.value) activeArray.push(alarmId)
      }
      return activeArray
    })
    // if there are active alarms, color will return the highest priority alarm color
    this.color = computed(() => {
      // disabled
      if (this.disabled.value) return COLORS.blue
      // running
      if (this.activeAlarms.value[0] == null) {
        if (this.run.value) return COLORS.green
        return 'white'
      }
      // alarms
      return this[this.activeAlarms.value[0]].color
    })
  }
}

字符串
注意在我的computed属性中,我是如何调用变量的.value来检查它是否是ref/computed的。
我不认为这有什么关系,但值得注意的是,这个类被其他类扩展,除了分配特殊值之外没有额外的计算,例如:

class Emergency extends BaseBlock {
  alarmPriority = ['n12', 'n13']
  alarms = ['n12', 'n13']

  constructor(id) {
    super(id)   
    Object.assign(
      this.n12, 
      {
        sigla: "SEM1",
        title: "Emergency Memory",
        description: "-",
        action: "-",
      }
    )
    Object.assign(
      this.n13, 
      {
        sigla: "SE1",
        title: "Emercency pushbutton",
        description: "Emergency pushbutton pressed",
        action: "Pull Emergency pushbutton",
      }
    )
  }
}


我的示例是在ref中创建的:

let blocks = ref({
  'MCP01': new MainCabinet('MCP01'),
  'CSW1': new LocalCabinet('CSW1'),
  'CSW2': new LocalCabinet('CSW2'),
  'CSW3': new LocalCabinet('CSW3'),
})


现在,假设我想在代码中的其他地方将blocks.value['MCP01'].run更改为true**,我期望做的是

blocks.value['MCP01'].run.value = true


但是这个不起作用,我需要做的是:

blocks.value['MCP01'].run = true


由于我没有从ref中更改.value,我希望我实际上完全替换了变量,因此失去了React性。情况并非如此:我的类在代码中的任何地方都保持(显然?)React性,甚至是我的计算属性。
我的问题是:这是怎么回事为什么我的ref会自动展开,就像我在模板里面一样?为什么React性不会中断(或者可能会中断,但我还没有意识到?)**
P.S.通过搜索类似的问题,我意识到vue的最佳实践是完全避免类,而是使用可组合的(例如,在我的示例中,useBaseBlock),但在这个项目中,这有点太晚了,而且我真的很想了解发生了什么。

sy5wg1nm

sy5wg1nm1#

如果给定了一个对象,ref会将其内部的所有ref展开。
从docs:
如果一个对象被赋值为一个ref的值,那么这个对象将与reactive()深度React。这也意味着如果这个对象包含嵌套的ref,那么它们将被深度展开。
为了避免深度转换,请使用shallowRef()
你可以在返回类型中看到这一点:Ref<UnwrapRef<T>>
因此let blocks = ref({ /* ... */ })创建了对象的ref,并将其内部的所有ref展开。因此,作为ref的属性现在在父ref中暴露为简单值,因此必须直接使用,而不是通过.value

相关问题