предисловие
В этой статье в основном написан исходный код Vue2.0 от руки.Принцип асинхронного обновления
В предыдущей статье мы в основном представили VueПринцип обновления рендерингаМы уже можем реализовать автоматическое обновление изменений данных и представлений, поэтому эта статья в основном посвящена оптимизации производительности обновлений представлений, включая nextTick, важную реализацию API.
Для людей:Учащиеся, у которых нет времени смотреть официальный исходный код или которые запутались и не хотят смотреть исходный код
Предложение: в этой статье рассматриваются концепции, связанные с циклом событий js.Студенты, которые не очень хорошо разбираются в макрозадачах и микрозадачах, могут сначала просмотреть соответствующие материалы.
текст
<script>
// Vue实例化
let vm = new Vue({
el: "#app",
data() {
return {
a: 123,
};
},
// render(h) {
// return h('div',{id:'a'},'hello')
// },
template: `<div id="a">hello {{a}}</div>`,
});
// 当我们每一次改变数据的时候 渲染watcher都会执行一次 这个是影响性能的
setTimeout(() => {
vm.a = 1;
vm.a = 2;
vm.a = 3;
}, 1000);
</script>
Подумайте об этом. Согласно предыдущей логике, каждый раз, когда мы изменяем данные, соответствующий наблюдатель будет запускаться для обновления. Если наблюдатель отображается, означает ли это, что данные будут повторно отображаться после изменения данных? на самом деле пустая трата производительности. Можем ли мы сделать лучше? Метод для равномерного обновления представления после завершения изменения данных.
1. Переписать обновление наблюдателя
// src/observer/watcher.js
import { queueWatcher } from "./scheduler";
export default class Watcher {
update() {
// 每次watcher进行更新的时候 是否可以让他们先缓存起来 之后再一起调用
// 异步队列机制
queueWatcher(this);
}
run() {
// 真正的触发更新
this.get();
}
}
Давайте изменим метод обновления обновления, чтобы увеличить механизм асинхронной очереди.
2.queueWatcher реализует механизм очереди
// src/observer/scheduler.js
import { nextTick } from "../util/next-tick";
let queue = [];
let has = {};
function flushSchedulerQueue() {
for (let index = 0; index < queue.length; index++) {
// 调用watcher的run方法 执行真正的更新操作
queue[index].run();
}
// 执行完之后清空队列
queue = [];
has = {};
}
// 实现异步队列机制
export function queueWatcher(watcher) {
const id = watcher.id;
// watcher去重
if (has[id] === undefined) {
// 同步代码执行 把全部的watcher都放到队列里面去
queue.push(watcher);
has[id] = true;
// 进行异步调用
nextTick(flushSchedulerQueue);
}
}
}
В новом файле scheduler.js указано, что он связан с планированием. Во-первых, синхронно поставьте наблюдателей в очередь. После выполнения событий в очереди очистите очередь. В основном используйте nextTick для выполнения очереди наблюдателей.
3. Принцип реализации NextTick
// src/util/next-tick.js
let callbacks = [];
let pending = false;
function flushCallbacks() {
pending = false; //把标志还原为false
// 依次执行回调
for (let i = 0; i < callbacks.length; i++) {
callbacks[i]();
}
}
let timerFunc; //定义异步方法 采用优雅降级
if (typeof Promise !== "undefined") {
// 如果支持promise
const p = Promise.resolve();
timerFunc = () => {
p.then(flushCallbacks);
};
} else if (typeof MutationObserver !== "undefined") {
// MutationObserver 主要是监听dom变化 也是一个异步方法
let counter = 1;
const observer = new MutationObserver(flushCallbacks);
const textNode = document.createTextNode(String(counter));
observer.observe(textNode, {
characterData: true,
});
timerFunc = () => {
counter = (counter + 1) % 2;
textNode.data = String(counter);
};
} else if (typeof setImmediate !== "undefined") {
// 如果前面都不支持 判断setImmediate
timerFunc = () => {
setImmediate(flushCallbacks);
};
} else {
// 最后降级采用setTimeout
timerFunc = () => {
setTimeout(flushCallbacks, 0);
};
}
export function nextTick(cb) {
// 除了渲染watcher 还有用户自己手动调用的nextTick 一起被收集到数组
callbacks.push(cb);
if (!pending) {
// 如果多次调用nextTick 只会执行一次异步 等异步队列清空之后再把标志变为false
pending = true;
timerFunc();
}
}
Новый util/next-tick.js представляет собой инструментальную функцию, потому что пользователи nextTick также могут вызывать ее вручную Основная идея заключается в использовании метода микрозадачи для вызова асинхронного метода для выполнения метода, обернутого nextTick.
4. Прототип монтирования $nextTick
// src/render.js
import { nextTick } from "./util/next-tick";
export function renderMixin(Vue) {
// 挂载在原型的nextTick方法 可供用户手动调用
Vue.prototype.$nextTick = nextTick;
}
Наконец, смонтируйте $nextTick в прототип Vue.
4. Асинхронно обновляемая карта разума
резюме
На данный момент принцип асинхронного обновления Vue завершен.Основной принцип заключается в том, что nextTick реализует асинхронные очереди.Предпосылка заключается в том, что вам необходимо понять механизм цикла событий js.Вы можете посмотреть на карту ума и написать основной код самостоятельно. , Если вы не понимаете или у вас есть споры, пожалуйста, оставьте комментарий.
Наконец, если вы найдете эту статью полезной, помнитеКак СанлияБольшое спасибо!
Ссылка на сериал (будет обновлена позже)
- Написанный от руки исходный код Vue2.0 (1) — принцип адаптивных данных
- Рукописный исходный код Vue2.0 (2) - принцип компиляции шаблона
- Рукописный исходный код Vue2.0 (3) — принцип начального рендеринга
- Рукописный исходный код Vue2.0 (четыре) — принцип обновления рендеринга
- Рукописный исходный код Vue2.0 (5) - принцип асинхронного обновления
- Рукописный исходный код Vue2.0 (6) - принцип алгоритма diff
- Рукописный исходный код Vue2.0 (7) - Принцип микширования
- Рукописный исходный код Vue2.0 (8)-компонентный принцип
- Рукописный исходный код Vue2.0 (9) - принцип свойства прослушивания
- Рукописный исходный код Vue2.0 (10) — Принцип вычисляемых свойств
- Рукописный исходный код Vue2.0 (11) — принцип глобального API
- Самые полные вопросы интервью Vue + подробные ответы
- Рукописный исходный код vue-router
- Рукописный исходный код vuex
- Рукописный исходный код vue3.0
Группа передовых рыболовных технологий Brother Shark
Приветствую всех на технических биржахСвязь