Краткий обзор знаний Vue2.x, соберите его для себя.

Vue.js
Краткий обзор знаний Vue2.x, соберите его для себя.

В чем разница в расчете vue компьютерных атрибутов и методе общих атрибутов?

Вычисляемое свойство — это свойство вычислений vue, которое является отображением преобразования данных из уровня данных в слой представления; вычисляемые свойства кэшируются на основе их зависимостей, и они будут переоцениваться только при изменении связанных зависимостей, то есть пока зависимость свойства не изменилась, то при каждом обращении к вычисляемому свойству будет немедленно возвращен предыдущий вычисленный результат, и функция больше не будет выполняться;

вычисленный реактивен, методы не реактивны.

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

Члены в вычислении могут определять функцию только как свойство, доступное только для чтения, или они могут определять get/set, чтобы оно стало свойством для чтения и записи, чего не могут делать члены в методах.

Computed не поддерживает асинхронность, он недействителен при наличии асинхронных операций в вычислении и не может отслеживать изменения данных. Если объявленное вычисляемое свойство имеет очень большой объем вычислений, а количество посещений очень велико, возможность для изменения мала, то нам нужно использовать вычисляемое; кеширование позволит сократить много вычислений.

Каков принцип двусторонней привязки Vue?

Vue.js принимает метод угона данных, в сочетании с режимом издателя-абонента, и использует метод Object.DefineProperty (), предоставленный ES5 для hijack (монитор). Соседниты и получатели каждого свойства, и публикуют сообщения для подписчиков, когда данные изменения. Запустить соответствующий обратный вызов слушателя. И, поскольку синхронизация срабатывает на разных данных, изменения могут быть отправлены на связанный вид точно, вместо того, чтобы выполнить проверку всех данных.

Конкретные шаги:

  1. Объект данных наблюдателя должен быть рекурсивно пройден, включая свойства объекта подсвойства, и добавлены геттер и сеттер.Если объекту присваивается значение, сеттер будет запущен, а затем изменение данных можно контролировать.
  2. Compile анализирует инструкции шаблона, заменяет переменные в шаблоне данными, затем инициализирует и отображает представление страницы, привязывает функцию обновления к узлу, соответствующему каждой инструкции, и добавляет подписчиков, которые отслеживают данные. уведомление и вид обновления
  3. Подписчик Watcher является связующим звеном между Observer и компилятором.
    • Добавьте себя к подписчику свойства (dep) при его создании
    • Он должен иметь сам метод update()
    • Когда свойство изменяет уведомление dep.notice(), вы можете вызвать свой собственный метод update() и вызвать связанный обратный вызов в компиляции, после чего вы будете на пенсии
  4. MVVM, как точка входа для привязки данных, объединяет наблюдатель, компилятор и наблюдатель, отслеживает изменения данных собственной модели через наблюдателя, компилирует инструкции шаблона посредством компиляции и, наконец, использует коммуникационный мост между наблюдателем и компилятором, созданный наблюдателем для достижения изменений данных. --попытаться обновить; просмотреть изменения взаимодействия (ввод) --> эффект двусторонней привязки изменений модели данных

Сравнение версий: vue — это двусторонняя привязка, основанная на коллекции зависимостей, Object.definePropetry используется до версии 3.0, а Proxy — в новой версии 3.0.

  1. Преимущество двусторонней привязки, основанной на перехвате данных/сборе зависимостей, не требует явных вызовов. изменить, мы можем точно получить измененное содержимое newValue без дополнительных операций сравнения
  2. Недостатки Object.defineProperty.
    • Не могу слушать массивы: потому что у массивов нет геттеров и сеттеров.
    • Поскольку неопределенность массивов, если слишком много нагрузки может контролировать только свойства Performance, а не весь объект, вам нужно пройти свой свойство цикла, может только контролировать изменения атрибута, слушатель не может приписать удалением
  3. Преимущества прокси
    • Массивы можно отслеживать
    • Прослушивание всего объекта не является свойством
    • 13 видов методов резки, сильный много
    • Возврат нового объекта вместо прямого изменения исходного объекта больше соответствует неизменяемости;
  4. Недостатки прокси
    • Совместимость плохая, полифиллом не сгладишь;

Подскажите по какому принципу работает vue-router?

Принцип реализации: Принцип vue-router заключается в обновлении представления без повторного запроса страницы.

