Vue3 - Table 删除数组项后不更新,需要刷新页面才能看到效果

Vue3 - Table not updating after deleting an array item, need to refresh the page to see effect

我的 table 在我删除其中一个元素时没有更新。

我的 Vue 页面:

<template>
    <div class="home">
        <div class="py-10">

            <header>
                <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
                <h1 class="text-3xl font-bold leading-tight text-gray-900">Items</h1>
                </div>
            </header>
            <main>
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
          <div class="flex flex-col">
            <div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
                <div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
                    <div class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
                    <table class="min-w-full divide-y divide-gray-200">
                        <thead class="bg-gray-50">
                        <tr>
                            <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                                Name
                            </th>
                            <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                                Hostname
                            </th>
                            <th scope="col" class="relative px-6 py-3">
                                <span class="sr-only">Actions</span>
                            </th>
                        </tr>
                        </thead>
                        <tbody>
                            <tr v-for="(item, index) in items.value" :key="index" :class="index % 2 === 0 ? 'bg-white' : 'bg-gray-50'">
                                <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ item._source.name }}</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ item._source.hostname }}</td>
                                <td class="px-6 py-4 whitespace-nowrap text-right text-sm">
                                    <div class="flex flex-row-reverse">
                                        <div @click="deleteItem(item._id)" class="px-1 text-red-600 hover:text-red-900">
                                            <TrashIcon class="h-5 w-5"/>
                                        </div>
                                    </div>
                                </td>
                            </tr>
                        </tbody>
                        
                </table>
                </div>
            </div>
            </div>
        </div>
        </div>
      </main>

        </div>
    </div>
</template>

<script>
import { ref } from '@vue/reactivity'
import { TrashIcon } from '@heroicons/vue/outline'
import ItemsService from '../../services/items.service'
export default {
    name: 'ReadItems',
    components: {
        TrashIcon,
    },
    data(){
        return {
            items: ref([]),
        }
    },

    async mounted(){
        this.items.value = await this.readItems()
    },

    methods: {
        async readItems(){
            let temp = null
            try {
                temp = await ItemsService.readItems()
                temp = temp.data.body.hits.hits
            } catch (error) {
                console.log('Error: could not retrieve all items.')
            }
            return temp
        },

        async deleteItem(itemId){
            await ItemsService.deleteItem({ _id: itemId })
            await this.readItems()
        }
    }
}
</script>

当我 运行 deleteItem 方法时,我需要重新加载页面才能看到该项目消失了。我想看到它而不必重新加载页面...

不要在选项 API 的数据函数中使用组合 API 中的 ref,这里的数据已经是反应性的:

const app = Vue.createApp({
  data() {
    return {
      items: [],
    };
  },
  async mounted(){
    this.items = await this.readItems()
  },
  methods: {
    async readItems(){
      let temp = null
      try {
        // setTimeout emulates async call
        setTimeout(() => this.items = [{_id: '1', _source: {name: 'aaa', hostname: 'aaa'}}, {_id: '2', _source: {name: 'bbb', hostname: 'bbb'}}, {_id: '3', _source: {name: 'ccc', hostname: 'ccc'}}], 2000)
        //temp = await ItemsService.readItems()
        //temp = temp.data.body.hits.hits
      } catch (error) {
        console.log('Error: could not retrieve all items.')
      }
      return temp
    },
    async deleteItem(itemId){
      // setTimeout emulates async call
      setTimeout(() => this.items = this.items.filter(i => i._id !== itemId), 1000)
      //await ItemsService.deleteItem({ _id: itemId })
    }
  }
})
app.mount('#demo')
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" integrity="sha512-wnea99uKIC3TJF7v4eKk4Y+lMz2Mklv18+r4na2Gn1abDRPPOeef95xTzdwGD9e6zXJBteMIhZ1+68QC5byJZw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://unpkg.com/vue@next"></script>
<div id="demo">
  <div class="home">
    <div class="py-10">
      <header>
        <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
          <h1 class="text-3xl font-bold leading-tight text-gray-900">Items</h1>
        </div>
      </header>
      <main>
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
          <div class="flex flex-col">
            <div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
              <div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
                <div class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
                  <table class="min-w-full divide-y divide-gray-200">
                    <thead class="bg-gray-50">
                      <tr>
                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                          Name
                        </th>
                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                          Hostname
                        </th>
                        <th scope="col" class="relative px-6 py-3">
                          <span class="sr-only">Actions</span>
                        </th>
                      </tr>
                    </thead>
                      <tbody>
                        <tr v-for="(item, index) in items" :key="index" :class="index % 2 === 0 ? 'bg-white' : 'bg-gray-50'">
                          <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ item._source.name }}</td>
                          <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ item._source.hostname }}</td>
                          <td class="px-6 py-4 whitespace-nowrap text-right text-sm">
                            <div class="flex flex-row-reverse">
                              <div @click="deleteItem(item._id)" class="px-1 text-red-600 hover:text-red-900 cursor-pointer">
                                <!--<TrashIcon class="h-5 w-5"/>-->
                                delete
                              </div>
                            </div>
                          </td>
                        </tr>
                     </tbody>
                  </table>
                </div>
              </div>
            </div>
          </div>
        </div>
      </main>
    </div>
  </div>
</div>