There are still several styles and classes left in the diagram. Functions converted

reference

Github.com/lxchuan12/v…

Juejin. Cn/post / 699497…

www.yuque.com/ruochuan12/…

www.yuque.com/ruochuan12/…

To prepare

  • Read the contribution guide to learn how to run, project structure, etc.

Find the shared module.

shared: Internal utilities shared across multiple packages (especially environment-agnostic utils used by both runtime and compiler packages).

And can match builds

The build script builds all public packages (packages without private: true in their package.json).

Packages to build can be specified with fuzzy matching:

# build runtime-core only
yarn build runtime-core

# build all packages matching "runtime"
yarn build runtime --all
Copy the code

Therefore, the command to be executed is

Git clone https://github.com/vuejs/vue-next.git CD vue - next yarn build Shared - effect $yarn build Shared yarn run V1.22.10 $node scripts/build.js shared C:\Users\82454\Desktop\vue3\vue-next\packages\shared\ SRC \index.ts 鈫? Packages \ Shared \ dist \ Shared esm - bundler. Js... Created packages \ Shared \ dist \ Shared esm - bundler. Js in 3.6 s C: \ Users \ \ Desktop \ vue3 \ vue - 82454 next \ packages \ Shared \ SRC \ index ts 鈫? Packages \ Shared \ dist \ Shared CJS. Js... Created packages\shared\dist\ shared.js. Js in 2s C:\Users\82454\Desktop\vue3\vue-next\packages\shared\ SRC \index.ts 鈫? packages\shared\dist\shared.cjs.prod.js... Created packages\shared\dist\shared. Js.prod. js in 1.8s Done in 8.55sCopy the code

It can be found that although there are many modules in the packaged package, only shared has the dist folder

Next to see the vue – next/packages/Shared/dist/Shared. Esm – bundler. Js

Tool function

  • The resulting function is
export { EMPTY_ARR, EMPTY_OBJ, NO, NOOP, PatchFlagNames, babelParserDefaultPlugins, camelize, capitalize, def, escapeHtml, escapeHtmlComment, extend, generateCodeFrame, getGlobalThis, hasChanged, hasOwn, hyphenate$1 as hyphenate, invokeArrayFns, isArray$1 as isArray, isBooleanAttr, isDate$1 as isDate, isFunction, isGloballyWhitelisted, isHTMLTag, isIntegerKey, isKnownHtmlAttr, isKnownSvgAttr, isMap$1 as isMap, isModelListener, isNoUnitNumericStyleProp, isObject$1 as isObject, isOn, isPlainObject$1 as isPlainObject, isPromise, isReservedProp, isSSRSafeAttrName, isSVGTag, isSet$1 as isSet, isSpecialBooleanAttr, isString$1 as isString, isSymbol, isVoidTag, looseEqual, looseIndexOf, makeMap, normalizeClass, normalizeProps, normalizeStyle, objectToString$1 as objectToString, parseStringStyle, propsToAttrMap, remove, slotFlagsText, stringifyStyle, toDisplayString, toHandlerKey, toNumber, toRawType, toTypeString$1 as toTypeString };
Copy the code

EMPTY_ARR empty array

Object.freeze

// If it is a development environment, return an unmodifiable array, otherwise return an empty array
constEMPTY_ARR = (process.env.NODE_ENV ! = ='production')?Object.freeze([]) : [];
Copy the code

EMPTY_OBJ empty object

Same as above

constEMPTY_OBJ = (process.env.NODE_ENV ! = ='production')?Object.freeze({})
    : {};
Copy the code

NO always returns a function of false

const NO = () = > false;
Copy the code

NOOP a function that returns an empty object

const NOOP = () = >{};// Many libraries have such definition functions in their source code, such as jQuery, underscore, lodash, etc
// Use scenarios: 1. Easy to judge, 2. Easy to compress
// 1. Current knowledge is not enough)
const instance = {
    render: NOOP
};

