Skip to content

Commit ab0febf

Browse files
author
febobo
committed
layout init
1 parent 37cbcc9 commit ab0febf

File tree

17 files changed

+2446
-18
lines changed

17 files changed

+2446
-18
lines changed

docs/.vuepress/config.js

+68-16
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,84 @@
11
module.exports = {
2-
title: 'Vue3.0 JS',
3-
description: '下一代web开发方式,更快,更轻,易维护,更多的原生支持',
4-
// base: '/slamdunk-the-vue3/',
2+
title: "Vue3.0 JS",
3+
description: "下一代web开发方式,更快,更轻,易维护,更多的原生支持",
4+
// base: '/slamdunk-the-vue3/',
55
head: [
6-
['link', { rel: 'icon', href: '/onepunch.jpeg' }],
7-
['meta', { name: 'keywords', content: 'vue3中文, vue3js文档, vue3资料, vue3 vue-composition-api, vuecli,vue-cli,vue-cli文档,vue-cli学习,vue文档,vue中文,vue学习,前端开发,vue框架,vue社区' }],
8-
['script', { src: 'https://hm.baidu.com/hm.js?db1f163122162bcdb6d04f76b5c1df17'}]
6+
["link", { rel: "icon", href: "/onepunch.jpeg" }],
7+
[
8+
"meta",
9+
{
10+
name: "keywords",
11+
content:
12+
"vue3中文, vue3js文档, vue3资料, vue3 vue-composition-api, vuecli,vue-cli,vue-cli文档,vue-cli学习,vue文档,vue中文,vue学习,前端开发,vue框架,vue社区",
13+
},
14+
],
15+
[
16+
"script",
17+
{ src: "https://hm.baidu.com/hm.js?db1f163122162bcdb6d04f76b5c1df17" },
18+
],
919
],
1020
themeConfig: {
11-
repo: 'vueClub/vue3doc',
21+
repo: "vueClub/vue3doc",
1222
// 自定义仓库链接文字。默认从 `themeConfig.repo` 中自动推断为
1323
// "GitHub"/"GitLab"/"Bitbucket" 其中之一,或是 "Source"。
14-
repoLabel: 'Github',
24+
repoLabel: "Github",
1525

1626
// 以下为可选的编辑链接选项
1727

1828
// 假如你的文档仓库和项目本身不在一个仓库:
19-
docsRepo: 'vueClub/vue3doc',
20-
// 假如文档不是放在仓库的根目录下:
21-
// docsDir: 'docs',
22-
// 假如文档放在一个特定的分支下:
23-
docsBranch: 'master',
29+
docsRepo: "vueClub/vue3doc",
30+
docsDir: "docs",
31+
docsBranch: "master",
2432
// 默认是 false, 设置为 true 来启用
2533
editLinks: true,
2634
// 默认为 "Edit this page"
27-
editLinkText: '帮助我们改善此页面!',
35+
editLinkText: "帮助我们改善此页面!",
36+
// displayAllHeaders: true,
37+
sidebar: [
38+
{
39+
title: "阅前必读",
40+
collapsable: false,
41+
children: [["start/", "写在最前面"]],
42+
},
43+
{
44+
title: "前置知识",
45+
collapsable: false,
46+
children: [
47+
["es6/", "proxy"],
48+
["es6/weekmap", "weekmap"],
49+
["es6/typeScript", "typeScript语法"],
50+
["es6/spec", "spec语法"],
51+
],
52+
},
53+
{
54+
title: "响应式系统",
55+
collapsable: false,
56+
sidebarDepth: 2,
57+
children: [
58+
["reactivity/", "整体概览"],
59+
["reactivity/reactive", "reactive"],
60+
["reactivity/reactive.spec", "reactive.spec"],
61+
["reactivity/effect", "effect"],
62+
["reactivity/effect.spec", "effect.spec"],
63+
],
64+
},
65+
{
66+
title: "编绎模块",
67+
collapsable: false,
68+
children: [
69+
["compiler/", "compiler"],
70+
],
71+
},
72+
{
73+
title: "Runtime",
74+
collapsable: false,
75+
children: [
76+
["runtime/", "runtime"],
77+
],
78+
},
79+
],
2880
},
2981
markdown: {
30-
lineNumbers: true,
82+
lineNumbers: true,
3183
},
32-
}
84+
};

docs/compiler/index.md

Whitespace-only changes.

docs/es6/index.md

