Есть старая поговорка, с нашими родителями мы всегда будем детьми, а с большими парнями я всегда буду цыпленком 🐣🐣🐣. Несмотря ни на что, страсть к обучению никогда не умрет. Если ответ неверный, спасибо за совет 🌚
Первый личный блог
Лучшее время посадить дерево было десять лет назад, затем сейчас
Что стоит изучить в исходном коде vue
-
柯里化
: функция изначально имеет несколько параметров, которые передаются только一个
параметры, сгенерировать новую функцию, и новая функция получает оставшиеся параметры для запуска, чтобы получить структуру -
偏函数
: функция изначально имеет несколько параметров, которые передаются только一部分
параметры, сгенерировать новую функцию, и новая функция получает оставшиеся параметры для запуска, чтобы получить структуру -
高阶函数
: функция参数是一个函数
, функция обрабатывает функцию параметра для получения функции, и функция, используемая для этой обработки, является функцией более высокого порядка - ...
vue отзывчивая система
Краткое описание:
Он будет использоваться при инициализации vue.Object.defineProperty()
Добавить к каждому атрибуту в данныхgetter
иsetter
, при созданииdep
иwatcher
провести依赖收集
и派发更新
, наконец черезdiff
Алгоритм сравнивает разницу между новым и старым vnode черезpatch
Мгновенное обновление DOM
Простая схема:
Подробная версия
Вы можете обратиться к следующемуАдрес ссылки на изображение: Иллюстрация принципа отзывчивости Vue
Почему данные Vue часто меняются, но обновляются только один раз
- Обнаружено изменение данных
- открыть очередь
- Буферизировать все изменения данных в одном и том же цикле событий
- если то же самое
watcher (watcherId相同)
Запускается несколько раз, он будет помещен только в очередь一次
Без оптимизации каждое изменение данных будет выполняться:setter->Dep->Watcher->update->run
Оптимизировано:执行顺序update -> queueWatcher -> 维护观察者队列(重复id的Watcher处理) -> waiting标志位处理 -> 处理$nextTick(在为微任务或者宏任务中异步更新DOM)
Vue использует дефекты Object.defineProperty()
Свойство длины массива инициализируетсяconfigurable false
, поэтому невозможно прослушивать свойство length с помощью метода get/set.
In vue путем перезаписи七个
Метод, который может изменить исходный массив для мониторинга данных
Объект по-прежнему использует Object.defineProperty() для добавления get и set для прослушивания.
Ссылаться на
-
Vue изменяет данные через индекс массива, изменится ли представление?
-
Почему defineProperty не может обнаружить изменения в длине массива
Принцип Vue.nextTick()
Отложенный обратный вызов выполняется после завершения следующего цикла обновления DOM. Используйте этот метод сразу после изменения данных, чтобы получить обновленную модель DOM.
Реализация исходного кода:Promise > MutationObserver > setImmediate > setTimeout
Справочная статья:Анализ принципа работы Vue.nextTick()
Принцип реализации вычисляемого
по сути, это наблюдатель с ленивой оценкойcomputed watcher
. через его внутреннююthis.dirty
Свойство указывает на необходимость повторной оценки вычисляемого свойства.
- При изменении состояния зависимости вычисляемого ленивый наблюдатель будет уведомлен,
computed watcher
пройти черезthis.dep.subs.length
Определить, есть ли подписчики, - Если есть, то он будет пересчитан, а затем будут сравнены новые и старые значения, и если они изменились, то будут перерендерены. (Vue хочет убедиться, что это не просто значение, от которого зависит вычисляемое свойство, но когда вычисляемое свойство изменяется
最终计算的值
изменяется только тогда, когда触发渲染 watcher
Ререндеринг — это, по сути, оптимизация. ) - Если нет, просто поставьте
this.dirty = true
(Когда вычисляемое свойство зависит от других данных, это свойство не будет пересчитано немедленно. Оно будет вычислено только тогда, когда свойство нужно будет прочитать в другом месте позже, то есть оно имеет функцию ленивых (ленивых вычислений).)
Понимание часов
watch
Кеширования нет, это скорее функция наблюдения, которая может отслеживать определенные данные для выполнения обратных вызовов. когда нам нужно深度监听对象中
, вы можете включить опцию deep: true, которая будет отслеживать каждый элемент в объекте. Это приведет к проблемам с производительностью.Если вы оптимизируете, вы можете использовать мониторинг строковой формы.
Примечание. Watcher: Объект наблюдателя, экземпляры делятся на渲染 watcher
(render watcher),计算属性 watcher
(computed watcher),侦听器 watcher
(наблюдатель за пользователем) три
vue алгоритм сравнения
- Сравните только старый и новый дочерние узлы с одним и тем же родительским узлом (сравнивается Vnode), а временная сложность составляет всего O (n)
- При сравнении diff петля сходится с обеих сторон к середине
Процесс сравнения нового и старого узла
1. Первый找
К тому же узлу, который не нужно перемещать, поиск повторно используемого узла с помощью значения ключа является наименее затратным.
2. Найти такой же, но нужный移动
узел, который потребляет второй по величине
3. В конце концов, если вы не можете найти его, вы пойдете新建删除
Узел, гарантированная обработка дна
Примечание. В процессе сравнения старых и новых узлов два дерева Vnode не будут изменены.比较的结果直接对 真实DOM 进行修改
Патч Vue即时的
, чтобы не упаковывать все модификации и, наконец, вместе манипулировать DOM (React ставит обновления в очередь и обрабатывает их централизованно)
Справочная статья:Подробное объяснение принципа Vue virtual dom diff
процесс рендеринга vue
- перечислить
compile
function для генерации строки функции рендеринга, процесс компиляции выглядит следующим образом:
- parse использует большое количество регулярных выражений для анализа строки шаблона и преобразует теги, инструкции, атрибуты и т. д. в абстрактные синтаксические деревья AST.
模板 -> AST (最消耗性能)
- Оптимизация проходит через AST, находит некоторые статические узлы и помечает их, чтобы эти статические узлы можно было пропустить непосредственно при сравнении различий при повторном отображении страницы.
优化runtime的性能
- Generate преобразует окончательный AST в строку функции рендеринга.
- перечислить
new Watcher
Функция, отслеживающая изменения данных, когда данные изменяются, функция рендеринга выполняется для создания объектов vnode. - перечислить
patch
метод, сравнивайте старые и новые объекты vnode, а также добавляйте, изменяйте и удаляйте реальные элементы DOM с помощью алгоритма DOM diff.
В сочетании с исходным кодом расскажите о жизненном цикле vue.
Официальная схема жизненного цикла Vue
Для чего используются ключи в Vue?
Ключ — это уникальный идентификатор, присвоенный каждому vnode, в зависимости от ключа наша операция сравнения может быть более точной и быстрой.
Точнее: поскольку ключ не используется повторно на месте, повторного использования на месте можно избежать в той же самой функции Node a.key === сравнение b.key. Поэтому будет точнее, если ключ не добавить, то сохранится состояние предыдущей ноды, что вызовет ряд багов.
Быстрее: ключи唯一性
Он может быть полностью использован структурой данных Map.По сравнению с временной сложностью обходного поиска O (n), временная сложность Map составляет всегоO(1)
, исходный код выглядит следующим образом:
function createKeyToOldIdx(children, beginIdx, endIdx) {
let i, key;
const map = {};
for (i = beginIdx; i <= endIdx; ++i) {
key = children[i].key;
if (isDef(key)) map[key] = i;
}
return map;
}
Примечание: в没有key
случае, это будет быстрее. Спасибо за раздел комментариев братанfengyangyangНапоминание:
Цитируя официальный сайт: специальный атрибут ключа в основном используется в алгоритме виртуального DOM Vue для идентификации VNodes при сравнении старых и новых узлов.如果不使用 key
, Vue будет использовать最大限度减少动态元素
и старайся как можно больше就地修改/复用
Алгоритмы для элементов одного типа. При использовании ключа он изменит порядок элементов на основе изменения ключа и удалит элементы, ключ которых не существует.
Существует несколько режимов маршрутизации vue-router.
По умолчанию:"hash"
(среда браузера) |"abstract"
(среда Node.js)
Дополнительные значения:"hash"
| "history"
| "abstract"
Настройте режим маршрутизации:
-
hash
: использовать хэш URL для маршрутизации.支持所有浏览器
, включая браузеры, не поддерживающие HTML5 History API. -
history
: зависит отHTML5 History API
и конфигурация сервера. -
abstract
: поддерживает все среды выполнения JavaScript, такие как серверная часть Node.js. Маршруты автоматически переводятся в этот режим, если API браузера не найден.
Расскажите о принципе реализации keep-alive
определение
keep-alive
Компонент принимает три параметра свойства:include
,exclude
,max
-
include
Укажите, что нужно кэшировать组件name
Коллекция, поддержка форматов параметровString, RegExp, Array。
Когда это строка, несколько имен компонентов разделяются запятыми. -
exclude
Указывает, что кэширование не требуется组件name
Collection, формат параметра такой же, как и include. -
max
Указывает максимальное количество компонентов, которые можно кэшировать, и удаляет первый компонент, если это число превышается. Формат параметра поддерживает строки и числа.
принцип
keep-alive
Экземпляр будет кэшировать виртуальный узел соответствующего компонента.При попадании в кеш соответствующий виртуальный узел будет возвращен непосредственно из объекта кеша.
LRU(Least recently used)
Алгоритм удаляет данные на основе исторических записей доступа к данным. Основная идея заключается в том, что «если доступ к данным был осуществлен недавно, вероятность доступа к ним в будущем также выше». (Закон Мерфи: чем больше вы беспокоитесь, тем больше вероятность того, что это произойдет)
Методы разрешения для доступа к свойствам объекта
например: посетите a.b.c.d
каррирование функции + замыкание + рекурсия
function createGetValueByPath( path ) {
let paths = path.split( '.' ); // [ xxx, yyy, zzz ]
return function getValueByPath( obj ) {
let res = obj;
let prop;
while( prop = paths.shift() ) {
res = res[ prop ];
}
return res;
}
}
let getValueByPath = createGetValueByPath( 'a.b.c.d' );
var o = {
a: {
b: {
c: {
d: {
e: '正确了'
}
}
}
}
};
var res = getValueByPath( o );
console.log( res );
Переписать 7 методов массива в vue
Вью через原型拦截
способ переписать 7 методов массива, сначала получить значение массиваObserver
. Если есть новое значение, вызовитеobserveArray
Прослушайте новое значение, затем вызовитеnotify
,Уведомлениеrender watcher
,воплощать в жизньupdate
const arrayProto = Array.prototype;
export const arrayMethods = Object.create(arrayProto);
const methodsToPatch = [
"push",
"pop",
"shift",
"unshift",
"splice",
"sort",
"reverse"
];
methodsToPatch.forEach(function(method) {
// cache original method
const original = arrayProto[method];
def(arrayMethods, method, function mutator(...args) {
const result = original.apply(this, args);
const ob = this.__ob__;
let inserted;
switch (method) {
case "push":
case "unshift":
inserted = args;
break;
case "splice":
inserted = args.slice(2);
break;
}
if (inserted) ob.observeArray(inserted);
// notify change
ob.dep.notify();
return result;
});
});
Observer.prototype.observeArray = function observeArray(items) {
for (var i = 0, l = items.length; i < l; i++) {
observe(items[i]);
}
};
vue обрабатывает реактивную реализацию defineReactive
// 简化后的版本
function defineReactive( target, key, value, enumerable ) {
// 折中处理后, this 就是 Vue 实例
let that = this;
// 函数内部就是一个局部作用域, 这个 value 就只在函数内使用的变量 ( 闭包 )
if ( typeof value === 'object' && value != null && !Array.isArray( value ) ) {
// 是非数组的引用类型
reactify( value ); // 递归
}
Object.defineProperty( target, key, {
configurable: true,
enumerable: !!enumerable,
get () {
console.log( `读取 ${key} 属性` ); // 额外
return value;
},
set ( newVal ) {
console.log( `设置 ${key} 属性为: ${newVal}` ); // 额外
value = reactify( newVal );
}
} );
}
Vue отзывчивая реактивная реализация
// 将对象 o 响应式化
function reactify( o, vm ) {
let keys = Object.keys( o );
for ( let i = 0; i < keys.length; i++ ) {
let key = keys[ i ]; // 属性名
let value = o[ key ];
if ( Array.isArray( value ) ) {
// 数组
value.__proto__ = array_methods; // 数组就响应式了
for ( let j = 0; j < value.length; j++ ) {
reactify( value[ j ], vm ); // 递归
}
} else {
// 对象或值类型
defineReactive.call( vm, o, key, value, true );
}
}
}
Почему доступ к атрибуту данных не требует данных
Доступ к недвижимости Proxy it.data.xxx в Vue для преобразования реализации этого.xxx
/** 将 某一个对象的属性 访问 映射到 对象的某一个属性成员上 */
function proxy( target, prop, key ) {
Object.defineProperty( target, key, {
enumerable: true,
configurable: true,
get () {
return target[ prop ][ key ];
},
set ( newVal ) {
target[ prop ][ key ] = newVal;
}
} );
}
Ссылочные статьи (кроме того, где статья уже говорится)
- Демистификация технологии Vue.js
- «Вопросы для интервью» 20 + Vue Вопросы для интервью
- 12 вопросов о Vue, основанных на принципах высокой частоты, на сколько вы можете ответить?
- Анализ исходного кода Vue станции B (видео отсутствует)
- Исходный код vue, который вы ищете, находится здесь
- Инсайдер технологии Vue