在Vue3中动态过滤for循环数据源

2022-04-07 00:00:00 vue.js vuejs3

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

示例
我有数据源[{TITLE:&Q;TITLE1&Q;},{TITLE:&Q;TITLE2&Q;}]。我在我的搜索栏中输入标题1。我只希望for循环的经过筛选的数据源显示标题为1的对象

问题
搜索输入更改(...)方法似乎起作用了,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属性更改它的值(或读取值),以便setupfilteredPosts的所有赋值都应该类似于filteredPosts.value = ....

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

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

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

数据-lang="js"数据-隐藏="假"数据-控制台="假"数据-巴贝尔="真">
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>

相关文章