vue-router может быть установлен в три режима с помощью параметра режима:

 hash模式
 history模式
 abstract模式。
  1. Режим хеширования По умолчанию используется хэш-режим.На основе API истории браузера используйте window.addEventListener('hashchange',callback,false) для мониторинга адреса браузера. При вызове push добавьте новый маршрут в начало стека истории доступа браузера. При использовании замены замените верхний маршрут в истории доступа браузера новым маршрутом. Значение хеш-функции равно содержимому # и более позднему в URL-адресе. Браузер загружает страницу в соответствующее местоположение DOM в соответствии с изменением хеш-значения. Изменение точки привязки — это только поведение браузера. После каждого изменения точки привязки в браузере по-прежнему будет оставаться запись истории. Вы можете вернуться к предыдущей позиции с помощью кнопки «Назад» в браузере.

  2. Режим истории истории, основанный на API истории браузера, использует window.onpopstate для мониторинга адресов браузера. Инкапсулируйте pushState() и replaceState() в API истории браузера. При вызове метода стек истории браузера будет изменен. Чтобы реализовать переход URL-адреса без загрузки страницы, но его проблема в том, что при обновлении страницы будет выполняться внутренняя маршрутизация, поэтому ему требуется помощь сервера, чтобы добраться до сути, чтобы избежать возврата на страницу, когда URL-адрес не может соответствовать ресурсу.

  3. Аннотация и не включает в себя адрес браузера соответствующих записей. Процесс с хэш-моделями, поддержав симуляцию массива с помощью стека истории браузера на сервере. Не полагайтесь на использование браузера Браузера История виртуального управления фон

В чем разница в расчете vue компьютерных атрибутов и методе общих атрибутов?

Вычисляемое свойство — это свойство вычислений vue, которое является отображением преобразования данных из уровня данных в слой представления; вычисляемые свойства кэшируются на основе их зависимостей, и они будут переоцениваться только при изменении связанных зависимостей, то есть пока зависимость свойства не изменилась, то при каждом обращении к вычисляемому свойству будет немедленно возвращен предыдущий вычисленный результат, и функция больше не будет выполняться;

  • вычисленный реактивен, методы не реактивны.
  • Члены в вычислении могут определять функцию только как свойство, доступное только для чтения, или они могут определять get/set, чтобы оно стало свойством для чтения и записи, чего не могут делать члены в методах.
  • Computed не поддерживает асинхронность, он недействителен при наличии асинхронных операций в вычислении и не может отслеживать изменения данных.

Если объявленное вычисляемое свойство имеет очень большой объем вычислений, а количество посещений очень велико, возможность для изменения мала, то нам нужно использовать вычисляемое; кеширование позволит сократить много вычислений.

Подскажите, насколько живой Vue реализован и что кэшируется конкретно?

keep-alive реквизит include字符串或正则表达式,只有名称匹配的组件会被匹配 exclude字符串或正则表达式。任何名称匹配的组件都不会被缓存 max数字。最多可以缓存多少组件实例

Когда keep-alive оборачивает динамические компоненты, экземпляры неактивных компонентов кэшируются.

Основной процесс

  1. Определить имя компонента, если его нет во включении или исключении, вернуть vnode напрямую, указывая, что компонент не кэшируется
  2. Получить ключ экземпляра компонента, если он получен с помощью ключа экземпляра, в противном случае сгенерировать повторно.
  3. Правила генерации ключей, cid+"::"+tag, одного cid недостаточно, потому что один и тот же конструктор может быть зарегистрирован как разные локальные компоненты
  4. Если объект кэша существует, экземпляр компонента напрямую получен из объекта кэша к VNODE, и если он не существует, он добавляется в объект кэша
  5. Максимальное количество кешей, когда количество кешей превышает максимальное значение, первый компонент в массиве ключей очищается.

Реализация поддержки активности

export default{
    name:'keep-alive',
    abstract:true,//一个抽象组件,自身不会渲染一个DOM元素,也不会出现在父组件中
    props:{
        include:patternTypes,//匹配的组件,缓存
        exclude:patternTypes,//不去匹配的组件,你缓存
        max:[String,Number],//缓存组件的最大实例数量,由于缓存的是组件实例(vnode),数量过多的时候,会占用过多的内存,可以用max指定上限
    },
    create(){
        //用于初始化缓存虚拟DOM数组和vnode的key
        this.cache=Object.create(null)
        this.keys=[]
    },
    destroyed(){
        //销毁缓存cache的组件实例
        for(const key in this.cache){
            pruneCacheEntry(this.cache,key,this.keys)
        }
    },
    mounted(){
        //监控include和exclude的改变,根据最新的include和exclude的内容,来实时削减缓存的组建的内容
        this.$watch('include',(val)=>{
            pruneCache(this,(name=>matches(val,name)))
        })
        this.$watch('exclude',(val)=>{
            pruneCache(this,(name)=>!matches(val,name))
        })
    },
}

