Skip to content

Commit

Permalink
feat: 初始化
Browse files Browse the repository at this point in the history
  • Loading branch information
张东 authored and 张东 committed Aug 8, 2024
1 parent 7cb3193 commit 3ec8c11
Show file tree
Hide file tree
Showing 4 changed files with 497 additions and 1 deletion.
11 changes: 11 additions & 0 deletions .vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ export default defineConfig({
{ text: "application", link: "/javascript/application/firstFrame" },
],
},
{
text: "框架",
items: [
{ text: "Vue", link: "/frame/vue/start" },
{ text: "React", link: "/frame/react/start" },
],
},
{ text: "Web-Api", link: "/Web-Api/ResizeObserver" },
{ text: "pnpm", link: "/pnpm/overview" },
{
Expand Down Expand Up @@ -102,6 +109,10 @@ export default defineConfig({
text: "闭包",
link: "/javascript/grammar/closure",
},
{
text: "装饰器和转发",
link: "/javascript/grammar/decorator",
},
{
text: "来自旧时代的var",
link: "/javascript/grammar/var",
Expand Down
148 changes: 148 additions & 0 deletions frame/react/start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
---
outline: deep
layout: doc
---
## react组件
就是一个返回jsx的函数,在jsx中可以写类似html的东西
jsx 看起来很像 htmlL,但它更严格一些,并且可以显示动态信息。要求所有标签明确的闭合
```js
function MyButton() {
return (
<button>I'm a button</button>
);
}
```
:::warning :warning:
React 组件名称必须始终以大写字母开头,而 HTML 标签必须小写
:::
:::tip DEEP DIVE
:::details 为什么只能返回一个根节点
jsx看起来像html,但是最后还是被转化成普通js对象,函数不能返回多个对象没有数组包裹。
:::
:::tip :rocket: 为什么使用className 而不是 class
jsx会转换为 js, jsx 编写的属性会成为 js 对象的键
例如,在一个自定义的React函数式组件中,可以通过解构赋值或直接访问props对象来读取属性值,并将它们存储到组件内部的变量中
```js
//假设props是
// {
// 'first-name''judy'
// }
const MyComponent = (props) => {
const { 'first-name' } = props;
return (
<div>
</div>
);
};
```
这样是不行的
:::
## 展示数据
jsx里面可以放入html,如果需要重新跳回js,可以使用大括号包裹
```js{3}
return (
<h1>
{user.name}
</h1>
);
```
修改属性需要用大括号替代引号
```js{3}
return (
<img
src={user.imageUrl}
/>
);
```
:::tip :rocket: 特殊的style
```jsx
style={{
width: user.imageSize,
height: user.imageSize
}}
```
这里需要写成一个对象的形式在放到花括号中
:::
在哪里使用花括号
在 JSX 中只能以两种方式使用花括号:
* 作为JSX 标签内的文本`<h1>{name}'s To Do List</h1>`:可以,但`<{tag}>Gregorio Y. Zara's To Do List</{tag}>` 不会。
* 作为紧跟在符号后面的属性=:`src={avatar}`将读取avatar变量,但`src="{avatar}"`会传递字符串"{avatar}"。
## 条件渲染
```jsx
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
```
当你不需要分支时else,你也可以使用更短的逻辑&&语法:
```js
<div>
{isLoggedIn && <AdminPanel />}
</div>
```
## 响应事件
onClick={handleClick}末尾没有括号
## 简单示例
子组件共享数据
```js
import { useState } from 'react';
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
```
:::warning :warning: 警告
组件可以渲染其他组件,但绝不能嵌套它们的定义:
```js
export default function Gallery() {
// 🔴 Never define a component inside another component!
function Profile() {
// ...
}
// ...
}
```
上面的代码片段非常慢,而且容易导致错误。相反,应该在顶层定义每个组件:
```js
export default function Gallery() {
// ...
}
// ✅ Declare components at the top level
function Profile() {
// ...
}
```
当子组件需要来自父组件的一些数据时,通过 props 传递它,而不是嵌套定义。
:::
151 changes: 150 additions & 1 deletion javascript/grammar/closure.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,49 @@ layout: doc
函数记住它创建于何处的方式,与函数被在哪儿调用无关
:::


:::warning :warning: 变量与函数初始化上有区别
![](https://zh.javascript.info/article/closure/closure-variable-phrase.svg)

当脚本开始运行,词法环境预先填充了所有声明的变量。

最初,它们处于“未初始化(Uninitialized)”状态。这是一种特殊的内部状态,这意味着引擎知道变量,但是在用 let 声明前,不能引用它。几乎就像变量不存在一样。

然后 let phrase 定义出现了。它尚未被赋值,因此它的值为 undefined。从这一刻起,我们就可以使用变量了。

phrase 被赋予了一个值。

phrase 的值被修改。

一个函数其实也是一个值,就像变量一样。

**不同之处在于函数声明的初始化会被立即完成。**

当创建了一个词法环境(Lexical Environment)时,函数声明会立即变为即用型函数(不像 let 那样直到声明处才可用)。

![alt text](https://zh.javascript.info/article/closure/closure-function-declaration.svg)

正常来说,这种行为仅适用于函数声明,而不适用于我们将函数分配给变量的函数表达式,例如 let say = function(name)...。

```js
console.log(a)
let a = 123 //这会发生什么
```
:::

:::details 答案
Error: Cannot access 'a' before initialization

而不是 ReferenceError: a is not defined

如果这里是var就是undefined了

从程序执行进入代码块(或函数)的那一刻起,变量就开始进入“未初始化”状态。它一直保持未初始化状态,直至程序执行到相应的 let 语句。

换句话说,一个变量从技术的角度来讲是存在的,但是在 let 之前还不能使用。

变量暂时无法使用的区域(从代码块的开始到 let)有时被称为“死区”。
:::
## 内存泄漏
通常,函数调用完成后,会将词法环境和其中的所有变量从内存中删除。因为现在没有任何对它们的引用了。与 JavaScript 中的任何其他对象一样,词法环境仅在可达时才会被保留在内存中。

Expand Down Expand Up @@ -51,4 +94,110 @@ function f() {
// 数组中的 3 个函数,每个都与来自对应的 f() 的词法环境相关联
let arr = [f(), f(), f()];
```
当词法环境对象变得不可达时,它就会死去(就像其他任何对象一样)。换句话说,它仅在至少有一个嵌套函数引用它时才存在。这会导致内存泄漏
当词法环境对象变得不可达时,它就会死去(就像其他任何对象一样)。换句话说,它仅在至少有一个嵌套函数引用它时才存在。这会导致内存泄漏

## 习题
函数会选择最新的内容吗?

函数 sayHi 使用外部变量。当函数运行时,将使用哪个值?

```js
let name = "John";

function sayHi() {
alert("Hi, " + name);
}

name = "Pete";

sayHi(); // 会显示什么:"John" 还是 "Pete"?
```
:::details 答案
答案:Pete。

函数将从内到外依次在对应的词法环境中寻找目标变量,它使用最新的值。

旧变量值不会保存在任何地方。当一个函数想要一个变量时,它会从自己的词法环境或外部词法环境中获取当前值。
:::

Counter 是独立的吗?

在这儿我们用相同的 makeCounter 函数创建了两个计数器(counters):counter 和 counter2。

它们是独立的吗?第二个 counter 会显示什么?0,1 或 2,3 还是其他?
```js
function makeCounter() {
let count = 0;

return function() {
return count++;
};
}

let counter = makeCounter();
let counter2 = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1

alert( counter2() ); // ?
alert( counter2() ); // ?
```

:::details 答案
答案是:0,1。

函数 counter 和 counter2 是通过 makeCounter 的不同调用创建的。

因此,它们具有独立的外部词法环境,每一个都有自己的 count。
:::

```js
"use strict";

let phrase = "Hello";

if (true) {
let user = "John";

function sayHi() {
alert(`${phrase}, ${user}`);
}
}

sayHi();//alert什么
```
:::details 答案
ReferenceError: sayHi is not defined

如果不是严格模式不会报错
:::

闭包 sum

编写一个像 sum(a)(b) = a+b 这样工作的 sum 函数。

是的,就是这种通过双括号的方式(并不是错误)。

举个例子:

sum(1)(2) = 3
sum(5)(-1) = 4

:::details 答案
为了使第二个括号有效,第一个(括号)必须返回一个函数。

就像这样:
```js
function sum(a) {

return function(b) {
return a + b; // 从外部词法环境获得 "a"
};

}

alert( sum(1)(2) ); // 3
alert( sum(5)(-1) ); // 4
```
:::
Loading

0 comments on commit 3ec8c11

Please sign in to comment.