+237
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
## Proxy
2+
3+
> 定义: 用于定义基本操作的自定义行为
4+
5+
由于`proxy`修改的是程序默认形为,就形同于在编程语言层面上做修改,属于元编程(`meta` `programming`)
6+
7+
**元编程(英语:Metaprogramming**,又译超编程,是指某类计算机程序的编写,这类计算机程序编写或者操纵其它程序(或者自身)作为它们的数据,或者在运行时完成部分本应在编译时完成的工作
8+
9+
一段代码来理解元编程
10+
```bash
11+
#!/bin/bash
12+
# metaprogram
13+
echo '#!/bin/bash' >program
14+
for ((I=1; I<=1024; I++)) do
15+
echo "echo $I" >>program
16+
done
17+
chmod +x program
18+
```
19+
这段程序每执行一次能帮我们生成一个名为program的文件,文件内容为1024行`echo`,如果我们手动来写1024行代码,显然就很低效
20+
21+
元编程优点:与手工编写全部代码相比,程序员可以获得更高的工作效率,或者给与程序更大的灵活度去处理新的情形而无需重新编译
22+
23+
`proxy`音译为代理,在操作目标对象前架设一层代理,将所有本该我们手动编写的程序交由代理来处理,通俗点可以理解为生活的代购,中介服务,所有的行为都不会直接触达目标对象
24+
25+
### 语法
26+
```js
27+
/
28+
* target 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理
29+
* handler 一个通常以函数作为属性的对象,用来定制拦截行为
30+
*/
31+
const proxy = new Proxy(target, handle)
32+
```
33+
34+
举个例子
35+
```js
36+
const origin = {}
37+
const obj = new Proxy(origin, {
38+
get: function (target, propKey, receiver) {
39+
return '10'
40+
}
41+
});
42+
43+
obj.a // 10
44+
obj.b // 10
45+
origin.a // undefined
46+
origin.b // undefined
47+
```
48+
上方代码我们给一个空对象的get架设了一层代理,所有`get`操作都会直接返回我们定制的数字10,需要注意的是,代理只会对`proxy`对象生效,如上方的`origin`就没有任何效果
49+
50+
### Handler 对象常用的方法
51+
52+
| 方法 | 描述 |
53+
| ---- | ---- |
54+
| handler.has() | in 操作符的捕捉器。|
55+
| handler.get() | 属性读取操作的捕捉器。|
56+
| handler.set() | 属性设置操作的捕捉器。|
57+
| handler.deleteProperty() | delete 操作符的捕捉器。|
58+
| handler.ownKeys() | Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。|
59+
| handler.apply() | 函数调用操作的捕捉器。|
60+
| handler.construct() | new 操作符的捕捉器|
61+
62+
63+
下面挑`handler.get`重点讲一下,其它方法的使用也都大同小异,不同的是参数的区别
64+
65+
#### handler.get
66+
67+
get我们在上面例子已经体验过了,这里再详细介绍一下,方法用于代理目标对象的属性读取操作
68+
69+
授受三个参数 `get(target, propKey, ?receiver) `
70+
- target 目标对象
71+
- propkey 属性名
72+
- receiver Proxy实例本身
73+
74+
**举个例子**
75+
```js
76+
const person = {
77+
like: "vuejs"
78+
}
79+
80+
const obj = new Proxy(person, {
81+
get: function(target, propKey) {
82+
if (propKey in target) {
83+
return target[propKey];
84+
} else {
85+
throw new ReferenceError("Prop name \"" + propKey + "\" does not exist.");
86+
}
87+
}
88+
})
89+
90+
obj.like // vuejs
91+
obj.test // Uncaught ReferenceError: Prop name "test" does not exist.
92+
```
93+
上面的代码表示在读取代理目标的值时,如果有值则直接返回,没有值就抛出一个自定义的错误
94+
95+
**注意:**
96+
- 如果要访问的目标属性是不可写以及不可配置的,则返回的值必须与该目标属性的值相同
97+
- 如果要访问的目标属性没有配置访问方法,即get方法是undefined的,则返回值必须为undefined
98+
99+
如下面的例子
100+
```js
101+
const obj = {};
102+
Object.defineProperty(obj, "a", {
103+
configurable: false,
104+
enumerable: false,
105+
value: 10,
106+
writable: false
107+
})
108+
109+
const p = new Proxy(obj, {
110+
get: function(target, prop) {
111+
return 20;
112+
}
113+
})
114+
115+
p.a // Uncaught TypeError: 'get' on proxy: property 'a' is a read-only and non-configurable..
116+
```
117+
118+
### 可撤消的Proxy
119+
120+
`proxy`有一个唯一的静态方法,`Proxy.revocable(target, handler) `
121+
122+
`Proxy.revocable()`方法可以用来创建一个可撤销的代理对象
123+
124+
该方法的返回值是一个对象,其结构为: `{"proxy": proxy, "revoke": revoke}`
125+
126+
- proxy
127+
表示新生成的代理对象本身,和用一般方式 new Proxy(target, handler) 创建的代理对象没什么不同,只是它可以被撤销掉。
128+
- revoke
129+
撤销方法,调用的时候不需要加任何参数,就可以撤销掉和它一起生成的那个代理对象。
130+
131+
该方法常用于完全封闭对目标对象的访问, 如下示例
132+
```js
133+
const target = { name: 'vuejs'}
134+
const {proxy, revoke} = Proxy.revocable(target, handler)
135+
proxy.name // 正常取值输出 vuejs
136+
revoke() // 取值完成对proxy进行封闭,撤消代理
137+
proxy.name // TypeError: Revoked
138+
```
139+
140+
### Proxy的应用场景
141+
142+
`Proxy`的应用范围很广,下方列举几个典型的应用场景
143+
- **校验器**
144+
145+
想要一个`number`,拿回来的却是`string`,头大不大?下面我们使用`Proxy`实现一个逻辑分离的数据格式验证器,嗯,真香!
146+
147+
```js
148+
const target = {
149+
_id: '1024',
150+
name: 'vuejs'
151+
}
152+
153+
const validators = {
154+
name(val) {
155+
return typeof val === 'string';
156+
},
157+
_id(val) {
158+
return typeof val === 'number' && val > 1024;
159+
}
160+
}
161+
162+
const createValidator = (target, validator) => {
163+
return new Proxy(target, {
164+
_validator: validator,
165+
set(target, propkey, value, proxy){
166+
let validator = this._validator[propkey](value)
167+
if(validator){
168+
return Reflect.set(target, propkey, value, proxy)
169+
}else {
170+
throw Error(`Cannot set ${propkey} to ${value}. Invalid type.`)
171+
}
172+
}
173+
})
174+
}
175+
176+
const proxy = createValidator(target, validators)
177+
178+
proxy.name = 'vue-js.com' // vue-js.com
179+
proxy.name = 10086 // Uncaught Error: Cannot set name to 10086. Invalid type.
180+
proxy._id = 1025 // 1025
181+
proxy._id = 22 // Uncaught Error: Cannot set _id to 22. Invalid type
182+
183+
```
184+
185+
186+
187+
- **防止对象的内部属性(私有属性)被外部读写**
188+
189+
在日常编写代码的过程中,我们想定义一些私有属性,通常是在团队中进行约定,大家按照约定在变量名之前添加下划线 _ 或者其它格式来表明这是一个私有属性,但我们不能保证他能真私‘私有化’,下方示例使用Proxy轻松实现私有属性拦截
190+
191+
```js
192+
const target = {
193+
_id: '1024',
194+
name: 'vuejs'
195+
}
196+
197+
const proxy = new Proxy(target, {
198+
get(target, propkey, proxy){
199+
if(propkey[0] === '_'){
200+
throw Error(`${propkey} is restricted`)
201+
}
202+
return Reflect.get(target, propkey, proxy)
203+
},
204+
set(target, propkey, value, proxy){
205+
if(propkey[0] === '_'){
206+
throw Error(`${propkey} is restricted`)
207+
}
208+
return Reflect.get(target, propkey, value, proxy)
209+
}
210+
})
211+
212+
proxy.name // vuejs
213+
proxy._id // Uncaught Error: _id is restricted
214+
proxy._id = '1025' // Uncaught Error: _id is restricted
215+
```
216+
217+
`Proxy`的使用场景还有很多很多,这里也不再一一列举,只要你需要在某一个动作的生命周期内做一些特定的处理,那么`Proxy`都是适合你的
218+
219+
### Proxy 与 Object.defineProperty
220+
`Proxy` 出现之前,`JavaScript` 中就提供过 `Object.defineProperty`,允许对对象的 `getter/setter` 进行拦截
221+
222+
大家熟悉的Vue框架双向绑定的实现也由`defineProperty`重构为`Proxy`,那么两者的区别在究竟在哪里呢?
223+
224+
请看下面这张图,图中所示的都是`defineProperty`现存的问题,而`Proxy`均已完美支持
225+
226+
![image.png](https://static.vue-js.com/5289d760-c675-11ea-ae44-f5d67be454e7.png)
227+
228+
### 兼容
229+
除了IE,其它浏览器最新版本均已支持
230+
231+
![image.png](https://static.vue-js.com/9a145b00-c675-11ea-ae44-f5d67be454e7.png)
232+
233+
参考:
234+
- [https://zh.wikipedia.org/wiki/](https://zh.wikipedia.org/wiki/)
235+
- [https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy)
236+
- [https://es6.ruanyifeng.com/#docs/proxy#Proxy-revocable](https://es6.ruanyifeng.com/#docs/proxy#Proxy-revocable)
237+
- [https://juejin.im/post/5e78d908f265da57340267f7#heading-2](https://juejin.im/post/5e78d908f265da57340267f7#heading-2)

docs/es6/spec.md

Whitespace-only changes.

docs/es6/typeScript.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## TypeScript 基本语法

docs/es6/weekmap.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## WeekMap
2+
3+
22

0 commit comments

Comments
 (0)