/ / conditions
const dev = true;
if(dev){
    instance.render = function(){
        console.log('render'); }}// Can be used as a judgment.
if(instance.render === NOOP){
 console.log('i');
}
// 2.
// Easy to compress code
Function (){} function(){
Copy the code

PatchFlagNames Is the flag of DIff?

Dev only flag -> name mapping */ dev only flag -> name mapping */
const PatchFlagNames = {
    [1 /* TEXT */] :`TEXT`[2 /* CLASS */] :`CLASS`[4 /* STYLE */] :`STYLE`[8 /* PROPS */] :`PROPS`[16 /* FULL_PROPS */] :`FULL_PROPS`[32 /* HYDRATE_EVENTS */] :`HYDRATE_EVENTS`[64 /* STABLE_FRAGMENT */] :`STABLE_FRAGMENT`[128 /* KEYED_FRAGMENT */] :`KEYED_FRAGMENT`[256 /* UNKEYED_FRAGMENT */] :`UNKEYED_FRAGMENT`[512 /* NEED_PATCH */] :`NEED_PATCH`[1024 /* DYNAMIC_SLOTS */] :`DYNAMIC_SLOTS`[2048 /* DEV_ROOT_FRAGMENT */] :`DEV_ROOT_FRAGMENT`[-1 /* HOISTED */] :`HOISTED`[-2 /* BAIL */] :`BAIL`
};
Copy the code

BabelParserDefaultPlugins Babel parsing the default plug-ins

/** ** ** ** ** ** ** *@babel/parser plugins that are used for template expression
 * transforms and SFC script transforms. By default we enable proposals slated
 * for ES2020. This will need to be updated as the spec moves forward.
 * Full list at https://babeljs.io/docs/en/next/babel-parser#plugins
 */
const babelParserDefaultPlugins = [
    'bigInt'.'optionalChaining'.'nullishCoalescingOperator'
];
Copy the code

MakeMap checks whether the key exists

//isHTMLTag('html')==>true
/** * Make a map and return a function for checking if a key * is in that map. * IMPORTANT: all calls of this function must be prefixed with * \/\*#\_\_PURE\_\_\*\/ * So that rollup can tree-shake them if necessary. */
function makeMap(str, expectsLowerCase) {
    const map = Object.create(null);
    const list = str.split(', ');
    for (let i = 0; i < list.length; i++) {
        map[list[i]] = true;
    }
    return expectsLowerCase ? val= >!!!!! map[val.toLowerCase()] :val= >!!!!! map[val]; }const HTML_TAGS = 'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +
    'header,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,' +
    'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +
    'data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,' +
    'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +
    'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +
    'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +
    'option,output,progress,select,textarea,details,dialog,menu,' +
    'summary,template,blockquote,iframe,tfoot';
const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS);
Copy the code

Camelize, hyphenate turn hump-cache

replace

const cacheStringFunction$1 = (fn) = > {
    const cache = Object.create(null);
    return ((str) = > {
        const hit = cache[str];
        return hit || (cache[str] = fn(str));
    });
};
const camelizeRE = /-(\w)/g;// Match - add numbers, upper and lower case letters, and underscores such as -a -B
const camelize = cacheStringFunction$1((str) = > {
    //'aa-a-a'.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : '')); Return to the "aaAA"
    return str.replace(camelizeRE, (_, c) = > (c ? c.toUpperCase() : ' '));
});
//'aaAaaA'.replace(/\B([A-Z])/g, '-$1').toLowerCase() "aa-aaa-a"
const hyphenateRE$1 = /\B([A-Z])/g;
const hyphenate$1 = cacheStringFunction$1((str) = > str.replace(hyphenateRE$1.'- $1').toLowerCase());
Copy the code
Const cache = object.create (null); const cache = object.create (null); const cache = object.create (null); return ((str) => { const hit = cache[str]; return hit || (cache[str] = str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));) ; }); } if camelize('aa-a') is executed for the first time, cache['aa-a'] is empty. If camelize('aa-a') is executed for the first time, cache['aa-a'] is emptyCopy the code

