vue.js 当使用'ref'而不是'reactive'时,如何使数组中的单个属性成为reactive?

qij5mzcb  于 2023-02-05  发布在  Vue.js
关注(0)|答案(1)|浏览(162)

我有一个显示数据行的组件,我想切换显示或隐藏细节。这是它应该看起来:

这是通过将数据Map到一个新数组并添加一个opened属性来完成的。

<script setup>
import { defineProps, reactive } from 'vue';

const props = defineProps({
  data: {
    type: Array,
    required: true,
  },
  dataKey: {
    type: String,
    required: true,
  },
});

const rows = reactive(props.data.map(value => {
  return {
    value,
    opened: false,
  };
}));

function toggleDetails(row) {
  row.opened = !row.opened;
}
</script>

<template>
  <div>
    <template v-for="row in rows" :key="row.value[dataKey]">
      <div>
        <!-- Toggle Details -->
        <a @click.prevent="() => toggleDetails(row)">
          {{ row.value.key }}: {{ row.opened ? 'Hide' : 'Show' }} details
        </a>

        <!-- Details -->
        <div v-if="row.opened" style="border: 1px solid #ccc">
          <div>opened: <pre>{{ row.opened }}</pre></div>
          <div>value: </div>
          <pre>{{ row.value }}</pre>
        </div>
      </div>
    </template>
  </div>
</template>

但是,我不想让Array具有很强的React性,所以我尝试使用ref,只让opened具有React性:

const rows = props.data.map(value => {
  return {
    value,
    opened: ref(false),
  };
});

function toggleDetails(row) {
  row.opened.value = !row.opened.value;
}

属性opened现在是完全被动的,但是切换不再起作用:

我怎样才能让这个开关工作,而不使整个价值React?

fruv7luv

fruv7luv1#

问题似乎来自Vue将ref替换为它的值。
row.opened是初始化为ref(false)的ref时,模板表达式如下:

{{ row.opened ? 'Hide' : 'Show' }}

似乎被解释为(字面上)

{{ false ? 'Hide' : 'Show' }}

不如预期的(比喻):

{{ row.opened.value ? 'Hide' : 'Show' }}

但是如果我像上面那样写(用.value),它就能工作。
if也是一样,如果我这样做,它就工作:

<div v-if="row.opened.value">

有趣的是,这种行为发生在v-if和三元组中,但不发生在直接访问上,即{{ rows[0].opened }}是React式的,而{{ rows[0].opened ? "true" : "false" }}不是,这似乎是Vue的表达式解析器的问题,here也有类似的问题。

相关问题