源码系列

# 源码系列

# 1.jquery源码

jquery的v3.4.1版本:jquery源码 (opens new window)

  • 核心模块

自执行匿名函数-防止与其他代码冲突和污染全局环境,外不能访内,内可以访外

(function(global, factory){
})(typeof window !== "underfined" ? window: this, function(window, noGlobal){
});
1
2
3

问题:外界如何访问到源码内的函数?

外部暴露访问-浏览器环境下,把$ 和 jQuery函数挂载到window上,在外界就可以访问到$和jQuery了

if ( !noGlobal ) {
	window.jQuery = window.$ = jQuery;
}
// 其中`noGlobal`参数只有在这里用到
1
2
3
4

# 2.axios拦截器源码

使用

//添加请求拦截
axios.interceptors.request.use(function (config) {
 // 做些请求拦截
 return config;
  }, function (error) {
 // 请求未发送,发生错误
 return Promise.reject(error);
})

// 添加响应拦截
axios.interceptors.response.use(function (response) {
 //响应状态码是2xx时,做的响应拦截
 return response;
  }, function (error) {
 // 响应状态码是2xx时,做的响应拦截
 return Promise.reject(error);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

源码:InterceptorManager.js

  • axios 把用户注册的每个拦截器构造成一个 promise.then 所接受的参数,把相对应的拦截器数组进行调用链的头部和尾部组装,在运行时把所有的拦截器按照一个 promise 链的形式以此执行,
  • use方法的作用就是将处理函数封装成一个处理对象放到拦截器数组(handlers)里。拦截器的use方法,分别传三个参数,其中fulfilled和rejected参数传入promise.then()中,是一个函数方
'use strict'

var utils = require('./../utils')

//handlers数组存放拦截器任务对象
function InterceptorManager() {
 this.handlers = [];
}

/**
 * 拦截器任务,返回拦截器任务数组中的索引,以方便移除
 *
 * @param {Function} fulfilled The function to handle `then` for a `Promise`
 * @param {Function} rejected The function to handle `reject` for a `Promise`
 *
 * @return {Number} An ID used to remove interceptor later
 */
InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
 this.handlers.push({
 fulfilled: fulfilled,
 rejected: rejected,
 synchronous: options ? options.synchronous : false,
 runWhen: options ? options.runWhen : null
  });
 return this.handlers.length - 1;
};

/**
 * 移除拦截器任务对象,根据拦截器任务的索引,将对象变为空
 *
 * @param {Number} id The ID that was returned by `use`
 */
InterceptorManager.prototype.eject = function eject(id) {
 if (this.handlers[id]) {
 this.handlers[id] = null;
  }
};

/**
 * axios提供遍历拦截器的方法,主要目的是将handlers数组为null的项跳过执行
 *
 * @param {Function} fn The function to call for each interceptor
 */
InterceptorManager.prototype.forEach = function forEach(fn) {
 utils.forEach(this.handlers, function forEachHandler(h) {
 if (h !== null) {
 fn(h);
   }
  });
};
module.exports = InterceptorManager;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

过程: Image text

# 3.vue-router源码

  • new Vue创建实例中加入router对象时,会注入$route和$router两个属性
  • $route—路由规则—meta,query
  • params传参不在地址栏显示,query传参在地址显示,所以尽可能多用paramsimg.png

Image Text

  • $router—路由对象
  • push(会记录历史)
  • replace(不会记录历史)
  • go方法—go(-1),上一个页面,go(-2),上上一个页面

Image Text

  • 获取指定的订单
{
    path: '/detail:id',
    name: 'detail',
    // 在组件中通过props来接受url参数
    props: true
}
// 获取id
// 组件内
props:['id'], {{id}} //不再依赖路由规则推荐
// 指定路由
this.$route.params.id //强依赖于路由,必须要有路由传递相应的参数
1
2
3
4
5
6
7
8
9
10
11
  • 模式
  • Hash: /#/—基于锚点,触发onhashchange事件—默认
  • History: / —服务端配置支持,基于html5的history api
  • history.pushState—实现客户端路由—>ie10

# 4.如何打造一个自己的脚手架mycli?

简单的流程

  • npm init -y创建一个项目
  • 在package.json配置bin为"bin": "bin/test",
  • 在test.js首行加入#! /usr/bin/env node,后面加入console.log("hello world");
  • 运行npm link,至全局
  • 命令行成功打印出 hello world