Vue.js source code defines some tool methods, browser side, server side vue.js can share these methods

Vue 2.x

Based on the 2.6.14

  • Specific path: SRC \shared\util.js

  • Background: Build a type system based on flow

  • Objective: To help program generate better VM code in JS engine, conducive to performance optimization, improve efficiency

Type judgment

isUndef & isDef

Check whether the value is undefined or null

function isUndef (v) {
  return v === undefined || v === null
}
function isDef (v) {
  returnv ! = =undefined&& v ! = =null
}
Copy the code

isTrue & isFalse

Determine whether it is true or false

function isTrue (v) {
  return v === true
}
function isFalse (v) {
  return v === false
}
Copy the code

isPrimitive

Whether the data type is a base type (partial)

function isPrimitive (value) {
  return (
    typeof value === 'string' ||
    typeof value === 'number' ||
    typeof value === 'symbol' ||
    typeof value === 'boolean')}Copy the code

Eg: SRC \core\vdom\create-element.js createElement

 if (Array.isArray(data) || isPrimitive(data)) {/ /... }
Copy the code

isObject

Whether it is a reference type or a type constructed by new

This method is used in Vue for quick object checking: to identify an object from a known value when that value is of a type that conforms to JSON

function isObject (obj) {
  returnobj ! = =null && typeof obj === 'object'  // Note that null is in the typeof pit
}
Copy the code

isPromise

Is it a Promise function

function isPromise (val) {
  return (
    isDef(val) &&
    typeof val.then === 'function' &&
    typeof val.catch === 'function')}Copy the code

Eg: SRC \core\util\error. Js invokeWithErrorHandling for handling asynchronous exceptions

if(res && ! res._isVue && isPromise(res) && ! res._handled) {/ /... }
Copy the code

toRawType

Gets the string of the original type of the value

Based on the Object. The prototype. ToString. Call, in addition to the custom types, almost universal. Return: ‘[object, type]

var _toString = Object.prototype.toString;

function toRawType (value) {
    return _toString.call(value).slice(8, -1)}Copy the code

Eg: SRC \core\util\options.js normalizeProps, normalizing the props property

// The props property type does not meet the requirements
warn(
    `Invalid value for option "props": expected an Array or an Object, ` +
    `but got ${toRawType(props)}. `,
    vm
) 
Copy the code

hasOwnProperty

Checks whether the object has the specified attribute

var hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn (obj, key) {
  return hasOwnProperty.call(obj, key)
}
Copy the code

Data conversion

toNumber

Convert to numbers

// Convert the value to a number. If the conversion fails, return the original string
function toNumber (val) {
  var n = parseFloat(val);
  return isNaN(n) ? val : n
}
Copy the code

toString

Convert to string

function toString (val) {
  return val == null
    ? ' '
    : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
      ? JSON.stringify(val, null.2)  // For arrays or objects
      : String(val)
}
Copy the code

Json.stringify (value[, replacer [, space]]);

toArray

Convert an array-like object to an 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
}
Copy the code

Eg: SRC \core\global-api\use.js initUse

 const args = toArray(arguments.1) // arguments can understand the array object of the arguments passed to the function
Copy the code

To convert an array-like object to an array, use the following methods:

(1) Array. The prototype. Slice. The call

(2) Array. The from ()

toObject

Merges an array of objects into an object

// Assign attributes to the target object
function extend (to, _from) {
  for (var key in _from) {
    to[key] = _from[key];
  }
  return to
}

function toObject (arr) {
  var res = {};
  for (var i = 0; i < arr.length; i++) {
    if(arr[i]) { extend(res, arr[i]); }}return res
}
Copy the code

Eg: SRC \platforms\weex\ Runtime \modules\style.js updateStyle

if (Array.isArray(style)) {
    style = vnode.data.style = toObject(style)
}
Copy the code

It is known that v-bind:style’s array syntax can apply multiple style objects to the same element

capitalize

Uppercase

// cached method below
var capitalize = cached(function (str) {
  return str.charAt(0).toUpperCase() + str.slice(1)});Copy the code

hyphenate

Camelback shortened horizontal line separation

var hyphenateRE = /\B([A-Z])/g;
var hyphenate = cached(function (str) {
  return str.replace(hyphenateRE, '- $1').toLowerCase()
});
Copy the code

camelize

The short horizontal line is changed to hump

var camelizeRE = /-(\w)/g;
var camelize = cached(function (str) {
  return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ' '; })});Copy the code

Cache data

cached

The pass is a function and the return is a function that is used to cache the function created. The capitalize, hyphenate, and capitalize described above all use the cached method

Why do you do that? Especially great ingenuity: conducive to performance optimization.

For details: Portal 1 Portal 2

function cached (fn) {
  var cache = Object.create(null);
  return (function cachedFn (str) {
    var hit = cache[str];  // Cache
    return hit || (cache[str] = fn(str))
  })
}
Copy the code

makeMap

Define a set of data that can be used to determine whether or not it is a built-in HTML tag

/ * * *@description: 
 * @param STR The character string *@param ExpectsLowerCase whether lowercase * is required@return {*}* /
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) { returnmap[val]; }}Copy the code

Eg: SRC \platforms\web\util\element.js isHTMLTag

var isHTMLTag = makeMap(
  'html,body,base,head,link,meta,style,title,' +
  '... ' +
  'content,element,shadow,template,blockquote,iframe,tfoot'
)

isHTMLTag('iframe')   // true
Copy the code

