Эта статья участвовала в "Проект «Звезда раскопок»”, чтобы выиграть творческий подарочный пакет и бросить вызов творческим поощрительным деньгам.
1. Введение
Привет всем, яВакагава. Добро пожаловать, чтобы следовать за мнойПубличный аккаунт Wakagawa Vision, недавно организованныйЧтение исходного кода, если вам интересно, вы можете добавить меня в WeChatruochuan12Участие продолжается уже больше двух месяцев, все вместе общались, учились и вместе двигались вперед, многие говорили, что многого добились.
Если вы хотите изучить исходный код, я настоятельно рекомендую то, что я написал ранее"Изучение серии "Общая архитектура исходного кода""ВключатьjQuery
,underscore
,lodash
,vuex
,sentry
,axios
,redux
,koa
,vue-devtools
,vuex4
,koa-compose
,vue 3.2 发布
,vue-this
,create-vue
,玩具vite
Более 10 статей исходного кода.
Эта статья Warehouse Vue-анализ, найти звезду ^ _ ^
недавно организованныйЧтение исходного кода, Давайте вместе изучим исходный код. Поэтому ищите разнообразный исходный код, который стоит изучить и содержит небольшое количество строк кода.
писал раньшеVue3
Две связанные статьи.
это написаноКак изучить основы JavaScript,Рекомендуемые книги и учебные материалы,И немного из моего опыта, чтобы поделиться.
присоединитьсяЧитайте исходный код вместеотзывов читателей о том, что TA на самом деле все еще используетVue2
. Вы можете написатьVue2
Основные служебные функции. какблогер знанийСкромный Лорд ЧислаДухИзучайте то, что я узнаю, используйте это для себя, помогайте другимцель, поэтому я написал эту статью. считатьVue3
вспомогательная функциясестра.
Прочитав эту статью, вы узнаете:
1. Vue2 源码 shared 模块中的几十个实用工具函数
2. 如何学习源码中优秀代码和思想,投入到自己的项目中
3. 如何学习 JavaScript 基础知识,会推荐很多学习资料
4. 我的一些经验分享
5. 等等
2. Подготовка окружающей среды
2.1 Прочтите Руководство по участию в проектах с открытым исходным кодом
Открытьvue-репозиторий,
Проекты с открытым исходным кодом обычно можно найти вREADME.md
или.github/contributing.mdНайдите рекомендации по содействию.
И Contribution Guide много пишет об участии в разработке проекта. Например, как запустить, какова структура каталогов проекта. Как инвестировать в развитие, какие нужны резервы знаний и т.д.
мы можемСтруктура каталогов проектаописание, найденоshared
модуль.
shared
: contains utilities shared across the entire codebase.
README.md
а такжеcontributing.md
Обычно на английском языке. Некоторые люди могут быть поставлены в тупик. На самом деле, если вы не можете понять это, вы можете использовать инструменты перевода, такие как перевод с разметкой слов, полностраничный перевод и перевод Google. Затем добавьте английский язык в план последующего обучения.
Эта статья оshared
модуль, соответствующий путь к файлу:vue/vue/src/shared
.
также можно использоватьgithub1s
доступ, быстрее.github1s vue/vue/src/shared
2.2 Чтобы упростить статью, непосредственно изучите упакованный исходный код.
исходный кодvue/vue/src/shared
,использовалFlowтип, который может быть не совсем понятен.
Чтобы уменьшить сложность статьи, мы напрямую учимся из репозитория исходного кода.Упакованная строка dist/vue.js с 14 по 379..
Конечно, передняя часть может быть более подробной. я могу говорить прямо
3. 工具函数
. Но благодаря моему вступлению выше даже новички могут понять исходный код некоторых проектов с открытым исходным кодом, и, возможно, у них будет определенное чувство выполненного долга. Кроме того, когда на собеседовании задаются аналогичные вопросы или письменные контрольные вопросы, вы говоритеVue2
Если вы узнаете из исходного кода, интервьюер обязательно посмотрит на вас с восхищением.
3. Вспомогательные функции
Упакованная линия Vue.js 14 до 379, следующий должен объяснить эти методы.
3.1 emptyObject
/*!
* Vue.js v2.6.14
* (c) 2014-2021 Evan You
* Released under the MIT License.
*/
/* */
var emptyObject = Object.freeze({});
Заморозить объекты. Первый слой не может быть изменен. У объекта также есть метод, чтобы определить, замораживать или нет.
Object.isFrozen(emptyObject); // true
Об объектахAPI
Рекомендую прочитать мои предыдущие статьиВесь API-анализ объектов JavaScript
Вы также можете увидеть работы Учителя Жуань Ифэна.Вводная книга ES6 отражает
3.2 IsUndef не определен?
// These helpers produce better VM code in JS engines due to their
// explicitness and function inlining.
function isUndef (v) {
return v === undefined || v === null
}
3.3 Определен ли isDef?
JavaScript
Есть шесть ложных значений.
false
null
undefined
0
'' (空字符串)
NaN
Чтобы судить точно, исходный код Vue2 инкапсулирован вisDef
,isTrue
,isFalse
функция точного суждения.
См. имя.
function isDef (v) {
return v !== undefined && v !== null
}
3.4 Верно ли isTrue?
См. имя.
function isTrue (v) {
return v === true
}
3.5 Является ли isFalse ложным
См. имя.
function isFalse (v) {
return v === false
}
3.6 isPrimitive определяет, является ли значение примитивным значением.
Определите, является ли это строкой, массивом илиsymbol
или логическое значение.
/**
* Check if value is primitive.
*/
function isPrimitive (value) {
return (
typeof value === 'string' ||
typeof value === 'number' ||
// $flow-disable-line
typeof value === 'symbol' ||
typeof value === 'boolean'
)
}
3.7 Оценка isObject — это объект
потому чтоtypeof null
является «объектом». Массивы и т. д. также верны, если судить по этой функции.
/**
* Quick object check - this is primarily used to tell
* Objects from primitive values when we know the value
* is a JSON-compliant type.
*/
function isObject (obj) {
return obj !== null && typeof obj === 'object'
}
// 例子:
isObject([]) // true
// 有时不需要严格区分数组和对象
3.8 toRawType преобразуется в необработанный тип
Object.prototype.toString()
Метод возвращает строку, представляющую объект.
спецификация экма, который описывает эти типы.
ECMAScript5.1 китайская версия
/**
* Get the raw type string of a value, e.g., [object Object].
*/
var _toString = Object.prototype.toString;
function toRawType (value) {
return _toString.call(value).slice(8, -1)
}
// 例子:
toRawType('') // 'String'
toRawType() // 'Undefined'
3.9 Является ли isPlainObject чистым объектом
/**
* Strict object type check. Only returns true
* for plain JavaScript objects.
*/
function isPlainObject (obj) {
return _toString.call(obj) === '[object Object]'
}
// 上文 isObject([]) 也是 true
// 这个就是判断对象是纯对象的方法。
// 例子:
isPlainObject([]) // false
isPlainObject({}) // true
3.10 Является ли isRegExp регулярным выражением
function isRegExp (v) {
return _toString.call(v) === '[object RegExp]'
}
// 例子:
// 判断是不是正则表达式
isRegExp(/ruochuan/) // true
3.11 Является ли isValidArrayIndex допустимым значением индекса массива?
Доступные значения индекса для массива: 0 ('0'), 1 ('1'), 2 ('2')...
/**
* Check if val is a valid array index.
*/
function isValidArrayIndex (val) {
var n = parseFloat(String(val));
return n >= 0 && Math.floor(n) === n && isFinite(val)
}
глобальныйisFinite()
Функция используется для определения того, является ли переданное значение параметра конечным значением (finite number
). При необходимости параметр сначала преобразуется в числовое значение.
isFinite(Infinity); // false
isFinite(NaN); // false
isFinite(-Infinity); // false
isFinite(0); // true
isFinite(2e64); // true, 在更强壮的Number.isFinite(null)中将会得到false
isFinite('0'); // true, 在更强壮的Number.isFinite('0')中将会得到false
3.12 isPromise определяет, является ли это обещанием
function isPromise (val) {
return (
isDef(val) &&
typeof val.then === 'function' &&
typeof val.catch === 'function'
)
}
// 例子:
isPromise(new Promise()) // true
использовать здесьisDef
Суждение относительноisObject
Немного неточно судить. Но достаточно.
3.13 toString в строку
Преобразовать в строку. представляет собой массив или объект, а объектtoString
путьObject.prototype.toString
,использоватьJSON.stringify
конвертировать.
/**
* Convert a value to a string that is actually rendered.
*/
function toString (val) {
return val == null
? ''
: Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
? JSON.stringify(val, null, 2)
: String(val)
}
3.14 toNumber to Number
Преобразовать в числа. Если преобразование не удалось, возвращается исходная строка.
/**
* Convert an input value to a number for persistence.
* If the conversion fails, return original string.
*/
function toNumber (val) {
var n = parseFloat(val);
return isNaN(n) ? val : n
}
toNumber('a') // 'a'
toNumber('1') // 1
toNumber('1a') // 1
toNumber('a1') // 'a1'
3.15 makeMap генерирует карту (объект)
Передайте строку, разделенную запятыми, чтобы сгенерироватьmap
(пара ключ-значение) и возвращает функцию для обнаруженияkey
Является ли ценность в этомmap
середина. Второй параметр — это вариант нижнего регистра.
/**
* Make a map and return a function for checking if a key
* is in that map.
*/
function makeMap (
str,
expectsLowerCase
) {
var map = Object.create(null);
var list = str.split(',');
for (var i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase
? function (val) { return map[val.toLowerCase()]; }
: function (val) { return map[val]; }
}
// Object.create(null) 没有原型链的空对象
3.16 Является ли isBuiltInTag встроенным тегом?
/**
* Check if a tag is a built-in tag.
*/
var isBuiltInTag = makeMap('slot,component', true);
// 返回的函数,第二个参数不区分大小写
isBuiltInTag('slot') // true
isBuiltInTag('component') // true
isBuiltInTag('Slot') // true
isBuiltInTag('Component') // true
3.17 Является ли isReservedAttribute зарезервированным атрибутом?
/**
* Check if an attribute is a reserved attribute.
*/
var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is');
isReservedAttribute('key') // true
isReservedAttribute('ref') // true
isReservedAttribute('slot') // true
isReservedAttribute('slot-scope') // true
isReservedAttribute('is') // true
isReservedAttribute('IS') // undefined
3.18 удалить: удаляет элемент из массива.
/**
* Remove an item from an array.
*/
function remove (arr, item) {
if (arr.length) {
var index = arr.indexOf(item);
if (index > -1) {
return arr.splice(index, 1)
}
}
}
splice
На самом деле, это очень ресурсоемкий метод. Чтобы удалить элемент в массиве, все остальные элементы должны быть перемещены.
Расширенный:axios InterceptorManager
Исходный код перехватчика, перехватчики хранятся в массиве. Но при фактическом удалении перехватчика просто установите перехватчик наnull
. Вместо того, чтобы использоватьsplice
Удалить. Последнее исполнениеnull
не реализует, тот же эффект.axios
Следует сказать, что в сценарии с перехватчиком большое внимание уделялось производительности.Поскольку перехватчики определяются пользователем, теоретически их может быть бесконечное количество, поэтому необходимо учитывать производительность..
Смотри нижеaxios
Пример кода перехватчика:
// 代码有删减
// 声明
this.handlers = [];
// 移除
if (this.handlers[id]) {
this.handlers[id] = null;
}
// 执行
if (h !== null) {
fn(h);
}
3.19 hasOwn определяет, является ли это его собственным свойством
/**
* Check whether an object has the property.
*/
var hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn (obj, key) {
return hasOwnProperty.call(obj, key)
}
// 例子:
// 特别提醒:__proto__ 是浏览器实现的原型写法,后面还会用到
// 现在已经有提供好几个原型相关的API
// Object.getPrototypeOf
// Object.setPrototypeOf
// Object.isPrototypeOf
// .call 则是函数里 this 显示指定以为第一个参数,并执行函数。
hasOwn({__proto__: { a: 1 }}, 'a') // false
hasOwn({ a: undefined }, 'a') // true
hasOwn({}, 'a') // false
hasOwn({}, 'hasOwnProperty') // false
hasOwn({}, 'toString') // false
// 是自己的本身拥有的属性,不是通过原型链向上查找的。
3.20 кэшированный кеш
Используйте функцию закрытия для кэширования данных
/**
* Create a cached version of a pure function.
*/
function cached (fn) {
var cache = Object.create(null);
return (function cachedFn (str) {
var hit = cache[str];
return hit || (cache[str] = fn(str))
})
}
Регулярная рекомендация по обучению системыЛао Яо: «Мини-книга по регулярным выражениям JavaScript» вышла!, все сказали хорошо. Поэтому в этой статье не будут подробно описываться знания, связанные с регуляризацией.
3.21 верблюжий дефис вместо маленького верблюда
Дефис - CamelCase по клику => onClick
/**
* Camelize a hyphen-delimited string.
*/
var camelizeRE = /-(\w)/g;
var camelize = cached(function (str) {
return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })
});
3.22 использовать заглавную первую букву
Сделать первую букву заглавной
/**
* Capitalize a string.
*/
var capitalize = cached(function (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
});
3.23 дефис Небольшой горб к дефису
onClick => on-click
/**
* Hyphenate a camelCase string.
*/
var hyphenateRE = /\B([A-Z])/g;
var hyphenate = cached(function (str) {
return str.replace(hyphenateRE, '-$1').toLowerCase()
});
3.24 прокладка для привязки polyfillBind
/**
* Simple bind polyfill for environments that do not support it,
* e.g., PhantomJS 1.x. Technically, we don't need this anymore
* since native bind is now performant enough in most browsers.
* But removing it would mean breaking code that was able to run in
* PhantomJS 1.x, so this must be kept for backward compatibility.
*/
/* istanbul ignore next */
function polyfillBind (fn, ctx) {
function boundFn (a) {
var l = arguments.length;
return l
? l > 1
? fn.apply(ctx, arguments)
: fn.call(ctx, a)
: fn.call(ctx)
}
boundFn._length = fn.length;
return boundFn
}
function nativeBind (fn, ctx) {
return fn.bind(ctx)
}
var bind = Function.prototype.bind
? nativeBind
: polyfillBind;
Проще говоря, он совместим со старыми версиями браузеров, которые не поддерживают нативные.bind
функция. В то же время он совместим с методом записи, и оценивается количество параметров, и использованиеcall
а такжеapply
Реализация, говорят, что параметры подходят для использованияapply
,бесполезныйcall
Лучшая производительность.
Если дляcall、apply、bind
Незнакомые с использованием и реализацией, вы можете проверить мойИнтервьюер спрашивает сериюнаписано наИнтервьюер спросил: Могу ли я смоделировать вызов и применить методы JS?
Интервьюер спросил: Могу ли я смоделировать метод привязки, реализующий JS?
3.25 toArray преобразует массив, подобный массиву, в настоящий массив.
Преобразует массив, подобный массиву, в массив, поддерживает начало и по умолчанию начинает с 0.
/**
* Convert an Array-like object to a real Array.
*/
function toArray (list, start) {
start = start || 0;
var i = list.length - start;
var ret = new Array(i);
while (i--) {
ret[i] = list[i + start];
}
return ret
}
// 例子:
function fn(){
var arr1 = toArray(arguments);
console.log(arr1); // [1, 2, 3, 4, 5]
var arr2 = toArray(arguments, 2);
console.log(arr2); // [3, 4, 5]
}
fn(1,2,3,4,5);
3.26 расширение слияния
/**
* Mix properties into target object.
*/
function extend (to, _from) {
for (var key in _from) {
to[key] = _from[key];
}
return to
}
// 例子:
const data = { name: '若川' };
const data2 = extend(data, { mp: '若川视野', name: '是若川啊' });
console.log(data); // { name: "是若川啊", mp: "若川视野" }
console.log(data2); // { name: "是若川啊", mp: "若川视野" }
console.log(data === data2); // true
3.27 toObject к объекту
/**
* Merge an Array of Objects into a single Object.
*/
function toObject (arr) {
var res = {};
for (var i = 0; i < arr.length; i++) {
if (arr[i]) {
extend(res, arr[i]);
}
}
return res
}
// 数组转对象
toObject(['若川', '若川视野'])
// {0: '若', 1: '川', 2: '视', 3: '野'}
3.28 пустая функция noop
/* eslint-disable no-unused-vars */
/**
* Perform no operation.
* Stubbing args to make Flow happy without leaving useless transpiled code
* with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/).
*/
function noop (a, b, c) {}
// 初始化赋值
3.29 no всегда возвращает false
/**
* Always return false.
*/
var no = function (a, b, c) { return false; };
/* eslint-enable no-unused-vars */
3.30 identity возвращает сам параметр
/**
* Return the same value.
*/
var identity = function (_) { return _; };
3.31 genStaticKeys генерирует статические свойства
/**
* Generate a string containing static keys from compiler modules.
*/
function genStaticKeys (modules) {
return modules.reduce(function (keys, m) {
return keys.concat(m.staticKeys || [])
}, []).join(',')
}
3.32 свободное равенство свободное равенство
Поскольку массивы, объекты и т. д. являются ссылочными типами, два содержимого кажутся равными, а строгое равенство не равно.
var a = {};
var b = {};
a === b; // false
a == b; // false
Итак, эта функция представляет собой рекурсивное сравнение массивов, дат и объектов. Свободное равенство, если содержимое точно равно.
/**
* Check if two values are loosely equal - that is,
* if they are plain objects, do they have the same shape?
*/
function looseEqual (a, b) {
if (a === b) { return true }
var isObjectA = isObject(a);
var isObjectB = isObject(b);
if (isObjectA && isObjectB) {
try {
var isArrayA = Array.isArray(a);
var isArrayB = Array.isArray(b);
if (isArrayA && isArrayB) {
return a.length === b.length && a.every(function (e, i) {
return looseEqual(e, b[i])
})
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime()
} else if (!isArrayA && !isArrayB) {
var keysA = Object.keys(a);
var keysB = Object.keys(b);
return keysA.length === keysB.length && keysA.every(function (key) {
return looseEqual(a[key], b[key])
})
} else {
/* istanbul ignore next */
return false
}
} catch (e) {
/* istanbul ignore next */
return false
}
} else if (!isObjectA && !isObjectB) {
return String(a) === String(b)
} else {
return false
}
}
3.33 свободный индекс
Эта функция реализует свободное равенство. оригинальныйindexOf
строго равны.
/**
* Return the first index at which a loosely equal value can be
* found in the array (if value is a plain object, the array must
* contain an object of the same shape), or -1 if it is not present.
*/
function looseIndexOf (arr, val) {
for (var i = 0; i < arr.length; i++) {
if (looseEqual(arr[i], val)) { return i }
}
return -1
}
3.34 Once гарантирует, что функция будет выполнена только один раз.
Используйте замыкания для хранения состояния
/**
* Ensure a function is called only once.
*/
function once (fn) {
var called = false;
return function () {
if (!called) {
called = true;
fn.apply(this, arguments);
}
}
}
const fn1 = once(function(){
console.log('哎嘿,无论你怎么调用,我只执行一次');
});
fn1(); // '哎嘿,无论你怎么调用,我只执行一次'
fn1(); // 不输出
fn1(); // 不输出
fn1(); // 不输出
3.35 Жизненный цикл и т. д.
var SSR_ATTR = 'data-server-rendered';
var ASSET_TYPES = [
'component',
'directive',
'filter'
];
[Vue 生命周期](https://cn.vuejs.org/v2/api/#%E9%80%89%E9%A1%B9-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90)
var LIFECYCLE_HOOKS = [
'beforeCreate',
'created',
'beforeMount',
'mounted',
'beforeUpdate',
'updated',
'beforeDestroy',
'destroyed',
'activated',
'deactivated',
'errorCaptured',
'serverPrefetch'
];
4. Напоследок порекомендуйте несколько статей и книг
Эта часть совпадает со статьей о функциях инструмента Vue3, рекомендуется, поэтому скопируйте ее сюда.
Я рекомендую сначала я думаю, что это хорошоJavaScript API
несколько статей и несколько книг, которые стоит прочитать.
Все API JavaScript String целая дешифровка
[Подробная длинная статья] Все API-интерфейсы массивов JavaScript полностью расшифрованы
Руководство пользователя внешнего интерфейса регулярных выражений
Лао Яо: «Мини-книга по регулярным выражениям JavaScript» вышла!
Lao Yao Talks: Как выучить JavaScript?
Весь API-анализ объектов JavaScript Биография Лу Синя 12.git ee.IO/ is -object- ах...
Продвинутое программирование с помощью JavaScript, 4-е издание
Полное руководство по JavaScript, 7-е издание
«Объектно-ориентированное программирование JavaScript 2»Объектно-ориентированный очень подробно.
Учитель Руан Ифэн: «Вводный курс по ES6»
Учебник по современному JavaScript
«JavaScript, которого вы не знаете», том 1
Шаблоны проектирования JavaScript и практика разработки
Я также испытал это, так как я не мог читать книги. Пишите статьи, чтобы поделиться.
Мой способ чтения книг: читать несколько книг одновременно и читать одни и те же и похожие главы, например функции. Прочитав эту книгу, вы можете ее не понять.Прочитав следующую книгу, вы в основном поймете ее после прочтения нескольких книг.Если вы не поняли ее один раз, прочитайте ее несколько раз, чтобы не забыть и закрепить соответствующие главы. Конечно, сначала было тяжело читать книгу, да и читать было сложно. Большинство из этих книг доступны для чтения в WeChat.Если вы привыкли читать бумажные книги, вы можете купить их.
Здесь вы можете посмотреть несколько видео и попрактиковаться в некоторых простых проектах.
Например: вы можете зарегистрироваться самостоятельноgithub
Аккаунт, разделенный на главы и подразделы, скопируйте код в книгу, отправьте наgithub
, чем больше вы практикуетесь, тем больше вы чувствуете.
Другой примерСайт онлайн-обучения китайскому языку freeCodeCampВеб-сайт. Чтение книг — очень хороший способ систематического обучения. Позже я просто больше смотрел на исходный код и писал статьи, которыми делился со всеми.
5. Резюме
Эта статья после просмотраVue2
в исходном кодеshared
модульУпакованная строка dist/vue.js с 14 по 379..Исходный код не такой уж сложный, по крайней мере многое можно понять, например, функции инструментов. Трудность может быть трудностью: я не знаю сценария применения.
Vue2
Функции инструментов хорошо названы, например:is
судить,to
конвертировать,has
Есть ли, чтобы разработчики могли сразу увидеть семантику функции.
Эти функции также очень одиночные, в основном функция делает только одну вещь.
Читателям и друзьям рекомендуется писать незнакомые функции от руки, что поможет закрепить базовые знания и заполнить пробелы.
Наконец, вы можете продолжать следовать за мной @ Ruo Chuan. добро пожаловать, чтобы добавить меня wechatruochuan12общаться, участвоватьЧитайте исходный код вместеДействия, все вместе изучают исходный код и вместе добиваются прогресса.
О группе && Exchange
недавно организованныйЧтение исходного кода, если вам интересно, вы можете добавить меня в WeChatruochuan12Участвуйте в долгосрочном обмене и обучении.
Автор: Чанг ИВакагаваНазвание смешано в реках и озерах. добро пожаловать, чтобы добавить меня wechatruochuan12
. По дороге на фронт | Знаю очень мало, только хорошо учусь.
Обратите внимание на паблик аккаунта Ruochuan Vision, Изучайте исходный код вместе каждую неделю, учитесь читать исходный код и переходите к расширенному интерфейсу.
Блог Вакагавы
segmentfault
Колонна Вакагава Видение, открылВидение ВакагаваКолонка, добро пожаловать на внимание ~
Колонка самородков, добро пожаловать, обратите внимание~
Колонна видений Чжиху Руочуань, открылВидение ВакагаваКолонка, добро пожаловать на внимание ~
github blog, спроситьstar
^_^~