Capitalize – Cache

const capitalize = cacheStringFunction$1((str) = > str.charAt(0).toUpperCase() + str.slice(1));
//'aaAAAA'.charAt(0).toUpperCase() + 'aaAAAA'.slice(1) "AaAAAA"
Copy the code

Both functions use the same object name cache, but the function is built repeatedly and the cache does not overwrite it

toHandlerKey

const toHandlerKey = cacheStringFunction$1((str) = >
  str ? `on${capitalize(str)}` : ` `
);
Copy the code

Def defines object attributes

All API parsing of JavaScript objects

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

EscapeHtml Escapes HTML symbols

Exec (string)= "if there is a match to =" ['String'.index: Matched serial number] If no =null
Copy the code
// Convert the "'&<> in the string to the corresponding encoding
const escapeRE = / [" & < >] /;
function escapeHtml(string) {
    const str = ' ' + string;
    const match = escapeRE.exec(str);
    //var str = "Visit W3School"; 
    //var patt = new RegExp("W3School","g");
    //console.log(patt.exec(str))
    //["W3School", index: 6, input: "Visit W3School", groups: undefined]
    if(! match) {return str;
    }
    let html = ' ';
    let escaped;
    let index;
    let lastIndex = 0;
    for (index = match.index; index < str.length; index++) {
        switch (str.charCodeAt(index)) {
            case 34: // "
                escaped = '" ';
                break;
            case 38: / / &
                escaped = '& ';
                break;
            case 39: / / '
                escaped = '& # 39; ';
                break;
            case 60: // <
                escaped = '< ';
                break;
            case 62: // >
                escaped = '> ';
                break;
            default:
                continue;
        }
        if(lastIndex ! == index) { html += str.substring(lastIndex, index); } lastIndex = index +1;
        html += escaped;
    }
    returnlastIndex ! == index ? html + str.substring(lastIndex, index) : html; }Copy the code

EscapeHtmlComment Comment symbol escape

/ / '<! -- xxxx -->'.replace(/^-? > | <! - | - > | -! > | <! -$/g, "") print" XXXX"
// https://www.w3.org/TR/html52/syntax.html#comments
const commentStripRE = / ^ -? > | <! - | - > | -! > | <! -$/g;
function escapeHtmlComment(src) {
    return src.replace(commentStripRE, ' ');
}
Copy the code

Extend extends/merges

const extend = Object.assign;
/ / example:
const data = { name: 'if the sichuan' };
const data2 = entend(data, { mp: 'Wakawa View'.name: 'It's Wakawa.' });
console.log(data); // {name: "yes ", mp:" yes "}
console.log(data2); // {name: "yes ", mp:" yes "}
console.log(data === data2); // true
// Array and array
 extend([3.4.5], [1.2= > [])1.2.5]
// number combination to object [1,2]=>{0:1,1:2}
extend({test1:'test1'.result1:'result1'},1.2.3]);
//{ '0': 1, '1': 2, '2': 3, test1: 'test1', result1: 'result1' }
// Add the object to the array
[ 1.2.3.test2: 'test2'.result2: 'result2' ]
Copy the code

generateCodeFrame

Give up, can not control

function generateCodeFrame(source, start = 0, end = source.length) {
    // Split the content into individual lines but capture the newline sequence
    // that separated each line. This is important because the actual sequence is
    // needed to properly take into account the full line length for offset
    // comparison
    let lines = source.split(/(\r? \n)/);
    // Separate the lines and newline sequences into separate arrays for easier referencing
    const newlineSequences = lines.filter((_, idx) = > idx % 2= = =1);
    lines = lines.filter((_, idx) = > idx % 2= = =0);
    let count = 0;
    const res = [];
    for (let i = 0; i < lines.length; i++) {
        count +=
            lines[i].length +
                ((newlineSequences[i] && newlineSequences[i].length) || 0);
        if (count >= start) {
            for (let j = i - range; j <= i + range || end > count; j++) {
                if (j < 0 || j >= lines.length)
                    continue;
                const line = j + 1;
                res.push(`${line}The ${' '.repeat(Math.max(3 - String(line).length, 0))}|  ${lines[j]}`);
                const lineLength = lines[j].length;
                const newLineSeqLength = (newlineSequences[j] && newlineSequences[j].length) || 0;
                if (j === i) {
                    // push underline
                    const pad = start - (count - (lineLength + newLineSeqLength));
                    const length = Math.max(1, end > count ? lineLength - pad : end - start);
                    res.push(` | ` + ' '.repeat(pad) + A '^'.repeat(length));
                }
                else if (j > i) {
                    if (end > count) {
                        const length = Math.max(Math.min(end - count, lineLength), 1);
                        res.push(` | ` + A '^'.repeat(length)); } count += lineLength + newLineSeqLength; }}break; }}return res.join('\n');
}
Copy the code

GetGlobalThis Global object

Like a scope chain, like a prototype chain

const getGlobalThis = () = > {
    return (_globalThis ||
        (_globalThis =
            typeofglobalThis ! = ='undefined'
                ? globalThis
                : typeofself ! = ='undefined'
                    ? self
                    : typeof window! = ='undefined'
                        ? window
                        : typeof global! = ='undefined'
                            ? global
                            : {}));
};
Copy the code

HasChanged change

Object.is

=== === === === === +0 is not equal to -0, NaN is equal to itself.
const hasChanged = (value, oldValue) = > !Object.is(value, oldValue);
// -0===0 true 1/-0 is negative infinity, and 1/0 is positive infinity
if (!Object.is) {
  Object.is = function(x, y) {
    // SameValue algorithm
    if (x === y) { // Steps 1-5, 7-10
      // Steps 6.b-6.e: +0 != -0
      returnx ! = =0 || 1 / x === 1 / y;
    } else {
      // Step 6.a: NaN == NaN
      returnx ! == x && y ! == y; }}; }Copy the code

HasOwn checks whether an attribute is owned

const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) = > hasOwnProperty.call(val, key);
//. Call is the function in which this is specified as the first argument and the function is executed.
//Object.prototype.hasOwnProperty.call(x,y)


hasOwn({__proto__: { a: 1 }}, 'a') // false
hasOwn({ a: undefined }, 'a') // true
hasOwn({}, 'a') // false
hasOwn({}, 'hasOwnProperty') // false
hasOwn({}, 'toString') // false
// is a property of its own, not up the chain through the prototype.
Copy the code

InvokeArrayFns executes the functions in the array

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

IsArray Identifies an array

const isArray = Array.isArray;

isArray([]); // true
const fakeArr = { __proto__: Array.prototype, length: 0 };
isArray(fakeArr); // false
fakeArr instanceof Array; // true
// So instanceof is not accurate
Copy the code

IsDate Whether a Data object

const isDate$1 = (val) = > val instanceof Date;
Copy the code

isFunction

const isFunction = (val) => typeof val === 'function'; // There are several ways to determine an array, but this one is more common and relatively compatible.Copy the code

IsIntegerKey Indicates whether the key is a number

const isString$1 = (val) = > typeof val === 'string';
const isIntegerKey = (key) = > isString$1(key) && key ! = ='NaN' &&
    key[0]! = =The '-' &&
    ' ' + parseInt(key, 10) === key;
/ / example:
isInegerKey('a'); // false
isInegerKey('0'); // true
isInegerKey('011'); // false
isInegerKey('11'); // true
// parseInt the second argument is base.
// Strings can be taken as array values.
// There is also a charAt function, but it is not commonly used
'abc'.charAt(0) // 'a'
// charAt returns an empty string '' when no value is retrieved
Copy the code

IsMap Determines whether the object is a Map object

const objectToString$1 = Object.prototype.toString;
const toTypeString$1 = (value) = > objectToString$1.call(value);
const isMap = (val) = > toTypeString(val) === '[object Map]';
//Object.prototype.toString.call(new Map())
/ / example:
const map = new Map(a); isMap(map);// true
Copy the code

IsObject Indicates whether an object

const isObject$1 = (val) = >val ! = =null && typeof val === 'object';
/ / example:
isObject(null); // false
isObject({name: 'if the sichuan'}); // true
// Typeof NULL is object
Copy the code

IsPlainObject is a pure object

const isPlainObject$1 = (val) = > toTypeString$1(val) === '[object Object]';
// What's the difference between pure and not pure?
Copy the code

IsOn Checks whether on+ is a non-lowercase letter

const onRE = /^on[^a-z]/;
const isOn = (key) = > onRE.test(key);

/ / example:
isOn('onChange'); // true
isOn('onchange'); // false
isOn('on3change'); // true
Copy the code

isPromise

// Check if it is an object and if there are then and catch methods
const isPromise = (val) = > {
    return isObject$1(val) && isFunction(val.then) && isFunction(val.catch);
};
// Determine if this is a Promise object
const p1 = new Promise(function(resolve, reject){
  resolve('if the sichuan');
});
isPromise(p1); // true
Copy the code

IsSSRSafeAttrName Indicates whether a security attribute word is used

//isSSRSafeAttrName('/t') 
//VM2655:9 unsafe attribute name: /t
//false
const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/;
const attrValidationCache = {};
function isSSRSafeAttrName(name) {
    if (attrValidationCache.hasOwnProperty(name)) {
        return attrValidationCache[name];
    }
    const isUnsafe = unsafeAttrCharRE.test(name);
    if (isUnsafe) {
        console.error(`unsafe attribute name: ${name}`);
    }
    return(attrValidationCache[name] = ! isUnsafe); }Copy the code

isSet

const isSet$1 = (val) = > toTypeString$1(val) === '[object Set]';
Copy the code

isString

const isString = (val) = > typeof val === 'string';
//toTypeString$1(val) === '[object String]'; I think we can use this
Copy the code

isSymbol

const isSymbol = (val) = > typeof val === 'symbol';
Copy the code

LooseEqual Determines whether objects are the same

Unlike Object.is, which refers to the same address, attributes and values are the same

function looseCompareArrays(a, b) {
    if(a.length ! == b.length)return false;
    let equal = true;
    for (let i = 0; equal && i < a.length; i++) {
        equal = looseEqual(a[i], b[i]);
        // If (! Equal return false, he wrote it that way
    }
    return equal;
}

function looseEqual(a, b) {
    // The reference address is the same, the value is also nothing like
    if (a === b)
        return true;
    // If both are date objects, than the timestamp
    let aValidType = isDate(a);
    let bValidType = isDate(b);
    if (aValidType || bValidType) {
        return aValidType && bValidType ? a.getTime() === b.getTime() : false;
    }
    // If both are arrays, ratio the length and ratio
    aValidType = isArray(a);
    bValidType = isArray(b);
    if (aValidType || bValidType) {
        return aValidType && bValidType ? looseCompareArrays(a, b) : false;
    }
    aValidType = isObject(a);
    bValidType = isObject(b);
    // If both objects are objects, the ratio of key quantity, key value and key value is similar to that of deep copy
    if (aValidType || bValidType) {
        /* istanbul ignore if: this if will probably never be called */
        if(! aValidType || ! bValidType) {return false;
        }
        const aKeysCount = Object.keys(a).length;
        const bKeysCount = Object.keys(b).length;
        if(aKeysCount ! == bKeysCount) {return false;
        }
        for (const key in a) {
            const aHasKey = a.hasOwnProperty(key);
            const bHasKey = b.hasOwnProperty(key);
            if((aHasKey && ! bHasKey) || (! aHasKey && bHasKey) || ! looseEqual(a[key], b[key])) {return false; }}}// Compare String, String(object) : [object object]
    return String(a) === String(b);
}
Copy the code

LooseIndexOf finds the same sequence number in the array as the parameter value

function looseIndexOf(arr, val) {
    return arr.findIndex(item= > looseEqual(item, val));
}
Copy the code

normalizeClass

//console.log(normalizeClass(["a c ", "b"])); ==>a c b
function normalizeClass(value) {
    let res = ' ';
    if (isString(value)) {
        res = value;
    }
    else if (isArray(value)) {
        // Like array join(' ')
        for (let i = 0; i < value.length; i++) {
            const normalized = normalizeClass(value[i]);
            if (normalized) {
                res += normalized + ' '; }}}else if (isObject(value)) {
        for (const name in value) {
            if (value[name]) {
                res += name + ' '; }}}returnres.trim(); } normalizeClass is used to attach label attributesclassConvert to standardclass.const str = 'a b c'
const arr = [
  {
    a: true.b: false.c: true,},]const obj = {
  a: true.b: false.c: true,}console.log(normalizeClass(str)) // a b c
console.log(normalizeClass(arr)) // a c
console.log(normalizeClass(obj)) // a c
Copy the code

normalizeStyle

const listDelimiterRE = /; (? ! [^(]*\))/g;
const propertyDelimiterRE = / / (+);
function parseStringStyle(cssText) {
    const ret = {};
    cssText.split(listDelimiterRE).forEach(item= > {
        if (item) {
            const tmp = item.split(propertyDelimiterRE);
            tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim()); }});return ret;
}
function normalizeStyle(value) {
    if (isArray(value)) {
        const res = {};
        for (let i = 0; i < value.length; i++) {
            const item = value[i];
            const normalized = isString(item)
                ? parseStringStyle(item)
                : normalizeStyle(item);
            if (normalized) {
                for (const key innormalized) { res[key] = normalized[key]; }}}return res;
    }
    else if (isString(value)) {
        return value;
    }
    else if (isObject(value)) {
        returnvalue; NormalizeStyle is used to convert attributes in the inline style of the tag to standard style attributes.const str = 'margin:10px; '
const arr = [
  {
    margin: '10px'.borderWidth: '10px',},]const obj = {
  margin: '10px'.borderWidth: '10px',}console.log(normalizeStyle(str)) // margin:10px;
console.log(normalizeStyle(arr)) // { margin: '10px', borderWidth: '10px' }
console.log(normalizeStyle(obj)) // { margin: '10px', borderWidth: '10px' }
Copy the code

normalizeProps

function normalizeProps(props) {
    if(! props)return null;
    let { class: klass, style } = props;
    if(klass && ! isString(klass)) { props.class = normalizeClass(klass); }if (style) {
        props.style = normalizeStyle(style);
    }
    returnprops; } normalizeProps Used for propsclassstyleAttribute transformation.const props = {
  class: [{ a: true.b: false.c: true}].style: [{ margin: '10px'.borderWidth: '10px'}}],console.log(normalizeProps(props)) // { class: 'a c', style: { margin: '10px', borderWidth: '10px' } }
Copy the code

stringifyStyle

const hyphenateRE = /\B([A-Z])/g;
const hyphenate = cacheStringFunction((str) = > str.replace(hyphenateRE, '- $1').toLowerCase());
const isNoUnitNumericStyleProp = /*#__PURE__*/ makeMap(`animation-iteration-count,border-image-outset,border-image-slice,` +
    `border-image-width,box-flex,box-flex-group,box-ordinal-group,column-count,` +
    `columns,flex,flex-grow,flex-positive,flex-shrink,flex-negative,flex-order,` +
    `grid-row,grid-row-end,grid-row-span,grid-row-start,grid-column,` +
    `grid-column-end,grid-column-span,grid-column-start,font-weight,line-clamp,` +
    `line-height,opacity,order,orphans,tab-size,widows,z-index,zoom,` +
    // SVG
    `fill-opacity,flood-opacity,stop-opacity,stroke-dasharray,stroke-dashoffset,` +
    `stroke-miterlimit,stroke-opacity,stroke-width`);
function stringifyStyle(styles) {
    let ret = ' ';
    if(! styles || isString(styles)) {return ret;
    }
    for (const key in styles) {
        const value = styles[key];
        const normalizedKey = key.startsWith(` - `)? key : hyphenate(key);if (isString(value) ||
            (typeof value === 'number' && isNoUnitNumericStyleProp(normalizedKey))) {
            // only render valid values
            ret += `${normalizedKey}:${value}; `; }}returnret; } stringifyStyle is used to convert the style of the object format to the object format and to convert the style properties.const str = 'margin:10px; '
const obj = {
  margin: '10px'.borderWidth: '10px',}console.log(stringifyStyle(str)) / /"
console.log(stringifyStyle(obj)) // margin:10px; border-width:10px;
Copy the code

propsToAttrMap

const propsToAttrMap = {
    acceptCharset: 'accept-charset'.className: 'class'.htmlFor: 'for'.httpEquiv: 'http-equiv'
};
Copy the code

The remove array removes a value

const remove = (arr, el) = > {
    const i = arr.indexOf(el);
    if (i > -1) {
        arr.splice(i, 1); }};Copy the code

ToDisplayString displays the corresponding string form

JSON.stringify

//toDisplayString({a:2,b:3})  
/ / {
// "a": 2,
// "b": 3
/ /}

const objectToString = Object.prototype.toString;
const replacer = (_key, val) = > {
    // can't use isRef here since @vue/shared has no deps
    if (val && val.__v_isRef) {
        return replacer(_key, val.value);
    }
    else if (isMap(val)) {
        return{[`Map(${val.size}) `]: [...val.entries()].reduce((entries, [key, val]) = > {
                entries[`${key}= > `] = val;
                returnentries; }, {}}; }else if (isSet(val)) {
        return{[`Set(${val.size}) `]: [...val.values()]
        };
    }
    else if(isObject(val) && ! isArray(val) && ! isPlainObject(val)) {return String(val);
    }
    return val;
};
const toDisplayString = (val) = > {
    return val == null
        ? ' '
        : isArray(val) || (isObject(val) && val.toString === objectToString)
            ? JSON.stringify(val, replacer, 2)
            : String(val);
};
Copy the code
console.log(
  toDisplayString(
    new Map([["a".2],
      ["b".3]]))); = = > {"Map(2)": {
    "a =>": 2."b =>": 3}}Copy the code

Turn toNumber digital

const toNumber = (val) = > {
    const n = parseFloat(val);
    return isNaN(n) ? val : n;
};

toNumber('111'); / / 111
toNumber('a111'); // 'a111'
parseFloat('a111'); // NaN
isNaN(NaN); // true
Copy the code

IsNaN is meant to be a NaN value, but it’s not accurate. For example, isNaN(‘a’) is true. So ES6 has a Number. IsNaN method to make up for this API.

Number.isNaN('a')  // false
Number.isNaN(NaN); // true
Copy the code

ToRawType similar typeof

const toRawType = (value) = > {
  // extract "RawType" from strings like "[object RawType]"
  return toTypeString$1(value).slice(8, -1);
};
//toRawType(''); 'String'
Copy the code

summary

  • There’s something in the cache
  • Re is sure to write tool functions or a necessary thing
  • Trango is still YYDS
  • The replace, Object. Freeze