【问题标题】:Dynamically filter for-loop data source in Vue3在Vue3中动态过滤for循环数据源
【发布时间】:2025-12-22 15:45:09
【问题描述】:

目标
我想根据搜索栏的输入过滤在 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>

谢谢!

【问题讨论】:

    标签: vue.js vuejs3


    【解决方案1】:

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

    setup 之外(比如methods),filteredPosts 是响应式对象(组件实例)的正常响应式属性,不需要.value(使用它是错误的)

    所有这些都非常令人困惑,也是不建议混合使用 Composition API 和 Options 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>

    【讨论】:

    • 有效!很好的例子。谢谢。