Skip to content

Commit 3ec8c11

Browse files
张东张东
authored andcommitted
feat: 初始化
1 parent 7cb3193 commit 3ec8c11

File tree

4 files changed

+497
-1
lines changed

4 files changed

+497
-1
lines changed

.vitepress/config.mts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ export default defineConfig({
3737
{ text: "application", link: "/javascript/application/firstFrame" },
3838
],
3939
},
40+
{
41+
text: "框架",
42+
items: [
43+
{ text: "Vue", link: "/frame/vue/start" },
44+
{ text: "React", link: "/frame/react/start" },
45+
],
46+
},
4047
{ text: "Web-Api", link: "/Web-Api/ResizeObserver" },
4148
{ text: "pnpm", link: "/pnpm/overview" },
4249
{
@@ -102,6 +109,10 @@ export default defineConfig({
102109
text: "闭包",
103110
link: "/javascript/grammar/closure",
104111
},
112+
{
113+
text: "装饰器和转发",
114+
link: "/javascript/grammar/decorator",
115+
},
105116
{
106117
text: "来自旧时代的var",
107118
link: "/javascript/grammar/var",

frame/react/start.md

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
---
2+
outline: deep
3+
layout: doc
4+
---
5+
## react组件
6+
就是一个返回jsx的函数,在jsx中可以写类似html的东西
7+
jsx 看起来很像 htmlL,但它更严格一些,并且可以显示动态信息。要求所有标签明确的闭合
8+
```js
9+
function MyButton() {
10+
return (
11+
<button>I'm a button</button>
12+
);
13+
}
14+
```
15+
:::warning :warning:
16+
React 组件名称必须始终以大写字母开头,而 HTML 标签必须小写
17+
:::
18+
19+
:::tip DEEP DIVE
20+
:::details 为什么只能返回一个根节点
21+
jsx看起来像html,但是最后还是被转化成普通js对象,函数不能返回多个对象没有数组包裹。
22+
:::
23+
24+
:::tip :rocket: 为什么使用className 而不是 class
25+
jsx会转换为 js, jsx 编写的属性会成为 js 对象的键
26+
27+
例如,在一个自定义的React函数式组件中,可以通过解构赋值或直接访问props对象来读取属性值,并将它们存储到组件内部的变量中
28+
```js
29+
//假设props是
30+
// {
31+
// 'first-name''judy'
32+
// }
33+
const MyComponent = (props) => {
34+
const { 'first-name' } = props;
35+
36+
return (
37+
<div>
38+
</div>
39+
);
40+
};
41+
```
42+
这样是不行的
43+
:::
44+
## 展示数据
45+
jsx里面可以放入html,如果需要重新跳回js,可以使用大括号包裹
46+
```js{3}
47+
return (
48+
<h1>
49+
{user.name}
50+
</h1>
51+
);
52+
```
53+
修改属性需要用大括号替代引号
54+
```js{3}
55+
return (
56+
<img
57+
src={user.imageUrl}
58+
/>
59+
);
60+
```
61+
:::tip :rocket: 特殊的style
62+
```jsx
63+
style={{
64+
width: user.imageSize,
65+
height: user.imageSize
66+
}}
67+
```
68+
这里需要写成一个对象的形式在放到花括号中
69+
:::
70+
71+
在哪里使用花括号
72+
在 JSX 中只能以两种方式使用花括号:
73+
74+
* 作为JSX 标签内的文本`<h1>{name}'s To Do List</h1>`:可以,但`<{tag}>Gregorio Y. Zara's To Do List</{tag}>` 不会。
75+
* 作为紧跟在符号后面的属性=:`src={avatar}`将读取avatar变量,但`src="{avatar}"`会传递字符串"{avatar}"。
76+
## 条件渲染
77+
```jsx
78+
<div>
79+
{isLoggedIn ? (
80+
<AdminPanel />
81+
) : (
82+
<LoginForm />
83+
)}
84+
</div>
85+
```
86+
当你不需要分支时else,你也可以使用更短的逻辑&&语法:
87+
```js
88+
<div>
89+
{isLoggedIn && <AdminPanel />}
90+
</div>
91+
```
92+
## 响应事件
93+
onClick={handleClick}末尾没有括号
94+
## 简单示例
95+
子组件共享数据
96+
```js
97+
import { useState } from 'react';
98+
99+
export default function MyApp() {
100+
const [count, setCount] = useState(0);
101+
102+
function handleClick() {
103+
setCount(count + 1);
104+
}
105+
106+
return (
107+
<div>
108+
<h1>Counters that update together</h1>
109+
<MyButton count={count} onClick={handleClick} />
110+
<MyButton count={count} onClick={handleClick} />
111+
</div>
112+
);
113+
}
114+
115+
function MyButton({ count, onClick }) {
116+
return (
117+
<button onClick={onClick}>
118+
Clicked {count} times
119+
</button>
120+
);
121+
}
122+
123+
```
124+
:::warning :warning: 警告
125+
组件可以渲染其他组件,但绝不能嵌套它们的定义:
126+
```js
127+
128+
export default function Gallery() {
129+
// 🔴 Never define a component inside another component!
130+
function Profile() {
131+
// ...
132+
}
133+
// ...
134+
}
135+
```
136+
上面的代码片段非常慢,而且容易导致错误。相反,应该在顶层定义每个组件:
137+
```js
138+
export default function Gallery() {
139+
// ...
140+
}
141+
142+
// ✅ Declare components at the top level
143+
function Profile() {
144+
// ...
145+
}
146+
```
147+
当子组件需要来自父组件的一些数据时,通过 props 传递它,而不是嵌套定义。
148+
:::

javascript/grammar/closure.md

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,49 @@ layout: doc
2121
函数记住它创建于何处的方式,与函数被在哪儿调用无关
2222
:::
2323

24+
25+
:::warning :warning: 变量与函数初始化上有区别
26+
![](https://zh.javascript.info/article/closure/closure-variable-phrase.svg)
27+
28+
当脚本开始运行,词法环境预先填充了所有声明的变量。
29+
30+
最初,它们处于“未初始化(Uninitialized)”状态。这是一种特殊的内部状态,这意味着引擎知道变量,但是在用 let 声明前,不能引用它。几乎就像变量不存在一样。
31+
32+
然后 let phrase 定义出现了。它尚未被赋值,因此它的值为 undefined。从这一刻起,我们就可以使用变量了。
33+
34+
phrase 被赋予了一个值。
35+
36+
phrase 的值被修改。
37+
38+
一个函数其实也是一个值,就像变量一样。
39+
40+
**不同之处在于函数声明的初始化会被立即完成。**
41+
42+
当创建了一个词法环境(Lexical Environment)时,函数声明会立即变为即用型函数(不像 let 那样直到声明处才可用)。
43+
44+
![alt text](https://zh.javascript.info/article/closure/closure-function-declaration.svg)
45+
46+
正常来说,这种行为仅适用于函数声明,而不适用于我们将函数分配给变量的函数表达式,例如 let say = function(name)...。
47+
48+
```js
49+
console.log(a)
50+
let a = 123 //这会发生什么
51+
```
52+
:::
53+
54+
:::details 答案
55+
Error: Cannot access 'a' before initialization
56+
57+
而不是 ReferenceError: a is not defined
58+
59+
如果这里是var就是undefined了
60+
61+
从程序执行进入代码块(或函数)的那一刻起,变量就开始进入“未初始化”状态。它一直保持未初始化状态,直至程序执行到相应的 let 语句。
62+
63+
换句话说,一个变量从技术的角度来讲是存在的,但是在 let 之前还不能使用。
64+
65+
变量暂时无法使用的区域(从代码块的开始到 let)有时被称为“死区”。
66+
:::
2467
## 内存泄漏
2568
通常,函数调用完成后,会将词法环境和其中的所有变量从内存中删除。因为现在没有任何对它们的引用了。与 JavaScript 中的任何其他对象一样,词法环境仅在可达时才会被保留在内存中。
2669

@@ -51,4 +94,110 @@ function f() {
5194
// 数组中的 3 个函数,每个都与来自对应的 f() 的词法环境相关联
5295
let arr = [f(), f(), f()];
5396
```
54-
当词法环境对象变得不可达时,它就会死去(就像其他任何对象一样)。换句话说,它仅在至少有一个嵌套函数引用它时才存在。这会导致内存泄漏
97+
当词法环境对象变得不可达时,它就会死去(就像其他任何对象一样)。换句话说,它仅在至少有一个嵌套函数引用它时才存在。这会导致内存泄漏
98+
99+
## 习题
100+
函数会选择最新的内容吗?
101+
102+
函数 sayHi 使用外部变量。当函数运行时,将使用哪个值?
103+
104+
```js
105+
let name = "John";
106+
107+
function sayHi() {
108+
alert("Hi, " + name);
109+
}
110+
111+
name = "Pete";
112+
113+
sayHi(); // 会显示什么:"John" 还是 "Pete"?
114+
```
115+
:::details 答案
116+
答案:Pete。
117+
118+
函数将从内到外依次在对应的词法环境中寻找目标变量,它使用最新的值。
119+
120+
旧变量值不会保存在任何地方。当一个函数想要一个变量时,它会从自己的词法环境或外部词法环境中获取当前值。
121+
:::
122+
123+
Counter 是独立的吗?
124+
125+
在这儿我们用相同的 makeCounter 函数创建了两个计数器(counters):counter 和 counter2。
126+
127+
它们是独立的吗?第二个 counter 会显示什么?0,1 或 2,3 还是其他?
128+
```js
129+
function makeCounter() {
130+
let count = 0;
131+
132+
return function() {
133+
return count++;
134+
};
135+
}
136+
137+
let counter = makeCounter();
138+
let counter2 = makeCounter();
139+
140+
alert( counter() ); // 0
141+
alert( counter() ); // 1
142+
143+
alert( counter2() ); // ?
144+
alert( counter2() ); // ?
145+
```
146+
147+
:::details 答案
148+
答案是:0,1。
149+
150+
函数 counter 和 counter2 是通过 makeCounter 的不同调用创建的。
151+
152+
因此,它们具有独立的外部词法环境,每一个都有自己的 count。
153+
:::
154+
155+
```js
156+
"use strict";
157+
158+
let phrase = "Hello";
159+
160+
if (true) {
161+
let user = "John";
162+
163+
function sayHi() {
164+
alert(`${phrase}, ${user}`);
165+
}
166+
}
167+
168+
sayHi();//alert什么
169+
```
170+
:::details 答案
171+
ReferenceError: sayHi is not defined
172+
173+
如果不是严格模式不会报错
174+
:::
175+
176+
闭包 sum
177+
178+
编写一个像 sum(a)(b) = a+b 这样工作的 sum 函数。
179+
180+
是的,就是这种通过双括号的方式(并不是错误)。
181+
182+
举个例子:
183+
184+
sum(1)(2) = 3
185+
sum(5)(-1) = 4
186+
187+
:::details 答案
188+
为了使第二个括号有效,第一个(括号)必须返回一个函数。
189+
190+
就像这样:
191+
```js
192+
function sum(a) {
193+
194+
return function(b) {
195+
return a + b; // 从外部词法环境获得 "a"
196+
};
197+
198+
}
199+
200+
alert( sum(1)(2) ); // 3
201+
alert( sum(5)(-1) ); // 4
202+
```
203+
:::

0 commit comments

Comments
 (0)