debug.js
Is the so-called whetstone is not wrong to cut wood workers, before really reading the source code to understand some variables is how to judge, the role of pure function is very necessary. Know what hammers, axes, wrenches, and scissors are for so you don’t feel unprepared when you meet them for the first time.
This file mainly exposes four methods warn, TIP, generateComponentTrace, formatComponentName, the main code is as follows
//noop is an empty method introduced from shared/util
export function noop (a? : any, b? : any, c? : any) {}
//debug.js
export let warn = noop
export let tip = noop
export let generateComponentTrace = (noop: any) // work around flow check
export let formatComponentName = (noop: any)
if(process.env.NODE_ENV ! = ='production') {
// Ignore this part for now
}
Copy the code
They are mainly used in debugging, but in production they are just empty functions and do nothing, and only in development will they be redefined.
Process.env.node_env! == ‘production’, this is from the performance perspective, some tests, warnings and other unnecessary prompts will only be processed in non-production environment to achieve optimal performance.
// Check whether the current environment supports console
const hasConsole = typeof console! = ='undefined'
// Regular expressions
const classifyRE = / (? :^|[-_])(\w)/g
// Convert the string format
const classify = str= > str
.replace(classifyRE, c= > c.toUpperCase())
.replace(/[-_]/g.' ')
Copy the code
The previous two are relatively easy to understand. The purpose of false is to convert the horizontal script in the string to camel form using the regular classifyRE. Such as:
classify('fishing-wang');
/ / output FisingWang
Copy the code
// Overwrite the print or warning content to the client
warn = (msg, vm) = > {
const trace = vm ? generateComponentTrace(vm) : ' '
if (config.warnHandler) {
config.warnHandler.call(null, msg, vm, trace)
} else if(hasConsole && (! config.silent)) {console.error(`[Vue warn]: ${msg}${trace}`)
}
}
tip = (msg, vm) = > {
if(hasConsole && (! config.silent)) {console.warn(`[Vue tip]: ${msg}` + (
vm ? generateComponentTrace(vm) : ' '))}}Copy the code
env.js
Is the so-called whetstone is not wrong to cut wood workers, before really reading the source code to understand some variables is how to judge, the role of pure function is very necessary. Know what hammers, axes, wrenches, and scissors are for so you don’t feel unprepared when you meet them for the first time.
Checks the current host environment’s support for variables.
// Check whether the current browser supports '__proto__'
export const hasProto = '__proto__' in {}
// Check whether the browser environment exists
export const inBrowser = typeof window! = ='undefined'
// Check whether the current environment is weeX
export const inWeex = typeofWXEnvironment ! = ='undefined'&&!!!!! WXEnvironment.platform// Whether weeX platform
export const weexPlatform = inWeex && WXEnvironment.platform.toLowerCase()
// Make sure that the current environment is a browser environment, then save the browser's use Agent information in the UA variable (for non-browser environment, return false)
export const UA = inBrowser && window.navigator.userAgent.toLowerCase()
// Whether to use Internet Explorer
export const isIE = UA && /msie|trident/.test(UA)
// Whether Internet Explorer 9 is used
export const isIE9 = UA && UA.indexOf('msie 9.0') > 0
// Whether to use Edge browser
export const isEdge = UA && UA.indexOf('edge/') > 0
// Whether to use Android
export const isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android')
// Whether to use the IOS environment
export const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios')
// Whether Chrome environment is available
export const isChrome = UA && /chrome\/\d+/.test(UA) && ! isEdge/ / the window. The navigator. Whether the userAgent contains phantomjs keyword
export const isPhantomJS = UA && /phantomjs/.test(UA)
// Whether the Firefox browser environment is available
export const isFF = UA && UA.match(/firefox\/(\d+)/)
Copy the code
export const nativeWatch = ({}).watch
Copy the code
The Object.prototype.watch method is provided natively in Firefox. So nativeWatch returns the correct function only if the current host environment is Firefox, otherwise it returns undefined. It can also be used to distinguish watches in VUE instances to prevent conflicts from causing accidents.
// Test whether the current browser supports passive through the listener call test-passive.
// The code is wrapped with a try catch, indicating poor support and error prone
export let supportsPassive = false
if (inBrowser) {
try {
const opts = {}
Object.defineProperty(opts, 'passive', ({
get () {
supportsPassive = true
}
}: Object))
window.addEventListener('test-passive'.null, opts)
} catch (e) {}
}
// Check whether the server environment exists
let _isServer
export const isServerRendering = () = > {
if (_isServer === undefined) {
if(! inBrowser && ! inWeex &&typeof global! = ='undefined') {
_isServer = global['process'] && global['process'].env.VUE_ENV === 'server'
} else {
_isServer = false}}return _isServer
}
// Check whether the tool environment is developed
export const devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__
Copy the code
// Check whether the current method is provided by native JS
export function isNative (Ctor: any) :boolean {
return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}
// Checks whether the current host environment supports native symbol reflects. ownKeys, which returns a Boolean value
export const hasSymbol =
typeof Symbol! = ='undefined' && isNative(Symbol) &&
typeof Reflect! = ='undefined' && isNative(Reflect.ownKeys)
Copy the code
lang.js
Is the so-called whetstone is not wrong to cut wood workers, before really reading the source code to understand some variables is how to judge, the role of pure function is very necessary. Know what hammers, axes, wrenches, and scissors are for so you don’t feel unprepared when you meet them for the first time.
This file exposes only one variable and three methods
export const unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3 001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/
Copy the code
Unicode regular expression used to parse the template template
export function isReserved (str: string) :boolean {
const c = (str + ' ').charCodeAt(0)
return c === 0x24 || c === 0x5F
}
Copy the code
Checking whether a string begins with an _ or dollar sign $is used to check whether variables in VUE component instances are properly named (VUE does not recommend naming variables in strings starting with _ or $, which is the framework’s way of naming names).
export function def (obj: Object, key: string, val: any, enumerable? : boolean) {
Object.defineProperty(obj, key, {
value: val,
enumerable:!!!!! enumerable,writable: true.configurable: true})}Copy the code
Object.defineproperty is wrapped in a simple wrapper, presumably to make it easier to call. The def function takes four arguments: the source object itself, the key value, the value, the enumerable or not. The final argument enumerable is optional.
const bailRE = new RegExp(` [^${unicodeRegExp.source}.$_\\d]`)
export function parsePath (path: string) :any {
if (bailRE.test(path)) {
return
}
const segments = path.split('. ')
return function (obj) {
for (let i = 0; i < segments.length; i++) {
if(! obj)return
obj = obj[segments[i]]
}
return obj
}
}
Copy the code
For a simple parse of a path, this method is relatively simple: return if path is regular (e.g., ~, /, *), otherwise Cut the path into an array, store it in segments, and return a function that iterates through the segments to get an object. This method is mainly used to trigger the reading of values when initializing the Watcher.
perf.js
Is the so-called whetstone is not wrong to cut wood workers, before really reading the source code to understand some variables is how to judge, the role of pure function is very necessary. Know what hammers, axes, wrenches, and scissors are for so you don’t feel unprepared when you meet them for the first time.
Performance Monitoring
Define two variables mark and measure that are used to monitor performance in non-production environments. In production environments, no monitoring is required and undefined is returned. Source code is as follows:
import { inBrowser } from './env'
export let mark
export let measure
if(process.env.NODE_ENV ! = ='production') {
const perf = inBrowser && window.performance
/* istanbul ignore if */
if (
perf &&
perf.mark &&
perf.measure &&
perf.clearMarks &&
perf.clearMeasures
) {
mark = tag= > perf.mark(tag)
measure = (name, startTag, endTag) = > {
perf.measure(name, startTag, endTag)
perf.clearMarks(startTag)
perf.clearMarks(endTag)
// perf.clearMeasures(name)}}}Copy the code
Perf is window.performance if and only if the host is a browser and in a non-production environment. Multiple judgments are made in the if statement to ensure that the current environment supports window.performance. After that, mark and measure were redefined. The result of the simplification of the above code in non-production environment is as follows:
const mark = tag= > window.performance.mark(tag);
const measure = (name,startTag,endTag) = > {
window.performance.measure(name,startTag,endTag)
window.performance.clearMarks(startTag)
window.performance.clearMarks(endTag)
}
Copy the code
What is window.performance?
The Web Performance API allows Web pages to access certain functions to measure the Performance of Web pages and Web applications. For details, go to window.Performance
shared/util.js
Is the so-called whetstone is not wrong to cut wood workers, before really reading the source code to understand some variables is how to judge, the role of pure function is very necessary. Know what hammers, axes, wrenches, and scissors are for so you don’t feel unprepared when you meet them for the first time.
emptyObject
export const emptyObject = Object.freeze({})
Copy the code
Create a frozen emptyObject, which means that the emptyObject is not extensible, that is, no new attributes can be added
isUndef
export function isUndef (v: any) :boolean %checks {
return v === undefined || v === null
}
Copy the code
To determine whether a variable is undefined, that is, if it is defined as unassigned, or if it is assigned to null
isDef
export function isDef (v: any) :boolean %checks {
returnv ! = =undefined&& v ! = =null
}
Copy the code
Determines whether a variable is defined
isTrue
export function isTrue (v: any) :boolean %checks {
return v === true
}
Copy the code
Determines whether the variable is true
isFalse
export function isFalse (v: any) :boolean %checks {
return v === false
}
Copy the code
Determine if the variable is false
isPrimitive
export function isPrimitive (value: any) :boolean %checks {
return (
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'symbol' ||
typeof value === 'boolean')}Copy the code
To determine whether a variable is a raw value, that is, to determine whether the variable is not compound data
isObject
export function isObject (obj: mixed) :boolean %checks {
returnobj ! = =null && typeof obj === 'object'
}
Copy the code
Check whether a variable is an object or an array
toRawType
const _toString = Object.prototype.toString
export function toRawType (value: any) :string {
return _toString.call(value).slice(8, -1)}Copy the code
Returns the original string type after determining the type. Such as judgment: an Array Object. The prototype. ToString. Call ([]) is the result of [the Object Array], then use the slice (8, 1) after the result is a string Array
isPlainObject
export function isPlainObject (obj: any) :boolean {
return _toString.call(obj) === '[object Object]'
}
Copy the code
Determines whether a variable is a pure object
isRegExp
export function isRegExp (v: any) :boolean {
return _toString.call(v) === '[object RegExp]'
}
Copy the code
Determines whether a variable is a regular object
isValidArrayIndex
export function isValidArrayIndex (val: any) :boolean {
const n = parseFloat(String(val))
return n >= 0 && Math.floor(n) === n && isFinite(val)
}
Copy the code
Determines whether a variable is a valid array index.
- A normal array index should be an integer greater than or equal to 0
- The variable is parsed and returns a floating point number, stored in variable n
- Returns true if and only if the variable is greater than or equal to 0, is an integer, and is a finite number
isPromise
export function isPromise (val: any) :boolean {
return (
isDef(val) &&
typeof val.then === 'function' &&
typeof val.catch === 'function')}Copy the code
Determine if a variable is a Promise
toString
export function toString (val: any) :string {
return val == null
? ' '
: Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
? JSON.stringify(val, null.2)
: String(val)
}
Copy the code
Convert variables to string format
- If null, an empty string is returned
- If it is an array or a pure object, use json.stringify
- Other cases are handled directly by the String function
toNumber
export function toNumber (val: string) :number | string {
const n = parseFloat(val)
return isNaN(n) ? val : n
}
Copy the code
Converts a variable to a numeric type, returning the initial value if the conversion fails (for example, converting the string “aaa” yields NaN)
makeMap
export function makeMap (str: string, expectsLowerCase? : boolean) : (key: string) = >true | void {
const map = Object.create(null)
const list: Array<string> = str.split(', ')
for (let i = 0; i < list.length; i++) {
map[list[i]] = true
}
return expectsLowerCase
? val= > map[val.toLowerCase()]
: val= > map[val]
}
Copy the code
Returns a function that determines whether a given string contains the specified content (mapping).
STR data format :a string of long intervals, such as a, B, C, D, and E expectercase: Specifies whether to lowercase the map value key
Use examples (check for lowercase vowels) :
let isLower = makeMap('a,b,c,d,e');
isLower('b'); // true
isLower('f'); // undefined
Copy the code
remove
export function remove (arr: Array<any>, item: any) :Array<any> | void {
if (arr.length) {
const index = arr.indexOf(item)
if (index > -1) {
return arr.splice(index, 1)}}}Copy the code
Removes the given element from an array and returns an array of the deleted items: [item]
If the array is not empty, get the number of the current element. If the element exists (greater than -1), splice will be used to delete it and return a new array of the deleted elements. Otherwise, undefined will be returned
Example:
let arr = ['a'.'b'.'c'];
remove(arr,'a'); // ['a']
/ / arr into [' b ', 'c']
Copy the code
hasOwn
/ / encapsulation ` Object. The prototype. HasOwnProperty `, used to detect whether a given Object containing a given ` key ` values
const hasOwnProperty = Object.prototype.hasOwnProperty
export function hasOwn (obj: Object | Array<*>, key: string) :boolean {
return hasOwnProperty.call(obj, key)
}
Copy the code
cached
export function cached<F: Function> (fn: F) :F {
const cache = Object.create(null)
return (function cachedFn (str: string) {
const hit = cache[str]
return hit || (cache[str] = fn(str))
}: any)
}
Copy the code
Creates a cached version of a function for a pure function creation. The input argument must be a pure function and the return must be a pure function.
- The first step is to determine why we must pass a pure function, because the output of a pure function depends only on the input, and the environment in which it is run cannot change the output.
- Create a closure object with an empty prototype chain
cache
Used to cache results. - A function is then returned
cachedFn
, read the cache first, if there is, return the returned value, otherwise use the original functionfn
Compute once and cache the results.
camelize
const camelizeRE = /-(\w)/g
export const camelize = cached((str: string): string= > {
return str.replace(camelizeRE, (_, c) = > c ? c.toUpperCase() : ' ')})Copy the code
Converts the hyphen to camel name
capitalize
export const capitalize = cached((str: string): string= > {
return str.charAt(0).toUpperCase() + str.slice(1)})Copy the code
Change the first letter of the string to uppercase
hyphenate
const hyphenateRE = /\B([A-Z])/g
export const hyphenate = cached((str: string): string= > {
return str.replace(hyphenateRE, '- $1').toLowerCase()
})
Copy the code
As opposed to the camelize method, change the camel name to a hyphen. For example: hyphenateRE(‘aaBb’) => AA-bb
polyfillBind
nativeBind
bind
function polyfillBind (fn: Function, ctx: Object) :Function {
function boundFn (a) {
const 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: Function, ctx: Object) :Function {
return fn.bind(ctx)
}
export const bind = Function.prototype.bind
? nativeBind
: polyfillBind
Copy the code
This is essentially a bind function that returns a new function that this points to.
polyfillBind
A binding function that is written manuallynativeBind
Native binding functions on the Function prototype chainbind
Whether native binding functions are supported or not is preferred; otherwise, manually implemented functions are used
toArray
export function toArray (list: any, start? : number) :Array<any> {
start = start || 0
let i = list.length - start
const ret: Array<any> = new Array(i)
while (i--) {
ret[i] = list[i + start]
}
return ret
}
Copy the code
A method that converts an array of classes to an array starting at the specified position (0 by default).
list
An array of classstart
Optional starting index location
extend
export function extend (to: Object, _from: ?Object) :Object {
for (const key in _from) {
to[key] = _from[key]
}
return to
}
Copy the code
Copies data from one object (_from) to another object (to). If the key value is duplicate, the data in _from will be replaced by the data in to. Note: If value is compound data, it is a shallow copy.
toObject
export function toObject (arr: Array<any>) :Object {
const res = {}
for (let i = 0; i < arr.length; i++) {
if (arr[i]) {
extend(res, arr[i])
}
}
return res
}
Copy the code
Iterates through each object element of the array, copies the contents to a new object, and returns the new object. The for loop iterates through the array, is used with extend, and is copied into the new object res. The logic is simple.
noop
export function noop (a? : any, b? : any, c? : any) {}
Copy the code
An empty function that does nothing.
no
export const no = (a? : any, b? : any, c? : any) = > false
Copy the code
Function that always returns false.
identity
export const identity = (_: any) = > _
Copy the code
A pure function that returns the input value directly
genStaticKeys
export function genStaticKeys (modules: Array<ModuleOptions>) :string {
return modules.reduce((keys, m) = > {
return keys.concat(m.staticKeys || [])
}, []).join(', ')}Copy the code
Generates a string containing static keys from the compiler module.
modules
Is an array, an option of the compiler, where each element is a possible containstaticKeys
Property. The purpose of this method is to iterate through a set of elements and collectstaticKeys
In order to.
Separate the concatenation string composed of.
looseEqual
export function looseEqual (a: any, b: any) :boolean {
if (a === b) return true
const isObjectA = isObject(a)
const isObjectB = isObject(b)
if (isObjectA && isObjectB) {
try {
const isArrayA = Array.isArray(a)
const isArrayB = Array.isArray(b)
if (isArrayA && isArrayB) {
return a.length === b.length && a.every((e, i) = > {
return looseEqual(e, b[i])
})
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime()
} else if(! isArrayA && ! isArrayB) {const keysA = Object.keys(a)
const keysB = Object.keys(b)
return keysA.length === keysB.length && keysA.every(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}}Copy the code
Determine whether two values are congruent.
looseIndexOf
export function looseIndexOf (arr: Array<mixed>, val: mixed) :number {
for (let i = 0; i < arr.length; i++) {
if (looseEqual(arr[i], val)) return i
}
return -1
}
Copy the code
Finds if the given element is in the specified array, returns the index of the current element’s array if it is, or -1 otherwise.
once
export function once (fn: Function) :Function {
let called = false
return function () {
if(! called) { called =true
fn.apply(this.arguments)}}}Copy the code
Implement a function that is called only once using the features of closures.