функция рендеринга

  1. Он будет записывать свой собственный контент внутри компонента поддержки активности, поэтому вы можете получить содержимое слота по умолчанию, а затем получить компонент в соответствии с этим.
  2. keep-alive действителен только для первого компонента, поэтому получите первый дочерний компонент
  3. Обычно используется с поддержкой активности динамическими компонентами и просмотром маршрута.
    function getFirstComponentChild(children:?Array<VNode>):?VNode{
        if(Array.isArray(children)){
            for(var i=0;i< children.length;i++){
                const c=children[i]
                if(isDef(c)&&isDef(c.componentOptions)||isAsyncPlaceholder(c)){
                    return c
                }
            }
        }
        const slot=this.$slots.default//获取默认插槽
        const vnode:VNode=getFirstComponentChild(slot)//获取第一个子组件
        const componentOptions:?VNodeComponentOptions=vnode && vnode.componentOptions//组件参数
        if(componentOptions){//是否有组件参数
            const name:?string=getComponentName(componentOptions)//获得组件名字
            const {include,exclude}=this
            if(
                //not include
                (include && (!name || !matches(include,name))) ||
                //excluded
                (exclude && name && matches(exclude,name))
            ){
                //如果不匹配当前组件的名字和include以及exclude
                //那么直接返回组件的实例
                return vnode
            }
            const {cache,keys}=this
            //获取这个组件的key
            const key:?string=vnode.key == null?componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}`:''):vnode.key
            if(cache[key]){
                //LRU缓存策略执行
                vnode.componentInstance=cache[key].componentInstance//组件初次渲染的时候componentInstance为undefined
                remove(keys,key)
                keys.push(key)
                //根据LRU缓存策略进行,将key从原来的位置移除,然后将这个key值放到最后
            }else{
                //在缓存列表里没有的话,则加入,同时判断当前加入之后,是否超过了max所设定的范围,是的话那么就移除
                //使用时间间隔最长的一个
                cache[key]=vnode
                keys.push(key)
                if(this.max && keys.length >parseInt(this.max)){
                    pruneCacheEntry(cache,key[0],keys,this._vnode)
                }
            }
            //将组件的keepAlive属性设置为true
            vnode.data.keepAlive=true//判断是否执行组件的created、mounted生命周期函数
        }
    }
    return vnode||(slot && slot[0])
}

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

Краткое изложение шагов

  1. Получите объект экземпляра первого подкомпонента в рамках проверки активности и используйте его для получения имени этого компонента.
  2. Используйте имя текущего компонента, чтобы оно соответствовало исходному включению и исключению, чтобы определить, нужно ли кэшировать текущий компонент, и напрямую возвращайте vnode экземпляра текущего компонента без кэширования.
  3. Нужно закэшировать, определить есть ли он в данный момент в массиве кеша, если есть, убрать ключ в исходное положение, и поставить ключ этого компонента в конец массива
  4. Если он не существует, поместите ключ компонента в массив, а затем оцените, превышает ли текущий массив ключей диапазон, заданный параметром max.Если превышает, то уменьшите значение ключа компонента, который не использовался дольше всего .
  5. Наконец, установите для KeepAlive этого компонента значение true.

Процесс создания и процесс исправления самого keep-alive При кешировании рендеринга он будет судить в соответствии с vnode.componentInstance (первый рендеринг vnode.componentInstance не определен) и свойствами keepAlive, что созданные, смонтированные и другие функции хука компонента не будут выполняться, но процесс исправления будет выполняться для кешированного компонент: напрямую поместить кешированный DOM Объект напрямую вставляется в целевой элемент, завершая процесс рендеринга в случае обновления данных

Первый компонент рендеринга для первого рендеринга: абстрактное свойство для определения компонента, только родительский компонент для монтирования внутри DOM

    const options=vm.$options
    let parent=options.parent
    if(parent && !options.abstract){//判断组件的abstract属性,才往父组件里面挂载DOM
        while(parent.$options.abstract && parent.$parent){
            parent=parent.$parent
        }
        parent.$children.push(vm)
    }
    vm.$parent=parent
    vm.$root=parent?parent:$root:vm
    vm.$children=[]
    vm.$refs={}
    vm._watcher=null
    vm._inactive=null
    vm._directInactive=false
    vm._isMounted=false
    vm._isDestroyed=false
    vm._isBeingDestoryed=false
}

Определите, есть ли текущий keepalive и CompletentInstance, чтобы определить, будет ли выполнить или выполнить компонент Parpatch создать компонент

    if(vnode.componentInstance && !vnode.componentInstance.__isDestroyed && vnode.data.keepAlive){//首次渲染 vnode.componentInstance为undefined
        const mounteNode:any=vnode
        componentVNodeHooks.prepatch(mountedNode,mountedNode)//prepatch函数执行的是组件更新的过程
    }else{
        const child=vnode.componentInstance=createComponentInstanceForVnode(vnode,activeInstance)
    }
    child.$mount(hydrating?vode.elm:undefined,hydrating)
}

Операция Prefatch не будет объявлять периодическую функцию в установленном и созданном исполняющем компонентах, но непосредственно вставьте DOM в

Стратегия кэширования LRU (наименее недавно использовавшаяся) Стратегия кэширования LRU: Найдите самые длинные неиспользуемые данные в памяти и замените их новыми данными. Алгоритм LRU (наименее недавно использовавшийся) удаляет данные в соответствии с историческими записями доступа к данным. Основная идея: если к данным недавно обращались , то и в дальнейшем шансы быть посещенными тоже выше. Наиболее распространенной реализацией является использование связанного списка для сохранения кэшированных данных.Детальный алгоритм реализован следующим образом.

  1. Вставить новые данные в заголовок связанного списка
  2. При каждом доступе к кэшированным данным перемещайте данные в начало связанного списка.
  3. Когда связанный список заполнен, данные в конце связанного списка отбрасываются.

Каковы ваши методы оптимизации проектов Vue?

  1. Оптимизация уровня кода
    1. v-if и v-show различают сценарии использования
    2. Вычисляемые и наблюдаемые сценарии использования
    3. V-для обхода необходимо добавить ключ к элементу и избегать использования V-если в то же время
    4. Оптимизация производительности длинного списка
    5. уничтожение событий
    6. Отложенная загрузка ресурса изображения
    7. Отложенная загрузка маршрута
    8. Внедрение сторонних плагинов по запросу
    9. Бесконечный список оптимизации производительности
    • WebPack сжимает фотографии
    • Сокращение избыточного кода с ES6 до ES5
    • Извлечь общедоступный код
    • Предварительная компиляция шаблона
    • Извлечь CSS компонента
    • Оптимизировать исходную карту
    • Анализ результатов сборки
    • Оптимизация компиляции для проектов Vue
  2. Оптимизация основных веб-технологий
    • Включите сжатие gzip
    • кеш браузера
    • Использование CDN
    • Найдите узкие места в производительности с помощью Chrome Performance

Почему данные в компоненте должны быть функцией, а затем возвращать объект, тогда как в новом экземпляре Vue данные могут быть напрямую объектом?

Поскольку компонент используется для повторного использования, а объект в JS является ссылочной связью, если данные в компоненте являются объектом, то область действия не изолирована, и значения атрибутов данных в подкомпоненте будут влиять друг на друга. Если параметр данных в компоненте — это функция, то каждый экземпляр может поддерживать независимую копию возвращаемого объекта, и значения атрибутов данных между экземплярами компонента не будут влиять друг на друга; и экземпляр нового Vue не будет повторно использоваться. , так что нет проблемы с эталонным объектом.

Может ли Vue обнаружить изменение, напрямую присвоив значение элементу массива?

Из-за ограничений JavaScript Vue не может обнаружить изменения в следующих массивах:

vm.items[indexOfItem] = newValueКогда вы изменяете длину массива, например:vm.items.length = newLengthДля решения первой проблемы Vue предоставляет следующие методы:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// vm.$set,Vue.set的一个别名
vm.$set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

Для решения второй проблемы Vue предоставляет следующие методы действий:

// Array.prototype.splice
vm.items.splice(newLength)

Каковы способы связи между компонентами Vue?

Связь между компонентами Vue относится только к следующим трем типам связи:

  • Взаимодействие компонентов родитель-потомок
  • Коммуникация межпоколенческого компонента
  • Взаимодействие компонентов родственного компонента

Ниже мы опишем каждый способ связи отдельно:

  1. props / $emit подходит для связи между родительскими и дочерними компонентами. Этот метод является основой компонентов Vue. Я думаю, что большинство студентов слышали о нем, поэтому я не буду его здесь представлять.
  2. ссылка сparent/parent / Сыновя сборка подходит для детей общения

Ref: если используется в общем эталонном точке элемента DOM, представляет собой элементы DOM; если используется в подсменов, к ссылке на экземпляр компонента

parent/parent/дочерние элементы: доступ к родительским/дочерним экземплярам

  1. EventBus(emit/emit/on) подходит для связи компонентов родитель-потомок, между поколениями и родственными компонентами.Этот метод использует пустой экземпляр Vue в качестве центральной шины событий (центра событий), которая используется для запуска событий и отслеживания событий, чтобы реализовать связь между любые компоненты, в том числе родительско-дочерние, межпоколенческие, родственные компоненты.
  2. attrs/attrs/слушатели для межпоколенческой компонентной коммуникации

attrs:В родительскую область не входятpropидентифицированный(и получить)Функциональные привязки(classа такжеstyleКроме). Когда компонент не объявляет никакихpropКогда, где все будет содержать связывание родительской массы(classа такжеstyleКроме)И поvbind="attrs: содержит свойство родительской области, не распознает (и не получает) свойства привязки (кроме класса и стиля). Когда компонент не объявляет никакой поддержки, где родительская область включает все привязки (кроме стиля класса) и может быть v-bind = "listeners:(Бесплатно.nativeмодификатор)vonпрослушиватель событий. это может пройтиvon="listeners: содержит прослушиватели событий v-on в родительской области (без декоратора .native). Доступ к нему можно получить через v-on="listeners" входящие внутренние компоненты

  1. обеспечить/внедрить подходит для связи между компонентами между поколениями.Компонент-предок предоставляет переменную через провайдера, а затем вводит переменную в компонент-потомок через инъекцию. API предоставления/внедрения в основном решает проблему связи между межуровневыми компонентами, но его сценарии использования в основном предназначены для подкомпонентов для получения состояния родительского компонента, а между межуровневыми компонентами устанавливается связь между активным предоставлением и внедрением зависимостей. .
  2. Vuex 适用于 父子、隔代、兄弟组件通信。 Vuex — это шаблон управления состоянием, разработанный для приложений Vue.js.每一个 Vuex 应用的核心就是 store(仓库)。 “store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

Хранилище состояния Vuex является реактивным. Когда компонент Vue считывает состояние из хранилища, если состояние в хранилище изменяется, соответствующий компонент будет эффективно обновлен соответствующим образом. Единственный способ изменить состояние в хранилище — это явно зафиксировать мутации. Это позволяет нам легко отслеживать каждое изменение состояния.

Скажем, порядок выполнения функций родительского компонента и подкомпонента жизненного цикла VUE?

Порядок выполнения функции обработчика жизненного цикла родительского компонента и дочернего компонента Vue можно разделить на следующие 4 части:

  • Загрузить процесс рендеринга

родитель beforeCreate -> созданный родитель -> родитель beforeMount -> дочерний beforeCreate -> созданный дочерний элемент -> дочерний beforeMount -> смонтированный дочерний элемент -> смонтированный родительский элемент

  • Процесс обновления подкомпонента

родитель до обновления -> дочерний перед обновлением -> дочерний обновлен -> родительский обновлен

  • Процесс обновления родительского компонента

родитель перед обновлением -> родитель обновлен

  • процесс разрушения

родитель перед уничтожением -> дочерний перед уничтожением -> дочерний уничтожен -> родитель уничтожен

Вы когда-нибудь использовали Vue SSR? Говорите о ССР?

  • Лучше SEO: SPA страница, потому что контент приобретен AJAX, а поисковые системы ползут инструмент и не ждут завершения асинхронного ajax, затем ползать содержимое страницы, это меньше страницы, чтобы ползлить через Ajax, приобретенное в спа-салоне содержимое; в то время как SSR напрямую возвращается сервером, имеет оказываемую страницу (данные, уже включенные в страницу), поэтому инструмент поисковых систем Closing может захватить визуализацию.
  • Более быстрое время поступления контента (более быстрая загрузка на первом экране): SPA будет ждать загрузки всех js-файлов, скомпилированных с помощью Vue, прежде чем начать рендеринг страницы.Это занимает определенное время для загрузки файлов и т. д., поэтому первый экран рендеринг требует определенного периода времени; SSR напрямую рендерит страницу сервером и возвращает ее прямо на дисплей, не дожидаясь загрузки js-файлов и повторного рендеринга, поэтому SSR имеет более быстрое время поступления контента
  1. Недостатки рендеринга на стороне сервера:
  • Дополнительные условия разработки: например, рендеринг на стороне сервера поддерживает только две функции ловушек, beforeCreate и created, из-за чего некоторые внешние библиотеки расширений потребуют специальной обработки, прежде чем они смогут работать в приложениях рендеринга на стороне сервера; и их можно развернуть в любом статическом приложении. Полностью статическое одностраничное приложение SPA на сервере отличается, и приложение для рендеринга на стороне сервера должно находиться в операционной среде сервера Node.js;
  • Большая нагрузка на сервер: рендеринг полного приложения в Node.js, очевидно, потребует больше ресурсов ЦП, чем сервер, обслуживающий только статические файлы (интенсивный ЦП — интенсивный ЦП), поэтому, если вы ожидаете среду с высоким трафиком (высокий трафик), подготовьтесь к соответствующую нагрузку на сервер и разумно используйте стратегию кэширования.

Расскажите мне о принципе Vue $nextTick?

механизм запуска js (Event Loop)

js执行是单线程的,它是基于事件循环的

Все задачи синхронизации выполняются в основном потоке, образуя стек выполнения. Вне основного потока будет очередь задач, пока у асинхронной задачи есть результат, событие будет помещено в очередь задач. Когда все задачи синхронизации в стеке выполнения выполнены, очередь задач считывается. Затем соответствующая асинхронная задача завершит состояние ожидания и войдет в стек выполнения.主线程不断重复第三步Процесс выполнения потока здесь — тик, а все асинхронные результаты планируются через очередь задач. Цикл событий разделен на макро-задачи и микро-задачи. Независимо от того, выполняются ли макро-задачи или микро-задачи, он войдет в следующий тик после завершения, а рендеринг пользовательского интерфейса процесса между двумя тиками выполняется асинхронно, потому что обновление Vue DOM выполняется асинхронно, то есть данные изменяются, представление не будет обновляться сразу, а будет отслеживать изменения данных и кэшировать их в том же цикле событий.После того, как все изменения данных в том же цикле данных будут завершены, представление будет обновлено в то же время. Чтобы обеспечить обновление DOM, установлен метод Vue.nextTick().

什么是$nextTickОдин из основных методов Vue, официальная документация объясняет его следующим образом: отложенный обратный вызов, который выполняется после следующего цикла обновления DOM. Используйте этот метод сразу после изменения данных, чтобы получить обновленный DOM.

  1. MutationObserver

MutationObserver – это API в HTML5. Это интерфейс для мониторинга изменений DOM. Он может отслеживать удаление дочерних узлов, изменение атрибутов и изменение текстового содержимого, которые происходят в объекте DOM. Вызывающий процесс должен сначала привязать к нему обратный вызов и получить объект экземпляра MO.Этот обратный вызов запускается, когда объект экземпляра MO отслеживается на наличие изменений. Обратный вызов MO здесь выполняется в микрозадаче

//创建MO实例
const Observer=new MutationObserver(callback);
const textNode="你好,世界!"
Observer.observe(textNode,{
    characterData:true//监听文本内容的修改
})
  1. Анализ исходного кода

nextTick реализация отдельного файла JS для его поддержки. Источник nextTick разделен на две части: Возможность обнаружения и определения емкости очереди обратного вызова Возможность обнаружения трудоемкой задачи, поскольку макрос больше, чем микрозадача, поэтому в случае поддерживаемых браузеров использование задачи с микроприоритетом по-разному . Если ваш браузер не поддерживает микрозадачи, то используйте задачу макроса

//空函数,可用作函数占位符
import {noop} from './util';

//错误处理函数
import {handleError} from './error';

//是否是IE、ios、内置函数
import {isIE,isIOS,isNative} from './env';

//用来存储所有需要执行的回调函数
const callbacks=[];

//标志下是否正在执行回调函数
const flag=false;

//对callback进行遍历,然后执行相应的回调函数
function shift(){
    flag=false
    //这里拷贝的原因是:有的回调函数执行过程中又往callbacks中加入内容
    //比如$nextTick的回调函数里还有$nextTick,后者应该放到下一轮的nextTick中执行,所以拷贝一份当前的,遍历执行完当前的即可,避免无休止的执行下去
    const cb=callbacks.slice(0)
    callbacks.length=0
    for(var i=0;i<cb.length;i++){
        cb[i]()
    }
}

const timeFunc;//异步执行函数,用于异步延迟调用flushCallbacks函数

if(typeof Promise !== "undefined" && isNative(Promise)){
    const p=Promise.resolve()
    timeFunc=()=>{
        p.then(flushCallbacks);
        //IOS的UIView、Peomise.then 回调被推入microTask队列,但是队列可能不会如期执行
        //因此,添加一个空计时器强制microTask
        if (isIOS) setTimeout(noop)
    }
    isUsingMicroTask=true;
}else if(!isIE && typeof MutationObserver !=='undefined' && (isNative(MutationObserver) || MutationObserver.toString === "[Object MutationObserverConstructor]")){
    //当原生Promise不可用时,使用原生MutationObserver
    let counter=1
    //创建MO实例,监听到DOM变动后会执行回调flushCallbacks
    const obs=new MutationObserver(flushCallbacks);
    const textNode=document.createTextNode(String(conter))
    obs.observe(textNode,{
        characterData:true,//监听目标的变化
    })
    //每次执行timeFunc都hi让文本节点的内容在0和1之间切换
    //切换之后将新值赋值到MO观察的文本节点上,节点内容变化会触发回调
    timeFunc=()=>{
        counter=(counter+1)%2
        textNode.data=String(counter)//触发回调函数
    }
    isUsingMicroTask=true;
}else if(typeof setImmediate !== 'undefined' && isNative(setImmediate)){
    timeFunc=()=>{
        setImmediate(flushCallbacks)
    }
}else{
    timeFunc=()=>{
        setTimeout(flushCallbacks,0)
    }
}

Приоритет отложенного вызова следующий: Promise > MutationObserver > setImmediate > setTimeout

export function nextTick(cd? Function,ctx:Object){
    let _resolve
    //cb回调函数会统一处理压入callbacks数组
    callbacks.push(()=>{
        if(cb){
            try{
                cb.call(ctx)
            }catch(e){
                handleError(e,ctx,'nextTick')
            }
        }else if(_resolve){
            _resolve(ctx)
        }
    })
    //flag为false  说明本轮事件循环中没有执行过timeFunc函数
    if(!flag){
        flag=true;
        timeFunc()
    }
    //当不传入cb参数时,提供一个promise化的调用
    //比如nextTick().then(()=>{}),当_resolve执行时,就会跳转到then逻辑中
    if(!cd && typeof Promise !== 'undefined'){
        return new Promise(resolve=>{
            _resolve=resolve
        })
    }
}

nextTick.js предоставляет параметр nextTick, поэтому каждый раз, когда вызывается Vue.nextTick, он будет выполняться:

  • Поместите входящую функцию обратного вызова cb в массив обратных вызовов.
  • Выполнить функцию timeFunc и отложить вызов функции flushCallbacks.
  • В массиве обратных вызовов выполнения обхода есть функции
  • Here there is no reason for callbacks execute the callback function directly in nextTick are: to ensure the implementation of nextTick many times within the same tick, do not open multiple asynchronous tasks, but these asynchronous tasks are pressed into a synchronous task, the next tick Законченный.
语法:Vue.nextTick([callback,context])
参数:
{Function}[callback]:回调函数,不传参数时提供promise调用
{Object}[context]:回调函数执行的上下文环境,不传默认是自动绑定到调用它的实例上
//改变数据
vm.message="changed";
//想要立即使用更新后的DOM,这样不行,因为设置message后DOM还没有更新
console.log(vm.$el.textContent)//并不会得到"changed"
//这样可以,nextTick里面的代码在DOM更新后执行
Vue.nextTick(function(){
    //DOM更新,可以得到"changed"
    console.log(vm.$el.textContent)
})
//作为一个promise使用,不传参数时回调
Vue.nextTick().then(function(){
    //DOM更新时的执行代码
})

Метод экземпляра Vue vm.$nextTick дополнительно инкапсулируется, устанавливая параметр контекста для текущего экземпляра Vue.Цель использования Vue.nextTick() — получить обновленный DOM. Время срабатывания: после изменения данных в том же цикле событий DOM обновляется, и обратный вызов Vue.nextTick() выполняется немедленно.

Код в том же цикле событий завершает выполнение — DOM обновляется — срабатывает обратный вызов nextTick

Сценарии применения

  • В созданной функции жизненного цикла Vue () крючок операций DOM должен быть размещен Vue.nextTick () функция обратного вызова, причина: создается () функция выполняется, когда крючок DOM на самом деле не отображается.

  • Когда операция должна выполняться после изменения данных, и эта операция должна использовать структуру DOM, которая меняется с изменением данных, эта операция должна быть помещена в функцию обратного вызова Vue.nextTick (). Причина: Vue выполняет обновления DOM Asynchrony До тех пор, пока наблюдаются изменения в данных, Vue откроет очередь и буфер все изменения данных, которые происходят в одном и том же контуре событий. Если тот же наблюдатель срабатывает несколько раз, он будет только в очередь в очереди

Суммировать

  • NextTick Vue — это, по сути, применение принципа выполнения JS EventLoop.

Основное приложение nextTick: собственные JS-методы Promise, MutationObserver, setImmediate и setTimeout для имитации реализации соответствующих микро/макрозадач Суть заключается в использовании этих асинхронных очередей задач обратного вызова JS для реализации собственных асинхронных очередей обратного вызова. в фреймворке Vue.

  • NextTick - это не только метод вызова асинхронной очереди внутри Vue, но также позволяет разработчикам использовать этот метод в реальных проектах для удовлетворения последующей логической обработки данных DOM в практических приложениях.

NextTick является типичным примером применения основных принципов выполнения JS к конкретным случаям

Причины внедрения механизма асинхронной очереди обновлений

Если это синхронное обновление, многократное назначение одного или нескольких атрибутов будет часто запускать рендеринг UI/DOM, что может уменьшить часть бесполезного рендеринга.

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

Как реализована v-модель и что такое синтаксический сахар?

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

Принцип реализации

  1. Действует на элементы нормальной формы

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

<input v-model="something"/>
//等同于
<input v-bind:value="message" v-on:input="message=$event.target.value"/>
//$event:当前触发的事件对象
//$event.target:当前触发的事件对象的dom
//$event.target.value:当前dom的value值
//在@input方法中,value-->something
//在:value中,something-->value
  1. воздействовать на компонент

В пользовательских компонентах v-model по умолчанию использует свойство с именем value и событие с именем input.

По сути, это синтаксический сахар для связи компонентов родитель-потомок, реализованный через prop и $.emit, поэтому синтаксический сахар v-модели родительского компонента можно существенно изменить на В реализации компонента мы можем настроить свойства prop, полученные дочерним компонентом, и имя события, отправляемое через свойство v-model.

//父组件
<parent-input v-model="parent"></parent-input>
//等价于
<parent-input v-bind:value="parent" v-on:input="parent=$event.target.value"></parent-input>

//子组件
<input v-bind:vaule="message" v-on:input="onmessage"/>
props:{value:message}
methods:{
    onmessage(e){
        $emit('input',e.target.value)
    }
}

По умолчанию v-модель компонента будет использовать значение в качестве свойства, а ввод — как событие, но некоторые типы ввода, такие как переключатели и кнопки-флажки, могут захотеть использовать свойство значения для разных целей. Используйте вариант модели, чтобы избежать конфликтов в этой ситуации. js отслеживает изменение входных данных в поле ввода и использует событие oninput, которое сработает сразу после изменения данных. передать входное событие в данныеemitВыйдите и получите его в родительском компоненте. Настройки родительского компонентаvmodelценностьinputвыдать полученное значение.

Может ли дочерний компонент напрямую изменять данные родительского компонента? Скажи мне свою причину?

В основном для поддержания одностороннего потока данных родительских и дочерних компонентов

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

Vue выдаст предупреждение в консоли браузера, если я это сделаю

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

Через $emit отправляется только пользовательское событие, после того как родительский компонент его получает, оно модифицируется родительским компонентом.

Можете ли вы рассказать о принципах реализации режимов маршрутизации хеширования и истории, обычно используемых в vue-router?

  1. Принцип реализации хеш-режима

Ранняя реализация внешней маршрутизации была основана на location.hash. Принцип реализации очень прост: значением location.hash является содержимое после # в URL. Например, для следующего веб-сайта его значение location.hash равно '#search':

www.word.com#searchДостигнуть режим хеш-маршрутизации в основном основан на следующих нескольких характеристиках:

Значение URL-хеша - это просто состояние клиента, то есть, когда запрос на сервер, часть хешей не будет отправлен; изменение значения хеша, он увеличит доступ к записи в истории браузера. Следовательно, мы можем браузер заправить, управление кнопкой вперед, чтобы переключить хеш. На этикетке и установите атрибут HREF, когда пользователь нажимает на метку, значение хеш-адреса URL-адреса будет изменяться; или по назначению loation.Hash Измените хеш-значение URL с помощью JavaScript. Мы можем использовать событие Hashchange для прослушивания изменений Hash Value, при этом скачок страницы (рендеринг) Принцип 2. Режим истории API истории HTML5 предоставляется для реализации изменений в URL. API, которые делают самые важные, являются следующими двумя: история. Pushstate () и история. Rplacestate (). Оба API могут без обновления, а также операционная история браузера. Единственное отличие состоит в том, что первая - это новая запись истории, которая является прямой заменой текущей истории, следующим образом:

window.history.pushState(null, null, path)
window.history.replaceState(null, null, path)

Реализация режима маршрутизации истории в основном основана на существовании следующих функций:

pushState 和 repalceState 两个 API 来操作实现 URL 的变化
我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染)
history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)

Vue говорит о вещах на каждом этапе жизненного цикла и о том, что нужно делать

beforeCreate(创建前)События наблюдения и инициализации данных не начались

created(创建后)Полное наблюдение за данными, работа свойств и методов, события инициализации, свойство $el не отображалось

beforeMounted(挂载前)

mounted(挂载后)

beforeUpdate(更新前)

update(更新后)

beforeDestroy(销毁前)

destroyed(销毁后) Вызывается после уничтожения экземпляра.调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。此钩子在服务端渲染期间不被调用

Расскажите мне о процессе от шаблона Vue до рендеринга?

Анализ процесса

Процесс компиляции шаблона vue выглядит следующим образом: шаблон — ast — функция рендеринга

Vue выполняет compileToFunctions при компиляции шаблона, чтобы преобразовать шаблон в функцию рендеринга.

compileToFunctionsОсновные основные моменты:

  1. Вызовите метод parse, чтобы преобразовать шаблон в ast-дерево (абстрактное синтаксическое дерево).

разобрать объект: ast — это шаблон в виде дерева, которое представляет собой форму объекта для описания всего шаблона js.

  1. Сгенерировать код generate компилирует абстрактное синтаксическое дерево ast в строку рендеринга и помещает статическую часть в staticRender и, наконец, генерирует функцию рендеринга через новую функцию (рендеринг)

Введение Функции навигации в Vue-router

  1. Функции глобального хука beforeEach и afterEach

beforeEach имеет три параметра: для представления объекта маршрута для входа и от объекта маршрута для выхода. next — это функция, которая должна быть выполнена. Если параметры не переданы, выполняется следующая функция ловушки. Если передано значение false, прыжок будет завершен. Если передан путь, будет выполнен переход по соответствующему маршруту. передается, затем навигация прекращается, и ошибка передается функции прослушивания ошибок.

  1. Функция ловушки beforeEnter эксклюзивна для одного маршрута, который определяется непосредственно в конфигурации маршрута.

  2. В компонентах есть три основных типа навигационных ловушек: beforeRouteEnter, beforeRouteUpdate и beforeRouteLeave. Они определяются непосредственно внутри компонента маршрутизации.