Skip to content

Commit

Permalink
docs📝: react 路由
Browse files Browse the repository at this point in the history
  • Loading branch information
lxfljw committed Jun 16, 2024
1 parent 1fa15ae commit 07e691e
Show file tree
Hide file tree
Showing 3 changed files with 346 additions and 0 deletions.
140 changes: 140 additions & 0 deletions code/hw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

async function fn1() {
/**
*
* @param {number} emptyCount
*/
function getGapWater(emptyCount, fullCount = 0) {
if (emptyCount < 2) return fullCount;
const rest = emptyCount % 3;
const currentCount = parseInt(emptyCount / 3);
if (rest + currentCount === 2) return currentCount + fullCount + 1;
return getGapWater(rest + currentCount, fullCount + currentCount);
}

while ((line = await readline())) {
if (line == 0) break;
console.log(getGapWater(line));
}
}
async function fn2() {
// Write your code here
let nums = [];
while ((line = await readline())) {
nums.push(Number(line));
}
nums.shift();
nums = nums.reduce((unRepeatNums, num) => {
if (unRepeatNums.length === 0) {
unRepeatNums.push(num);
return unRepeatNums;
}
if (!unRepeatNums.includes(num)) {
// unRepeatNums.push(num);
let start = 0;
let end = unRepeatNums.length - 1;
let mid = (start + end) >> 1;
while (start <= end) {
mid = (start + end) >> 1;
if (unRepeatNums[mid] > num) {
end = mid - 1;
} else {
start = mid + 1;
}
}
// let i = 0;
// for (; i < unRepeatNums.length; i++) {
// if (unRepeatNums[i] > num) {
// i;
// break;
// }
// }
unRepeatNums.splice(start + 1, 0, num);
}
return unRepeatNums;
}, []);
for (const num of nums) {
console.log(num);
}
}

async function fn3() {
const changeMap = {
A: 10,
B: 11,
C: 12,
D: 13,
E: 14,
F: 15,
};
while ((line = await readline())) {
let count = 0;
currentTime = 1;
for (let i = line.length - 1; i >= 2; i--) {
count += Number(changeMap[line[i]] || line[i]) * currentTime;
currentTime = currentTime * 16;
}
console.log(count);
}
}

async function a() {
// Write your code here
let nums = [];
while ((line = await readline())) {
nums.push(Number(line));
}
nums.shift();
nums = nums.reduce((unRepeatNums, num) => {
if (unRepeatNums.length === 0) {
unRepeatNums.push(num);
return unRepeatNums;
}
if (!unRepeatNums.includes(num)) {
// unRepeatNums.push(num);
let i = 0;
for (; i < unRepeatNums.length; i++) {
if (unRepeatNums[i] > num) {
break;
}
}

unRepeatNums.splice(i, 0, num);
}
return unRepeatNums;
}, []);
for (const num of nums) {
console.log(num);
}
}

async function ss() {
// Write your code here
while ((line = await readline())) {
const countMap = new Map();
// 获取各个字符串的计数
for (let i = 0; i < line.length; i++) {
const char = line[i];
if (!countMap.has(char)) {
countMap.set(char, 1);
} else {
countMap.set(char, countMap.get(char) + 1);
}
}
// 找出最小的那个 迭代 Map
const entries = Array.from(countMap.entries()).sort((a, b) => a[1] - b[1]);
// 有重复
const [_, minCount] = entries[0];
for (const entry of entries) {
if (entry[1] === minCount) {
line = line.replace(new RegExp(entry[0], "g"), "");
continue;
}
break;
}
console.log(line);
}
}
56 changes: 56 additions & 0 deletions code/zijie.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
*
* @param {number} number
*/
function fn(number) {
const str = number.toString();
let splitStr = "";
let count = 0;
for (let i = str.length - 1; i >= 0; i--) {
if (count === 3) {
splitStr = "," + splitStr;
count = 0;
}
splitStr = `${str[i]}${splitStr}`;
count++;
}
return splitStr;
}

/**
*
* @param {number} number
*/
function fn1(number) {
const str = number.toString();
return str.replace(/\B(?=(\d{3})+)/g, ",");
}

/**
*
* @param {Record<string, any>} obj
* @param {string|string[]} path
* @param {any} defaultValue
*/
function get(obj, path, defaultValue) {
let value = obj;
// 处理字符串路径
if (typeof path === "string") {
const newPath = path.replace(/([^\.]+)\[([^\.]+)\]/g, "$1.$2");
newPath.split(".").every((path) => {
try {
value = value[path];
return true;
} catch (e) {
value = defaultValue;
return false;
}
});
}
return value === undefined ? defaultValue : value;
}

