Vue 2 двусторонняя синхронизация ребенка и родителя

#javascript #vue.js #vuejs2

Вопрос:

это моя пользовательская оболочка вокруг пакета vue-multiselect. это ребенок в этом вопросе.

 <template>
    <div>
        <multiselect
            v-model="items"
            :options="filteredList"
            :multiple="multiple"
            :close-on-select="multiple ? false : true"
            :show-labels="false"
            :placeholder="placeholder"
            track-by="id"
            :label="label"
            @input="inputChanged"
            :internal-search="false"
            @search-change="searchItems"
        >
        </multiselect>
    </div>
</template>

<script>
    export default {
        model: {
            prop: 'parentItems',
            event: 'change',
        },
        props: ['multiple', 'list', 'placeholder', 'label', 'parentItems'],
        data() {
            return {
                items: this.parentItems,
                filteredList: this.list,
            }
        },
        methods: {
            searchItems(query) {
                let q = latinize(query.toLowerCase().replace(/s/g,''))
                this.filteredList = this.list.filter(li => latinize(li[this.label].toLowerCase().replace(/s/g,'')).includes(q))
            },
            inputChanged() {
                this.$emit('change', this.items)
                this.$emit('filters-changed')
            },
            resetItems() {
                this.items = this.multiple ? [] : null
            },
        },
    }
</script>
 

родительский элемент выглядит следующим образом

 <custom-multiselect
    v-model="car"
    :multiple="false"
    :list="cars"
    placeholder="Car"
    label="pseudo_id_name"
></custom-multiselect>
 

Я либо не хочу использовать items , я бы предпочел использовать только parentItems , что, конечно, приводит к этому предупреждению

 [Vue warn]: 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. Prop being mutated: "parentItems"
 

что считается повторной визуализацией родительского компонента? во всех моих тестах это решало двустороннюю синхронизацию и ничего не нарушало. если использование реквизита в качестве данных было жизнеспособным в моем случае, могу ли я что-то сделать, чтобы подавить это предупреждение?

если это все еще неправильно, я хотел бы знать, как синхронизировать элементы. я прочитал много вопросов/ответов stackoverflow по этой теме, но все еще не полностью раскрыт.

теперь с моей v-моделью я $emit меняюсь на родительскую, которая работает просто отлично. я борюсь с обратным.

когда я вызываю родительский элемент resetForm() , который устанавливает this.car = null , ребенок не знает, что items он также должен стать нулевым. как мне подготовиться к этому событию?

Ответ №1:

Вы можете сделать элементы вычисляемой опорой с помощью метода getter и setter и привязать ее к модели вашего дочернего компонента с помощью v-модели=»элементы». Это будет хорошо работать до тех пор, пока родительские элементы являются обязательной опорой, а это означает, что они всегда передаются в ваш пользовательский компонент. Если бы родительские элементы были необязательной опорой, я бы придерживался вашего решения сохранить копию этой опоры в данных (и придумать хорошее значение по умолчанию) и передать событие изменения в наблюдателе.

 computed: {
  items:{
    get(){
      return this.parentItems;
    },
    set(value){
      this.$emit('change', value);
    }
  }
}
 

Комментарии:

1. это выглядит хорошо, но я думаю, что мне нужна переменная в данных из-за того, как работает vue-multiselect. он должен иметь свойство v-модели на себе.

Ответ №2:

добавление этого в дочерний элемент, похоже, работает. однако, если есть более чистый способ, пожалуйста, дайте мне знать.

 watch: {
    parentItems: function (val, oldVal) {
        this.items = this.parentItems
    }
},