Идеи реализации компонента Toast

Vue.js

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

Обзор: Во внешнем проекте иногда необходимо уведомить и подсказать пользователю некоторую информацию, особенно в фоновой системе, правильно ли работает операция или нет, необходимо предоставить некоторую информацию пользователю.

1. Примеры

в компоненте VuemethodsВнутри вызовите следующий код

this.$toast({
    content: "可自动关闭",
    autoClose: true
})

В правой части страницы появится всплывающее окно Toast. Если щелкнуть несколько раз, оно будет отображаться по порядку, и Toast может быть автоматически закрыт. Конкретный эффект показан на рисунке.

最终效果

Кодовый адрес:Github UI-Library

2. Принцип

  • структура кода

    Разделите плагин Toast на две части:

    • Сам компонент Toast, включая его собственную структуру dom иdata, а также завершить монтирование и уничтожение страницы в течение ее жизненного цикла;
    • Создайте уровень прокси вне компонента и предоставьте соответствующие методы для вызова и управления порядком, в котором несколько всплывающих уведомлений отображаются на странице.
  • Метод тостов

    чтобы пройтиthis.$toast({...})Чтобы вызвать компонент Toast, он должен быть в VueprototypeДобавьте метод сверху следующим образом

    let instances = []
    let initIndex = 0
    Vue.prototype.$toast = (options = {}) => {
        /* 创建一个Toast组件的实例 */
        let instance = generateInstance(options)
        /* 将单个toast存入队列中 */    
        instances.push(instance)
    }
    

    При вызове этого метода передайтеgenerateInstanceСоздайте экземпляр компонента Toast и поместите его вinstances, единое управление.

    /* 构造单个toast */
    const ToastConstructor = Vue.extend(Toast)
    const verticalOffset = 16
    function generateInstance(options) {
        // 利用ToastConstructor创建一个Toast的实例
        let instance = new ToastConstructor({
            propsData: options
        }).$mount(document.createElement('div'))
        if (typeof options.onClose === 'function') instance.onClose = options.onClose
        //计算instance verticalOffset
        let id = 'toast_' + initIndex++
        instance.id = id
        // 初始化Toast在空间中的垂直偏移量
        instance.verticalOffset = initVerticalOffset(instance.position)
        //监听组件close
        instance.$once('toastClose', function () {
            const curInstance = this
            // 当Toast组件关闭时,重新计算垂直方向的偏移量
            updateVerticalOffset(curInstance)
            typeof curInstance.onClose === 'function' && curInstance.onClose()
        })
        return instance;
    }
    

    generateInstanceфункция, первое использованиеToastConstructorКонструктор создает экземпляр компонента Toast и передаетpropsDataПередайте значение атрибута, при передаче$mount(document.createElement('div'))Визуализируйте компонент.

    ToastConstructorчерезVue.extendСоздайте конструктор компонента Toast. Конкретные принципы этой части можно найти вОбщее решение для создания компонентов формы на основе конструктора Vue.

    initVerticalOffsetФункция вычисляет начальное смещение компонента Toast

    /* 初始化每个toast对象在页面中的垂直属性 */
    function initVerticalOffset(position) {
        // 筛选同一方向的Toast组件
        let typeInstances = instances.filter(item => item.position === position)
        // 计算偏移量
        return typeInstances.reduce((sum, elem) => 
                    (elem.$el.offsetHeight + sum + verticalOffset), 
               verticalOffset)
    }
    

    Позже, когда Toast закрывается, необходимо обновить смещения всех экземпляров Toast на странице.

    /* 更新每个toast对象在页面中的垂直属性 */
    function updateVerticalOffset(removeInstance) {
        let index = 0
        let removeHeight = removeInstance.verticalOffset
        // 兼容ie 去掉find method
        for (; index < instances.length; index++) {
            if (instances[index].id === removeInstance.id) break;
        }
        instances.splice(index, 1);
    
        // 删除关闭的Toast组件
        instances.splice(index, 1)
        // 更新在删除位置之后的组件的位置
        for (; index < instances.length; ++index) {
            if (instances[index].position === removeInstance.position) {
                [instances[index].verticalOffset, removeHeight] = 
                [removeHeight, instances[index].verticalOffset]
            }
        }
    }
    

    Вышеизложенное завершает создание компонента Toast, как инициализировать и обновить позицию на странице.

  • Компонент тостов

    Функция компонента относительно проста. Ему нужно только отображать информацию, и он имеет две функции автоматического закрытия и ручного закрытия. Атрибуты также включают тип, местоположение и содержимое всплывающего уведомления.

    • жизненный цикл компонента
    let instance = new ToastConstructor({
        propsData: options
    }).$mount(document.createElement('div'))
    

    Когда компонент Toast$mountПри вызове срабатываетmountedжизненный цикл

    mounted() {
        // 挂载Toast在页面中
        document.body.appendChild(this.$el);
        // 需要自动关闭时,调用startTimer
        if (this.autoClose) this.startTimer();
    },
    beforeDestroy() {
        this.stopTimer();
        this.$el.removeEventListener("transitionend", this.destroyElement);
    },
    destroyed() {
        // 注销
        this.$el.parentNode.removeChild(this.$el);
    }
    
    • автоматическое закрытие Когда вам нужен автоматический, вы должны использовать егоsetTimeoutзавершить функцию, а при выходеclearTimeoutдля предотвращения утечки.
    startTimer() {
          if (this.duration > 0) {
            this.timer = setTimeout(() => {
                if (!this.closed) {
                    this.close();
                }
            }, this.duration);
          }
    },
    stopTimer() {
        if (this.timer) clearTimeout(this.timer);
    }
    

3. Используйте

Далее инкапсулируйте его в плагин Vue.

export default {
    install (Vue) {
        Vue.prototype.$toast = (options = {}) => {...}
    }
}

И обрабатывать обработку исключений для необходимых атрибутов, которые необходимо передать в

let requireProps = Object.keys(Toast.props)
                         .filter((elem) => (Toast.props[elem].required))
requireProps.forEach((elem) => {
    if (!options[elem]) throw `err: options lack ${elem} prop`
})
if ( options.type && !types.some(elem => elem === options.type) ) 
    throw `err: toast not exist ${options.type} type`

4. Резюме

Инкапсулируя подключаемый модуль Toast, общие части между различными предприятиями извлекаются, чтобы снизить нагрузку на бизнес.

Прошлые статьи:

Оригинальное заявление: Данная статья является оригинальной, при перепечатке просьба указывать источник.