const testObj = { a: [{ b: { c: "6" } }], d: { e: 90 } };

console.log("--1", get(testObj, "a[2].b.c", "818"));
// console.log("--2", get(testObj, "d.e"));
150 changes: 150 additions & 0 deletions pages/9-React/1.react-router 原理.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# React Router 原理

React Router 是 React 官方提供的路由管理器,它可以帮助我们管理应用的路由,实现不同 URL 对应的不同组件的渲染。

## 工作原理
我们先看一段 React Router 的代码:

```jsx
import React from'react';
import { BrowserRouter as Router, Switch, Route } from'react-router-dom';


function App() {
return (
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/users" component={Users} />
<Route path="/users/:id" component={User} />
<Route path="/users/:id/edit" component={UserEdit} />
</Switch>
</Router>
);

}

export default App;
```


React Router 的工作原理如下:

1. 首先,我们需要定义好路由规则,比如我们有如下路由规则:


```
/users
/users/:id
/users/:id/edit
```

2. 然后,我们需要在应用的入口文件中,使用 React Router 的 `Router` 组件,将路由规则和对应的组件进行绑定。

3. 当用户访问 `/users` 页面时,React Router 会匹配到对应的路由规则,并渲染 `Users` 组件。

4. 当用户访问 `/users/:id` 页面时,React Router 会匹配到对应的路由规则,并渲染 `User` 组件,并将 `:id` 作为参数传递给 `User` 组件。

5. 当用户访问 `/users/:id/edit` 页面时,React Router 会匹配到对应的路由规则,并渲染 `UserEdit` 组件,并将 `:id` 作为参数传递给 `UserEdit` 组件。

React Router 的路由匹配规则是基于路径的,因此,我们需要确保路径的正确性。

6. 当用户访问 `/users/123/edit` 页面时,React Router 会匹配到 `/users/:id/edit` 路由规则,并渲染 `UserEdit` 组件,并将 `123` 作为参数传递给 `UserEdit` 组件。


## 代码实现

### 1. Router 组件

`Router` 组件是 React Router 的核心组件,它负责管理应用的路由,并渲染对应的组件。

```jsx
export default class BrowserRouter extends React.Component {
constructor(props) {
this.history = createBrowserHistory();
}
render() {
const
return (
<RouterContext.Provider value={{history: this.history, location: this.history.location, staticContext: undefined}}>
{this.props.children}
</RouterContext.Provider>
);
}
}

```

### 2.Route 组件

```jsx
export default class Route extends React.Component {
constructor(props) {
super(props);
this.state = {
match: props.computeMatch(props.location.pathname)
};
}
componentDidMount() {
const { history } = this.props;
const unlisten = history.listen((location) => {
this.setState({
match: this.props.computeMatch(location.pathname)
});
});
this.setState({
unlisten
});
}
componentWillUnmount() {
this.state.unlisten();
}
render() {
const { component: Component, render, children,computedMatch } = this.props;
if (!computedMatch) {
return null;
}

const match = computedMatch|| matchPath(this.props.location.pathname, this.props);
if (match) {
if (Component) {
return <Component {...this.props} />;
} else if (render) {
return render({...this.props, match });
} else if (children) {
return children({...this.props, match });
}
}
return null;
}

}
```
### 3.Switch 组件

```jsx
export default class Switch extends React.Component {
render() {
const { location, children } = this.props;
let match = null;
React.Children.forEach(children, (element) => {
// 如果没有 match 才执行计算
if (match == null && React.isValidElement(element)) {
const { path, exact, strict, sensitive, from } = element.props;
const pathname = getFullPath(location.pathname, from);
if (path) {
match = matchPath(pathname, { path, exact, strict, sensitive });
} else {
match = pathMatch(pathname);
}
}
});
return match ? React.cloneElement(React.Children.only(children), { computedMatch: match }) : null;
}
}
```



## 总结
Router 组件是负责上下文的注入,还有统一前缀等配置,Route 组件可以根据 path 进行匹配,并且内部提供了 compuMatch 方法,由外部控制是否渲染,Switch 组件可以根据路由匹配到的第一个组件进行渲染。

0 comments on commit 07e691e

Please sign in to comment.