From 07e691ed247decaea3b3de9ca140c85fcc8a1dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A2=E6=99=93=E9=94=8B?= Date: Sun, 16 Jun 2024 15:12:28 +0800 Subject: [PATCH] =?UTF-8?q?docs=F0=9F=93=9D:=20react=20=E8=B7=AF=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/hw.js | 140 ++++++++++++++++ code/zijie.js | 56 +++++++ ....react-router \345\216\237\347\220\206.md" | 150 ++++++++++++++++++ 3 files changed, 346 insertions(+) create mode 100644 code/hw.js create mode 100644 code/zijie.js create mode 100644 "pages/9-React/1.react-router \345\216\237\347\220\206.md" diff --git a/code/hw.js b/code/hw.js new file mode 100644 index 0000000..c279ebb --- /dev/null +++ b/code/hw.js @@ -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); + } +} diff --git a/code/zijie.js b/code/zijie.js new file mode 100644 index 0000000..188ca0f --- /dev/null +++ b/code/zijie.js @@ -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} 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")); diff --git "a/pages/9-React/1.react-router \345\216\237\347\220\206.md" "b/pages/9-React/1.react-router \345\216\237\347\220\206.md" new file mode 100644 index 0000000..0871b73 --- /dev/null +++ "b/pages/9-React/1.react-router \345\216\237\347\220\206.md" @@ -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 ( + + + + + + + + + ); + +} + +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 ( + + {this.props.children} + + ); + } + } + +``` + +### 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 ; + } 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 组件可以根据路由匹配到的第一个组件进行渲染。 \ No newline at end of file