предисловие
В этой статье в основном написан исходный код Vue2.0 от руки.глобальный принцип API
В предыдущей статье мы в основном представили VueПринципы вычислительных свойствЗнайте, как реализованы функции кэширования вычисляемых свойств. Пока что мы в основном написали основное содержимое всего исходного кода Vue. Затем в этой статье разберемся с глобальным API Vue.
Для людей:
1. Хотите иметь глубокое понимание исходного кода vue для лучшего ежедневного развития бизнеса
2. Хотите владеть исходным кодом vue framework в резюме (больше не боитесь вопросов интервьюера о серийных убийцах, ха-ха)
3. Учащиеся, у которых нет времени смотреть официальный исходный код или им трудно понять с первого взгляда исходный код
1 Vue.util
// src/global-api/index.js
// exposed util methods.
// NOTE: these are not considered part of the public API - avoid relying on
// them unless you are aware of the risk.
Vue.util = {
warn,
extend,
mergeOptions,
defineReactive,
};
Vue.util — это инструментальный метод внутри Vue. Не рекомендуется использовать бизнес-компоненты, поскольку они могут меняться с версией. Если мы не будем разрабатывать сторонние плагины Vue, он будет использоваться меньше.
2 Vue.set / Vue.delete
export function set(target: Array<any> | Object, key: any, val: any): any {
// 如果是数组 直接调用我们重写的splice方法 可以刷新视图
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key);
target.splice(key, 1, val);
return val;
}
// 如果是对象本身的属性,则直接添加即可
if (key in target && !(key in Object.prototype)) {
target[key] = val;
return val;
}
const ob = (target: any).__ob__;
// 如果对象本身就不是响应式 不需要将其定义成响应式属性
if (!ob) {
target[key] = val;
return val;
}
// 利用defineReactive 实际就是Object.defineProperty 将新增的属性定义成响应式的
defineReactive(ob.value, key, val);
ob.dep.notify(); // 通知视图更新
return val;
}
export function del(target: Array<any> | Object, key: any) {
// 如果是数组依旧调用splice方法
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.splice(key, 1);
return;
}
const ob = (target: any).__ob__;
// 如果对象本身就没有这个属性 什么都不做
if (!hasOwn(target, key)) {
return;
}
// 直接使用delete 删除这个属性
delete target[key];
// 如果对象本身就不是响应式 直接返回
if (!ob) {
return;
}
ob.dep.notify(); //通知视图更新
}
На самом деле эти два API используются во многих бизнес-сценариях: метод set используется для добавления реагирующих данных, метод delete используется для удаления реагирующих данных, поскольку весь процесс реагирования Vue опирается на базовый API Object.defineProperty, но только этот API Он может захватить объявленные в настоящее время свойства объекта, поэтому недавно добавленные свойства не являются чувствительными данными, и прямое изменение индекса массива не приведет к обновлению представления.Это связано с соображениями производительности, поэтому нам нужно использовать $set и $delete для работы.Если вы не знакомы с принципом отзывчивости, вы можете прочитатьНаписанный от руки исходный код Vue2.0 (1) — принцип адаптивных данных
3 Vue.nextTick
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();
}
}
nextTick является ядром асинхронного обновления Vue. Этот API также часто используется в реальном бизнесе. Как правило, он используется для получения свойств, связанных с узлом dom, сразу после изменения данных. Затем вы можете поместить такой метод в nextTick, чтобы реализовать принцип асинхронного обновления.Рукописный исходный код Vue2.0 (5) - принцип асинхронного обновления
4 Vue.observable
Vue.observable = <T>(obj: T): T => {
observe(obj);
return obj;
};
Суть заключается в вызове метода наблюдения для преобразования входящих данных в реагирующий объект, который можно использовать для создания глобальных переменных и обмена данными между компонентами.Подробности см. в методе наблюдения.Принцип реактивных данных — захват данных объектов
5 Vue.options
Vue.options = Object.create(null);
ASSET_TYPES.forEach((type) => {
Vue.options[type + "s"] = Object.create(null);
});
// this is used to identify the "base" constructor to extend all plain-object
// components with in Weex's multi-instance scenarios.
Vue.options._base = Vue;
extend(Vue.options.components, builtInComponents); //内置组件
Vue.options — это контейнер для директив и фильтров компонентов, а Vue.options._base указывает на конструктор Vue.
6 Vue.use
Vue.use = function (plugin: Function | Object) {
const installedPlugins =
this._installedPlugins || (this._installedPlugins = []);
if (installedPlugins.indexOf(plugin) > -1) {
// 如果安装过这个插件直接返回
return this;
}
const args = toArray(arguments, 1); // 获取参数
args.unshift(this); //在参数中增加Vue构造函数
if (typeof plugin.install === "function") {
plugin.install.apply(plugin, args); // 执行install方法
} else if (typeof plugin === "function") {
plugin.apply(null, args); // 没有install方法直接把传入的插件执行
}
// 记录安装的插件
installedPlugins.push(plugin);
return this;
};
Vue.use в основном используется для регистрации плагина, вызова метода установки плагина и передачи собственного Vue в метод установки плагина, чтобы избежать сильной зависимости сторонних плагинов от Vue.
7 Vue.mixin
export function initMixin(Vue: GlobalAPI) {
Vue.mixin = function (mixin: Object) {
this.options = mergeOptions(this.options, mixin); //只要调用mergeOptions来合并选项
return this;
};
}
/**
* Merge two option objects into a new one.
* Core utility used in both instantiation and inheritance.
*/
export function mergeOptions(
parent: Object,
child: Object,
vm?: Component
): Object {
if (!child._base) {
// 这个代表是组件 需要先把自己定义的extends和mixins与父级属性进行合并
if (child.extends) {
parent = mergeOptions(parent, child.extends, vm);
}
if (child.mixins) {
for (let i = 0, l = child.mixins.length; i < l; i++) {
parent = mergeOptions(parent, child.mixins[i], vm);
}
}
}
// 把自己的和父亲的属性进行合并
const options = {};
let key;
for (key in parent) {
mergeField(key);
}
for (key in child) {
if (!hasOwn(parent, key)) {
mergeField(key);
}
}
function mergeField(key) {
//真正合并字段的方法
const strat = strats[key] || defaultStrat; //strats代表合并策略 会优先查找对应的合并策略 找不到就用默认的合并策略
options[key] = strat(parent[key], child[key], vm, key);
}
return options;
}
Vue.mixin — это глобальный метод микширования. Обычно он используется для извлечения глобальных общедоступных методов и свойств. Если вы хотите узнать больше об этом, вы можете увидетьРукописный исходный код Vue2.0 (7) - Принцип микширования
8 Vue.extend
Vue.extend = function (extendOptions: Object): Function {
const Sub = function VueComponent(options) {
// 创建子类的构造函数 并且调用初始化方法
this._init(options);
};
Sub.prototype = Object.create(Super.prototype); // 子类原型指向父类
Sub.prototype.constructor = Sub; //constructor指向自己
Sub.options = mergeOptions(
//合并自己的options和父类的options
Super.options,
extendOptions
);
return Sub;
};
Vue.extend называется конструктором компонентов. Создание компонентов Vue зависит от этого API. Фактически, он использует прототипное наследование для создания подклассов, наследуемых от Vue. Если вас интересует инициализация и рендеринг компонентов, см.Рукописный исходный код Vue2.0 (8)-компонентный принцип
9 компонентов, директивы, фильтры
export function initAssetRegisters(Vue: GlobalAPI) {
var ASSET_TYPES = ["component", "directive", "filter"];
/**
* Create asset registration methods.
*/
ASSET_TYPES.forEach((type) => {
Vue[type] = function (
id: string,
definition: Function | Object
): Function | Object | void {
if (!definition) {
return this.options[type + "s"][id];
} else {
if (type === "component" && isPlainObject(definition)) {
definition.name = definition.name || id;
definition = this.options._base.extend(definition);
}
if (type === "directive" && typeof definition === "function") {
definition = { bind: definition, update: definition };
}
this.options[type + "s"][id] = definition; //把组件 指令 过滤器 放到Vue.options中
return definition;
}
};
});
}
Определите три API Vue.component Vue.directive Vue.filter и отформатируйте входящий контент пользователя и, наконец, поместите результат в Vue.options.
10 глобальных ассоциативных карт API
резюме
На данный момент глобальный принцип API Vue завершен. По сути, мы написали много основных API для принципов серии Vue ранее. Они чаще используются в ежедневном процессе разработки, а также являются общими тестовыми площадками для интервью. Вы можете посмотреть на карту разума и сделать это самостоятельно.Напишите основной код еще раз.Если вы столкнулись с чем-то, что вы не понимаете или у вас есть споры, пожалуйста, оставьте комментарий.
Наконец, если вы найдете эту статью полезной, помнитеКак СанлианБольшое спасибо!
Ссылка на сериал (будет обновлена позже)
- Написанный от руки исходный код 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
Приветствую всех на технических биржахСвязь