DevGang
Авторизоваться

Как сделать значение модели v-model необязательным в Vue.js

При написании моей библиотеки пользовательского интерфейса Vue.js, Inkline, мне пришлось найти способ заставить некоторые компоненты работать как с указанием значения модели ( v-model), так и без него. Хотя это не распространенный сценарий, вы обязательно столкнетесь с ним, если пишете библиотеку и серьезно относитесь к Developer Experience (DX).

Я называю их необязательно контролируемыми компонентами, потому что они должны работать из коробки без предоставления v-model, но предоставят вам полный контроль над их состоянием, если вы предоставите v-model.

Пример меню

Одним из ярких примеров необязательно управляемого компонента может быть меню, которое можно открыть (развернуть) или закрыть (свернуть). Назовем компонент просто MyMenu.

С точки зрения взаимодействия с разработчиками вы, вероятно, захотите, чтобы пользователь вашей библиотеки мог вставить <my-menu> в свой код и сразу же начать добавлять сворачиваемый контент, не беспокоясь об обработке его открытого или закрытого состояния.

Вот как бы компонент выглядел без поддержки v-model:

<template>
    <div class="my-menu">
        <button @click="toggleMenu">
            Menu
        </button>
        <menu v-show="open">
            <slot />
        </menu>
    </div>
</template>

<script>
export default {
    name: 'MyMenu',
    data() {
        return {
            open: false
        };
    },
    methods: {
        toggleMenu() {
            this.open = !this.open;
        }
    }
}
</script>

Необязательное значение модели

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

Я нашел перспективное решение, которое избавит вас от многих проблем. Вот как это выглядит:

<template>
    <div class="my-menu">
        <button @click="toggleMenu">
            Menu
        </button>
        <menu v-show="open">
            <slot />
        </menu>
    </div>
</template>

<script>
export default {
    name: 'MyMenu',
    emits: [
        'update:modelValue'
    ],
    props: {
        modelValue: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            open: this.modelValue
        };
    },
    methods: {
        toggleMenu() {
            this.open = !this.open;
            this.$emit('update:modelValue', this.open);
        }
    },
    watch: {
        modelValue(value) {
            this.open = value;
        }
    }
}
</script>

Попробуйте простой пример в прямом эфире на CodeSandbox.

Вы можете видеть выше, что я добавил обычную опору modelValue для поддержки v-model в Vue 3, но в основном я сделал три вещи:

  1. Я устанавливаю начальное значение нашего внутреннего свойства состояния open равным значению, предоставленному через v-model. Это творит чудеса, потому что, когда нет v-model, она будет равна указанному значению по умолчанию, в нашем случае false.
  2. Я генерирую событие update:modelValue каждый раз, когда меняю внутреннее значение this.open
  3. Я добавил событие, который гарантирует, что я всегда синхронизирую внутреннее значение open с входящей внешней опорой modelValue.

Вывод

Классно, не правда ли? Важно никогда не забывать об опыте разработчика. Такая мелочь, как эта, может сэкономить драгоценные часы времени на разработку, если все будет сделано правильно и последовательно.

Надеюсь, сегодня вы узнали что-то интересное. Удачного кодирования!

Источник:

#JavaScript #Vue.js
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу