将 b-table 的每个单元格中的文本切换到输入框并返回

Switching text in each cell of a b-table to input box and back

vue 新手,到目前为止我很喜欢它。 基本上尝试使用 BV tables 创建一个 excel 像 table 布局。当我单击单元格文本时,我希望将其替换为输入框并恢复为模糊文本。据我所知,排序对输入字段不起作用,因此隐藏似乎是最好的选择。

此代码在技术上有效(不知道如何在 SO 的代码编辑器中实际 运行),但我试图不为每个字段设置一个 isHidden 字段。目前我需要 isHiddenStartTime 和 isHiddenEndTime 加上 1 为每个其他领域。考虑到一次只有 1 个需要标志,这看起来很乱。

new Vue({
  el: "#app",
  data() {
    return {
      fields: [
        {
          key: 'startTime',
          sortable: true
          },
        {
          key: 'endTime',
          sortable: true
        }
      ],
      port: [
        {
          "portNumber": 1,
          "startTime": "00:00:00.00",
          "endTime": "21:59:59.01",
          "isHidden": false,
          "hiddenType": ""
        }, 
        {
          "portNumber": 7,
          "startTime": "00:00:00.00",
          "endTime": "22:59:59.00",
          "isHidden": false,
          "hiddenType": ""
        }
      ]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.5.0/dist/bootstrap-vue.js"></script>

<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css" />

<div id="app">
  <b-table  :items="port" :fields="fields" striped fixed responsive="sm">
    <template v-slot:cell(endTime)="{ item }">
      <div v-if="!item.isHidden" @click="item.isHidden = true">
        {{ item.endTime }}
      </div>
      <div v-else>
        <b-form-input 
          v-model="item.endTime" 
          @blur="item.isHidden = false" 
          placeholder="Enter end time" 
          autofocus
        ></b-form-input>
      </div>
    </template>
  </b-table>
</div>

我尝试添加一个 hiddenType,其中包含单击时添加的字段名称,但在单击之前添加了 v-if 运行s。如果我使用相同的标志 (port.isHidden),整行都会改变。如果我将标志放在字段中,整个列都会改变。考虑到它是一个列表,我看不到使用 ref 的正确方法。

再一次,新观点,所有问题都有意义,我只是找不到一个干净的方法来让它工作。

您可以为每个字段创建一个 isHidden 属性,而不是创建一个包含您正在编辑的当前字段的 属性。

在下面的示例中,我创建了一个 isEditingField 属性 并将其设置为列的 key,因此 startTimeendTime。然后在模糊时,我只需使用 $delete.

再次从对象中删除 属性

如果对象上尚不存在新的 属性,请务必使用 $set 创建新的 属性,否则它不会反应。您可以在 [此处] 阅读更多相关信息。(https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats)

您可能还会注意到我在使用 v-slot:cell() 时没有指定字段。这是因为它是一个后备插槽,用于放置所有未专门放置的字段。因此,在这种情况下,它将计入所有插槽,而无需为每个插槽创建一个特定插槽。

new Vue({
  el: "#app",
  data() {
    return {
      fields: [
        {
          key: 'startTime',
          sortable: true
          },
        {
          key: 'endTime',
          sortable: true
        }
      ],
      port: [
        {
          "portNumber": 1,
          "startTime": "00:00:00.00",
          "endTime": "21:59:59.01",
          "hiddenType": ""
        }, 
        {
          "portNumber": 7,
          "startTime": "00:00:00.00",
          "endTime": "22:59:59.00",
          "hiddenType": ""
        }
      ]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.5.0/dist/bootstrap-vue.js"></script>

<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css" />

<div id="app">
  <b-table  :items="port" :fields="fields" striped fixed responsive="sm">
    <template v-slot:cell()="{ item, field: { key } }">
      <div v-if="item.isEditingField == key">
        <b-form-input 
          v-model="item[key]" 
          @blur="$delete(item, 'isEditingField')" 
          placeholder="Enter end time" 
          autofocus
        ></b-form-input>
      </div>
      <div v-else @click="$set(item, 'isEditingField', key)">
        {{ item[key] }}
      </div>
    </template>
  </b-table>
</div>