Vue3动态过滤for循环数据源

Dynamically filter for-loop data source in Vue3

目标
我想根据搜索栏的输入过滤 for 循环中使用的数据源。

例子
我有数据源 [{ title: "Title1" }, { title: "Title2" }]。我在搜索栏中输入“Title1”。我只希望 for 循环的过滤数据源显示带有“Title1”的对象

问题
searchInputChange(...) 方法似乎有效并且 this.filteredPosts 数据源似乎正确更改。但是,数据源似乎没有在 HTML 模板中更新。它始终包含两个对象。

Home.vue

    <template>
        <Searchfield @searchInputChange="searchInputChange" />
    
        <div v-for="post in filteredPosts" :key="post.id">
          {{ post.title }}
        </div>
    </template>
    
    <script>
    import { ref } from 'vue'
    import Searchfield from '../components/Searchfield.vue'
    
    export default {
      name: 'Home',
      components: { Searchfield },
      setup() {
        let filteredPosts = ref([])
        
        let allPosts = [
          {
            "id": 1,
            "title": "Title1",
          },
          {
            "id": 2,
            "title": "Title2",
          }
        ]
      
        filteredPosts.value = [...allPosts]
    
        return { allPosts, filteredPosts }
      },
      methods: {
        searchInputChange(value) {
          const filterPosts = this.allPosts.filter(post => post.title.toLowerCase().includes(value.toLowerCase()));
          this.filteredPosts.value = [...filterPosts]
        }
      }
    }
    </script>

Searchfield.vue

    <template>
        <input type="text" @change="searchInputChange" placeholder="Search...">
    </template>
    
    <script>
    export default {
        name: 'Searchfield',
        setup(props, context) {
            
            const searchInputChange = (event) => {
                context.emit('searchInputChange', event.target.value)
            }
    
            return { searchInputChange }
        }
    }
    </script>

谢谢!

setup 中使用 ref 时,您需要使用 value 属性 更改它的值(或读取值),因此所有赋值(在 setup) 到 filteredPosts 应该看起来像 filteredPosts.value = ....

setup 之外(假设在 methods 中),filteredPosts 是反应对象(组件实例)和 [=20= 的正常反应 属性 ] 不需要(使用它是错误的)

所有这些都非常令人困惑,这也是为什么不建议混合组合 API 和选项 API 的原因之一 - 只使用其中之一。

在您的情况下,filteredPosts 可以是一个简单的 computed,无需在每次更改输入时手动重新分配它...

const app = Vue.createApp({
  setup(){
    const searchTerm = Vue.ref('')
          
    let allPosts = [
      {
        "id": 1,
        "title": "Title1",
      },
      {
        "id": 2,
        "title": "Title2",
      }
    ]
    
    const filteredPosts = Vue.computed(() => allPosts.filter(post => post.title.toLowerCase().includes(searchTerm.value.toLowerCase())) )
   
    return {
      searchTerm, 
      filteredPosts
    }
  },
})

app.component('Searchfield', {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    const model = Vue.computed({
      get: () => props.modelValue,
      set: (newValue) => emit('update:modelValue', newValue)
    })
    
    return { model }
  },
  template: `<input type="text" v-model="model" placeholder="Search...">`
})
app.mount('#app')
<script src="https://unpkg.com/vue@3.2.23/dist/vue.global.js"></script>
<div id='app'>
  <searchfield v-model="searchTerm"></searchfield>
 
  <div v-for="post in filteredPosts" :key="post.id">
      {{ post.title }}
    </div>
</div>