vue自定义过滤输入组件

Vue custom filtering input component

我正在尝试创建一个具有 'just' 文本输入的组件。在此输入中键入的字符串将用于过滤列表。我的问题是我无法处理如何在我的组件和包含要过滤的列表的主应用程序之间共享此过滤字符串。

我尝试了几件事,但大多数时候我都收到错误消息: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value

所以我查看了 Vuex,但我认为它在这种情况下无济于事,因为我可以在同一页面中为不同的列表使用多个过滤器组件,我不希望它们同步 ^^

这是我的:

过滤器组件

<script type="x/template" id="filterTpl">
    <div> 
        <span class="filter-wrapper">
            <input type="search" class="input input-filter" v-model.trim="filter" />
        </span>
    </div>
</script>

<script>
    Vue.component('list-filter', {
        props: {
            filter: String
        }
        template: '#filterTpl'
    });
</script>

我的主要应用程序:

<div id="contacts">
        <list-filter :filter="filter"></list-filter>
        <ul class="contacts-list managed-list flex">
            <li class="contact" v-for="contactGroup in filteredData">
                [...]
            </li>
        </ul>
    </div>

<script>
    var contactsV = new Vue({
        el: '#contacts',
        data: {
            filter: "",
            studyContactsGroups: []
        },
        computed: {
            filteredData: function(){
                // Using this.filter to filter the studyContactsGroups data
                [...]
                return filteredContacts;
            }
        }
    });
</script>

感谢您的帮助或提示:)

您可以通过显式 prop-event 连接或使用 sync 修饰符更简洁 v-bind 来同步子值和父 prop:

new Vue({
  el: '#app',
  data: {
    rawData: ['John', 'Jane', 'Jim', 'Eddy', 'Maggy', 'Trump', 'Che'],
    filter: ''
  },
  components: {
    'my-input' : {
      // bind prop 'query' to value and
      // @input update parent prop 'filter' via event used with '.sync'
      template: `<input :value="query" @input="updateFilter">`,
      props: ['query'],
      methods: {
       updateFilter: function(e) {
          this.$emit('update:query', e.target.value) // this is described in documentation
        }
      }
    }
  },
  computed: {
    filteredData: function() {
      // simple filter function
      return this.rawData.filter(el => el.toLowerCase()
       .match(this.filter.toLowerCase()))
    }
  }
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
  <my-input :query.sync="filter"></my-input>
  <hr>
  <ul>
    <li v-for="line in filteredData">{{ line }}</li>
  </ul>
</div>