Vue.js源码阅读(一)基础篇

书中仙
2019.05.14 22:51 字数 5634 阅读 29 评论 0 喜欢 0

长期阅读源码是一种好习惯,我们可以从中学习到很多知识,很多思想,看看大神的代码是怎么写的,下面我就带大家来看一下Vue的源码。

很多人看Vue的源码是看的Vue的src目录下的文件,我就不一样了,我从Vue的dist文件夹下看起,从不同的视角去看Vue,看是否能给大家不同的启发。

首先我们去GitHub上搜索Vue,找到之后把它clone下来,clone下来之后它的目录结构应该是这样的


我们主要关心它的dist文件夹里的vue.js,注意啊,我们这次分析的Vue版本是v2.6.9

打开一看,代码有点多,11926行,不用怕,我们一点点来分析

/*!
* Vue.js v2.6.9
* (c) 2014-2019 Evan You
* Released under the MIT License.
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.Vue = factory());
}(this, function () { 'use strict';

很多人上来一看,前5行都看蒙了,我们静下心来看,这是一个自调用函数,将this和一个function当作参数传了进去,这个自调用函数里边是一个大的三元表达式,上来先判断module.exports是否成立,如果是的话就将factory函数导出,如果不成立的话在判断当前是否是AMD规范,这个AMD我也不是太了解,有兴趣的可以去自己学习,如果是AMD规范的话就 define(factory),define也是类似于exports的关键字。最后都不是的话那说明运行在未经过webpack打包的普通的浏览器端,就将factory挂载在全局对象的Vue属性上。

然后我们来看这个factory函数的内部

从14行到大约200行都是Vue封装的一些工具函数,都很简单,函数名也都非常清晰易懂,像isObject,判断是否是Object类型,isUndef,判断是否是undefined类型,我这边就注明一下函数名,不详细介绍了

从14行到32行

  var emptyObject = Object.freeze({});   /* 定义了一个冻结的对象,下面会用到 */

// These helpers produce better VM code in JS engines due to their
// explicitness and function inlining.
function isUndef (v) { /* 判断是不是undefined或者null */
return v === undefined || v === null
}

function isDef (v) { /* 判断是不是非unedefined和null */
return v !== undefined && v !== null
}

function isTrue (v) { /* 判断是不是true */
return v === true
}

function isFalse (v) { /* 判断是不是false */
return v === false
}

从34行到75行

  /**
* Check if value is primitive.
*/
function isPrimitive (value) { /* 判断是否是除undefined和null之外的原始类型 */
return (
typeof value === 'string' ||
typeof value === 'number' ||
// $flow-disable-line
typeof value === 'symbol' ||
typeof value === 'boolean'
)
}

/**
* 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) { /* 判断是否是object */
return obj !== null && typeof obj === 'object'
}

/**
* 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)
}

/**
* Strict object type check. Only returns true
* for plain JavaScript objects.
*/
function isPlainObject (obj) { /* 判断是否是Object本身 */
return _toString.call(obj) === '[object Object]'
}

function isRegExp (v) { /* 判断是否是正则表达式 */
return _toString.call(v) === '[object RegExp]'
}

从80行到129行

  /**
* 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)
}

function isPromise (val) { /* 判断是否是promise */
return (
isDef(val) &&
typeof val.then === 'function' &&
typeof val.catch === 'function'
)
}

/**
* 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)
}

/**
* 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
}

/**
* Make a map and return a function for checking if a key
* is in that map.
*/
function makeMap ( /* 创建一个map并返回一个函数来检查是否有键在map上。 */
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]; }
}

从134行到193行

  /**
* Check if a tag is a built-in tag.
*/
var isBuiltInTag = makeMap('slot,component', true); /* 检测标签是否为内置标签,正好用上了上面的方法 */

/**
* Check if an attribute is a reserved attribute.
*/
var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is'); /* 检测属性是否为保留属性 */

/**
* 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)
}
}
}

/**
* Check whether an object has the property.
*/
var hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn (obj, key) { /* 判断此属性是否是该对象上的原生属性 */
return hasOwnProperty.call(obj, key)
}

/**
* 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))
})
}

/**
* Camelize a hyphen-delimited string.
*/
var camelizeRE = /-(\w)/g;
var camelize = cached(function (str) { /* 使连字符分隔的字符串驼峰化 */
return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })
});

/**
* Capitalize a string.
*/
var capitalize = cached(function (str) { /* 字符串首字母大写 */
return str.charAt(0).toUpperCase() + str.slice(1)
});

/**
* Hyphenate a camelCase string.
*/
var hyphenateRE = /\B([A-Z])/g; /* 使驼峰化的字符串用-$1连接 */
var hyphenate = cached(function (str) {
return str.replace(hyphenateRE, '-$1').toLowerCase()
});

未完待续...





支付二维码
登录 后发表评论
${comment_count}条评论 评论

智慧如你,不想发表一点想法咩~

推荐阅读
更多精彩内容