Determines whether objects are equal

looseEqual

The overall idea: first type judgment, and then recursive call

function looseEqual (a, b) {
  // a, b are equal to, return true
  if (a === b) { return true }
  var isObjectA = isObject(a);
  var isObjectB = isObject(b);
  // Determine if it is an object (reference type)
  if (isObjectA && isObjectB) {
    try {
      var isArrayA = Array.isArray(a);
      var isArrayB = Array.isArray(b);
      if (isArrayA && isArrayB) {
        If the length of each item is the same, return false if the length is not the same
        return a.length === b.length && a.every(function (e, i) {
          return looseEqual(e, b[i])
        })
      } else if (a instanceof Date && b instanceof Date) {
        // If the two types are Date, use the timestamp to check
        return a.getTime() === b.getTime()
      } else if(! isArrayA && ! isArrayB) {If the length of each attribute is the same, return false if the length is not the same
        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) {// If neither is an object (reference type), convert it to a string comparison
    return String(a) === String(b)
  } else {
    return false}}Copy the code

other

remove

Delete an array item

function remove (arr, item) {
  if (arr.length) {
    var index = arr.indexOf(item);
    if (index > -1) {
      return arr.splice(index, 1)}}}Copy the code

once

The function is executed only once

function once (fn) {
  var called = false;
  return function () {
    if(! called) { called =true;
      fn.apply(this.arguments); }}}Copy the code

Vue 3.x

Based on the 3.2.6

  • Source link

  • Background: Type validation is based on TypeScript, and instead of flow, we have to mention Vue2. X’s compelling comments

// src\core\instance\lifecycle.js
const propOptions: any = vm.$options.props // wtf flow?

// src\platforms\web\server\modules\dom-props.js
// $flow-disable-line (WTF?)
const attr = propsToAttrMap[key] || key.toLowerCase()
Copy the code

TypeScript vs Flow, what a nice follow-up to TypeScript. Portals

Reserve & Supplement

  • CacheStringFunction: Reserved, that is, cached

  • MakeMap: keep

  • LooseEqual: Retain, rewrite optimization, supplement looseCompareArrays method, compare whether two arrays are equal or not

// source code: packages shared SRC looseequal.ts
function looseCompareArrays(a, b) {
    // If the length is inconsistent, return false
    if(a.length ! == b.length)return false;
    let equal = true;
    // If the length is the same, compare each item
    for (let i = 0; equal && i < a.length; i++) {
        equal = looseEqual(a[i], b[i]);
    }
    return equal;
}
Copy the code
  • Data conversion

    • Remove toArray and toObject

      The toArray with Array. Prototype. Slice. Call and Array from instead

    • Added toTypeString, object to string

    const objectToString = Object.prototype.toString;
    const toTypeString = (value) = > objectToString.call(value);
    
    toTypeString({num: 0})  // "[object Object]"
    Copy the code
  • Type judgment: supplementary adjustment, more detailed

const isArray = Array.isArray;
const isMap = (val) = > toTypeString(val) === '[object Map]';
const isSet = (val) = > toTypeString(val) === '[object Set]';
const isDate = (val) = > val instanceof Date;
const isFunction = (val) = > typeof val === 'function';
const isString = (val) = > typeof val === 'string';
const isSymbol = (val) = > typeof val === 'symbol';
const isObject = (val) = >val ! = =null && typeof val === 'object';
const isPromise = (val) = > {
    return isObject(val) && isFunction(val.then) && isFunction(val.catch);
};
/ /...
Copy the code

new

getGlobalThis

Gets the global this to the object

let _globalThis;
const getGlobalThis = () = > {
    // If _globalThis is already defined (executed method), it is returned without further judgment
    return (_globalThis ||
        (_globalThis =
            typeofglobalThis ! = ='undefined'
                ? globalThis
                : typeofself ! = ='undefined'
                    ? self
                    : typeof window! = ='undefined'
                        ? window
                        : typeof global! = ='undefined'
                            ? global
                            : {}));
};
Copy the code

def

Defining object properties

const def = (obj, key, value) = > {
    Object.defineProperty(obj, key, {
        configurable: true.// It is configurable
        enumerable: false.// not enumerable
        value
    });
};
Copy the code

isModelListener

Checks whether the current string starts with onUpdate:

const isModelListener = (key) = > key.startsWith('onUpdate:');
Copy the code

String. The prototype. The startsWith (searchString [position]) : returns a Boolean value that indicates whether the parameter String in the head of the original String.

isIntegerKey

Checks whether the value is an integer key

const isIntegerKey = (key) = >isString(key) && key ! = ='NaN' &&
    key[0]! = =The '-' &&
    ' ' + parseInt(key, 10) === key;
Copy the code

invokeArrayFns

FNS is an array, each element is a function, traversal number group execution, facilitate the execution of multiple functions at one time

const invokeArrayFns = (fns, arg) = > {
    for (let i = 0; i < fns.length; i++) { fns[i](arg); }};Copy the code

hasChanged

Comparing two values for equality, using object. is, behaves essentially the same as the strict comparison operator (===), but note:

  • Plus 0 is not equal to minus 0
  • NaN equals itself
const hasChanged = (value, oldValue) = > !Object.is(value, oldValue);

hasChanged(+0, -0)  // true
hasChanged(NaN.NaN) // false
Copy the code

Link drive door

JSON.stringify

Class is bound to Style

Object.is

Last but not least

If there is anything wrong, please give me your advice