Mock.js 主要干了两件事:
- 生成随机数据
- 拦截 Ajax 请求
走走,这就去看看是咋回事儿
如何生成随机数据
即
Mock.mock(template)
的工作原理
// 属性名 name
// 生成规则 rule
// 属性值 value
"name|rule": value
原理概述
正则拆分,分类处理
- 根据
template
的类型,来调用对应的handler
处理 - 借助正则,在步骤 1 中,将当前处理的属性名拆成
name
,rule
两部分 - 在
handler
中,依据生成规则rule
,占位符placeholder
处理生成对应的value
- 如为对象,各属性按步骤 1 继续处理
举个例子
以常见的情况为例,看源码中的相关处理方式
可以在控制台中实验一波:mockjs.com/examples.ht…
Mock.mock({
"apples": {
"weight": "@range(5)",
"color|5": ["red"]
},
"sum": "@./apples/weight",
"copy": "@sum"
})
1. Mock.mock(template) ->源码直通车
只传入模版,调用 Handler.gen(template)
->源码直通车
2. Handler.gen(template, name, context)
此时 template
的类型为 object
,接下来调用 Handler['object']
Handler['object']
的返回值会作为 mock 的结果
3. Handler['object'] ->源码直通车
字段中包含
template
,表示包含生成规则的 **如
path
指不包含生成规则的访问路径;templatePath
指包含生成规则的访问路径
依次处理属性,递归调用 Handler.gen(template, name, context)
template
为当前处理到的属性名 name
(包含生成规则)对应的属性值
在处理过程中维护 context
中记录的字段:
path
/templatePath
:记录当前访问路径currentContext
/templateCurrentContext
:处理完的数据root
/templateRoot
:根对象
首次调用会将对应的数据保存到 root
/ templateRoot
中
4. Handler['string'] ->源码直通车
"weight": "@range(5)" 或 "sum": "@./apples/weight" 或 "copy": "@sum"
空字符串
-
如指定生成规则,则取对应个数的随机字符;否则,直接取空字符串
"ASCII|1-10": ""
=> 1~10 内取一随机数作为个数
非空字符串
-
根据生成规则中指定的数字,得到一待处理的完整字符串
-
依次处理可能的占位符,调用
Handler.placeholder(placeholder, obj, templateContext, options)
得到对应的值,替换原有占位符"@range(5)@test"
=>["@range(5)", "@test"]
-
placeholder
,待处理的占位符,如"@range(5)"
-
obj
/templateContext
,对应前文context
中保存的currentContext
/templateCurrentContext
,处理完的数据 -
options
,传给该处理函数的所有字段,如当前处理的属性值类型type
,属性值模版template
,上下文context
等等 ->源码直通车
5. Handler.placeholder(placeholder, obj, templateContext, options) ->源码直通车
拆分占位符,得到对应的名称(下文以 key
代指)及参数
引用模版中属性
"copy": "@sum"
obj[key]
已处理完,则直接使用(示例情况)key
还未处理到,则调用Handler.gen
,先计算被引用的属性值
绝对 / 相对路径
"sum": "@./apples/weight"
在
Handler.gen
首次执行时,将 1 作为路径根 ->源码直通车
依次处理 path
路径数组
-
占位符拆分,得到路径数组,拼接成绝对路径
- 当前路径:
[1, "sum"]
- 相对路径:
[".", "apples", "weight"]
- 绝对路径:
[1, "apples", "weight"]
- 当前路径:
-
根据路径,从
options
中的context
里,依据root
/templateRoot
,依次向下取值- 已处理,直接用
- 未处理,调用
Handler.gen
,先计算被引用的属性值
-
路径没找到,返回
undefined
特定占位符
"weight": "@range(5)"
Random 文件夹下,内置了许多随机生成函数
-
Random 中有对应
key
- 函数类型,传参数,直接调用
- 数组类型,随机取一个
-
无对应
key
,占位符原样返回
6. Handler['array'] ->源码直通车
"color|5": ["red"]
空数组
直接返回 ""
非空数组
- 如无生成规则,直接遍历元素,递归调用
Handler.gen
- 如有,则会在遍历过程中处理,如从数组中随机取一个生成,重复添加多次等
关系总览
如何拦截 Ajax 请求
即
Mock.mock( rurl, rtype?, template|function(options))
的工作原理
原理概述
从 1.0 开始,Mock.js 通过覆盖和模拟原生 XMLHttpRequest 的行为来拦截 Ajax 请求
-
用
MockXMLHttpRequest
覆盖原生window.XMLHttpRequest
-
在
open
中,如果初始化的url
和method
,在_mocked
中找到,则会打上拦截标记(原型属性match
,置为true
),否则使用原生 XHR -
在
send
中,通过拦截标记判断是否使用原生 XHR,如拦截请求,根据template|function(options)
,设置响应数据:- 传入函数,返回函数调用结果
- 传入 template,利用 Mock.mock,返回生成的假数据
关系总览
字节跳动幸福里前端团队急缺人才(校招/社招大量HC),欢迎加我微信 orca_o 咨询~