├── test.md ├── img ├── learn.webp ├── logo.png ├── qrcode.png └── reactStudy.png ├── weekly ├── 第三期.md ├── 第一期.md └── 第二期.md ├── .idea ├── .gitignore ├── vcs.xml ├── modules.xml └── fucking-frontend.iml ├── Answer ├── 11-20 │ ├── 17.md │ └── 16.md └── 1 ~ 10 │ ├── 1.md │ ├── 2.md │ ├── 4.md │ ├── 5.md │ ├── 6.md │ └── 3.md ├── .github └── workflows │ ├── issue.yml │ ├── comment.yml │ └── markdown.yml ├── .gitignore ├── script ├── comment.js └── issue.js ├── package.json ├── LICENSE ├── deep └── 第一期.md ├── yarn.lock ├── README.md └── excalidraw └── React 学习路径.excalidraw /test.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/learn.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhan2020/all-of-frontend/main/img/learn.webp -------------------------------------------------------------------------------- /img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhan2020/all-of-frontend/main/img/logo.png -------------------------------------------------------------------------------- /img/qrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhan2020/all-of-frontend/main/img/qrcode.png -------------------------------------------------------------------------------- /weekly/第三期.md: -------------------------------------------------------------------------------- 1 | - [关于前端职业规划的一点思考](https://mp.weixin.qq.com/s/Pe-I8b60Gyo91wJDTTx50Q) 2 | -------------------------------------------------------------------------------- /img/reactStudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhan2020/all-of-frontend/main/img/reactStudy.png -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # 基于编辑器的 HTTP 客户端请求 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Answer/11-20/17.md: -------------------------------------------------------------------------------- 1 | ```js 2 | var a = 0 3 | var b = async () => { 4 | a = a + await 10 5 | console.log('2', a) // -> ? 6 | } 7 | b() 8 | a++ 9 | console.log('1', a) // -> ? 10 | ``` 11 | 12 | 这道题目大部分读者肯定会想到 `await` 左边是异步代码,因此会先把同步代码执行完,此时 `a` 已经变成 1,所以答案应该是 11。 13 | 14 | 其实 `a` 为 0 是因为加法运算法,先算左边再算右边,所以会把 0 固定下来。如果我们把题目改成 `await 10 + a` 的话,答案就是 11 了。 -------------------------------------------------------------------------------- /.github/workflows/issue.yml: -------------------------------------------------------------------------------- 1 | on: 2 | issues: 3 | types: [opened, edited] 4 | 5 | jobs: 6 | issue: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2 11 | - name: Dump GitHub context 12 | env: 13 | GITHUB_CONTEXT: ${{ toJSON(github) }} 14 | ISSUEHOST: ${{ secrets.ISSUEHOST }} 15 | run: | 16 | yarn 17 | node ./script/issue.js 18 | -------------------------------------------------------------------------------- /.github/workflows/comment.yml: -------------------------------------------------------------------------------- 1 | on: 2 | issue_comment: 3 | types: [created, edited] 4 | 5 | jobs: 6 | issue: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2 11 | - name: Dump GitHub context 12 | env: 13 | GITHUB_CONTEXT: ${{ toJSON(github) }} 14 | COMMENTHOST: ${{ secrets.COMMENTHOST }} 15 | run: | 16 | yarn 17 | node ./script/comment.js 18 | -------------------------------------------------------------------------------- /.idea/fucking-frontend.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # OS 14 | .DS_Store 15 | 16 | # Tests 17 | /coverage 18 | /.nyc_output 19 | 20 | # IDEs and editors 21 | /.idea 22 | .project 23 | .classpath 24 | .c9/ 25 | *.launch 26 | .settings/ 27 | *.sublime-workspace 28 | 29 | # IDE - VSCode 30 | .vscode/* 31 | !.vscode/settings.json 32 | !.vscode/tasks.json 33 | !.vscode/launch.json 34 | !.vscode/extensions.json -------------------------------------------------------------------------------- /script/comment.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const { 3 | event: { 4 | comment, 5 | issue: { number }, 6 | }, 7 | } = JSON.parse(process.env.GITHUB_CONTEXT); 8 | const { 9 | body, 10 | updated_at, 11 | html_url, 12 | id, 13 | user: { avatar_url, login }, 14 | } = comment; 15 | const host = process.env.COMMENTHOST; 16 | 17 | axios.post(host, { 18 | issueId: number, 19 | commentId: id, 20 | htmlUrl: html_url, 21 | userName: login, 22 | avatarUrl: avatar_url, 23 | content: body, 24 | updatedAt: updated_at, 25 | }); 26 | -------------------------------------------------------------------------------- /Answer/11-20/16.md: -------------------------------------------------------------------------------- 1 | ```js 2 | let length = 10 3 | function fn() { 4 | console.log(this.length); 5 | } 6 | let obj = { 7 | length: 5, 8 | method(fn) { 9 | // 两次调用各输出什么 10 | fn() 11 | arguments[0](0) 12 | } 13 | } 14 | obj.method(fn, 1) 15 | ``` 16 | 17 | 这道题目核心是在考 `this` 的指向,但是还有一些别的坑。 18 | 19 | 执行第一次 `fn` 的时候,这时候的 `this` 就是 `window`,但是 `window.length` 并不是指向用 `let` 声明的 `length` 上的,而是「返回当前窗口中包含的框架数量(框架包括frame和iframe两种元素)」,具体可以参考 [文档](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/length)。 20 | 21 | 执行第二次 `fn` 的时候,此时 `this` 为 `arguments`,`arguments.length` 为实参的长度,也就是 2。 -------------------------------------------------------------------------------- /script/issue.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const { 3 | event: { issue, action }, 4 | } = JSON.parse(process.env.GITHUB_CONTEXT); 5 | const { author_association, body, title, number } = issue; 6 | const host = process.env.ISSUEHOST; 7 | 8 | if (author_association === "OWNER") { 9 | if (action === "edited") { 10 | axios.put(host, { 11 | name: title, 12 | issueId: number, 13 | content: body, 14 | }); 15 | } else if (action === "opened") { 16 | axios.post(host, { 17 | name: title, 18 | issueId: number, 19 | content: body, 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Answer/1 ~ 10/1.md: -------------------------------------------------------------------------------- 1 | ```js 2 | try { 3 | (async function() { a().b().c() })() 4 | } catch (e) { 5 | console.log(`执行出错:${e.message}`) 6 | } 7 | ``` 8 | 9 | 这道题目主要三个考点: 10 | 11 | 1. 执行一个没有定义的函数会发生什么 12 | 2. 在 `async` 内部发生报错会发生什么 13 | 3. `try catch` 只能捕获同步代码的异常 14 | 15 | 因此答案就明了了。 16 | 17 | 因为我们执行了一个未定义的函数,所以会报错 `a is not defind`,又因为是在 `async` 中,所以报错信息会显示 `in promise`。最后 `try cathch` 只能捕获同步代码的抛错,因为是 `async`,所以走不到 `catch` 里面。 18 | 19 | 如果我们把代码这样改一下就可以了: 20 | 21 | ```js 22 | try { 23 | await (async function() { a().b().c() })() 24 | } catch (e) { 25 | console.log(`执行出错:${e.message}`) 26 | } 27 | ``` 28 | 29 | 另外说个小知识点,最新的 Chrome 已经支持在全局作用域下使用 `await` 了。 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fucking-frontend", 3 | "version": "1.0.0", 4 | "description": "仓库内容分为以下几块:", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/KieSun/fucking-frontend.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/KieSun/fucking-frontend/issues" 18 | }, 19 | "homepage": "https://github.com/KieSun/fucking-frontend#readme", 20 | "dependencies": { 21 | "axios": "^0.21.1", 22 | "gitment": "^0.0.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Answer/1 ~ 10/2.md: -------------------------------------------------------------------------------- 1 | ```js 2 | try { 3 | let a = 0 4 | ;(async function() { 5 | a += 1 6 | console.log('inner', a) 7 | throw new Error('123') 8 | // a() 9 | })() 10 | console.log('outer', a) 11 | } catch(e) { 12 | console.warn('Error', e) 13 | } 14 | ``` 15 | 16 | 这道题目基础不好的同学容易答错,很容易以为 `async` 的函数内部代码就是异步的,实际都还是同步的,把代码改成这样大家就明白了: 17 | 18 | ```js 19 | function a() { 20 | return new Promise(function(resolve, reject) { 21 | a += 1 22 | console.log('inner', a) 23 | throw new Error('123') 24 | }) 25 | } 26 | ``` 27 | 28 | 另外发现还有同学疑问为什么 `throw` 出去的错误被 `promise catch` 住了,这个我们直接看标准: 29 | 30 | [标准具体地址](https://tc39.es/ecma262/#sec-control-abstraction-objects) 31 | 32 | [这里也有一个不错的作答](https://github.com/KieSun/fucking-frontend/issues/2#issuecomment-793266365) 33 | -------------------------------------------------------------------------------- /.github/workflows/markdown.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | # This workflow will install Deno then run Deno lint and test. 7 | # For more information see: https://github.com/denoland/setup-deno 8 | 9 | name: markdown-autodocs 10 | 11 | on: 12 | push: 13 | branches: [main] 14 | pull_request: 15 | branches: [main] 16 | 17 | jobs: 18 | test: 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: install 24 | run: | 25 | npm i -g prettier 26 | prettier README.md -w 27 | - uses: EndBug/add-and-commit@v7 # You can change this to use a specific version. 28 | with: 29 | add: './README.md' 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 yck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Answer/1 ~ 10/4.md: -------------------------------------------------------------------------------- 1 | 页面上有三个按钮,分别为 A、B、C,点击各个按钮都会发送异步请求且互不影响,每次请求回来的数据都为按钮的名字。 2 | 3 | 请实现当用户依次点击 A、B、C、A、C、B 的时候,最终获取的数据为 ABCACB。 4 | 5 | 这道题目主要两个考点: 6 | 7 | 1. 请求不能阻塞,但是输出可以阻塞。比如说 B 请求需要耗时 3 秒,其他请求耗时 1 秒,那么当用户点击 BAC 时,三个请求都应该发起,但是因为 B 请求回来的慢,所以得等着输出结果。 8 | 2. 如何实现一个队列? 9 | 10 | 其实我们无需自己去构建一个队列,直接利用 `promise.then` 方法就能实现队列的效果了。 11 | 12 | 答案摘自 [pandaomeng(https://github.com/KieSun/fucking-frontend/issues/5#issuecomment-796657041) 13 | 14 | ```js 15 | class Queue { 16 | promise = Promise.resolve(); 17 | 18 | excute(promise) { 19 | this.promise = this.promise.then(() => promise); 20 | return this.promise; 21 | } 22 | } 23 | 24 | const queue = new Queue(); 25 | 26 | const delay = (params) => { 27 | const time = Math.floor(Math.random() * 5); 28 | return new Promise((resolve) => { 29 | setTimeout(() => { 30 | resolve(params); 31 | }, time * 500); 32 | }); 33 | }; 34 | 35 | const handleClick = async (name) => { 36 | const res = await queue.excute(delay(name)); 37 | console.log(res); 38 | }; 39 | 40 | handleClick('A'); 41 | handleClick('B'); 42 | handleClick('C'); 43 | handleClick('A'); 44 | handleClick('C'); 45 | handleClick('B'); 46 | ``` 47 | -------------------------------------------------------------------------------- /deep/第一期.md: -------------------------------------------------------------------------------- 1 | 本周精读的第一篇文章是 [Migrating a 150K LOC codebase to Vite and ESBuild](https://dev.to/noriste/migrating-a-150k-loc-codebase-to-vite-and-esbuild-why-part-1-3-2idj),其实这是一个系列文章了,主体内容在第二篇。 2 | 3 | 这篇文章主要讲了两块内容: 4 | 5 | 1. Webpack 对比 Vite 的一些数据 6 | 2. 迁移至 Vite 过程中踩得坑 7 | 8 | 踩得坑在第二篇文章,如果你近期想试试迁移的话可以读一下,当然其实他并没有写多少踩坑的内容,让我稍微对于他这个迁移那么大项目居然才那么点坑产生怀疑,或者说很多没写上来。 9 | 10 | 但是对于数据这块大家还是可以参考参考的,选型时候还是用得上。 11 | 12 | 第一块数据是 Webpack 和 Vite 在 `yarn start` 以及 `hmr` 层面的一些对比,可以看到在这两块内容上 Vite 是碾压胜出的,其它两个数据差别不大,可以略过。 13 | 14 | ![Y2f6el](https://yck-1254263422.file.myqcloud.com/uPic/Y2f6el.png) 15 | 16 | 第二块数据是使用了 esbuild-loader 插件的 Webpack 和 Vite 的数据对比,基本上还是 Vite 胜出,但是可以发现当 Webpack 加上 ESBuild 以后,很多数据相比之前已经有了很大幅度的提升,无非限制于 Webpack 本身的一些打包机制导致了在一些数据上没什么起色。 17 | 18 | ![KGiSCa](https://yck-1254263422.file.myqcloud.com/uPic/KGiSCa.png) 19 | 20 | 第三块数据是 Build 层面的数据分析,使用了 esbuild-loader 插件的 Webpack 胜出了 Vite。 21 | 22 | ![wZrWQX](https://yck-1254263422.file.myqcloud.com/uPic/wZrWQX.png) 23 | 24 | 总的来说,从上述这些数据中我们可以看出 Vite 和 ESBuild 对于提效的加成是很大的,轻轻松松提速几倍。 25 | 26 | 但是这一切都是美好的,实际你如果要把这套东西在业务中真真正正用起来,会踩到很多坑,目前应该是没有一个大厂能把这套体系在很多业务里跑起来。虽然提效确实挺多,但是迁移的成本也是很大的。 27 | 28 | 综合来说,可以自己项目里玩玩,未来这个体系肯定是会普及的,但并不是现在。 29 | 30 | 另外对于原理有兴趣的可以看看云谦写的[玩具](https://github.com/sorrycc/toy-vite)。 -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | axios@^0.21.1: 6 | version "0.21.1" 7 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" 8 | integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== 9 | dependencies: 10 | follow-redirects "^1.10.0" 11 | 12 | follow-redirects@^1.10.0: 13 | version "1.13.3" 14 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" 15 | integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA== 16 | 17 | gitment@^0.0.3: 18 | version "0.0.3" 19 | resolved "https://registry.yarnpkg.com/gitment/-/gitment-0.0.3.tgz#dbccbad7480b1345b656913bd70eff792a7b38b8" 20 | integrity sha1-28y610gLE0W2VpE71w7/eSp7OLg= 21 | dependencies: 22 | mobx "^3.1.7" 23 | 24 | mobx@^3.1.7: 25 | version "3.6.2" 26 | resolved "https://registry.yarnpkg.com/mobx/-/mobx-3.6.2.tgz#fb9f5ff5090539a1ad54e75dc4c098b602693320" 27 | integrity sha512-Dq3boJFLpZEvuh5a/MbHLUIyN9XobKWIb0dBfkNOJffNkE3vtuY0C9kSDVpfH8BB0BPkVw8g22qCv7d05LEhKg== 28 | -------------------------------------------------------------------------------- /weekly/第一期.md: -------------------------------------------------------------------------------- 1 | ## 新闻 2 | 3 | 其实以下几个玩意更新的版本我基本没咋关心,看了眼就过了,反正短期用不到的。 4 | 5 | \- [Chrome 91 发布](https://developer.chrome.com/blog/new-in-chrome-91/) 6 | 7 | \- [TypeScript 4.3 发布](https://devblogs.microsoft.com/typescript/announcing-typescript-4-3/) 8 | 9 | \- [Jest 27 发布](https://jestjs.io/blog/2021/05/25/jest-27) 10 | 11 | ## 优秀文章 12 | 13 | \- [Migrating a 150K LOC codebase to Vite and ESBuild](https://dev.to/noriste/migrating-a-150k-loc-codebase-to-vite-and-esbuild-why-part-1-3-2idj) 14 | 15 | 一个系列文章,大概讲了讲 15w 行代码从 Webpack 迁移至 Vite 过程中遇到的坑。Vite 这玩意我周末也讲过它的优点,但是它的缺点其实我和一些大厂的大佬也聊过以后发现大家遇到的问题几乎一致。环境的问题(ESM)导致了太多坑的出现,接入一个业务需要花的成本是挺高的。大家可以通过这篇文章来了解具体的问题。 16 | 17 | 18 | 19 | \- [跨域的一篇长文](https://ieftimov.com/post/deep-dive-cors-history-how-it-works-best-practices/) 20 | 21 | 这篇文章我没看什么,但是它写了特别多内容,打算去看看到底写了些啥玩意,如果你也好奇的话可以了解下。 22 | 23 | 24 | 25 | \- [防御型编程](https://github.com/Tencent/secguide/blob/main/JavaScript%E5%AE%89%E5%85%A8%E6%8C%87%E5%8D%97.md) 26 | 27 | 这玩意前几天推荐过了,大家有兴趣的读一读吧。 28 | 29 | ## Code 30 | 31 | \- [preconstruct](https://github.com/preconstruct/preconstruct) 32 | 33 | monorepo 开发构建工具,我更倾向于把它当成源码学习。 34 | 35 | 36 | 37 | \- [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) 38 | 39 | 一个能帮助寻找及加载各类配置文件的工具。比如说 `package.json` 各种 `rc` 文件等等,工具链产品中寻找配置文件是个很常见的需求。 -------------------------------------------------------------------------------- /Answer/1 ~ 10/5.md: -------------------------------------------------------------------------------- 1 | 异步请求通过 `Promise.all` 处理,怎么让其中失败的所有请求重试。 2 | 3 | ```js 4 | Promise.all([A, B, C, D]) 5 | // 4 个请求完成后发现 AD 请求失败了,如果让 AD 请求重试 6 | ``` 7 | 8 | 这个题目其实很简单,因为 `Promise.all` 中一个 `promise` 挂了就挂了,所以我们直接在接口上处理 `catch` 就行了。 9 | 10 | 看了些答案,结果是对的,但是处理方式是错误的。比如说在 `resolve` 中去判断是否要重试。一般我们业务中请求都是封装过的函数,出现错误肯定直接 `reject` 了,不可能 `resolve` 出来。 11 | 12 | 答案摘自 [vandvassily](https://github.com/KieSun/fucking-frontend/issues/6#issuecomment-797237791) 13 | 14 | 其他类似优秀答案:[yancongwen](https://github.com/KieSun/fucking-frontend/issues/6#issuecomment-797283287) 15 | 16 | ```js 17 | function request(name, count = 0) { 18 | return new Promise((resolve, reject) => { 19 | const isSuccess = Math.random() > 0.5; 20 | console.log(`接口${name}: ${isSuccess}`); 21 | setTimeout(() => { 22 | isSuccess > 0.5 ? resolve(name) : reject(name); 23 | }, Math.random() * 1000); 24 | }).catch((err) => { 25 | count++; 26 | 27 | if (count > 2) { 28 | return Promise.reject(`后端大爷${name}接口写的666`); 29 | } 30 | return request(name, count); 31 | }); 32 | } 33 | 34 | let queue = [request('A'), request('B'), request('C'), request('D')]; 35 | 36 | Promise.all(queue) 37 | .then((arr) => { 38 | console.log(arr); 39 | }) 40 | .catch((err) => { 41 | console.log(err); 42 | }); 43 | ``` 44 | -------------------------------------------------------------------------------- /Answer/1 ~ 10/6.md: -------------------------------------------------------------------------------- 1 | ```js 2 | /** 3 | * @param input 4 | * @param size 5 | * @returns {Array} 6 | */ 7 | _.chunk(['a', 'b', 'c', 'd'], 2) 8 | // => [['a', 'b'], ['c', 'd']] 9 | 10 | _.chunk(['a', 'b', 'c', 'd'], 3) 11 | // => [['a', 'b', 'c'], ['d']] 12 | 13 | _.chunk(['a', 'b', 'c', 'd'], 5) 14 | // => [['a', 'b', 'c', 'd']] 15 | 16 | _.chunk(['a', 'b', 'c', 'd'], 0) 17 | // => [] 18 | ``` 19 | 20 | 这道题目其实就是让大家实现一个 lodash 里的函数,这边我们需要注意的一个点是不能更改原数组,虽然题目没有提到,但是我们得想到这个。 21 | 22 | 笔者这里推荐几个答案,分别是不同的写法,难度从低到高吧。 23 | 24 | 首先是遍历的写法: 25 | 26 | [答案链接](https://github.com/KieSun/fucking-frontend/issues/8#issuecomment-799053150) 27 | 28 | ```js 29 | function chunk(arr, num) { 30 | if (num === 0) return []; 31 | if (Array.isArray(arr) && typeof num === "number") { 32 | let result = []; 33 | let i = 0; 34 | while (i < arr.length) { 35 | result.push(arr.slice(i, i + num)); 36 | i += num; 37 | } 38 | return result; 39 | } else { 40 | console.log("params type error"); 41 | } 42 | } 43 | ``` 44 | 45 | 我们也可以使用 `reduce` 来解题: 46 | 47 | [答案链接](https://github.com/KieSun/fucking-frontend/issues/8#issuecomment-799021398) 48 | 49 | ```js 50 | const chunk = (arr, len) => arr.reduce((pre, cur, index) => { 51 | if (index % len === 0) { 52 | pre.push([cur]) 53 | return pre 54 | } 55 | const temp = pre[pre.length - 1] 56 | temp && temp.push(cur) 57 | return pre 58 | }, []) 59 | ``` 60 | 61 | 甚至直接优化到一行: 62 | 63 | [答案链接](https://github.com/KieSun/fucking-frontend/issues/8#issuecomment-799344324) 64 | 65 | ```js 66 | function chunk(arr, size){ 67 | return Array.from({length: (size = Number.parseInt(size)) ? Math.ceil(arr.length/size) : 0}) 68 | .map((a,i) => arr.slice(i*size, (i+1)*size)) 69 | } 70 | ``` 71 | -------------------------------------------------------------------------------- /Answer/1 ~ 10/3.md: -------------------------------------------------------------------------------- 1 | ```js 2 | // 请使用原生代码实现一个Events模块,可以实现自定义事件的订阅、触发、移除功能 3 | const fn1 = (... args)=>console.log('I want sleep1', ... args) 4 | const fn2 = (... args)=>console.log('I want sleep2', ... args) 5 | const event = new Events(); 6 | event.on('sleep', fn1, 1, 2, 3); 7 | event.on('sleep', fn2, 1, 2, 3); 8 | event.fire('sleep', 4, 5, 6); 9 | // I want sleep1 1 2 3 4 5 6 10 | // I want sleep2 1 2 3 4 5 6 11 | event.off('sleep', fn1); 12 | event.once('sleep', () => console.log('I want sleep')); 13 | event.fire('sleep'); 14 | // I want sleep2 1 2 3 15 | // I want sleep 16 | event.fire('sleep'); 17 | // I want sleep2 1 2 3 18 | ``` 19 | 20 | 今天的题目算是一道常考题了,没有一个标准解法,输出正确就行。 21 | 22 | 但是如果你能用上一些 ES6 的语法以及处理好一些边界问题,面试官对你的评价会更好点。 23 | 24 | ```js 25 | class Events { 26 | constructor() { 27 | this.events = new Map(); 28 | } 29 | 30 | addEvent(key, fn, isOnce, ...args) { 31 | const value = this.events.get(key) ? this.events.get(key) : this.events.set(key, new Map()).get(key) 32 | value.set(fn, (...args1) => { 33 | fn(...args, ...args1) 34 | isOnce && this.off(key, fn) 35 | }) 36 | } 37 | 38 | on(key, fn, ...args) { 39 | if (!fn) { 40 | console.error(`没有传入回调函数`); 41 | return 42 | } 43 | this.addEvent(key, fn, false, ...args) 44 | } 45 | 46 | fire(key, ...args) { 47 | if (!this.events.get(key)) { 48 | console.warn(`没有 ${key} 事件`); 49 | return; 50 | } 51 | for (let [, cb] of this.events.get(key).entries()) { 52 | cb(...args); 53 | } 54 | } 55 | 56 | off(key, fn) { 57 | if (this.events.get(key)) { 58 | this.events.get(key).delete(fn); 59 | } 60 | } 61 | 62 | once(key, fn, ...args) { 63 | this.addEvent(key, fn, true, ...args) 64 | } 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /weekly/第二期.md: -------------------------------------------------------------------------------- 1 | ## 新闻 2 | 3 | - [What's New In DevTools (Chrome 92)](https://developer.chrome.com/blog/new-in-devtools-92/) 4 | 5 | 有挺多新功能的,但是我觉得里面最香的是这个:Support for `const` redeclarations in the Console。 6 | 7 | ![qGZMZp](https://yck-1254263422.file.myqcloud.com/uPic/qGZMZp.jpg) 8 | 9 | 以后再也不需要换变量名了,特别香! 10 | 11 | - Node 12 岁生日了 12 | - [.at() 进入 Stage 3](https://github.com/tc39/proposal-relative-indexing-method) 13 | 14 | 这是个挺不错的新语法。其他有些语言是可以用 `arr[-1]` 来获取数组末尾的元素,但是对于 JS 来说这是实现不了的事情。因为 `[key]` 对于对象来说就是在获取 `key` 对应的值。数组也是对象,对于数组使用 `arr[-1]` 就是在获取 `key` 为 `-1` 的值。由于以上原因,我们想获取末尾元素就得这样写 `arr[arr.length - 1]`,以后有了 `at` 这个方法,我们就可以通过 `arr.at(-1)` 来拿末尾的元素了,另外同样适用类数组、字符串。 15 | 16 | ```js 17 | // Polyfill 18 | function at(n) { 19 | // ToInteger() abstract op 20 | n = Math.trunc(n) || 0; 21 | // Allow negative indexing from the end 22 | if(n < 0) n += this.length; 23 | // OOB access is guaranteed to return undefined 24 | if(n < 0 || n >= this.length) return undefined; 25 | // Otherwise, this is just normal property access 26 | return this[n]; 27 | } 28 | ``` 29 | 30 | ## 文章 31 | 32 | - [居然有比 npm link 更好的调试?](https://mp.weixin.qq.com/s/I4hhrgI3-Y18HD8zw_9g9w) 33 | 34 | 用 `npm link` 调试包应该是基本操作了,但是这种方式在某些情况下还是会带来一些不便利性。比如说在使用 React Hooks 的情况下调试与 React 相关的包就会报错。有公共依赖冲突的情况下我们可以 [yalc](https://github.com/wclr/yalc) 这个库来解决问题。它会将包丢到全局,然后我们在项目里添加该依赖即可,公共依赖会从项目的 node_modules 里面拿,其它的就从全局拿,这样就可以解决依赖冲突带来的问题了。 35 | 36 | - [CSS 对 Web Vitas 的影响](https://web.dev/css-web-vitals/) 37 | 38 | 如果你不了解什么是 Web Vitas,那么很推荐浏览下这网站里的内容。如果你了解什么是 Web Vitas,那么你可以来学习下哪些 CSS 属性会对指标产生影响。 39 | 40 | - [尤雨溪:做技术哪有什么两全之策,都是取舍和平衡](https://mp.weixin.qq.com/s/_q_SnCbGyXrNnXA876tXbA) 41 | 42 | 没啥好说的。 43 | 44 | - [当聊到前端性能优化时,我们会关注什么?](https://mp.weixin.qq.com/s/-yQ9PLzveEsXk4uSdlO36g) 45 | 46 | 性能优化老生常谈的话题了,每个团队根据业务场景的不同关注的点可能都不同,文章结合作者针对一个 toB 系统的性能优化实践去剖析一些大家可能共同关注的点。 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | contributors 3 | Stars 4 | Forks 5 | GitHub 6 | visitor badge 7 |

8 | 9 |

10 | 11 |

12 | 13 | ## 真全栈,全免费项目,学完直接上一个台阶 14 | 15 | 真全栈项目,适合前端进阶及转方向使用。项目包括前端、后端、Web3 最新技术栈,大杂烩,技术一锅端。 16 | 17 | 另外不是网上那些各种仿 xxx 的简单项目,尤其是后端会包括很多东西,学完直接上手做后端项目完全没问题。 18 | 19 | 教学全免费,在 B 站直播,具体内容可点击仓库查看:https://github.com/KieSun/fullstack-project。 20 | 21 | ## 🔥 这是什么? 22 | 23 | 笔者在学会 JS 以及框架的应用后,有一段时间不知道该如何深入下去,活能干,就是不知道该学啥。相信这个问题也会有很多读者朋友遇到。 24 | 25 | 当然笔者目前已经突破了这个瓶颈,也成为了知名公司基础架构组的成员。因此想通过自己成长的经历及积累的资料整理出一系列的学习路线及资料推荐,帮助各位读者朋友解决这个问题。 26 | 27 | > 笔者会列出所有前端必学及热门领域的学习路径及推荐资料,比如浏览器、性能优化、框架、工程化、算法等等,工程浩大,大家可以持续关注该项目! 28 | 29 | **此资料适用于小白入门、初中级进阶、高级查漏补缺。** 30 | 31 | **内容每天都在更新,大家可以持续关注。** 32 | 33 | ## 💻 如何使用 34 | 35 | 如果你是初中级工程师来说,笔者也推荐先行学习「前端核心学习路径」,主要是巩固基础,之后再挑选感兴趣的主题。 36 | 37 | 如果你是高级工程师,笔者推荐跳过「前端核心学习路径」,直接挑选感兴趣的主题学习即可。 38 | 39 | 以下所有知识点笔者都会帮助读者朋友们将知识连贯起来,从而建立自己的知识体系而不是单独记忆松散的知识点。 40 | 41 | **推荐大家 Star 并 Fork 本项目(点击仓库顶部右上角按钮),然后 `git clone` 到本地后从上至下逐步完成学习计划。** 42 | 43 | ## 如何获取本仓库资料 44 | 45 | **笔者已经将仓库内容里的重要资料整理好了,还附赠了前端 10 万字的面试攻略,已经帮助上千人拿到 offer。大家可以关注公众号发送「资料」获取。** 46 | 47 |
48 | 49 | ## 如何贡献 50 | 51 | 推荐你认为优秀或者仓库缺失的内容至正确的位置即可,另外需要附带你的推荐理由。 52 | 53 | ## 📖 目录 54 | 55 | - [🔥 这是什么?](#-这是什么) 56 | - [💻 如何使用](#-如何使用) 57 | - [如何获取本仓库资料](#如何获取本仓库资料) 58 | - [如何贡献](#如何贡献) 59 | - [📖 目录](#-目录) 60 | - [如何高效自学](#如何高效自学) 61 | - [书籍推荐](#书籍推荐) 62 | - [初级](#初级) 63 | - [进阶](#进阶) 64 | - [高级](#高级) 65 | - [前端核心学习路径](#前端核心学习路径) 66 | - [JS 核心知识点](#js-核心知识点) 67 | - [数据类型](#数据类型) 68 | - [类型判断](#类型判断) 69 | - [类型转换](#类型转换) 70 | - [this](#this) 71 | - [闭包](#闭包) 72 | - [作用域](#作用域) 73 | - [变量提升](#变量提升) 74 | - [new](#new) 75 | - [call、apply、bind](#callapplybind) 76 | - [原型](#原型) 77 | - [Class](#class) 78 | - [继承](#继承) 79 | - [模块化](#模块化) 80 | - [Promise](#promise) 81 | - [迭代器与生成器](#迭代器与生成器) 82 | - [async await](#async-await) 83 | - [事件循环](#事件循环) 84 | - [节流与防抖](#节流与防抖) 85 | - [柯里化](#柯里化) 86 | - [垃圾回收](#垃圾回收) 87 | - [设计模式](#设计模式) 88 | - [其他零散但重要的知识点](#其他零散但重要的知识点) 89 | - [HTML](#html) 90 | - [语义化](#语义化) 91 | - [CSS](#css) 92 | - [盒子模型](#盒子模型) 93 | - [选择器](#选择器) 94 | - [Flex](#flex) 95 | - [grid](#grid) 96 | - [其他](#其他) 97 | - [框架](#框架) 98 | - [虚拟 DOM](#虚拟-dom) 99 | - [路由](#路由) 100 | - [React](#react) 101 | - [React 推荐学习路径](#react-推荐学习路径) 102 | - [React 推荐学习资料](#react-推荐学习资料) 103 | - [如何编写一个组件](#如何编写一个组件) 104 | - [受控组件和非受控组件](#受控组件和非受控组件) 105 | - [高阶组件(HOC)](#高阶组件hoc) 106 | - [Hooks](#hooks) 107 | - [合成事件](#合成事件) 108 | - [React 路由](#react-路由) 109 | - [React 状态管理](#react-状态管理) 110 | - [React 接口请求](#react-接口请求) 111 | - [React SSR](#react-ssr) 112 | - [React 单测](#react-单测) 113 | - [React CSS 方案](#react-css-方案) 114 | - [React 原理](#react-原理) 115 | - [Blog 推荐](#blog-推荐) 116 | - [Vue](#vue) 117 | - [Vue 推荐学习路径](#vue-推荐学习路径) 118 | - [Vue 推荐学习资料](#vue-推荐学习资料) 119 | - [Vue 原理](#vue-原理) 120 | - [浏览器](#浏览器) 121 | - [架构](#架构) 122 | - [整体流程](#整体流程) 123 | - [渲染相关](#渲染相关) 124 | - [JS 执行机制](#js-执行机制) 125 | - [缓存](#缓存) 126 | - [Devtools](#devtools) 127 | - [浏览器安全](#浏览器安全) 128 | - [性能优化](#性能优化) 129 | - [推荐书籍](#推荐书籍) 130 | - [推荐网站](#推荐网站) 131 | - [整体优化建议](#整体优化建议) 132 | - [性能指标](#性能指标) 133 | - [性能监控](#性能监控) 134 | - [TypeScript](#typescript) 135 | - [Electron](#electron) 136 | - [组件库](#组件库) 137 | - [微前端](#微前端) 138 | - [推荐学习资料](#推荐学习资料) 139 | - [跨端框架](#跨端框架) 140 | - [监控](#监控) 141 | - [日常充电](#日常充电) 142 | - [CSS 日常充电](#css-日常充电) 143 | - [Github 优秀学习资料](#github-优秀学习资料) 144 | - [JS 优秀学习资料](#js-优秀学习资料) 145 | - [React 优秀学习资料](#react-优秀学习资料) 146 | - [代码样式及安全](#代码样式及安全) 147 | - [生产力工具](#生产力工具) 148 | - [流程图](#流程图) 149 | - [作者信息](#作者信息) 150 | 151 | ## 如何高效自学 152 | 153 | ![Z0qdJz](./img/learn.webp) 154 | 155 | 自学是每个工程师都需要掌握的一项技能。这个学习方法笔者百试百灵,学习任何技术都会用上这个思路。另外我们还能通过这个思路拓宽自己的技术栈,将各个知识联系起来建立自己的知识体系,并且通过这种学习方式学到的知识也不容易遗忘。 156 | 157 | ## 书籍推荐 158 | 159 | 以下书籍主要还是推荐了 JS 方面的,其它比如说框架、TS 等等技术会在各自章节为大家介绍。 160 | 161 | ### 初级 162 | 163 | - [JavaScript 高级程序设计(第 4 版)](https://book.douban.com/subject/35175321/) 164 | 165 | ### 进阶 166 | 167 | - [JavaScript 忍者秘籍(第 2 版)](https://book.douban.com/subject/30143702/) 168 | - [你不知道的 JS 三卷](https://book.douban.com/subject/26351021/),该书英文版是开源的,并且作者已经在写第二版,有能力阅读英文的读者推荐直接看 [原著](https://github.com/getify/You-Dont-Know-JS) 169 | 170 | ### 高级 171 | 172 | - [JavaScript 悟道](https://book.douban.com/subject/35469273/) 173 | - [JavaScript 语言精髓与编程实践(第 3 版)](https://book.douban.com/subject/35085910/) 174 | 175 | **上述书籍大家可以关注【[公众号](#作者信息)】发送「资料」获取,另外还附赠了前端 10 万字的面试攻略,已经帮助上千人拿到 offer。** 176 | 177 | ## 前端核心学习路径 178 | 179 | 前端知识点很多这是公认的事情,但是我们确实没必要把所有知识都去学习,那样只会贪多嚼不烂。我们能把核心知识点、热门技术以及工作中需要用到的知识学好就已经能打败大部分前端工程师了,剩下的大家可以自行根据兴趣选择学习内容。 180 | 181 | **但是在学习其他内容之前,笔者强烈推荐各位务必一定一定先把基础打扎实了,基础不好真的不可能把自己技术往上拔高的。** 182 | 183 | > 为了保证大家学到的知识是正确的,下文中的文档资料笔者都使用了英文版本。因为在审核资料的过程中笔者发现不少中文文档都存在翻译错误或者过时的情况。 184 | 185 | 如果你还是一位初学者,推荐先自行完整阅读一至二本书后再按照该计划学习,因为以下计划并没有囊括 JS 的所有知识,而是列出了所有核心知识点。 186 | 187 | 关于书籍笔者推荐以下两本: 188 | 189 | - [JavaScript 高级程序设计(第 4 版)](https://book.douban.com/subject/35175321/) 190 | - [JavaScript 忍者秘籍(第 2 版)](https://book.douban.com/subject/30143702/) 191 | 192 | ### JS 核心知识点 193 | 194 | #### 数据类型 195 | 196 | JS 数据类型分为两大类及八种数据类型,注意别漏了新增的 `bigint`。 197 | 198 | - [ ] 文档: 199 | - [ ] [JavaScript 数据类型和数据结构](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures) 200 | 201 | #### 类型判断 202 | 203 | 类型判断有好几种方式,分别为: 204 | 205 | - `typeof` 206 | - `instanceof` 207 | - `Object.prototype.toString` 208 | - `isXXX`,比如 `isArray` 209 | 210 | - [ ] 文档 211 | - [ ] [typeof](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) 212 | - [ ] [instanceof](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof) 213 | - [ ] [Object.prototype.toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString#using_tostring_to_detect_object_class) 214 | - [ ] 推荐文章,Issue 也挺重要 215 | - [ ] [JavaScript 专题之类型判断(上)](https://github.com/mqyqingfeng/Blog/issues/28) 216 | - [ ] [JavaScript 专题之类型判断(下)](https://github.com/mqyqingfeng/Blog/issues/30) 217 | 218 | #### 类型转换 219 | 220 | 类型转换算是 JS 中情况繁杂且容易出错,但是开发中还经常会遇到的知识点。强行全部记忆容易遗忘,推荐记忆及练习开发中的常见情况。 221 | 222 | - [ ] 文档 223 | - [ ] [ES 标准](https://tc39.es/ecma262/#sec-abstract-operations) 224 | - 标准并不好读,如果读者英文水平欠佳,可以只阅读该小节内的表格内容。 225 | - [ ] [双等判断](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) 226 | - [ ] 推荐文章 227 | - [ ] [You Don't Know JS 书中关于类型转换的一章节](https://github.com/weiqinl/You-Dont-Know-JS-CN/blob/master/types%20%26%20grammar/ch4.md) 228 | - [ ] [几种基本类型简单的类型转换](https://zh.javascript.info/type-conversions) 229 | - [ ] [JavaScript 深入之头疼的类型转换(上)](https://github.com/mqyqingfeng/Blog/issues/159) 230 | - [ ] [JavaScript 深入之头疼的类型转换(下)](https://github.com/mqyqingfeng/Blog/issues/164) 231 | 232 | #### this 233 | 234 | `this` 算是不少初学者容易搞混的一个知识点,但是它很重要,务必掌握。 235 | 236 | - [ ] 文档 237 | - [ ] [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) 238 | - [ ] 推荐文章 239 | - [ ] [You Don't Know JS 书中关于 this 的第一章节](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch1.md) 240 | - [ ] [You Don't Know JS 书中关于 this 的第二章节](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch2.md) 241 | - [ ] [深入理解 js this 绑定 ( 无需死记硬背,尾部有总结和面试题解析 )](https://segmentfault.com/a/1190000011194676) 242 | 243 | #### 闭包 244 | 245 | 闭包特别常用,但是其实挺多工程师对于闭包的理解是错误的。 246 | 247 | - [ ] 文档 248 | - [ ] [闭包](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) 249 | - [ ] 推荐文章 250 | - [ ] [You Don't Know JS 第二版中对于闭包的解释](https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/ch7.md),该版本暂无中文翻译,读者可用 [DeepL](https://www.deepl.com/translator) 进行翻译。 251 | - [ ] [JavaScript 的静态作用域链与“动态”闭包链](https://juejin.cn/post/6957913856488243237) 252 | - [ ] [知乎中关于闭包的讨论](https://www.zhihu.com/question/34210214) 253 | 254 | #### 作用域 255 | 256 | 作用域是指程序中定义变量的区域,该位置决定了变量的生命周期,也就是变量和函数的可访问范围。 257 | 258 | - [ ] 文档 259 | - [ ] [作用域](https://developer.mozilla.org/en-US/docs/Glossary/Scope) 260 | - [ ] [块作用域](https://developer.mozilla.org/en-US/docs/Glossary/Block/Scripting) 261 | - [ ] 推荐文章 262 | - [ ] [JavaScript 深入之词法作用域和动态作用域](https://github.com/mqyqingfeng/Blog/issues/3) 263 | - [ ] [JavaScript 深入之作用域链](https://github.com/mqyqingfeng/Blog/issues/6) 264 | - [ ] [Variable scope, closure](https://javascript.info/closure),另有 [中文翻译版](https://zh.javascript.info/closure) 265 | - [ ] [You Don't Know JS Yet: Scope & Closures](https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed/scope-closures) 266 | - [ ] [The battle between function scope and block scope](https://www.deadcoderising.com/2017-04-11-es6-var-let-and-const-the-battle-between-function-scope-and-block-scope/) 267 | 268 | #### 变量提升 269 | 270 | 变量提升(Hoisting)可以将变量和函数在编译阶段放入内存,从而在执行阶段时在声明前使用。 271 | 272 | - [ ] 文档 273 | - [ ] [JS 变量提升](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting),变量提升的概念 274 | - [ ] 推荐文章 275 | - [ ] [JavsScript 变量提升和函数提升](https://towind.fun/2021/05/10/js-hoisting/),深度解析变量提升和函数提升,举例说明各种情况下的变量提升 276 | - [ ] [我用了两个月的时间才理解 let](https://fangyinghang.com/let-in-js/),深度理解解析 let 和 val 的区别,和 let 的暂时死区 277 | - [ ] [JavaScript Scoping and Hoisting](http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html),JavaScript 中的作用域和函数声明和变量声明的提升 278 | 279 | #### new 280 | 281 | `new` 操作符可以帮助我们构建出一个实例,并且绑定上 `this`。 282 | 283 | - [ ] 文档 284 | - [ ] [new](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new) 285 | - [ ] 推荐文章 286 | - [ ] [JS 的 new 到底是干什么的?](https://zhuanlan.zhihu.com/p/23987456) 287 | - [ ] [JavaScript 深入之 new 的模拟实现](https://github.com/mqyqingfeng/Blog/issues/13) 288 | 289 | #### call、apply、bind 290 | 291 | - [ ] 文档 292 | - [ ] [call](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call),call 的概念 293 | - [ ] [apply](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply),apply 的概念 294 | - [ ] [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind),bind 的概念 295 | - [ ] 推荐文章 296 | - [ ] [JS 中的 call、apply、bind 方法详解](https://segmentfault.com/a/1190000018270750),对这三个方法的使用、面试题及具体实现做了详解 297 | - [ ] [call 和 apply 的模拟实现](https://github.com/mqyqingfeng/Blog/issues/11),模拟实现 call 和 apply,帮助更好理解 298 | - [ ] [bind 的模拟实现](https://github.com/mqyqingfeng/Blog/issues/12),模拟实现 bind,帮助更好理解 299 | 300 | #### 原型 301 | 302 | 通过原型这种机制,JavaScript 中的对象从其他对象继承功能特性。 303 | 304 | - [ ] 文档 305 | - [ ] [原型](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes) 306 | - [ ] 推荐文章 307 | - [ ] [You Don't Know JS: this & Object Prototypes](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch5.md) 308 | - [ ] [深入理解 JavaScript 原型](https://mp.weixin.qq.com/s/1UDILezroK5wrcK-Z5bHOg) 309 | - [ ] [深度解析原型中的各个难点](https://juejin.cn/post/6844903575974313992) 310 | - [ ] [Prototypes in JavaScript](https://betterprogramming.pub/prototypes-in-javascript-5bba2990e04b) 需自备梯子 311 | 312 | #### Class 313 | 314 | `class` 只是原型链的语法糖,与其它语言中的类不是同一样东西。 315 | 316 | - [ ] 文档 317 | - [ ] [Class](https://developer.mozilla.org/en-US/docs/Glossary/Class) 318 | - [ ] 推荐文章 319 | - [ ] [理解 JavaScript 的类](https://www.digitalocean.com/community/tutorials/understanding-classes-in-javascript) 320 | - [ ] [Babel 是如何编译 Class 上](https://github.com/mqyqingfeng/Blog/issues/105) 321 | - [ ] [Babel 是如何编译 Class 下](https://github.com/mqyqingfeng/Blog/issues/106) 322 | - [ ] [给 ES6 class 说句公道话](https://juejin.cn/post/6924108426125508616) 323 | - [ ] [应该在 JavaScript 中使用 Class 吗?](https://zhuanlan.zhihu.com/p/158956514) 324 | 325 | #### 继承 326 | 327 | 继承是面向对象语言(Object-Oriented Language)三大特征之一,在 JS 中也占有非常重要的地位。而想要实现继承有多种方式,它们都有各自的优缺点。 328 | 329 | - [ ] 文档 330 | - [ ] [继承](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance) 331 | - [ ] 推荐文章 332 | - [ ] [JavaScript 深入之继承的多种方式和优缺点](https://github.com/mqyqingfeng/Blog/issues/16) 333 | - [ ] [JavaScript 中的继承](https://medium.com/@happymishra66/inheritance-in-javascript-21d2b82ffa6f),需自备梯子 334 | - [ ] [JS 类继承](https://javascript.info/class-inheritance),另有 [中文翻译版](https://zh.javascript.info/class-inheritance) 335 | 336 | #### 模块化 337 | 338 | 这块知识必会,最好了解下模块化的前世今生以及对 ES6 的原生模块化有个深入的理解。 339 | 340 | - [ ] 文档 341 | - [ ] [Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) 342 | - [ ] 推荐文章 343 | - [ ] [【深度全面】前端 JavaScript 模块化规范进化论](https://segmentfault.com/a/1190000023711059),记录了 JS 模块化的进化之路 344 | - [ ] [JavaScript modules](https://v8.dev/features/modules),由浅入深解释 JS 模块化 345 | - [ ] [ES modules: A cartoon deep-dive](https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/),一篇对 JS 模块化深入解释的文章,另有 [中文版](https://juejin.cn/post/6844903591979778061) 346 | 347 | #### Promise 348 | 349 | - [ ] 文档 350 | - [ ] [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) 351 | - [ ] [Promises/A+ 规范](https://promisesaplus.com/) 352 | - [ ] 推荐文章 353 | - [Callbacks Vs Promises and basics of JS](https://theflyingmantis.medium.com/callbacks-vs-promises-and-basics-of-js-80d3d1515e81),需自备梯子 354 | - [ ] [最简实现 Promise,支持异步链式调用(20 行)](https://juejin.cn/post/6844904094079926286) 355 | - [ ] [100 行代码实现 Promises/A+ 规范](https://mp.weixin.qq.com/s/qdJ0Xd8zTgtetFdlJL3P1g) 356 | - [ ] Github 357 | - [ ] [promise-fun](https://github.com/sindresorhus/promise-fun) 358 | 359 | #### 迭代器与生成器 360 | 361 | - [ ] 文档 362 | - [ ] [迭代器与生成器](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators) 363 | - [ ] 推荐文章 364 | - [ ] [[译] 什么是 JavaScript 生成器?如何使用生成器?](https://juejin.cn/post/6844903616357072910) 365 | - [ ] [Understanding Generators in ES6 JavaScript with Examples](https://codeburst.io/understanding-generators-in-es6-javascript-with-examples-6728834016d5),需自备梯子 366 | - [ ] [A Simple Guide to ES6 Iterators in JavaScript with Examples](https://codeburst.io/a-simple-guide-to-es6-iterators-in-javascript-with-examples-189d052c3d8e),需自备梯子 367 | 368 | #### async await 369 | 370 | - [ ] 文档 371 | - [ ] [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) 372 | - [ ] [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) 373 | - [ ] 推荐文章 374 | - [ ] [手写 async await 的最简实现(20 行)](https://juejin.cn/post/6844904102053281806) 375 | - [ ] [Babel 将 Generator 编译成了什么样子 ](https://github.com/mqyqingfeng/Blog/issues/102) 376 | 377 | #### 事件循环 378 | 379 | 大家都知道 JS 是一门单线程的非阻塞的脚本语言。这也就意味着,代码在执行的任何时候只有一个主线程来处理所有的任务。所以弄懂事件循环机制对我们学习 JS 至关重要。 380 | 381 | - [ ] 文档 382 | - [ ] [事件循环](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop) 383 | - [ ] 推荐文章 384 | - [ ] [这一次,彻底弄懂 JavaScript 执行机制](https://juejin.cn/post/6844903512845860872) 385 | - [ ] [一次弄懂 Event Loop](https://juejin.cn/post/6844903764202094606) 386 | - [ ] [JavaScript 的工作原理](https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5),需自备梯子,另有 [中文翻译版](https://github.com/Troland/how-javascript-works/blob/master/event-loop.md)。 387 | - [ ] 事件循环可视化 388 | - [ ] [Loupe](http://latentflip.com/loupe/?code=JC5vbignYnV0dG9uJywgJ2NsaWNrJywgZnVuY3Rpb24gb25DbGljaygpIHsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gdGltZXIoKSB7CiAgICAgICAgY29uc29sZS5sb2coJ1lvdSBjbGlja2VkIHRoZSBidXR0b24hJyk7ICAgIAogICAgfSwgMjAwMCk7Cn0pOwoKY29uc29sZS5sb2coIkhpISIpOwoKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coIkNsaWNrIHRoZSBidXR0b24hIik7Cn0sIDUwMDApOwoKY29uc29sZS5sb2coIldlbGNvbWUgdG8gbG91cGUuIik7!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D) 389 | 390 | #### 节流与防抖 391 | 392 | 节流指连续触发事件的情况下,在某个时间段内,函数只会执行一次。 393 | 防抖指在事件被触发一定时间后再执行回调函数,如果在一定时间内该事件又被重复触发,则重启计时。 394 | 395 | - [ ] 推荐文章 396 | - [ ] [函数防抖与函数节流](https://zhuanlan.zhihu.com/p/38313717) 397 | - [ ] [浅谈 JS 防抖和节流](https://segmentfault.com/a/1190000018428170) 398 | - [ ] [Debounce – How to Delay a Function in JavaScript](https://www.freecodecamp.org/news/javascript-debounce-example) 399 | - [ ] [Debouncing and Throttling in JavaScript](https://www.telerik.com/blogs/debouncing-and-throttling-in-javascript) 400 | 401 | #### 柯里化 402 | 403 | 柯里化就是将接收多个参数的函数转换成接收一个参数的函数。 404 | 405 | - [ ] 推荐文章 406 | - [ ] [柯里化(Currying)](https://zh.javascript.info/currying-partials) 407 | - [ ] [JavaScript 专题之函数柯里化](https://github.com/mqyqingfeng/Blog/issues/42) 408 | - [ ] [Understanding Currying in JavaScript](https://blog.bitsrc.io/understanding-currying-in-javascript-ceb2188c339),需自备梯子,另有 [中文翻译版](https://www.cnblogs.com/GeniusLyzh/p/9937829.html) 409 | 410 | #### 垃圾回收 411 | 412 | JavaScrip 在变量被创建时分配内存,并在对象不再使用时自动释放内存,这个过程被称为垃圾回收。另外我们主要学习 V8 引擎下的垃圾回收机制。 413 | 414 | - [ ] 文档 415 | - [ ] [内存管理 & 垃圾回收](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management) 416 | - [ ] 推荐文章 417 | - [ ] [深入理解 Chrome V8 垃圾回收机制](https://github.com/yacan8/blog/issues/33),该文章的参考文献也可阅读下 418 | - [ ] [GC in v8](https://github.com/lrlna/sketchin/blob/master/guides/garbage-collection-in-v8.md) 419 | - [ ] [JavaScript 工作原理:内存管理 + 处理常见的 4 种内存泄漏](https://blog.sessionstack.com/how-javascript-works-memory-management-how-to-handle-4-common-memory-leaks-3f28b94cfbec),另有[中文版](https://juejin.cn/post/6844903519078580238) 420 | 421 | #### 设计模式 422 | 423 | - [ ] 文档 424 | - [ ] [wikipedia](https://en.wikipedia.org/wiki/Software_design_pattern) 425 | - [ ] [中文版维基百科]() 426 | - [ ] 推荐书籍 427 | - [ ] 《Head First Design Pattern》 也有中文版的 428 | - [ ] 《Design Patterns: Elements of Reusable Object-Oriented Software》 设计模式:可复用面向对象软件的基础 429 | 430 | #### 其他零散但重要的知识点 431 | 432 | - [ ] [0.1 + 0.2 !== 0.3](https://zhuanlan.zhihu.com/p/225490777),JS 浮点数会造成的问题 433 | 434 | ### HTML 435 | 436 | #### 语义化 437 | 438 | html 语义化就是让页面的内容结构化,便于对浏览器、搜索引擎解析。在没有引入样式 CCS 样式的时候也能以一种可以分辨出来大致表示内容的文档格式显示,并且是容易阅读的。 搜索引擎的爬虫依赖于标记来确定上下文和各个关键字的权重,利于 SEO。 使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。 439 | 440 | - [ ] 文档 441 | - [ ] [HTML 中的语义](https://developer.mozilla.org/en-US/docs/Glossary/Semantics#semantics_in_html),什么是 HTML 语义化,HTML 语义化有什么好处 442 | - [ ] 推荐文章 443 | - [ ] [IFE-NOTE:页面结构语义化](https://rainylog.com/post/ife-note-1/),HTML5 语义化中的页面结构语义化的一些经验和理解 444 | - [ ] [关于 HTML 语义和前端架构](http://nicolasgallagher.com/about-html-semantics-front-end-architecture/),HTML 语义化在开发中配合 CSS 结构化类名的使用构建可重用和可组合的组件 445 | 446 | ### CSS 447 | 448 | - [ ] 推荐文章 449 | - [ ] [一文梳理 CSS 必会知识点](https://juejin.cn/post/6854573212337078285) 450 | 451 | #### 盒子模型 452 | 453 | 在 CSS 中,所有的元素都被一个个的“盒子(box)”包围着,我们广泛地使用两种“盒子” —— 块级盒子 (block box) 和 内联盒子 (inline box),理解这些“盒子”的基本原理,是我们使用 CSS 实现准确布局、处理元素排列的关键。 454 | 455 | - [ ] 文档 456 | - [ ] [CSS 盒子模型](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model),官方文档深入了解 CSS 盒子模型 457 | - [ ] 推荐文章 458 | - [ ] [CSS 盒模型之内边距、边框、外边距 十九问](https://juejin.cn/post/6880111680153059341),通过举例说明盒子模型各种常见形态和问题 459 | - [ ] [CSS Box Model](https://www.w3.org/TR/css-box-3/),盒子模型的一些规范介绍 460 | - [ ] [CSS 盒模型详解(图文教程)](https://www.cnblogs.com/qianguyihao/p/7256371.html),通过图片和例子说明盒子模型的各个部分和在页面上的表现形式 461 | 462 | #### 选择器 463 | 464 | CSS 中,选择器用来指定网页上我们想要样式化的 HTML 元素。CSS 选择器提供了很多种方法,所以在选择要样式化的元素时,我们可以做到很精细的地步。 465 | 466 | CSS 选择器是 CSS 规则的第一部分。它是元素和其他部分组合起来告诉浏览器哪个 HTML 元素应当是被选为应用规则中的 CSS 属性值的方式。选择器所选择的元素,叫做“选择器的对象”。 467 | 468 | - [ ] 文档 469 | - [ ] [CSS 选择器](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors),官方文档详细地讲授选择器的不同使用方式,并了解它们的工作原理。 470 | - [ ] 推荐文章 471 | - [ ] [30 个你必须熟记的 CSS 选择器](https://code.tutsplus.com/zh-hans/tutorials/the-30-css-selectors-you-must-memorize--net-16048),开发中常用的 CSS 选择器,熟练掌握以后可以很大程度提高 CSS 的编码体验 472 | - [ ] [深入解析 CSS 样式优先级](https://cloud.tencent.com/developer/article/1545341),详细介绍了 CSS 样式的权重优先级,避免写重复样式和样式被覆盖不生效的问题 473 | 474 | #### Flex 475 | 476 | - [ ] 文档 477 | - [ ] [flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) 478 | - [ ] 推荐文章 479 | - [ ] [A Complete Guide to Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) 480 | - [ ] [Flexbox 布局中不为人知的细节](https://juejin.cn/post/6938292463605907492) 481 | - [] 实战 482 | - [ ] [FLEXBOX FROGGY](https://flexboxfroggy.com/) 一个趣味性小游戏学习 Flex 的网站 483 | 484 | #### grid 485 | 486 | - [ ] 文档 487 | - [ ] [grid](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout) 488 | - [ ] 推荐文档 489 | - [ ] [A Complete Guide to Grid](https://css-tricks.com/snippets/css/complete-guide-grid/) 490 | - [ ] [最强大的 CSS 布局 —— Grid 布局](https://juejin.cn/post/6854573220306255880) 491 | 492 | #### 其他 493 | 494 | - [ ] 推荐文档 495 | - [ ] [详谈层合成(composite)](http://jartto.wang/2017/09/29/expand-on-performance-composite/) 496 | - [ ] [移动设备如何实现真正 1px 的线?](https://jinlong.github.io/2015/05/24/css-retina-hairlines/) 497 | 498 | ## 框架 499 | 500 | 框架一般选其一深入学习即可。 501 | 502 | ### 虚拟 DOM 503 | 504 | Virtual DOM 也就是虚拟节点。通过 JS 的 Object 对象模拟 DOM 中的真实节点对象,再通过特定的 render 方法将其渲染成真实的 DOM 节点。 505 | 506 | - 文档 507 | - [React 官网介绍](https://reactjs.org/docs/faq-internals.html) 508 | - 推荐文章 509 | - [ Virtual Dom 和 Diff 算法在 React 中是如何工作的?](https://medium.com/@gethylgeorge/how-virtual-dom-and-diffing-works-in-react-6fc805f9f84e),需自备梯子 510 | - [ React 核心知识点 -- Virtual Dom 与 Diff ](https://github.com/pfan123/Articles/issues/62) 511 | 512 | ### 路由 513 | 514 | 路由在 SPA 架构中都有被用到,实际原理就是运用 `hash` 及 `history` 相关的 API 实现。 515 | 516 | - 文档 517 | - [hashchange](https://developer.mozilla.org/en-US/docs/Web/API/Window/hashchange_event) 518 | - [history](https://developer.mozilla.org/en-US/docs/Web/API/History) 519 | - 推荐文章 520 | - [前端路由简介以及 vue-router 实现原理](https://zhuanlan.zhihu.com/p/37730038),对前端路由及 Vue-Route 库原理做了解释,**几个框架的路由库原理都一致** 521 | 522 | ## React 523 | 524 | 学习框架务必从[文档](https://reactjs.org/)出发,起码熟读一遍及自己写过一些初步的 Demo 之后再考虑学习别的资料。 525 | 526 | ### React 推荐学习路径 527 | 528 | ![LR1Dyo](./img/reactStudy.png) 529 | 530 | 大家可以跟着以上学习路径学习,其中除了概念相关的内容是必须学习之外,生态相关的内容大家可以在使用时再学习。 531 | 532 | ### React 推荐学习资料 533 | 534 | - [React 学习之道](https://leanpub.com/the-road-to-learn-react-chinese/),可以 0 元购买 535 | - [React 生命周期](https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/) 536 | 537 | ### 如何编写一个组件 538 | 539 | - 文档 540 | - [React 官方文档](https://reactjs.org/docs/components-and-props.html) 541 | - 推荐文章 542 | - [[译]React 函数组件和类组件的差异](https://jishuin.proginn.com/p/763bfbd4cad4) 543 | - [寫 React Components 該注意的 6 個地方與技巧](https://medium.com/@chihsuan/%E5%AF%AB-react-components-%E8%A9%B2%E6%B3%A8%E6%84%8F%E7%9A%846%E5%80%8B%E5%9C%B0%E6%96%B9%E8%88%87%E6%8A%80%E5%B7%A7-faa2bb87a18e) 544 | - [编写高效且可读组件的 5 个最佳实践](https://www.infoq.cn/article/ry4icky5crb1pokvi0ql) 545 | - [designing-react-components-best-practices](https://www.thisdot.co/blog/designing-react-components-best-practices) 546 | - [React 复合组件](https://www.smashingmagazine.com/2021/08/compound-components-react/) 547 | 548 | ### 受控组件和非受控组件 549 | 550 | - 受控组件:在 HTML 中,表单元素(如 input、 textarea 和 select )通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState() 或者 props 来更新 551 | - 非受控组件:是一个存储其自己的内部状态,并且您使用查询 DOM ref,当你需要它来找到它的当前值,这有点像传统的 HTML 552 | 553 | - 文档 554 | - [React 官方文档](https://reactjs.org/docs/uncontrolled-components.html) 555 | - 推荐文章 556 | - [受控和非受控组件真的那么难理解吗](https://juejin.cn/post/6858276396968951822) 557 | - [[译]受控组件 & 非受控组件](https://www.baobangdong.cn/controlled-components-and-uncontrolled-components/) 558 | 559 | ### 高阶组件(HOC) 560 | 561 | 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。 562 | 563 | 具体而言,高阶组件是参数为组件,返回值为新组件的函数。 564 | 565 | - 文档 566 | - [React 官方文档](https://reactjs.org/docs/higher-order-components.html) 567 | - 推荐文章 568 | - [React 高阶组件(HOC)入门指南](https://github.com/MrErHu/blog/issues/4) 569 | - [hoc 库 recompose](https://github.com/acdlite/recompose) 570 | - [精读 React 高阶组件](https://zhuanlan.zhihu.com/p/27434557) 571 | 572 | ### Hooks 573 | 574 | Hook 是 React 16.8 的新增特性。它可以让你在不编写类组件的情况下使用 React 的特性。 575 | 576 | - 文档 577 | - [React Hooks 官方文档](https://zh-hans.reactjs.org/docs/hooks-intro.html) 578 | - 推荐文章 579 | - [彻底理解 React hook useCallback 和 useMemo 的区别](https://juejin.cn/post/6844904032113278990) 580 | - [React hooks 最佳实践](https://mp.weixin.qq.com/s/0sykIHDM_Ih3W3md-DwFkw) 581 | 582 | ### 合成事件 583 | 584 | 合成事件(SyntheticEvent)是 React 模拟原生 DOM 事件所有能力的一个事件对象,即浏览器原生事件的跨浏览器包装器。React 根据 [W3C 规范](https://www.w3.org/TR/DOM-Level-3-Events/) 定义了合成事件。需要注意的是 v16 和 17 版本中的合成事件有差异。 585 | 586 | - 文档 587 | - [React 官方文档](https://reactjs.org/docs/events.html) 588 | - 推荐文章 589 | - [探索 React 合成事件](https://segmentfault.com/a/1190000038251163) 590 | - [大佬,怎么办?升级 React17,Toast 组件不能用了](https://zhuanlan.zhihu.com/p/380941094) 591 | - [What’s the Difference Between Synthetic React Events and JavaScript Events?](https://betterprogramming.pub/whats-the-difference-between-synthetic-react-events-and-javascript-events-ba7dbc742294),需自备梯子 592 | - [React 17 removes event pooling in the modern browsers](https://blog.saeloun.com/2021/04/06/react-17-removes-event-pooling-in-modern-system.html) 593 | 594 | ### React 路由 595 | 596 | - [react-router](https://github.com/remix-run/react-router),React 声明式路由 597 | - [reach router](https://github.com/reach/router),下一代的 React 路由 598 | 599 | ### React 状态管理 600 | 601 | React 状态管理可谓百花齐放百家争鸣,远远不止笔者列的这些库。但是实际上很多项目完全是不需要用到状态管理的,反而是增加编码复杂度,其实利用 React Context 或者 [react-query](https://github.com/tannerlinsley/react-query) 这类接口请求库就能很好地满足需求了。 602 | 603 | - [redux](https://github.com/reduxjs/redux),JS 应用的状态容器,提供可预测的状态管理 604 | - [mobx](https://github.com/mobxjs/mobx),简单,可扩展的状态管理库 605 | - [recoil](https://github.com/facebookexperimental/Recoil),React 状态管理库 606 | - [xstate](https://github.com/statelyai/xstate),有限状态机 607 | - [zustand](https://github.com/pmndrs/zustand),简单、快速和可扩展的骨状态管理解决方案 608 | 609 | ### React 接口请求 610 | 611 | - [axios](https://github.com/axios/axios),传统接口请求库 612 | - [react-query](https://github.com/tannerlinsley/react-query),用于获取、缓存和更新 React 中异步数据的 Hooks 接口请求库 613 | - [swr](https://github.com/vercel/swr),用于数据请求的 React Hooks 库 614 | 615 | ### React SSR 616 | 617 | - [nest.js](https://github.com/nestjs/nest),一个渐进式的 Node.js 框架,用于构建高效、可靠和可扩展的服务端应用。 618 | 619 | ### React 单测 620 | 621 | - [jest](https://github.com/facebook/jest),优雅、简洁的 JavaScript 测试框架,单测必选项 622 | - [react-testing-library](https://github.com/testing-library/react-testing-library),简单且完整的 React DOM 测试工具 623 | 624 | ### React CSS 方案 625 | 626 | - [styled-components](https://github.com/styled-components/styled-components),CSS in JS 方案 627 | - [tailwindcss](https://github.com/tailwindlabs/tailwindcss),Atom CSS 方案 628 | 629 | ### React 原理 630 | 631 | - [react-source-code-debug](https://github.com/neroneroffy/react-source-code-debug),学习如何调试源码 632 | - [react-illustration-series](https://github.com/7kms/react-illustration-series),图解 react 源码,用大量配图的方式,致力于将 react 原理表述清楚 633 | - [just-react](https://github.com/BetaSu/just-react),「React 技术揭秘」,一本自顶向下的 React 源码分析书 634 | - [tiny-react](https://github.com/PiNengShaoNian/tiny-react),基于 React17 精简而来的最小版实现 635 | 636 | ### Blog 推荐 637 | 638 | - [Dan Abramov](https://overreacted.io/),React 核心开发者的 Blog 639 | 640 | ## Vue 641 | 642 | 学习框架务必从[文档](https://vuejs.org/)出发,起码熟读一遍及自己写过一些初步的 Demo 之后再考虑学习别的资料。 643 | 644 | 对于 Vue 来说,官方文档内容相当齐全,并且全家桶也都是官方出的,因此无需头疼技术栈选型。 645 | 646 | ### Vue 推荐学习路径 647 | 648 | 目前 3.0 生态并不完善,在公司内部基本需要先熟悉 2.0 的写法,因此推荐新手先学习 2.0 的内容。 649 | 650 | - [新手向:Vue 2.0 的建议学习顺序](https://zhuanlan.zhihu.com/p/23134551),尤雨溪自己写的学习路径,时至今日也不过时 651 | 652 | ### Vue 推荐学习资料 653 | 654 | - [ ] [awesome-vue](https://github.com/vuejs/awesome-vue) 655 | - [ ] [vue-patterns](https://github.com/learn-vuejs/vue-patterns),有用的 Vue 模式、技巧、提示以及有帮助的精选链接 656 | 657 | ### Vue 原理 658 | 659 | - [vue-analysis](https://github.com/ustbhuangyi/vue-analysis),黄老师出品 660 | - [vue-design](https://github.com/HcySunYang/vue-design),官方人员出品,域名已过期,需要大家自行在仓库内浏览内容。虽然麻烦了点,但是质量绝对过关 661 | 662 | ## 浏览器 663 | 664 | 一般说到浏览器,常指的都是 Chrome。浏览器作为前端不可或缺的载体,我们势必需要好好学习及掌握其相关的知识。 665 | 666 | **另外浏览器中涉及到的知识面很多,与 JS 执行机制、网络、性能优化、安全等领域都有关联,因此大家在学习这部分的内容时需要多与之前学习的知识联系起来。** 667 | 668 | ### 架构 669 | 670 | - [Inside look at modern web browser](https://developers.google.com/web/updates/2018/09/inside-browser-part1),这是一个 Google 出的系列专栏,共有四篇文章,内容上到浏览器的整体架构,下至页面的渲染规则都说了一遍,另有 [中文翻译](https://cloud.tencent.com/developer/article/1806716) 671 | 672 | ### 整体流程 673 | 674 | - [浏览器的工作原理:新式网络浏览器幕后揭秘](https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/),这虽然是一篇 11 年的文章,但是内容在如今也不过时,文章广为流传 675 | - [当···时发生了什么?](https://github.com/skyline75489/what-happens-when-zh_CN),经典面试题,文中对于这个流程里的相关内容力求尽可能具体,不遗漏任何细节 676 | - [从输入 URL 到页面加载完成的过程中都发生了什么事情?](https://fex.baidu.com/blog/2014/05/what-happen/),这篇文章涉及了大量网络及硬件知识 677 | 678 | ### 渲染相关 679 | 680 | - [浏览器的渲染原理简介](https://coolshell.cn/articles/9666.html),左耳朵耗子出品,如果上文「浏览器的工作原理:新式网络浏览器幕后揭秘」觉得太长不看或者看完觉得没看懂什么,那么可以来阅读下本文,起码能从中学会一些能用在工作上的东西 681 | - [浏览器的回流与重绘 (Reflow & Repaint)](https://juejin.cn/post/6844903569087266823) 682 | 683 | ### JS 执行机制 684 | 685 | - [从浏览器多进程到 JS 单线程,JS 运行机制最全面的一次梳理](https://segmentfault.com/a/1190000012925872),超长文,这篇文章能让你对进程线程,浏览器多进程、浏览器内核多线程、JS 单线程、JS 运行机制有个不错的理解 686 | 687 | ### 缓存 688 | 689 | - [文档](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching) 690 | - [彻底理解浏览器的缓存机制](https://juejin.cn/post/6844903593275817998),浏览器缓存机制与性能优化息息相关 691 | - [图解 Http 缓存控制之 max-age=0、no-cache、no-store 区别](https://zhuanlan.zhihu.com/p/55623075),很有趣的图解文章 692 | 693 | ### Devtools 694 | 695 | - [Chrome DevTools](https://developer.chrome.com/docs/devtools/),Google 出的 DevTools 的使用说明书,对于每个功能的使用都有详细的介绍,看啥文章都不如看这个 696 | - [Chrome_Devtools_Tricks](https://github.com/dendoink/FrontendWingman/tree/master/Chrome_Devtools_Tricks),介绍了 Chrome DevTools 的使用技巧,从不同的情景来说明应该如何搭配使用 Chrome DevTools 中的小技巧,适合英文不怎么好的读者阅读 697 | 698 | ### 浏览器安全 699 | 700 | - [文档](https://developer.mozilla.org/en-US/docs/Web/Security) 701 | - [一文读懂 Web 安全](https://segmentfault.com/a/1190000023396707),简单介绍了一些前端需要注意的安全知识 702 | - [the-book-of-secret-knowledge](https://github.com/trimstray/the-book-of-secret-knowledge),如果你对安全领域有兴趣,可以阅读下这个仓库的内容 703 | 704 | ## 性能优化 705 | 706 | 性能优化是一个系统性工程,涉及到的方面很多,不仅仅只是大家常说的静态文件和代码优化那么简单。 707 | 708 | 大家学习这部分内容的时候可以先从推荐的文章中了解具体有哪些性能优化手段及具体方法,然后根据这些内容去实验。 709 | 710 | ### 推荐书籍 711 | 712 | 其实性能优化相关的书籍市面上出的不多,优秀的也都是好几年前的老书了,看不看也无所谓了。 713 | 714 | - [Web 性能权威指南](https://book.douban.com/subject/25856314/),豆瓣 8.9 分,老书 715 | - [高性能网站建设进阶指南](https://book.douban.com/subject/4719162/),豆瓣 8.9 分,老书 716 | 717 | ### 推荐网站 718 | 719 | - [web.dev](https://web.dev/),Google 自家的 blog,你能在这上面学到很多性能优化及如何做好用户体验的知识,其实很多市面上的文章内容都有这个网站的影子 720 | 721 | ### 整体优化建议 722 | 723 | - [前端性能优化 24 条建议(2020)](https://juejin.cn/post/6892994632968306702),类似现代版雅虎军规 724 | - [前端性能优化之旅](https://github.com/alienzhou/fe-performance-journey),系统性介绍性能优化的手段,参考资料也值得学习 725 | - [Front-End Performance Checklist 2021](https://www.smashingmagazine.com/2021/01/front-end-performance-2021-free-pdf-checklist/),一本很火的免费 PDF,包含了很多性能优化相关的 Checklist 726 | - [React 性能优化 | 包括原理、技巧、Demo、工具使用](https://juejin.cn/post/6935584878071119885) 727 | 728 | ### 性能指标 729 | 730 | - [文档](https://web.dev/learn-web-vitals/) 731 | - [还在看那些老掉牙的性能优化文章么?这些最新性能指标了解下](https://juejin.cn/post/6850037270729359367),文章会介绍谷歌提倡的七个用户体验指标(也可以认为是性能指标) 732 | - [做性能优化时,我们关注哪些指标?](https://mp.weixin.qq.com/s/SlS0J9eSb20PCLW062sQVg) 733 | 734 | ### 性能监控 735 | 736 | - [前端搞工程化:从零打造性能检测库「源码 + 视频」](https://juejin.cn/post/6919295789630455815),光会性能优化的手段还是不够的,如何体现优化的价值也是至关重要的 737 | 738 | ## TypeScript 739 | 740 | TypeScript 是为开发大型应用而设计的,并且 TypeScript 可转译成 JavaScript。由于 TypeScript 是 JavaScript 的严格超集,任何现有的 JavaScript 程序都是合法的 TypeScript 程序。 741 | 742 | 文档 743 | 744 | - [TypeScript 官方文档](https://www.typescriptlang.org/docs/) 745 | 746 | 推荐文章 747 | 748 | - [TypeScript 入门教程](https://ts.xcatliu.com/) 749 | - [TypeScript 的另一面:类型编程](https://juejin.cn/post/6989796543880495135) 750 | - [TypeScript Deep Dive](https://basarat.gitbook.io/typescript/) 另有[中文版](https://jkchao.github.io/typescript-book-chinese/) 751 | 752 | 推荐开源项目 753 | 754 | - [TypeScript-for-Beginner-Programmers](https://github.com/chibicode/TypeScript-for-Beginner-Programmers) 需自备梯子 755 | - [type-challenges](https://github.com/type-challenges/type-challenges) 756 | - [TypeScript exercises](https://github.com/typescript-exercises/typescript-exercises) 757 | 758 | ## Electron 759 | 760 | Electron 是一个可以使用 Web 技术如 JavaScript、HTML 和 CSS 来创建跨平台原生桌面应用的框架。借助 Electron,我们可以使用纯 JavaScript 来调用丰富的原生 APIs。 761 | 762 | 文档 763 | 764 | - [Electron 官网](https://www.electronjs.org/) 765 | - [Electron 中文教程](https://weishuai.gitbooks.io/electron-/content/) 766 | 767 | 推荐文章 768 | 769 | - [分享这半年的 Electron 应用开发和优化经验](https://juejin.cn/post/6844904029231775758) 770 | - [用 JS 开发跨平台桌面应用,从原理到实践](https://juejin.cn/post/6844903862302670862) 771 | - [Building a desktop application with Electron](https://medium.com/developers-writing/building-a-desktop-application-with-electron-204203eeb658) 需翻墙访问 772 | 773 | 推荐开源项目 774 | 775 | - [Electron 资源](https://github.com/sindresorhus/awesome-electron) 776 | - [Electron Playground](https://github.com/tal-tech/electron-playground) 777 | - [electron-vue-cloud-music](https://github.com/xiaozhu188/electron-vue-cloud-music) 778 | - [electron-builder](https://github.com/electron-userland/electron-builder) 779 | 780 | ## 组件库 781 | 782 | 组件库顾名思义指的就是将多个公共模块或者可复用的组件提取整合生成的一个仓库 783 | 784 | 知名度较广的组件库: 785 | 786 | - [antd](https://github.com/ant-design/ant-design.git) 787 | - [elementUI](https://github.com/ElemeFE/element.git) 788 | 789 | 相关文档: 790 | 791 | - [lerna](https://github.com/lerna/lerna) 792 | - [angular commit 规范](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit) 793 | - [yarn](https://yarnpkg.com/) 794 | - [css variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) 795 | 796 | 推荐文章: 797 | 798 | - [从 0 到 1,搭建一个体系完善的前端 React 组件库](https://www.infoq.cn/article/i4q9ybdmxzmu8eex8qvh) 799 | - [如何规范你的 Git commit?](https://zhuanlan.zhihu.com/p/182553920) 800 | - [基于 lerna 和 yarn workspace 的 monorepo 工作流](https://zhuanlan.zhihu.com/p/71385053) 801 | - [FusionNext 可配置能力从 Sass 体系升级为支持 Css Variable](https://zhuanlan.zhihu.com/p/257159028) 802 | 803 | ## 微前端 804 | 805 | 是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将单页面前端应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。 806 | 807 | 优势: 808 | 809 | - 代码库更小,更内聚、可维护性更高 810 | - 松耦合、自治的团队可扩展性更好 811 | - 渐进地升级、更新甚至重写部分前端功能成为了可能 812 | - 独立开发部署,缩小变更范围,进而降低相关风险 813 | 814 | 框架: 815 | 816 | - [single-spa](https://single-spa.js.org/) 817 | - [蚂蚁-乾坤](https://github.com/umijs/qiankun) 818 | - [淘系-icestark](https://github.com/ice-lab/icestark) 819 | - [字节-Garfish](https://github.com/modern-js-dev/garfish) 820 | - [京东-micro-app](https://github.com/micro-zoe/micro-app) 821 | - [Bit](https://bit.dev) 822 | - [EMP - Micro Frontends solution](https://github.com/efoxTeam/emp) 基于 webpack 5 & module federation 823 | 824 | 推荐文章: 825 | 826 | - [从零到一实现企业级微前端框架,保姆级教学](https://juejin.cn/post/7004661323124441102) 827 | - [字节跳动是如何落地微前端的](https://mp.weixin.qq.com/s/L9wbfNG5fTXF5bx7dcgj4Q) 828 | - [What Are Micro Frontends?](https://livebook.manning.com/book/micro-frontends-in-action/chapter-1/v-4/) 829 | - [Bifrost 微前端框架及其在美团闪购中的实践](https://tech.meituan.com/2019/12/26/meituan-bifrost.html) 830 | - [每日优鲜供应链前端团队微前端改造](https://juejin.cn/post/6844903943873675271) 831 | - [微前端在美团外卖的实践](https://tech.meituan.com/2020/02/27/meituan-waimai-micro-frontends-practice.html) 832 | - [How We Build Micro Frontends](https://blog.bitsrc.io/how-we-build-micro-front-ends-d3eeeac0acfc) 833 | - [Revolutionizing Micro Frontends with Webpack 5, Module Federation and Bit](https://blog.bitsrc.io/revolutionizing-micro-frontends-with-webpack-5-module-federation-and-bit-99ff81ceb0) 834 | - [万字长文+图文并茂+全面解析微前端框架 qiankun 源码](https://github.com/a1029563229/blogs/blob/master/Source-Code/qiankun/1.md) 835 | 836 | ### 推荐学习资料 837 | 838 | - [](https://github.com/billyjov/microfrontend-resources),🔥 关于微前端的各类资料推荐 839 | 840 | ## 跨端框架 841 | 842 | 跨端的最主要的含义就是一套代码多端运行,减少重复劳动 843 | 844 | 目前看来,国内比较流行的是小程序, H5, App 三端跨的框架, [uniapp](https://github.com/dcloudio/uni-app) 及 [taro](https://github.com/NervJS/taro) 是其中做的比较出彩的两个框架。当然在 taro3.0 之前(以下主要是说小程序),taro 跟 uniapp 都是使用编译时做更多的事情,编译成小程序能够运行的代码。 845 | 846 | 而在 taro3.0 之后变成了与 [remax](https://github.com/remaxjs/remax) 相同的思想,在运行时做更多的事情,保证了原框架代码能够完全使用,而不需要为了转换成其他小程序时做兼容。 847 | 848 | - [awesome-remax](https://github.com/remaxjs/awesome-remax) 849 | - [美团自研 react 跨端](https://tech.meituan.com/2021/06/10/react-native-hybrid-practice-dsl-in-meituan.html) 850 | - [京东 taro](https://juejin.cn/post/6844904036743774216) 851 | 852 | ## 监控 853 | 854 | 当业务进入稳定,最需要做的肯定是对于业务线上的各种性能、异常及常规业务进行监控,避免在上线之后成为瞎子。 855 | 856 | 目前市场比较出名的监控系统: 857 | 858 | - [sentry](https://sentry.io/welcome/) 859 | - [ali node](https://www.aliyun.com/product/nodejs) 860 | - [bugly](https://bugly.qq.com/v2/) 861 | - [mixpanel](https://mixpanel.com/) 862 | - [听云](https://www.tingyun.com/) 863 | 864 | 推荐开源库: 865 | 866 | - [rrweb](https://github.com/rrweb-io/rrweb),提供像素级的录制与回放,帮助正确定位问题是如何发生的 867 | - [monitor](https://github.com/clouDr-f2e/monitor),👀 一款轻量级的收集页面的用户点击行为、路由跳转、接口报错、代码报错、并上报服务端的 SDK 868 | - [mitojs](https://github.com/mitojs/mitojs) 上面 `monitor` 作者新维护的库。全新插拔式的监控 SDK,代码架构更清晰,配置项更丰富,高度可定制化 869 | 870 | 推荐文章: 871 | 872 | - [美团可视化埋点方案](https://tech.meituan.com/2019/08/15/mtflexbox-automation-buried-point-exploration.html) 873 | - [如何进行 web 性能监控?](http://www.alloyteam.com/2020/01/14184/#prettyPhoto) 874 | - [蚂蚁金服如何把前端性能监控做到极致?](https://www.infoq.cn/article/dxa8am44oz*lukk5ufhy) 875 | - [如何做前端异常监控?](https://www.zhihu.com/question/29953354) 876 | - [前端监控平台系列:JS SDK(已开源)](https://juejin.cn/post/6862559324632252430#heading-17) 877 | - [前端监控 SDK 的一些技术要点原理分析](https://juejin.cn/post/7017974567943536671?utm_source=gold_browser_extension) 878 | 879 | ## 日常充电 880 | 881 | - [Best-websites-a-programmer-should-visit](https://github.com/sdmg15/Best-websites-a-programmer-should-visit),优秀的工程师都应该阅读的网站 882 | 883 | ### CSS 日常充电 884 | 885 | - [You-need-to-know-css](https://github.com/l-hammer/You-need-to-know-css) 886 | - [CSS Inspiration](https://csscoco.com/inspiration/#/) 887 | - [CSS Tricks](https://qishaoxuan.github.io/css_tricks/) 888 | - [spinkit](https://tobiasahlin.com/spinkit/) 需自备梯子 889 | - [animista](https://animista.net/) 890 | 891 | ## Github 优秀学习资料 892 | 893 | ### JS 优秀学习资料 894 | 895 | - [33-js-concepts](https://github.com/leonardomso/33-js-concepts) 896 | - [JavaScript 安全指南](https://github.com/Tencent/secguide/blob/main/JavaScript%E5%AE%89%E5%85%A8%E6%8C%87%E5%8D%97.md#1.1) 897 | - [What the f\*ck JavaScript?](https://github.com/denysdovhan/wtfjs),有趣的 JavaScript 示例列表,附有解释 898 | - [clean-code-javascript](https://github.com/ryanmcdermott/clean-code-javascript),适应于 JavaScript 的优雅代码建议 899 | 900 | ### React 优秀学习资料 901 | 902 | - [react-philosophies](https://github.com/mithi/react-philosophies),React 哲学,内容为写 React 代码时思考的事情 903 | 904 | ### 代码样式及安全 905 | 906 | - [secguide](https://github.com/Tencent/secguide),面向开发人员梳理的代码安全指南 907 | 908 | ## 生产力工具 909 | 910 | ### 流程图 911 | 912 | - [whimsical](https://whimsical.com/) 913 | 914 | ## 作者信息 915 | 916 | | 微信扫码关注公众号,订阅更多精彩内容 | 加笔者微信进群与大厂大佬讨论技术 | 917 | | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | 918 | | | | 919 | -------------------------------------------------------------------------------- /excalidraw/React 学习路径.excalidraw: -------------------------------------------------------------------------------- 1 | { 2 | "type": "excalidraw", 3 | "version": 2, 4 | "source": "https://board.oktangle.com", 5 | "elements": [ 6 | { 7 | "id": "oaOv9MavJt0yT3lAmk5lM", 8 | "type": "rectangle", 9 | "x": 305.21875, 10 | "y": 216.1640625, 11 | "width": 161.70703125, 12 | "height": 52.98828125, 13 | "angle": 0, 14 | "strokeColor": "#000000", 15 | "backgroundColor": "transparent", 16 | "fillStyle": "hachure", 17 | "strokeWidth": 1, 18 | "strokeStyle": "solid", 19 | "roughness": 1, 20 | "opacity": 100, 21 | "seed": 1076749733, 22 | "version": 58, 23 | "versionNonce": 2029096325, 24 | "isDeleted": false, 25 | "groupIds": [] 26 | }, 27 | { 28 | "id": "-iXji9mbfysktw-cfQhP-", 29 | "type": "text", 30 | "x": 321.072265625, 31 | "y": 229.658203125, 32 | "width": 130, 33 | "height": 26, 34 | "angle": 0, 35 | "strokeColor": "#000000", 36 | "backgroundColor": "transparent", 37 | "fillStyle": "hachure", 38 | "strokeWidth": 1, 39 | "strokeStyle": "solid", 40 | "roughness": 1, 41 | "opacity": 100, 42 | "seed": 892346603, 43 | "version": 71, 44 | "versionNonce": 80712933, 45 | "isDeleted": false, 46 | "groupIds": [], 47 | "text": "React 学习路径", 48 | "fontSize": 20, 49 | "fontFamily": 1, 50 | "textAlign": "left", 51 | "baseline": 21 52 | }, 53 | { 54 | "id": "2_Ti4GDw5Z7ns-KaE6z_H", 55 | "type": "rectangle", 56 | "x": 528.287109375, 57 | "y": 336.939453125, 58 | "width": 161.70703125, 59 | "height": 52.98828125, 60 | "angle": 0, 61 | "strokeColor": "#000000", 62 | "backgroundColor": "transparent", 63 | "fillStyle": "hachure", 64 | "strokeWidth": 1, 65 | "strokeStyle": "solid", 66 | "roughness": 1, 67 | "opacity": 100, 68 | "seed": 2062702155, 69 | "version": 155, 70 | "versionNonce": 80185963, 71 | "isDeleted": false, 72 | "groupIds": [ 73 | "55-3UZDfH6SaLVz0rLo_r" 74 | ] 75 | }, 76 | { 77 | "id": "n8JIrRIBatWOYZW8Q-tmt", 78 | "type": "text", 79 | "x": 569.140625, 80 | "y": 350.171875, 81 | "width": 80, 82 | "height": 26, 83 | "angle": 0, 84 | "strokeColor": "#000000", 85 | "backgroundColor": "transparent", 86 | "fillStyle": "hachure", 87 | "strokeWidth": 1, 88 | "strokeStyle": "solid", 89 | "roughness": 1, 90 | "opacity": 100, 91 | "seed": 616384485, 92 | "version": 190, 93 | "versionNonce": 891086277, 94 | "isDeleted": false, 95 | "groupIds": [ 96 | "55-3UZDfH6SaLVz0rLo_r" 97 | ], 98 | "text": "概念相关", 99 | "fontSize": 20, 100 | "fontFamily": 1, 101 | "textAlign": "left", 102 | "baseline": 21 103 | }, 104 | { 105 | "id": "-n0JqoDrHW6I7OW5OXR_b", 106 | "type": "draw", 107 | "x": 394.85546875, 108 | "y": 286, 109 | "width": 80.06640625, 110 | "height": 81.46875, 111 | "angle": 0, 112 | "strokeColor": "#000000", 113 | "backgroundColor": "transparent", 114 | "fillStyle": "hachure", 115 | "strokeWidth": 1, 116 | "strokeStyle": "solid", 117 | "roughness": 1, 118 | "opacity": 100, 119 | "seed": 504707557, 120 | "version": 72, 121 | "versionNonce": 18348165, 122 | "isDeleted": false, 123 | "groupIds": [], 124 | "points": [ 125 | [ 126 | 0, 127 | 0 128 | ], 129 | [ 130 | 1.74609375, 131 | 13.953125 132 | ], 133 | [ 134 | 13.5390625, 135 | 42.421875 136 | ], 137 | [ 138 | 34.1171875, 139 | 67.2578125 140 | ], 141 | [ 142 | 51.2109375, 143 | 76.72265625 144 | ], 145 | [ 146 | 80.06640625, 147 | 81.46875 148 | ] 149 | ], 150 | "lastCommittedPoint": null 151 | }, 152 | { 153 | "id": "39Q8xGnYz2q_Rn0wUAX2F", 154 | "type": "draw", 155 | "x": 470.80859375, 156 | "y": 353.51171875, 157 | "width": 24.66015625, 158 | "height": 21.4375, 159 | "angle": 0, 160 | "strokeColor": "#000000", 161 | "backgroundColor": "transparent", 162 | "fillStyle": "hachure", 163 | "strokeWidth": 1, 164 | "strokeStyle": "solid", 165 | "roughness": 1, 166 | "opacity": 100, 167 | "seed": 1554032037, 168 | "version": 61, 169 | "versionNonce": 921009739, 170 | "isDeleted": false, 171 | "groupIds": [], 172 | "points": [ 173 | [ 174 | 0, 175 | 0 176 | ], 177 | [ 178 | 11.06640625, 179 | 18.8984375 180 | ], 181 | [ 182 | -13.59375, 183 | 21.4375 184 | ] 185 | ], 186 | "lastCommittedPoint": null 187 | }, 188 | { 189 | "id": "igk0wUTycDP-_Fe3gKyzk", 190 | "type": "rectangle", 191 | "x": 263.0945870535704, 192 | "y": 493.99079241071445, 193 | "width": 161.70703125, 194 | "height": 52.98828125, 195 | "angle": 0, 196 | "strokeColor": "#000000", 197 | "backgroundColor": "transparent", 198 | "fillStyle": "hachure", 199 | "strokeWidth": 1, 200 | "strokeStyle": "solid", 201 | "roughness": 1, 202 | "opacity": 100, 203 | "seed": 1845522123, 204 | "version": 262, 205 | "versionNonce": 854630373, 206 | "isDeleted": false, 207 | "groupIds": [ 208 | "hIU9Zn52R12VISY6OXGfZ" 209 | ] 210 | }, 211 | { 212 | "id": "yK6tUK5jdjPlBm9LFi9fg", 213 | "type": "text", 214 | "x": 330.9481026785704, 215 | "y": 507.48493303571365, 216 | "width": 26, 217 | "height": 26, 218 | "angle": 0, 219 | "strokeColor": "#000000", 220 | "backgroundColor": "transparent", 221 | "fillStyle": "hachure", 222 | "strokeWidth": 1, 223 | "strokeStyle": "solid", 224 | "roughness": 1, 225 | "opacity": 100, 226 | "seed": 1134229349, 227 | "version": 308, 228 | "versionNonce": 701857003, 229 | "isDeleted": false, 230 | "groupIds": [ 231 | "hIU9Zn52R12VISY6OXGfZ" 232 | ], 233 | "text": "JSX", 234 | "fontSize": 20, 235 | "fontFamily": 1, 236 | "textAlign": "left", 237 | "baseline": 21 238 | }, 239 | { 240 | "id": "koySXqYYMtvEkN0dUmiHb", 241 | "type": "rectangle", 242 | "x": 263.6297433035704, 243 | "y": 578.3423549107132, 244 | "width": 161.70703125, 245 | "height": 52.98828125, 246 | "angle": 0, 247 | "strokeColor": "#000000", 248 | "backgroundColor": "transparent", 249 | "fillStyle": "hachure", 250 | "strokeWidth": 1, 251 | "strokeStyle": "solid", 252 | "roughness": 1, 253 | "opacity": 100, 254 | "seed": 1803758341, 255 | "version": 290, 256 | "versionNonce": 637360965, 257 | "isDeleted": false, 258 | "groupIds": [ 259 | "VokYW0wpkh8aZnBFIVFnq" 260 | ] 261 | }, 262 | { 263 | "id": "-le_NyLxy5s-V26btNfUD", 264 | "type": "text", 265 | "x": 323.9090401785704, 266 | "y": 591.8364955357132, 267 | "width": 40, 268 | "height": 26, 269 | "angle": 0, 270 | "strokeColor": "#000000", 271 | "backgroundColor": "transparent", 272 | "fillStyle": "hachure", 273 | "strokeWidth": 1, 274 | "strokeStyle": "solid", 275 | "roughness": 1, 276 | "opacity": 100, 277 | "seed": 1641853899, 278 | "version": 342, 279 | "versionNonce": 1200400267, 280 | "isDeleted": false, 281 | "groupIds": [ 282 | "VokYW0wpkh8aZnBFIVFnq" 283 | ], 284 | "text": "组件", 285 | "fontSize": 20, 286 | "fontFamily": 1, 287 | "textAlign": "left", 288 | "baseline": 21 289 | }, 290 | { 291 | "id": "Aq23TDu_e_PU61oWxzCGk", 292 | "type": "rectangle", 293 | "x": 266.6609933035704, 294 | "y": 659.5025111607132, 295 | "width": 161.70703125, 296 | "height": 52.98828125, 297 | "angle": 0, 298 | "strokeColor": "#000000", 299 | "backgroundColor": "transparent", 300 | "fillStyle": "hachure", 301 | "strokeWidth": 1, 302 | "strokeStyle": "solid", 303 | "roughness": 1, 304 | "opacity": 100, 305 | "seed": 1939908459, 306 | "version": 304, 307 | "versionNonce": 1117498021, 308 | "isDeleted": false, 309 | "groupIds": [ 310 | "bUmItrYDMKqEcPuLwlbri" 311 | ] 312 | }, 313 | { 314 | "id": "bZu3QV6G40Q_0y9uYjeta", 315 | "type": "text", 316 | "x": 307.5145089285704, 317 | "y": 672.9966517857132, 318 | "width": 80, 319 | "height": 26, 320 | "angle": 0, 321 | "strokeColor": "#000000", 322 | "backgroundColor": "transparent", 323 | "fillStyle": "hachure", 324 | "strokeWidth": 1, 325 | "strokeStyle": "solid", 326 | "roughness": 1, 327 | "opacity": 100, 328 | "seed": 296753349, 329 | "version": 358, 330 | "versionNonce": 105217579, 331 | "isDeleted": false, 332 | "groupIds": [ 333 | "bUmItrYDMKqEcPuLwlbri" 334 | ], 335 | "text": "元素渲染", 336 | "fontSize": 20, 337 | "fontFamily": 1, 338 | "textAlign": "left", 339 | "baseline": 21 340 | }, 341 | { 342 | "id": "BIDqxNWMjqXI3_oZZ4vh2", 343 | "type": "rectangle", 344 | "x": 263.0555245535704, 345 | "y": 759.2446986607132, 346 | "width": 161.70703125, 347 | "height": 52.98828125, 348 | "angle": 0, 349 | "strokeColor": "#000000", 350 | "backgroundColor": "transparent", 351 | "fillStyle": "hachure", 352 | "strokeWidth": 1, 353 | "strokeStyle": "solid", 354 | "roughness": 1, 355 | "opacity": 100, 356 | "seed": 1361776453, 357 | "version": 316, 358 | "versionNonce": 158928389, 359 | "isDeleted": false, 360 | "groupIds": [ 361 | "FFXGZ5BQxCgb-Wq-ephLr" 362 | ] 363 | }, 364 | { 365 | "id": "xodJFzN9nem7QmyOah5_x", 366 | "type": "text", 367 | "x": 292.9090401785704, 368 | "y": 772.7388392857132, 369 | "width": 102, 370 | "height": 26, 371 | "angle": 0, 372 | "strokeColor": "#000000", 373 | "backgroundColor": "transparent", 374 | "fillStyle": "hachure", 375 | "strokeWidth": 1, 376 | "strokeStyle": "solid", 377 | "roughness": 1, 378 | "opacity": 100, 379 | "seed": 1984181131, 380 | "version": 376, 381 | "versionNonce": 820674763, 382 | "isDeleted": false, 383 | "groupIds": [ 384 | "FFXGZ5BQxCgb-Wq-ephLr" 385 | ], 386 | "text": "props、state", 387 | "fontSize": 20, 388 | "fontFamily": 1, 389 | "textAlign": "left", 390 | "baseline": 21 391 | }, 392 | { 393 | "id": "wSz20-9Lyy7GbZqjiMql_", 394 | "type": "rectangle", 395 | "x": 482.7664620535704, 396 | "y": 496.7798549107141, 397 | "width": 161.70703125, 398 | "height": 52.98828125, 399 | "angle": 0, 400 | "strokeColor": "#000000", 401 | "backgroundColor": "transparent", 402 | "fillStyle": "hachure", 403 | "strokeWidth": 1, 404 | "strokeStyle": "solid", 405 | "roughness": 1, 406 | "opacity": 100, 407 | "seed": 502172651, 408 | "version": 365, 409 | "versionNonce": 160630117, 410 | "isDeleted": false, 411 | "groupIds": [ 412 | "CcWFH8mc6erv4qeLDrrkt" 413 | ] 414 | }, 415 | { 416 | "id": "M7koooSWxVHJkB7wbgf7c", 417 | "type": "text", 418 | "x": 519.2215401785704, 419 | "y": 508.93805803571365, 420 | "width": 80, 421 | "height": 26, 422 | "angle": 0, 423 | "strokeColor": "#000000", 424 | "backgroundColor": "transparent", 425 | "fillStyle": "hachure", 426 | "strokeWidth": 1, 427 | "strokeStyle": "solid", 428 | "roughness": 1, 429 | "opacity": 100, 430 | "seed": 1728101445, 431 | "version": 385, 432 | "versionNonce": 1360408427, 433 | "isDeleted": false, 434 | "groupIds": [ 435 | "CcWFH8mc6erv4qeLDrrkt" 436 | ], 437 | "text": "生命周期", 438 | "fontSize": 20, 439 | "fontFamily": 1, 440 | "textAlign": "left", 441 | "baseline": 21 442 | }, 443 | { 444 | "id": "IVvO9BnzRFiHYoE2m6E_2", 445 | "type": "rectangle", 446 | "x": 487.1570870535704, 447 | "y": 585.1626674107132, 448 | "width": 161.70703125, 449 | "height": 52.98828125, 450 | "angle": 0, 451 | "strokeColor": "#000000", 452 | "backgroundColor": "transparent", 453 | "fillStyle": "hachure", 454 | "strokeWidth": 1, 455 | "strokeStyle": "solid", 456 | "roughness": 1, 457 | "opacity": 100, 458 | "seed": 1683503147, 459 | "version": 278, 460 | "versionNonce": 372707525, 461 | "isDeleted": false, 462 | "groupIds": [ 463 | "FfQqhctZm2nNsOeRf_O2k" 464 | ] 465 | }, 466 | { 467 | "id": "Mm69SC6xRQiOdwe3R1TuF", 468 | "type": "text", 469 | "x": 527.7488839285704, 470 | "y": 598.6568080357132, 471 | "width": 80, 472 | "height": 26, 473 | "angle": 0, 474 | "strokeColor": "#000000", 475 | "backgroundColor": "transparent", 476 | "fillStyle": "hachure", 477 | "strokeWidth": 1, 478 | "strokeStyle": "solid", 479 | "roughness": 1, 480 | "opacity": 100, 481 | "seed": 1451684869, 482 | "version": 335, 483 | "versionNonce": 1494419979, 484 | "isDeleted": false, 485 | "groupIds": [ 486 | "FfQqhctZm2nNsOeRf_O2k" 487 | ], 488 | "text": "事件处理", 489 | "fontSize": 20, 490 | "fontFamily": 1, 491 | "textAlign": "left", 492 | "baseline": 21 493 | }, 494 | { 495 | "id": "KbHLGVoCdDjbu2NA_8naH", 496 | "type": "rectangle", 497 | "x": 486.7195870535704, 498 | "y": 663.2368861607132, 499 | "width": 161.70703125, 500 | "height": 52.98828125, 501 | "angle": 0, 502 | "strokeColor": "#000000", 503 | "backgroundColor": "transparent", 504 | "fillStyle": "hachure", 505 | "strokeWidth": 1, 506 | "strokeStyle": "solid", 507 | "roughness": 1, 508 | "opacity": 100, 509 | "seed": 390373381, 510 | "version": 346, 511 | "versionNonce": 1023586341, 512 | "isDeleted": false, 513 | "groupIds": [ 514 | "tJGwiuUhkG0fzUTl8PSAo" 515 | ] 516 | }, 517 | { 518 | "id": "-1lswrdQKAMXhgvCudlRZ", 519 | "type": "text", 520 | "x": 527.5731026785704, 521 | "y": 676.7310267857132, 522 | "width": 80, 523 | "height": 26, 524 | "angle": 0, 525 | "strokeColor": "#000000", 526 | "backgroundColor": "transparent", 527 | "fillStyle": "hachure", 528 | "strokeWidth": 1, 529 | "strokeStyle": "solid", 530 | "roughness": 1, 531 | "opacity": 100, 532 | "seed": 1691946699, 533 | "version": 402, 534 | "versionNonce": 232493227, 535 | "isDeleted": false, 536 | "groupIds": [ 537 | "tJGwiuUhkG0fzUTl8PSAo" 538 | ], 539 | "text": "条件渲染", 540 | "fontSize": 20, 541 | "fontFamily": 1, 542 | "textAlign": "left", 543 | "baseline": 21 544 | }, 545 | { 546 | "id": "peAvaLJQ9j_eAVOWpIwhI", 547 | "type": "rectangle", 548 | "x": 700.6542968749989, 549 | "y": 498.6079799107141, 550 | "width": 161.70703125, 551 | "height": 52.98828125, 552 | "angle": 0, 553 | "strokeColor": "#000000", 554 | "backgroundColor": "transparent", 555 | "fillStyle": "hachure", 556 | "strokeWidth": 1, 557 | "strokeStyle": "solid", 558 | "roughness": 1, 559 | "opacity": 100, 560 | "seed": 158210373, 561 | "version": 266, 562 | "versionNonce": 2078499717, 563 | "isDeleted": false, 564 | "groupIds": [ 565 | "OfBdcTyRbAKuzd5eCKECT" 566 | ] 567 | }, 568 | { 569 | "id": "tVI-jCe6QSjURfm98vt7C", 570 | "type": "text", 571 | "x": 768.0078124999989, 572 | "y": 512.1021205357137, 573 | "width": 27, 574 | "height": 26, 575 | "angle": 0, 576 | "strokeColor": "#000000", 577 | "backgroundColor": "transparent", 578 | "fillStyle": "hachure", 579 | "strokeWidth": 1, 580 | "strokeStyle": "solid", 581 | "roughness": 1, 582 | "opacity": 100, 583 | "seed": 521062795, 584 | "version": 308, 585 | "versionNonce": 823804747, 586 | "isDeleted": false, 587 | "groupIds": [ 588 | "OfBdcTyRbAKuzd5eCKECT" 589 | ], 590 | "text": "HOC", 591 | "fontSize": 20, 592 | "fontFamily": 1, 593 | "textAlign": "left", 594 | "baseline": 21 595 | }, 596 | { 597 | "id": "SyvJFBfBhcAJ-kCz3fVSc", 598 | "type": "rectangle", 599 | "x": 707.7938058035704, 600 | "y": 583.5845424107132, 601 | "width": 161.70703125, 602 | "height": 52.98828125, 603 | "angle": 0, 604 | "strokeColor": "#000000", 605 | "backgroundColor": "transparent", 606 | "fillStyle": "hachure", 607 | "strokeWidth": 1, 608 | "strokeStyle": "solid", 609 | "roughness": 1, 610 | "opacity": 100, 611 | "seed": 1789611973, 612 | "version": 321, 613 | "versionNonce": 924232421, 614 | "isDeleted": false, 615 | "groupIds": [ 616 | "riCovAiLYLQAe4_S9nxT-" 617 | ] 618 | }, 619 | { 620 | "id": "LrMIRiaomclBn6Ab6IrP3", 621 | "type": "text", 622 | "x": 758.1473214285704, 623 | "y": 597.0786830357132, 624 | "width": 61, 625 | "height": 26, 626 | "angle": 0, 627 | "strokeColor": "#000000", 628 | "backgroundColor": "transparent", 629 | "fillStyle": "hachure", 630 | "strokeWidth": 1, 631 | "strokeStyle": "solid", 632 | "roughness": 1, 633 | "opacity": 100, 634 | "seed": 1682324235, 635 | "version": 368, 636 | "versionNonce": 1797890539, 637 | "isDeleted": false, 638 | "groupIds": [ 639 | "riCovAiLYLQAe4_S9nxT-" 640 | ], 641 | "text": "Context", 642 | "fontSize": 20, 643 | "fontFamily": 1, 644 | "textAlign": "left", 645 | "baseline": 21 646 | }, 647 | { 648 | "id": "4C6TJ1n_i5v8Km9PSPv8r", 649 | "type": "rectangle", 650 | "x": 488.5086495535704, 651 | "y": 759.9439174107132, 652 | "width": 161.70703125, 653 | "height": 52.98828125, 654 | "angle": 0, 655 | "strokeColor": "#000000", 656 | "backgroundColor": "transparent", 657 | "fillStyle": "hachure", 658 | "strokeWidth": 1, 659 | "strokeStyle": "solid", 660 | "roughness": 1, 661 | "opacity": 100, 662 | "seed": 1509222283, 663 | "version": 311, 664 | "versionNonce": 1865025093, 665 | "isDeleted": false, 666 | "groupIds": [ 667 | "7Dlc9f1S34Q3sVkIFQZMN" 668 | ] 669 | }, 670 | { 671 | "id": "PS9-ngwaA_HWQGrvPzPlP", 672 | "type": "text", 673 | "x": 527.3621651785704, 674 | "y": 773.4380580357132, 675 | "width": 84, 676 | "height": 26, 677 | "angle": 0, 678 | "strokeColor": "#000000", 679 | "backgroundColor": "transparent", 680 | "fillStyle": "hachure", 681 | "strokeWidth": 1, 682 | "strokeStyle": "solid", 683 | "roughness": 1, 684 | "opacity": 100, 685 | "seed": 433547941, 686 | "version": 374, 687 | "versionNonce": 1964256395, 688 | "isDeleted": false, 689 | "groupIds": [ 690 | "7Dlc9f1S34Q3sVkIFQZMN" 691 | ], 692 | "text": "列表、key", 693 | "fontSize": 20, 694 | "fontFamily": 1, 695 | "textAlign": "left", 696 | "baseline": 21 697 | }, 698 | { 699 | "id": "THhqQWDPymWuE0--8IyIp", 700 | "type": "rectangle", 701 | "x": 703.6688058035704, 702 | "y": 678.0767299107132, 703 | "width": 161.70703125, 704 | "height": 52.98828125, 705 | "angle": 0, 706 | "strokeColor": "#000000", 707 | "backgroundColor": "transparent", 708 | "fillStyle": "hachure", 709 | "strokeWidth": 1, 710 | "strokeStyle": "solid", 711 | "roughness": 1, 712 | "opacity": 100, 713 | "seed": 1668764101, 714 | "version": 347, 715 | "versionNonce": 922416549, 716 | "isDeleted": false, 717 | "groupIds": [ 718 | "wXAwqE_D__nEwGVxjvsij" 719 | ] 720 | }, 721 | { 722 | "id": "nQQgLVQzz9e9EvRPktPiR", 723 | "type": "text", 724 | "x": 728.5223214285704, 725 | "y": 691.5708705357132, 726 | "width": 112, 727 | "height": 26, 728 | "angle": 0, 729 | "strokeColor": "#000000", 730 | "backgroundColor": "transparent", 731 | "fillStyle": "hachure", 732 | "strokeWidth": 1, 733 | "strokeStyle": "solid", 734 | "roughness": 1, 735 | "opacity": 100, 736 | "seed": 800282891, 737 | "version": 409, 738 | "versionNonce": 43279147, 739 | "isDeleted": false, 740 | "groupIds": [ 741 | "wXAwqE_D__nEwGVxjvsij" 742 | ], 743 | "text": "组合 vs 继承", 744 | "fontSize": 20, 745 | "fontFamily": 1, 746 | "textAlign": "left", 747 | "baseline": 21 748 | }, 749 | { 750 | "id": "1un-lro5mXHz_hqCFwik8", 751 | "type": "rectangle", 752 | "x": 701.2664620535704, 753 | "y": 847.5103236607132, 754 | "width": 161.70703125, 755 | "height": 52.98828125, 756 | "angle": 0, 757 | "strokeColor": "#000000", 758 | "backgroundColor": "transparent", 759 | "fillStyle": "hachure", 760 | "strokeWidth": 1, 761 | "strokeStyle": "solid", 762 | "roughness": 1, 763 | "opacity": 100, 764 | "seed": 1474629515, 765 | "version": 393, 766 | "versionNonce": 1773598981, 767 | "isDeleted": false, 768 | "groupIds": [ 769 | "pjxZwtE0RAEbrbNi2HoB_" 770 | ] 771 | }, 772 | { 773 | "id": "IEn1w5ehXFK_qpAb9m3s0", 774 | "type": "text", 775 | "x": 762.1199776785704, 776 | "y": 861.0044642857132, 777 | "width": 40, 778 | "height": 26, 779 | "angle": 0, 780 | "strokeColor": "#000000", 781 | "backgroundColor": "transparent", 782 | "fillStyle": "hachure", 783 | "strokeWidth": 1, 784 | "strokeStyle": "solid", 785 | "roughness": 1, 786 | "opacity": 100, 787 | "seed": 1348321957, 788 | "version": 438, 789 | "versionNonce": 1813300683, 790 | "isDeleted": false, 791 | "groupIds": [ 792 | "pjxZwtE0RAEbrbNi2HoB_" 793 | ], 794 | "text": "Hooks", 795 | "fontSize": 20, 796 | "fontFamily": 1, 797 | "textAlign": "left", 798 | "baseline": 21 799 | }, 800 | { 801 | "id": "qGwXPPc39trwyL-inHE1D", 802 | "type": "rectangle", 803 | "x": 702.4578683035704, 804 | "y": 759.3228236607132, 805 | "width": 161.70703125, 806 | "height": 52.98828125, 807 | "angle": 0, 808 | "strokeColor": "#000000", 809 | "backgroundColor": "transparent", 810 | "fillStyle": "hachure", 811 | "strokeWidth": 1, 812 | "strokeStyle": "solid", 813 | "roughness": 1, 814 | "opacity": 100, 815 | "seed": 1571355653, 816 | "version": 297, 817 | "versionNonce": 551260261, 818 | "isDeleted": false, 819 | "groupIds": [ 820 | "_Qn31aoHbO6JdUAf2M_mK" 821 | ] 822 | }, 823 | { 824 | "id": "5u5DHtndMg-3szNhgdroQ", 825 | "type": "text", 826 | "x": 723.3113839285704, 827 | "y": 773.0786830357132, 828 | "width": 120, 829 | "height": 26, 830 | "angle": 0, 831 | "strokeColor": "#000000", 832 | "backgroundColor": "transparent", 833 | "fillStyle": "hachure", 834 | "strokeWidth": 1, 835 | "strokeStyle": "solid", 836 | "roughness": 1, 837 | "opacity": 100, 838 | "seed": 1786278603, 839 | "version": 372, 840 | "versionNonce": 414176363, 841 | "isDeleted": false, 842 | "groupIds": [ 843 | "_Qn31aoHbO6JdUAf2M_mK" 844 | ], 845 | "text": "组件设计模式", 846 | "fontSize": 20, 847 | "fontFamily": 1, 848 | "textAlign": "left", 849 | "baseline": 21 850 | }, 851 | { 852 | "id": "DTLBDfyTiV1ONQF68jIJl", 853 | "type": "rectangle", 854 | "x": 1263.503627232131, 855 | "y": 290.8786272321436, 856 | "width": 161.70703125, 857 | "height": 52.98828125, 858 | "angle": 0, 859 | "strokeColor": "#000000", 860 | "backgroundColor": "transparent", 861 | "fillStyle": "hachure", 862 | "strokeWidth": 1, 863 | "strokeStyle": "solid", 864 | "roughness": 1, 865 | "opacity": 100, 866 | "seed": 1340804229, 867 | "version": 575, 868 | "versionNonce": 1424624331, 869 | "isDeleted": false, 870 | "groupIds": [ 871 | "zi6zkZFooQkNgpwYsPGV0", 872 | "kCdd4nGpU5tLDmWZCaIVO" 873 | ] 874 | }, 875 | { 876 | "id": "ECjwr24okxu8TUUdajQXF", 877 | "type": "text", 878 | "x": 1306.357142857131, 879 | "y": 304.3727678571436, 880 | "width": 76, 881 | "height": 26, 882 | "angle": 0, 883 | "strokeColor": "#000000", 884 | "backgroundColor": "transparent", 885 | "fillStyle": "hachure", 886 | "strokeWidth": 1, 887 | "strokeStyle": "solid", 888 | "roughness": 1, 889 | "opacity": 100, 890 | "seed": 1098754635, 891 | "version": 631, 892 | "versionNonce": 1319705445, 893 | "isDeleted": false, 894 | "groupIds": [ 895 | "kCdd4nGpU5tLDmWZCaIVO" 896 | ], 897 | "text": "CSS 方案", 898 | "fontSize": 20, 899 | "fontFamily": 1, 900 | "textAlign": "left", 901 | "baseline": 21 902 | }, 903 | { 904 | "id": "3KlHHghew0N7zfSZfccku", 905 | "type": "rectangle", 906 | "x": 858.509207589283, 907 | "y": 296.4868861607147, 908 | "width": 161.70703125, 909 | "height": 52.98828125, 910 | "angle": 0, 911 | "strokeColor": "#000000", 912 | "backgroundColor": "transparent", 913 | "fillStyle": "hachure", 914 | "strokeWidth": 1, 915 | "strokeStyle": "solid", 916 | "roughness": 1, 917 | "opacity": 100, 918 | "seed": 728780267, 919 | "version": 269, 920 | "versionNonce": 546601323, 921 | "isDeleted": false, 922 | "groupIds": [ 923 | "DX7KHYf0PtbRYRC7JN1Zz" 924 | ] 925 | }, 926 | { 927 | "id": "WEfqVvOWlCzen7wmL289n", 928 | "type": "text", 929 | "x": 925.862723214283, 930 | "y": 309.6071428571431, 931 | "width": 27, 932 | "height": 26, 933 | "angle": 0, 934 | "strokeColor": "#000000", 935 | "backgroundColor": "transparent", 936 | "fillStyle": "hachure", 937 | "strokeWidth": 1, 938 | "strokeStyle": "solid", 939 | "roughness": 1, 940 | "opacity": 100, 941 | "seed": 1022630469, 942 | "version": 318, 943 | "versionNonce": 1008363205, 944 | "isDeleted": false, 945 | "groupIds": [], 946 | "text": "SSR", 947 | "fontSize": 20, 948 | "fontFamily": 1, 949 | "textAlign": "left", 950 | "baseline": 21 951 | }, 952 | { 953 | "id": "DG1iRXPDF8p7PQevOkr3Y", 954 | "type": "rectangle", 955 | "x": 1175.6074218750005, 956 | "y": 471.6654575892868, 957 | "width": 161.70703125, 958 | "height": 52.98828125, 959 | "angle": 0, 960 | "strokeColor": "#000000", 961 | "backgroundColor": "transparent", 962 | "fillStyle": "hachure", 963 | "strokeWidth": 1, 964 | "strokeStyle": "solid", 965 | "roughness": 1, 966 | "opacity": 100, 967 | "seed": 459645355, 968 | "version": 298, 969 | "versionNonce": 1983386635, 970 | "isDeleted": false, 971 | "groupIds": [ 972 | "DPRyW_-Hex2oNOx9ZNdMq" 973 | ] 974 | }, 975 | { 976 | "id": "ol61ppUqG31VddfYI6i3C", 977 | "type": "text", 978 | "x": 1236.4609375000005, 979 | "y": 485.1595982142868, 980 | "width": 40, 981 | "height": 26, 982 | "angle": 0, 983 | "strokeColor": "#000000", 984 | "backgroundColor": "transparent", 985 | "fillStyle": "hachure", 986 | "strokeWidth": 1, 987 | "strokeStyle": "solid", 988 | "roughness": 1, 989 | "opacity": 100, 990 | "seed": 1887363717, 991 | "version": 351, 992 | "versionNonce": 940262949, 993 | "isDeleted": false, 994 | "groupIds": [], 995 | "text": "跨端", 996 | "fontSize": 20, 997 | "fontFamily": 1, 998 | "textAlign": "left", 999 | "baseline": 21 1000 | }, 1001 | { 1002 | "id": "gUsIE_mLtBuK40mVwxdZh", 1003 | "type": "rectangle", 1004 | "x": 597.091796874997, 1005 | "y": 113.74693080357196, 1006 | "width": 161.70703125, 1007 | "height": 52.98828125, 1008 | "angle": 0, 1009 | "strokeColor": "#000000", 1010 | "backgroundColor": "transparent", 1011 | "fillStyle": "hachure", 1012 | "strokeWidth": 1, 1013 | "strokeStyle": "solid", 1014 | "roughness": 1, 1015 | "opacity": 100, 1016 | "seed": 1178619269, 1017 | "version": 240, 1018 | "versionNonce": 365910699, 1019 | "isDeleted": false, 1020 | "groupIds": [ 1021 | "c6yXEwLCIuZVZ5W5x8QbI" 1022 | ] 1023 | }, 1024 | { 1025 | "id": "746EZJhXwepYbHiLZzYLo", 1026 | "type": "text", 1027 | "x": 657.945312499997, 1028 | "y": 127.24107142857196, 1029 | "width": 40, 1030 | "height": 26, 1031 | "angle": 0, 1032 | "strokeColor": "#000000", 1033 | "backgroundColor": "transparent", 1034 | "fillStyle": "hachure", 1035 | "strokeWidth": 1, 1036 | "strokeStyle": "solid", 1037 | "roughness": 1, 1038 | "opacity": 100, 1039 | "seed": 1993931083, 1040 | "version": 294, 1041 | "versionNonce": 1969830277, 1042 | "isDeleted": false, 1043 | "groupIds": [], 1044 | "text": "单测", 1045 | "fontSize": 20, 1046 | "fontFamily": 1, 1047 | "textAlign": "left", 1048 | "baseline": 21 1049 | }, 1050 | { 1051 | "id": "8zKFrSt8JruWJMux2ejFF", 1052 | "type": "rectangle", 1053 | "x": 896.3763950892846, 1054 | "y": 152.2391183035714, 1055 | "width": 161.70703125, 1056 | "height": 52.98828125, 1057 | "angle": 0, 1058 | "strokeColor": "#000000", 1059 | "backgroundColor": "transparent", 1060 | "fillStyle": "hachure", 1061 | "strokeWidth": 1, 1062 | "strokeStyle": "solid", 1063 | "roughness": 1, 1064 | "opacity": 100, 1065 | "seed": 2035699659, 1066 | "version": 316, 1067 | "versionNonce": 442775179, 1068 | "isDeleted": false, 1069 | "groupIds": [ 1070 | "e0_Sh76TFWWWzPCzmjkIm", 1071 | "3EVO1qEbVbVke0FrxXXr6" 1072 | ] 1073 | }, 1074 | { 1075 | "id": "DWzoMttNL4g8krQ5nZlVo", 1076 | "type": "text", 1077 | "x": 956.4877232142842, 1078 | "y": 164.7293526785714, 1079 | "width": 40, 1080 | "height": 26, 1081 | "angle": 0, 1082 | "strokeColor": "#000000", 1083 | "backgroundColor": "transparent", 1084 | "fillStyle": "hachure", 1085 | "strokeWidth": 1, 1086 | "strokeStyle": "solid", 1087 | "roughness": 1, 1088 | "opacity": 100, 1089 | "seed": 701474405, 1090 | "version": 389, 1091 | "versionNonce": 1443400613, 1092 | "isDeleted": false, 1093 | "groupIds": [ 1094 | "3EVO1qEbVbVke0FrxXXr6" 1095 | ], 1096 | "text": "生态", 1097 | "fontSize": 20, 1098 | "fontFamily": 1, 1099 | "textAlign": "left", 1100 | "baseline": 21 1101 | }, 1102 | { 1103 | "id": "OpXG37DRRdNQ7NWky7FZl", 1104 | "type": "rectangle", 1105 | "x": 1272.672154017853, 1106 | "y": -160.9294084821429, 1107 | "width": 161.70703125, 1108 | "height": 52.98828125, 1109 | "angle": 0, 1110 | "strokeColor": "#000000", 1111 | "backgroundColor": "transparent", 1112 | "fillStyle": "hachure", 1113 | "strokeWidth": 1, 1114 | "strokeStyle": "solid", 1115 | "roughness": 1, 1116 | "opacity": 100, 1117 | "seed": 1856501029, 1118 | "version": 461, 1119 | "versionNonce": 1349144523, 1120 | "isDeleted": false, 1121 | "groupIds": [ 1122 | "VTsw_fOhKvSF9pNY7F4Zb", 1123 | "O6ukizvhkfXowMoxw4UtL" 1124 | ] 1125 | }, 1126 | { 1127 | "id": "jAR-VRzIZwbwfr2o8deVq", 1128 | "type": "text", 1129 | "x": 1333.525669642852, 1130 | "y": -147.4352678571429, 1131 | "width": 40, 1132 | "height": 26, 1133 | "angle": 0, 1134 | "strokeColor": "#000000", 1135 | "backgroundColor": "transparent", 1136 | "fillStyle": "hachure", 1137 | "strokeWidth": 1, 1138 | "strokeStyle": "solid", 1139 | "roughness": 1, 1140 | "opacity": 100, 1141 | "seed": 668539819, 1142 | "version": 510, 1143 | "versionNonce": 2113644133, 1144 | "isDeleted": false, 1145 | "groupIds": [ 1146 | "O6ukizvhkfXowMoxw4UtL" 1147 | ], 1148 | "text": "路由", 1149 | "fontSize": 20, 1150 | "fontFamily": 1, 1151 | "textAlign": "left", 1152 | "baseline": 21 1153 | }, 1154 | { 1155 | "id": "rLXXlqkadWgU4PbBE3Xx2", 1156 | "type": "rectangle", 1157 | "x": 1274.7480468749943, 1158 | "y": 26.375279017857054, 1159 | "width": 161.70703125, 1160 | "height": 52.98828125, 1161 | "angle": 0, 1162 | "strokeColor": "#000000", 1163 | "backgroundColor": "transparent", 1164 | "fillStyle": "hachure", 1165 | "strokeWidth": 1, 1166 | "strokeStyle": "solid", 1167 | "roughness": 1, 1168 | "opacity": 100, 1169 | "seed": 941594155, 1170 | "version": 410, 1171 | "versionNonce": 767827563, 1172 | "isDeleted": false, 1173 | "groupIds": [ 1174 | "I02BRj0cORoLNOj0iZ_2T", 1175 | "JVMd5xAtaX4PV1nVlEwW8" 1176 | ] 1177 | }, 1178 | { 1179 | "id": "LUNrL5uZC8LbdWaGeRIJp", 1180 | "type": "text", 1181 | "x": 1315.6015624999943, 1182 | "y": 39.86941964285705, 1183 | "width": 80, 1184 | "height": 26, 1185 | "angle": 0, 1186 | "strokeColor": "#000000", 1187 | "backgroundColor": "transparent", 1188 | "fillStyle": "hachure", 1189 | "strokeWidth": 1, 1190 | "strokeStyle": "solid", 1191 | "roughness": 1, 1192 | "opacity": 100, 1193 | "seed": 200046085, 1194 | "version": 472, 1195 | "versionNonce": 384012741, 1196 | "isDeleted": false, 1197 | "groupIds": [ 1198 | "JVMd5xAtaX4PV1nVlEwW8" 1199 | ], 1200 | "text": "状态管理", 1201 | "fontSize": 20, 1202 | "fontFamily": 1, 1203 | "textAlign": "left", 1204 | "baseline": 21 1205 | }, 1206 | { 1207 | "id": "Fr75y4krnaVxKcz1YrDF7", 1208 | "type": "rectangle", 1209 | "x": 737.2480468749998, 1210 | "y": -30.566685267857224, 1211 | "width": 161.70703125, 1212 | "height": 52.98828125, 1213 | "angle": 0, 1214 | "strokeColor": "#000000", 1215 | "backgroundColor": "transparent", 1216 | "fillStyle": "hachure", 1217 | "strokeWidth": 1, 1218 | "strokeStyle": "solid", 1219 | "roughness": 1, 1220 | "opacity": 100, 1221 | "seed": 107814987, 1222 | "version": 392, 1223 | "versionNonce": 1747654923, 1224 | "isDeleted": false, 1225 | "groupIds": [ 1226 | "aaw79ikHIBkiljWXMbdH6", 1227 | "gHdjXUzHCLPSjx8lg4Kx9" 1228 | ] 1229 | }, 1230 | { 1231 | "id": "qVLyoMJZ4vs7rL4J4Dwdz", 1232 | "type": "text", 1233 | "x": 778.1015624999998, 1234 | "y": -16.698660714285666, 1235 | "width": 80, 1236 | "height": 26, 1237 | "angle": 0, 1238 | "strokeColor": "#000000", 1239 | "backgroundColor": "transparent", 1240 | "fillStyle": "hachure", 1241 | "strokeWidth": 1, 1242 | "strokeStyle": "solid", 1243 | "roughness": 1, 1244 | "opacity": 100, 1245 | "seed": 984358373, 1246 | "version": 456, 1247 | "versionNonce": 1450643749, 1248 | "isDeleted": false, 1249 | "groupIds": [ 1250 | "gHdjXUzHCLPSjx8lg4Kx9" 1251 | ], 1252 | "text": "接口请求", 1253 | "fontSize": 20, 1254 | "fontFamily": 1, 1255 | "textAlign": "left", 1256 | "baseline": 21 1257 | }, 1258 | { 1259 | "id": "JJgWGAq3VRGkDrpnD1OyM", 1260 | "type": "rectangle", 1261 | "x": 1530.633091517854, 1262 | "y": -140.93387276785717, 1263 | "width": 161.70703125, 1264 | "height": 52.98828125, 1265 | "angle": 0, 1266 | "strokeColor": "#000000", 1267 | "backgroundColor": "transparent", 1268 | "fillStyle": "hachure", 1269 | "strokeWidth": 1, 1270 | "strokeStyle": "solid", 1271 | "roughness": 1, 1272 | "opacity": 100, 1273 | "seed": 883329227, 1274 | "version": 532, 1275 | "versionNonce": 1025097643, 1276 | "isDeleted": false, 1277 | "groupIds": [ 1278 | "q3slFLuQ2tzi0tThTCjBO", 1279 | "2WjtHjQ2cbWnxHTwKWsMz", 1280 | "NTO8qOYRmOhznxLGnL6Oz" 1281 | ] 1282 | }, 1283 | { 1284 | "id": "-SmtUASnLehuo5mrdzTV_", 1285 | "type": "text", 1286 | "x": 1562.486607142854, 1287 | "y": -127.81361607142861, 1288 | "width": 98, 1289 | "height": 26, 1290 | "angle": 0, 1291 | "strokeColor": "#000000", 1292 | "backgroundColor": "transparent", 1293 | "fillStyle": "hachure", 1294 | "strokeWidth": 1, 1295 | "strokeStyle": "solid", 1296 | "roughness": 1, 1297 | "opacity": 100, 1298 | "seed": 897285477, 1299 | "version": 606, 1300 | "versionNonce": 170108037, 1301 | "isDeleted": false, 1302 | "groupIds": [ 1303 | "NTO8qOYRmOhznxLGnL6Oz" 1304 | ], 1305 | "text": "Reach Router", 1306 | "fontSize": 20, 1307 | "fontFamily": 1, 1308 | "textAlign": "left", 1309 | "baseline": 21 1310 | }, 1311 | { 1312 | "id": "RJ2ZIZYjLCW8lH3FUi205", 1313 | "type": "rectangle", 1314 | "x": 1515.1420200892833, 1315 | "y": -254.21512276785717, 1316 | "width": 161.70703125, 1317 | "height": 52.98828125, 1318 | "angle": 0, 1319 | "strokeColor": "#000000", 1320 | "backgroundColor": "transparent", 1321 | "fillStyle": "hachure", 1322 | "strokeWidth": 1, 1323 | "strokeStyle": "solid", 1324 | "roughness": 1, 1325 | "opacity": 100, 1326 | "seed": 269563755, 1327 | "version": 433, 1328 | "versionNonce": 1455067723, 1329 | "isDeleted": false, 1330 | "groupIds": [ 1331 | "99oA-H59ARekkYkleek__", 1332 | "TCJmnBHLqnNERfbsywxgJ" 1333 | ] 1334 | }, 1335 | { 1336 | "id": "ccNHziGYaXy9WFi5q6cbg", 1337 | "type": "text", 1338 | "x": 1545.9955357142833, 1339 | "y": -240.72098214285717, 1340 | "width": 100, 1341 | "height": 26, 1342 | "angle": 0, 1343 | "strokeColor": "#000000", 1344 | "backgroundColor": "transparent", 1345 | "fillStyle": "hachure", 1346 | "strokeWidth": 1, 1347 | "strokeStyle": "solid", 1348 | "roughness": 1, 1349 | "opacity": 100, 1350 | "seed": 508594373, 1351 | "version": 521, 1352 | "versionNonce": 1973865445, 1353 | "isDeleted": false, 1354 | "groupIds": [], 1355 | "text": "React Router", 1356 | "fontSize": 20, 1357 | "fontFamily": 1, 1358 | "textAlign": "left", 1359 | "baseline": 21 1360 | }, 1361 | { 1362 | "id": "3UfVx38nwA7WBIXvGIwI7", 1363 | "type": "draw", 1364 | "x": 994.2544642857135, 1365 | "y": 131.71540178571422, 1366 | "width": 238.61049107142856, 1367 | "height": 236.93080357142856, 1368 | "angle": 0, 1369 | "strokeColor": "#000000", 1370 | "backgroundColor": "transparent", 1371 | "fillStyle": "hachure", 1372 | "strokeWidth": 1, 1373 | "strokeStyle": "solid", 1374 | "roughness": 1, 1375 | "opacity": 100, 1376 | "seed": 1736386533, 1377 | "version": 221, 1378 | "versionNonce": 904401131, 1379 | "isDeleted": false, 1380 | "groupIds": [], 1381 | "points": [ 1382 | [ 1383 | 0, 1384 | 0 1385 | ], 1386 | [ 1387 | 0, 1388 | -15.5859375 1389 | ], 1390 | [ 1391 | 8.454241071428555, 1392 | -35.8203125 1393 | ], 1394 | [ 1395 | 43.7109375, 1396 | -91.67410714285717 1397 | ], 1398 | [ 1399 | 90.05580357142856, 1400 | -142.68415178571428 1401 | ], 1402 | [ 1403 | 133.77232142857144, 1404 | -179.7265625 1405 | ], 1406 | [ 1407 | 226.86383928571433, 1408 | -235.57477678571428 1409 | ], 1410 | [ 1411 | 238.61049107142856, 1412 | -236.93080357142856 1413 | ] 1414 | ], 1415 | "lastCommittedPoint": null 1416 | }, 1417 | { 1418 | "id": "9kKojct7HUXMi6Fb6Ovfd", 1419 | "type": "draw", 1420 | "x": 1218.713169642854, 1421 | "y": -120.39397321428578, 1422 | "width": 32.29910714285734, 1423 | "height": 26.724330357142833, 1424 | "angle": 0, 1425 | "strokeColor": "#000000", 1426 | "backgroundColor": "transparent", 1427 | "fillStyle": "hachure", 1428 | "strokeWidth": 1, 1429 | "strokeStyle": "solid", 1430 | "roughness": 1, 1431 | "opacity": 100, 1432 | "seed": 186923589, 1433 | "version": 189, 1434 | "versionNonce": 151914309, 1435 | "isDeleted": false, 1436 | "groupIds": [], 1437 | "points": [ 1438 | [ 1439 | 0, 1440 | 0 1441 | ], 1442 | [ 1443 | 18.59375, 1444 | 0.033482142857110375 1445 | ], 1446 | [ 1447 | 32.29910714285734, 1448 | 10.3125 1449 | ], 1450 | [ 1451 | 13.074776785714448, 1452 | 26.724330357142833 1453 | ] 1454 | ], 1455 | "lastCommittedPoint": null 1456 | }, 1457 | { 1458 | "id": "RlZox4f8h4yBHQI9q4naZ", 1459 | "type": "arrow", 1460 | "x": 1454.537293220356, 1461 | "y": -174.4021296790935, 1462 | "width": 53.89127820821227, 1463 | "height": 26.159254249478025, 1464 | "angle": 0, 1465 | "strokeColor": "#000000", 1466 | "backgroundColor": "transparent", 1467 | "fillStyle": "hachure", 1468 | "strokeWidth": 1, 1469 | "strokeStyle": "solid", 1470 | "roughness": 1, 1471 | "opacity": 100, 1472 | "seed": 2109149675, 1473 | "version": 186, 1474 | "versionNonce": 1546435467, 1475 | "isDeleted": false, 1476 | "groupIds": [], 1477 | "points": [ 1478 | [ 1479 | 0, 1480 | 0 1481 | ], 1482 | [ 1483 | 53.89127820821227, 1484 | -26.159254249478025 1485 | ] 1486 | ], 1487 | "lastCommittedPoint": null 1488 | }, 1489 | { 1490 | "id": "bC7YPL-HOz6t1SxP76ANm", 1491 | "type": "arrow", 1492 | "x": 1470.359374999997, 1493 | "y": -116.1473214285715, 1494 | "width": 45.60267857142844, 1495 | "height": 0.22879464285716722, 1496 | "angle": 0, 1497 | "strokeColor": "#000000", 1498 | "backgroundColor": "transparent", 1499 | "fillStyle": "hachure", 1500 | "strokeWidth": 1, 1501 | "strokeStyle": "solid", 1502 | "roughness": 1, 1503 | "opacity": 100, 1504 | "seed": 1276662949, 1505 | "version": 165, 1506 | "versionNonce": 1454823077, 1507 | "isDeleted": false, 1508 | "groupIds": [], 1509 | "points": [ 1510 | [ 1511 | 0, 1512 | 0 1513 | ], 1514 | [ 1515 | 45.60267857142844, 1516 | 0.22879464285716722 1517 | ] 1518 | ], 1519 | "lastCommittedPoint": null 1520 | }, 1521 | { 1522 | "id": "46kW80vemtlBhZDj5nvz5", 1523 | "type": "rectangle", 1524 | "x": 1523.6241629464237, 1525 | "y": -43.082310267857224, 1526 | "width": 161.70703125, 1527 | "height": 52.98828125, 1528 | "angle": 0, 1529 | "strokeColor": "#000000", 1530 | "backgroundColor": "transparent", 1531 | "fillStyle": "hachure", 1532 | "strokeWidth": 1, 1533 | "strokeStyle": "solid", 1534 | "roughness": 1, 1535 | "opacity": 100, 1536 | "seed": 724121573, 1537 | "version": 591, 1538 | "versionNonce": 901976619, 1539 | "isDeleted": false, 1540 | "groupIds": [ 1541 | "NqbEQNVZ6B8nyChiorbyo", 1542 | "bPeT0e6ir45mi1qP4tYJE", 1543 | "TLN35sFQzshpT8zlcEA_B", 1544 | "TiggRlLr7Ka-MEksthVmV" 1545 | ] 1546 | }, 1547 | { 1548 | "id": "2aBbr34cT1Ti31eCJil9S", 1549 | "type": "text", 1550 | "x": 1583.4776785714237, 1551 | "y": -29.96205357142867, 1552 | "width": 42, 1553 | "height": 26, 1554 | "angle": 0, 1555 | "strokeColor": "#000000", 1556 | "backgroundColor": "transparent", 1557 | "fillStyle": "hachure", 1558 | "strokeWidth": 1, 1559 | "strokeStyle": "solid", 1560 | "roughness": 1, 1561 | "opacity": 100, 1562 | "seed": 1628595435, 1563 | "version": 673, 1564 | "versionNonce": 1229896197, 1565 | "isDeleted": false, 1566 | "groupIds": [ 1567 | "TiggRlLr7Ka-MEksthVmV" 1568 | ], 1569 | "text": "Redux", 1570 | "fontSize": 20, 1571 | "fontFamily": 1, 1572 | "textAlign": "left", 1573 | "baseline": 21 1574 | }, 1575 | { 1576 | "id": "cG24fwWqeKNXsc5cgaS2a", 1577 | "type": "rectangle", 1578 | "x": 1524.182198660709, 1579 | "y": 52.905412946428555, 1580 | "width": 161.70703125, 1581 | "height": 52.98828125, 1582 | "angle": 0, 1583 | "strokeColor": "#000000", 1584 | "backgroundColor": "transparent", 1585 | "fillStyle": "hachure", 1586 | "strokeWidth": 1, 1587 | "strokeStyle": "solid", 1588 | "roughness": 1, 1589 | "opacity": 100, 1590 | "seed": 834570603, 1591 | "version": 615, 1592 | "versionNonce": 1133876427, 1593 | "isDeleted": false, 1594 | "groupIds": [ 1595 | "TTg_6EWQfFwMaBdDX0JMt", 1596 | "nIwzCMCF-IQjeLFck2b3j", 1597 | "GF-byFMBa8s3T1A4pHkxA", 1598 | "bT-0apZbrpFyogXumGKN5" 1599 | ] 1600 | }, 1601 | { 1602 | "id": "0SHw7mgvFFVGH1qqspWKv", 1603 | "type": "text", 1604 | "x": 1588.1618303571374, 1605 | "y": 66.02566964285711, 1606 | "width": 33, 1607 | "height": 26, 1608 | "angle": 0, 1609 | "strokeColor": "#000000", 1610 | "backgroundColor": "transparent", 1611 | "fillStyle": "hachure", 1612 | "strokeWidth": 1, 1613 | "strokeStyle": "solid", 1614 | "roughness": 1, 1615 | "opacity": 100, 1616 | "seed": 911824581, 1617 | "version": 705, 1618 | "versionNonce": 433271141, 1619 | "isDeleted": false, 1620 | "groupIds": [ 1621 | "bT-0apZbrpFyogXumGKN5" 1622 | ], 1623 | "text": "Mobx", 1624 | "fontSize": 20, 1625 | "fontFamily": 1, 1626 | "textAlign": "left", 1627 | "baseline": 21 1628 | }, 1629 | { 1630 | "id": "LjOA4xlfTlKsDK2AUvVbU", 1631 | "type": "rectangle", 1632 | "x": 1525.3763950892805, 1633 | "y": 139.16099330357144, 1634 | "width": 161.70703125, 1635 | "height": 52.98828125, 1636 | "angle": 0, 1637 | "strokeColor": "#000000", 1638 | "backgroundColor": "transparent", 1639 | "fillStyle": "hachure", 1640 | "strokeWidth": 1, 1641 | "strokeStyle": "solid", 1642 | "roughness": 1, 1643 | "opacity": 100, 1644 | "seed": 1216765899, 1645 | "version": 656, 1646 | "versionNonce": 87999339, 1647 | "isDeleted": false, 1648 | "groupIds": [ 1649 | "j80jlMwuNzJUyFN52Chd9", 1650 | "3tQPyVlwe41LKgMrEvK_0", 1651 | "3nYtE9qbwBLcb_9LY1fIy", 1652 | "UJdUIDO8KyECqtiPgL_Uw" 1653 | ] 1654 | }, 1655 | { 1656 | "id": "BC8qbM3ACI9bkfdXaLDCc", 1657 | "type": "text", 1658 | "x": 1550.2299107142805, 1659 | "y": 151.90736607142856, 1660 | "width": 112, 1661 | "height": 26, 1662 | "angle": 0, 1663 | "strokeColor": "#000000", 1664 | "backgroundColor": "transparent", 1665 | "fillStyle": "hachure", 1666 | "strokeWidth": 1, 1667 | "strokeStyle": "solid", 1668 | "roughness": 1, 1669 | "opacity": 100, 1670 | "seed": 828937829, 1671 | "version": 755, 1672 | "versionNonce": 93437125, 1673 | "isDeleted": false, 1674 | "groupIds": [ 1675 | "UJdUIDO8KyECqtiPgL_Uw" 1676 | ], 1677 | "text": "React Context", 1678 | "fontSize": 20, 1679 | "fontFamily": 1, 1680 | "textAlign": "left", 1681 | "baseline": 21 1682 | }, 1683 | { 1684 | "id": "hK-Tunpem7msTj1k8eIFG", 1685 | "type": "rectangle", 1686 | "x": 1529.7123325892833, 1687 | "y": 226.677734375, 1688 | "width": 161.70703125, 1689 | "height": 52.98828125, 1690 | "angle": 0, 1691 | "strokeColor": "#000000", 1692 | "backgroundColor": "transparent", 1693 | "fillStyle": "hachure", 1694 | "strokeWidth": 1, 1695 | "strokeStyle": "solid", 1696 | "roughness": 1, 1697 | "opacity": 100, 1698 | "seed": 753270661, 1699 | "version": 634, 1700 | "versionNonce": 587800075, 1701 | "isDeleted": false, 1702 | "groupIds": [ 1703 | "ZL4ano5OnGAH9A1c-OrpV", 1704 | "Rd3am8nY2Dff2zzQMOXTH", 1705 | "bOr0adnO9P_RHomvE7QWv", 1706 | "L_gHrs2spIjn7NPFixqQQ" 1707 | ] 1708 | }, 1709 | { 1710 | "id": "krz75F5eXn2iu1HW6hVhT", 1711 | "type": "text", 1712 | "x": 1589.1975446428548, 1713 | "y": 240.16629464285705, 1714 | "width": 42, 1715 | "height": 26, 1716 | "angle": 0, 1717 | "strokeColor": "#000000", 1718 | "backgroundColor": "transparent", 1719 | "fillStyle": "hachure", 1720 | "strokeWidth": 1, 1721 | "strokeStyle": "solid", 1722 | "roughness": 1, 1723 | "opacity": 100, 1724 | "seed": 2082432843, 1725 | "version": 726, 1726 | "versionNonce": 1143462949, 1727 | "isDeleted": false, 1728 | "groupIds": [ 1729 | "L_gHrs2spIjn7NPFixqQQ" 1730 | ], 1731 | "text": "Recoil", 1732 | "fontSize": 20, 1733 | "fontFamily": 1, 1734 | "textAlign": "left", 1735 | "baseline": 21 1736 | }, 1737 | { 1738 | "id": "CCL-QcDsDN_9CQcB8SgtX", 1739 | "type": "arrow", 1740 | "x": 1453.757812499997, 1741 | "y": 23.90290178571422, 1742 | "width": 47.82366071428555, 1743 | "height": 17.354910714285722, 1744 | "angle": 0, 1745 | "strokeColor": "#000000", 1746 | "backgroundColor": "transparent", 1747 | "fillStyle": "hachure", 1748 | "strokeWidth": 1, 1749 | "strokeStyle": "solid", 1750 | "roughness": 1, 1751 | "opacity": 100, 1752 | "seed": 1975780267, 1753 | "version": 153, 1754 | "versionNonce": 1475290283, 1755 | "isDeleted": false, 1756 | "groupIds": [], 1757 | "points": [ 1758 | [ 1759 | 0, 1760 | 0 1761 | ], 1762 | [ 1763 | 47.82366071428555, 1764 | -17.354910714285722 1765 | ] 1766 | ], 1767 | "lastCommittedPoint": null 1768 | }, 1769 | { 1770 | "id": "CsTtvE6066J2JXuikWTGh", 1771 | "type": "arrow", 1772 | "x": 1458.1104910714255, 1773 | "y": 67.39062499999994, 1774 | "width": 43.34821428571422, 1775 | "height": 2.717633928571445, 1776 | "angle": 0, 1777 | "strokeColor": "#000000", 1778 | "backgroundColor": "transparent", 1779 | "fillStyle": "hachure", 1780 | "strokeWidth": 1, 1781 | "strokeStyle": "solid", 1782 | "roughness": 1, 1783 | "opacity": 100, 1784 | "seed": 1416673477, 1785 | "version": 158, 1786 | "versionNonce": 1031999365, 1787 | "isDeleted": false, 1788 | "groupIds": [], 1789 | "points": [ 1790 | [ 1791 | 0, 1792 | 0 1793 | ], 1794 | [ 1795 | 43.34821428571422, 1796 | 2.717633928571445 1797 | ] 1798 | ], 1799 | "lastCommittedPoint": null 1800 | }, 1801 | { 1802 | "id": "rZFGRKPbO_hmexAQI7J7Y", 1803 | "type": "arrow", 1804 | "x": 1446.9888392857108, 1805 | "y": 111.64285714285711, 1806 | "width": 49.13504464285711, 1807 | "height": 43.454241071428555, 1808 | "angle": 0, 1809 | "strokeColor": "#000000", 1810 | "backgroundColor": "transparent", 1811 | "fillStyle": "hachure", 1812 | "strokeWidth": 1, 1813 | "strokeStyle": "solid", 1814 | "roughness": 1, 1815 | "opacity": 100, 1816 | "seed": 1233199909, 1817 | "version": 165, 1818 | "versionNonce": 463165259, 1819 | "isDeleted": false, 1820 | "groupIds": [], 1821 | "points": [ 1822 | [ 1823 | 0, 1824 | 0 1825 | ], 1826 | [ 1827 | 49.13504464285711, 1828 | 43.454241071428555 1829 | ] 1830 | ], 1831 | "lastCommittedPoint": null 1832 | }, 1833 | { 1834 | "id": "iCsJjf0rBG34btK-JRifE", 1835 | "type": "arrow", 1836 | "x": 1408.5401785714255, 1837 | "y": 117.17299107142856, 1838 | "width": 92.13169642857156, 1839 | "height": 123.21428571428567, 1840 | "angle": 0, 1841 | "strokeColor": "#000000", 1842 | "backgroundColor": "transparent", 1843 | "fillStyle": "hachure", 1844 | "strokeWidth": 1, 1845 | "strokeStyle": "solid", 1846 | "roughness": 1, 1847 | "opacity": 100, 1848 | "seed": 1546716459, 1849 | "version": 171, 1850 | "versionNonce": 2145441509, 1851 | "isDeleted": false, 1852 | "groupIds": [], 1853 | "points": [ 1854 | [ 1855 | 0, 1856 | 0 1857 | ], 1858 | [ 1859 | 92.13169642857156, 1860 | 123.21428571428567 1861 | ] 1862 | ], 1863 | "lastCommittedPoint": null 1864 | }, 1865 | { 1866 | "id": "MISZk_q7euyqbv6fbNLyV", 1867 | "type": "arrow", 1868 | "x": 1085.9229910714255, 1869 | "y": 139.51116071428567, 1870 | "width": 145.2678571428571, 1871 | "height": 69.765625, 1872 | "angle": 0, 1873 | "strokeColor": "#000000", 1874 | "backgroundColor": "transparent", 1875 | "fillStyle": "hachure", 1876 | "strokeWidth": 1, 1877 | "strokeStyle": "solid", 1878 | "roughness": 1, 1879 | "opacity": 100, 1880 | "seed": 275500843, 1881 | "version": 179, 1882 | "versionNonce": 208156139, 1883 | "isDeleted": false, 1884 | "groupIds": [], 1885 | "points": [ 1886 | [ 1887 | 0, 1888 | 0 1889 | ], 1890 | [ 1891 | 145.2678571428571, 1892 | -69.765625 1893 | ] 1894 | ], 1895 | "lastCommittedPoint": null 1896 | }, 1897 | { 1898 | "id": "B8gf-l1uQF3Gkx4KctPjh", 1899 | "type": "arrow", 1900 | "x": 903.7667410714278, 1901 | "y": 125.70870535714278, 1902 | "width": 58.454241071428555, 1903 | "height": 83.984375, 1904 | "angle": 0, 1905 | "strokeColor": "#000000", 1906 | "backgroundColor": "transparent", 1907 | "fillStyle": "hachure", 1908 | "strokeWidth": 1, 1909 | "strokeStyle": "solid", 1910 | "roughness": 1, 1911 | "opacity": 100, 1912 | "seed": 35907525, 1913 | "version": 172, 1914 | "versionNonce": 1976480325, 1915 | "isDeleted": false, 1916 | "groupIds": [], 1917 | "points": [ 1918 | [ 1919 | 0, 1920 | 0 1921 | ], 1922 | [ 1923 | -58.454241071428555, 1924 | -83.984375 1925 | ] 1926 | ], 1927 | "lastCommittedPoint": null 1928 | }, 1929 | { 1930 | "id": "7Xb1Ms4QptqpLzcUBKvr_", 1931 | "type": "rectangle", 1932 | "x": 505.5114397321415, 1933 | "y": -139.95619419642864, 1934 | "width": 161.70703125, 1935 | "height": 52.98828125, 1936 | "angle": 0, 1937 | "strokeColor": "#000000", 1938 | "backgroundColor": "transparent", 1939 | "fillStyle": "hachure", 1940 | "strokeWidth": 1, 1941 | "strokeStyle": "solid", 1942 | "roughness": 1, 1943 | "opacity": 100, 1944 | "seed": 1543656363, 1945 | "version": 398, 1946 | "versionNonce": 425738379, 1947 | "isDeleted": false, 1948 | "groupIds": [ 1949 | "Ipumnp_nfAUrSYTjNyzUE", 1950 | "YeCatkDJHlH-I1VK9a33I" 1951 | ] 1952 | }, 1953 | { 1954 | "id": "joJquB7MIQWTSiqtuOWYp", 1955 | "type": "text", 1956 | "x": 568.3649553571415, 1957 | "y": -126.08816964285708, 1958 | "width": 36, 1959 | "height": 26, 1960 | "angle": 0, 1961 | "strokeColor": "#000000", 1962 | "backgroundColor": "transparent", 1963 | "fillStyle": "hachure", 1964 | "strokeWidth": 1, 1965 | "strokeStyle": "solid", 1966 | "roughness": 1, 1967 | "opacity": 100, 1968 | "seed": 448680069, 1969 | "version": 470, 1970 | "versionNonce": 1546264997, 1971 | "isDeleted": false, 1972 | "groupIds": [], 1973 | "text": "axios", 1974 | "fontSize": 20, 1975 | "fontFamily": 1, 1976 | "textAlign": "left", 1977 | "baseline": 21 1978 | }, 1979 | { 1980 | "id": "Lzi2q0GLlDuX-CHLEMM64", 1981 | "type": "rectangle", 1982 | "x": 705.8741629464273, 1983 | "y": -212.11021205357144, 1984 | "width": 161.70703125, 1985 | "height": 52.98828125, 1986 | "angle": 0, 1987 | "strokeColor": "#000000", 1988 | "backgroundColor": "transparent", 1989 | "fillStyle": "hachure", 1990 | "strokeWidth": 1, 1991 | "strokeStyle": "solid", 1992 | "roughness": 1, 1993 | "opacity": 100, 1994 | "seed": 1725628875, 1995 | "version": 485, 1996 | "versionNonce": 1816000299, 1997 | "isDeleted": false, 1998 | "groupIds": [ 1999 | "0ni9TwcpElbKDkqdqhjIe", 2000 | "XpRQxxCvvBVxS4Bqfp-Sy" 2001 | ] 2002 | }, 2003 | { 2004 | "id": "bUZ2T8i0wQ-clDyggw2i9", 2005 | "type": "text", 2006 | "x": 743.2276785714273, 2007 | "y": -198.24218749999994, 2008 | "width": 87, 2009 | "height": 26, 2010 | "angle": 0, 2011 | "strokeColor": "#000000", 2012 | "backgroundColor": "transparent", 2013 | "fillStyle": "hachure", 2014 | "strokeWidth": 1, 2015 | "strokeStyle": "solid", 2016 | "roughness": 1, 2017 | "opacity": 100, 2018 | "seed": 1235686501, 2019 | "version": 563, 2020 | "versionNonce": 2015405317, 2021 | "isDeleted": false, 2022 | "groupIds": [], 2023 | "text": "react query", 2024 | "fontSize": 20, 2025 | "fontFamily": 1, 2026 | "textAlign": "left", 2027 | "baseline": 21 2028 | }, 2029 | { 2030 | "id": "IZsb70nUuJCKtBksGWoiX", 2031 | "type": "rectangle", 2032 | "x": 917.0516183035709, 2033 | "y": -152.60686383928584, 2034 | "width": 161.70703125, 2035 | "height": 52.98828125, 2036 | "angle": 0, 2037 | "strokeColor": "#000000", 2038 | "backgroundColor": "transparent", 2039 | "fillStyle": "hachure", 2040 | "strokeWidth": 1, 2041 | "strokeStyle": "solid", 2042 | "roughness": 1, 2043 | "opacity": 100, 2044 | "seed": 1752372907, 2045 | "version": 425, 2046 | "versionNonce": 325835211, 2047 | "isDeleted": false, 2048 | "groupIds": [ 2049 | "HtPZm5a5Z8YzH32BEJpyl", 2050 | "EM3UHykhi4dFjkSOWeQBp" 2051 | ] 2052 | }, 2053 | { 2054 | "id": "kcrp1NiwM7byXfo8gXoDC", 2055 | "type": "text", 2056 | "x": 984.9051339285709, 2057 | "y": -138.73883928571428, 2058 | "width": 26, 2059 | "height": 26, 2060 | "angle": 0, 2061 | "strokeColor": "#000000", 2062 | "backgroundColor": "transparent", 2063 | "fillStyle": "hachure", 2064 | "strokeWidth": 1, 2065 | "strokeStyle": "solid", 2066 | "roughness": 1, 2067 | "opacity": 100, 2068 | "seed": 1559182725, 2069 | "version": 495, 2070 | "versionNonce": 221232229, 2071 | "isDeleted": false, 2072 | "groupIds": [], 2073 | "text": "swr", 2074 | "fontSize": 20, 2075 | "fontFamily": 1, 2076 | "textAlign": "left", 2077 | "baseline": 21 2078 | }, 2079 | { 2080 | "id": "rKy8XymRIkf9pkVnIpq--", 2081 | "type": "arrow", 2082 | "x": 714.5513392857135, 2083 | "y": -18.8191964285715, 2084 | "width": 74.85491071428578, 2085 | "height": 31.9140625, 2086 | "angle": 0, 2087 | "strokeColor": "#000000", 2088 | "backgroundColor": "transparent", 2089 | "fillStyle": "hachure", 2090 | "strokeWidth": 1, 2091 | "strokeStyle": "solid", 2092 | "roughness": 1, 2093 | "opacity": 100, 2094 | "seed": 140068427, 2095 | "version": 89, 2096 | "versionNonce": 1812228203, 2097 | "isDeleted": false, 2098 | "groupIds": [], 2099 | "points": [ 2100 | [ 2101 | 0, 2102 | 0 2103 | ], 2104 | [ 2105 | -74.85491071428578, 2106 | -31.9140625 2107 | ] 2108 | ], 2109 | "lastCommittedPoint": null 2110 | }, 2111 | { 2112 | "id": "vz_VD0a5-QH_0ptUQSJ9g", 2113 | "type": "arrow", 2114 | "x": 798.2734374999993, 2115 | "y": -52.6082589285715, 2116 | "width": 3.258928571428555, 2117 | "height": 74.6875, 2118 | "angle": 0, 2119 | "strokeColor": "#000000", 2120 | "backgroundColor": "transparent", 2121 | "fillStyle": "hachure", 2122 | "strokeWidth": 1, 2123 | "strokeStyle": "solid", 2124 | "roughness": 1, 2125 | "opacity": 100, 2126 | "seed": 2054101893, 2127 | "version": 172, 2128 | "versionNonce": 321185733, 2129 | "isDeleted": false, 2130 | "groupIds": [], 2131 | "points": [ 2132 | [ 2133 | 0, 2134 | 0 2135 | ], 2136 | [ 2137 | -3.258928571428555, 2138 | -74.6875 2139 | ] 2140 | ], 2141 | "lastCommittedPoint": null 2142 | }, 2143 | { 2144 | "id": "xojT-Sbm9xpPzxaIhia1J", 2145 | "type": "arrow", 2146 | "x": 874.333705357142, 2147 | "y": -49.845982142857224, 2148 | "width": 57.93526785714289, 2149 | "height": 26.690848214285722, 2150 | "angle": 0, 2151 | "strokeColor": "#000000", 2152 | "backgroundColor": "transparent", 2153 | "fillStyle": "hachure", 2154 | "strokeWidth": 1, 2155 | "strokeStyle": "solid", 2156 | "roughness": 1, 2157 | "opacity": 100, 2158 | "seed": 159707525, 2159 | "version": 167, 2160 | "versionNonce": 1272062731, 2161 | "isDeleted": false, 2162 | "groupIds": [], 2163 | "points": [ 2164 | [ 2165 | 0, 2166 | 0 2167 | ], 2168 | [ 2169 | 57.93526785714289, 2170 | -26.690848214285722 2171 | ] 2172 | ], 2173 | "lastCommittedPoint": null 2174 | }, 2175 | { 2176 | "id": "TRzrP0sdYVkCpa6KXoQ6A", 2177 | "type": "arrow", 2178 | "x": 676.859375, 2179 | "y": 408.81026785714283, 2180 | "width": 71.59040178571422, 2181 | "height": 48.33705357142861, 2182 | "angle": 0, 2183 | "strokeColor": "#000000", 2184 | "backgroundColor": "transparent", 2185 | "fillStyle": "hachure", 2186 | "strokeWidth": 1, 2187 | "strokeStyle": "solid", 2188 | "roughness": 1, 2189 | "opacity": 100, 2190 | "seed": 1392353541, 2191 | "version": 26, 2192 | "versionNonce": 1800374699, 2193 | "isDeleted": false, 2194 | "groupIds": [], 2195 | "points": [ 2196 | [ 2197 | 0, 2198 | 0 2199 | ], 2200 | [ 2201 | 71.59040178571422, 2202 | 48.33705357142861 2203 | ] 2204 | ], 2205 | "lastCommittedPoint": null 2206 | }, 2207 | { 2208 | "id": "0A1-LExkCVydh_jZ2FDW7", 2209 | "type": "arrow", 2210 | "x": 598.4162946428571, 2211 | "y": 415.50111607142856, 2212 | "width": 19.50334821428578, 2213 | "height": 51.96428571428572, 2214 | "angle": 0, 2215 | "strokeColor": "#000000", 2216 | "backgroundColor": "transparent", 2217 | "fillStyle": "hachure", 2218 | "strokeWidth": 1, 2219 | "strokeStyle": "solid", 2220 | "roughness": 1, 2221 | "opacity": 100, 2222 | "seed": 749670085, 2223 | "version": 20, 2224 | "versionNonce": 1518828165, 2225 | "isDeleted": false, 2226 | "groupIds": [], 2227 | "points": [ 2228 | [ 2229 | 0, 2230 | 0 2231 | ], 2232 | [ 2233 | -19.50334821428578, 2234 | 51.96428571428572 2235 | ] 2236 | ], 2237 | "lastCommittedPoint": null 2238 | }, 2239 | { 2240 | "id": "Ds-yxYmnInSBCZB6OyUFg", 2241 | "type": "arrow", 2242 | "x": 512.7299107142857, 2243 | "y": 410.85825892857144, 2244 | "width": 114.40290178571422, 2245 | "height": 61.20535714285711, 2246 | "angle": 0, 2247 | "strokeColor": "#000000", 2248 | "backgroundColor": "transparent", 2249 | "fillStyle": "hachure", 2250 | "strokeWidth": 1, 2251 | "strokeStyle": "solid", 2252 | "roughness": 1, 2253 | "opacity": 100, 2254 | "seed": 1809665637, 2255 | "version": 32, 2256 | "versionNonce": 262609995, 2257 | "isDeleted": false, 2258 | "groupIds": [], 2259 | "points": [ 2260 | [ 2261 | 0, 2262 | 0 2263 | ], 2264 | [ 2265 | -114.40290178571422, 2266 | 61.20535714285711 2267 | ] 2268 | ], 2269 | "lastCommittedPoint": null 2270 | }, 2271 | { 2272 | "id": "EUF2BTAqnua2jY--XeTip", 2273 | "type": "arrow", 2274 | "x": 647.8046875, 2275 | "y": 311.9185267857143, 2276 | "width": 205.4296875, 2277 | "height": 117.03683035714283, 2278 | "angle": 0, 2279 | "strokeColor": "#000000", 2280 | "backgroundColor": "transparent", 2281 | "fillStyle": "hachure", 2282 | "strokeWidth": 1, 2283 | "strokeStyle": "solid", 2284 | "roughness": 1, 2285 | "opacity": 100, 2286 | "seed": 811728683, 2287 | "version": 57, 2288 | "versionNonce": 1998578149, 2289 | "isDeleted": false, 2290 | "groupIds": [], 2291 | "points": [ 2292 | [ 2293 | 0, 2294 | 0 2295 | ], 2296 | [ 2297 | 205.4296875, 2298 | -117.03683035714283 2299 | ] 2300 | ], 2301 | "lastCommittedPoint": null 2302 | }, 2303 | { 2304 | "id": "07FPp_S2J4TS5bl2cqbcA", 2305 | "type": "arrow", 2306 | "x": 1114, 2307 | "y": 215.94196428571428, 2308 | "width": 168.57700892857156, 2309 | "height": 53.32589285714289, 2310 | "angle": 0, 2311 | "strokeColor": "#000000", 2312 | "backgroundColor": "transparent", 2313 | "fillStyle": "hachure", 2314 | "strokeWidth": 1, 2315 | "strokeStyle": "solid", 2316 | "roughness": 1, 2317 | "opacity": 100, 2318 | "seed": 736932363, 2319 | "version": 28, 2320 | "versionNonce": 1957911275, 2321 | "isDeleted": false, 2322 | "groupIds": [], 2323 | "points": [ 2324 | [ 2325 | 0, 2326 | 0 2327 | ], 2328 | [ 2329 | 168.57700892857156, 2330 | 53.32589285714289 2331 | ] 2332 | ], 2333 | "lastCommittedPoint": null 2334 | }, 2335 | { 2336 | "id": "abdh4_w6EPEzKSKRKozQM", 2337 | "type": "rectangle", 2338 | "x": 1506.5750558035716, 2339 | "y": 402.4891183035715, 2340 | "width": 161.70703125, 2341 | "height": 52.98828125, 2342 | "angle": 0, 2343 | "strokeColor": "#000000", 2344 | "backgroundColor": "transparent", 2345 | "fillStyle": "hachure", 2346 | "strokeWidth": 1, 2347 | "strokeStyle": "solid", 2348 | "roughness": 1, 2349 | "opacity": 100, 2350 | "seed": 1899176299, 2351 | "version": 576, 2352 | "versionNonce": 1727290693, 2353 | "isDeleted": false, 2354 | "groupIds": [ 2355 | "GKjekNiLtXTOUP7unmTbq", 2356 | "XPA7OXQMljct_x7zp1VFQ" 2357 | ] 2358 | }, 2359 | { 2360 | "id": "3Ak6Kd5jIRY1OWn8HjI-3", 2361 | "type": "text", 2362 | "x": 1552.5546875, 2363 | "y": 416.35156250000006, 2364 | "width": 69, 2365 | "height": 26, 2366 | "angle": 0, 2367 | "strokeColor": "#000000", 2368 | "backgroundColor": "transparent", 2369 | "fillStyle": "hachure", 2370 | "strokeWidth": 1, 2371 | "strokeStyle": "solid", 2372 | "roughness": 1, 2373 | "opacity": 100, 2374 | "seed": 1209679557, 2375 | "version": 648, 2376 | "versionNonce": 1996408203, 2377 | "isDeleted": false, 2378 | "groupIds": [], 2379 | "text": "CSS-in-JS", 2380 | "fontSize": 20, 2381 | "fontFamily": 1, 2382 | "textAlign": "left", 2383 | "baseline": 21 2384 | }, 2385 | { 2386 | "id": "8PSBMIurljeBreMNEqtYv", 2387 | "type": "rectangle", 2388 | "x": 1501.3685825892849, 2389 | "y": 330.2290736607141, 2390 | "width": 161.70703125, 2391 | "height": 52.98828125, 2392 | "angle": 0, 2393 | "strokeColor": "#000000", 2394 | "backgroundColor": "transparent", 2395 | "fillStyle": "hachure", 2396 | "strokeWidth": 1, 2397 | "strokeStyle": "solid", 2398 | "roughness": 1, 2399 | "opacity": 100, 2400 | "seed": 214023179, 2401 | "version": 628, 2402 | "versionNonce": 291663013, 2403 | "isDeleted": false, 2404 | "groupIds": [ 2405 | "a-WRz5OU4-JJ37v8NLb2u", 2406 | "OaX_aV1covMM7rKbDANZ1" 2407 | ] 2408 | }, 2409 | { 2410 | "id": "wPTPCUl3loRXWIkNuYIjC", 2411 | "type": "text", 2412 | "x": 1542.2220982142849, 2413 | "y": 343.7232142857141, 2414 | "width": 80, 2415 | "height": 26, 2416 | "angle": 0, 2417 | "strokeColor": "#000000", 2418 | "backgroundColor": "transparent", 2419 | "fillStyle": "hachure", 2420 | "strokeWidth": 1, 2421 | "strokeStyle": "solid", 2422 | "roughness": 1, 2423 | "opacity": 100, 2424 | "seed": 1716526629, 2425 | "version": 711, 2426 | "versionNonce": 2109987883, 2427 | "isDeleted": false, 2428 | "groupIds": [], 2429 | "text": "传统方案", 2430 | "fontSize": 20, 2431 | "fontFamily": 1, 2432 | "textAlign": "left", 2433 | "baseline": 21 2434 | }, 2435 | { 2436 | "id": "IZP-Lq0gtVylLIl5EY9VV", 2437 | "type": "rectangle", 2438 | "x": 1520.1911272321424, 2439 | "y": 487.0817522321429, 2440 | "width": 161.70703125, 2441 | "height": 52.98828125, 2442 | "angle": 0, 2443 | "strokeColor": "#000000", 2444 | "backgroundColor": "transparent", 2445 | "fillStyle": "hachure", 2446 | "strokeWidth": 1, 2447 | "strokeStyle": "solid", 2448 | "roughness": 1, 2449 | "opacity": 100, 2450 | "seed": 233562693, 2451 | "version": 601, 2452 | "versionNonce": 370642949, 2453 | "isDeleted": false, 2454 | "groupIds": [ 2455 | "6ccvioLwsqaiVbH7rRG5y", 2456 | "jqvEXZp5pnFTwH-tL_lO7" 2457 | ] 2458 | }, 2459 | { 2460 | "id": "ldNJxFyTWelrsY2PgC27Z", 2461 | "type": "text", 2462 | "x": 1564.5446428571424, 2463 | "y": 500.5758928571429, 2464 | "width": 73, 2465 | "height": 26, 2466 | "angle": 0, 2467 | "strokeColor": "#000000", 2468 | "backgroundColor": "transparent", 2469 | "fillStyle": "hachure", 2470 | "strokeWidth": 1, 2471 | "strokeStyle": "solid", 2472 | "roughness": 1, 2473 | "opacity": 100, 2474 | "seed": 15601803, 2475 | "version": 670, 2476 | "versionNonce": 619519691, 2477 | "isDeleted": false, 2478 | "groupIds": [], 2479 | "text": "Atom CSS", 2480 | "fontSize": 20, 2481 | "fontFamily": 1, 2482 | "textAlign": "left", 2483 | "baseline": 21 2484 | }, 2485 | { 2486 | "id": "72NyIAbAFqe0eMIGDavfN", 2487 | "type": "arrow", 2488 | "x": 1456.853794642857, 2489 | "y": 342.61607142857144, 2490 | "width": 22.723214285714448, 2491 | "height": 9.977678571428555, 2492 | "angle": 0, 2493 | "strokeColor": "#000000", 2494 | "backgroundColor": "transparent", 2495 | "fillStyle": "hachure", 2496 | "strokeWidth": 1, 2497 | "strokeStyle": "solid", 2498 | "roughness": 1, 2499 | "opacity": 100, 2500 | "seed": 2145701413, 2501 | "version": 14, 2502 | "versionNonce": 1125205861, 2503 | "isDeleted": false, 2504 | "groupIds": [], 2505 | "points": [ 2506 | [ 2507 | 0, 2508 | 0 2509 | ], 2510 | [ 2511 | 22.723214285714448, 2512 | 9.977678571428555 2513 | ] 2514 | ], 2515 | "lastCommittedPoint": null 2516 | }, 2517 | { 2518 | "id": "g3M_RpAk0XHBjPruiLpuO", 2519 | "type": "arrow", 2520 | "x": 1419.080357142857, 2521 | "y": 371.6841517857143, 2522 | "width": 61.9140625, 2523 | "height": 42.08147321428572, 2524 | "angle": 0, 2525 | "strokeColor": "#000000", 2526 | "backgroundColor": "transparent", 2527 | "fillStyle": "hachure", 2528 | "strokeWidth": 1, 2529 | "strokeStyle": "solid", 2530 | "roughness": 1, 2531 | "opacity": 100, 2532 | "seed": 2113030091, 2533 | "version": 32, 2534 | "versionNonce": 655691115, 2535 | "isDeleted": false, 2536 | "groupIds": [], 2537 | "points": [ 2538 | [ 2539 | 0, 2540 | 0 2541 | ], 2542 | [ 2543 | 61.9140625, 2544 | 42.08147321428572 2545 | ] 2546 | ], 2547 | "lastCommittedPoint": null 2548 | }, 2549 | { 2550 | "id": "tbW6LRBmrXurcNmR4NzJ4", 2551 | "type": "arrow", 2552 | "x": 1383.2544642857142, 2553 | "y": 383.00669642857144, 2554 | "width": 105.2734375, 2555 | "height": 118.66629464285711, 2556 | "angle": 0, 2557 | "strokeColor": "#000000", 2558 | "backgroundColor": "transparent", 2559 | "fillStyle": "hachure", 2560 | "strokeWidth": 1, 2561 | "strokeStyle": "solid", 2562 | "roughness": 1, 2563 | "opacity": 100, 2564 | "seed": 653240741, 2565 | "version": 33, 2566 | "versionNonce": 1251807941, 2567 | "isDeleted": false, 2568 | "groupIds": [], 2569 | "points": [ 2570 | [ 2571 | 0, 2572 | 0 2573 | ], 2574 | [ 2575 | 105.2734375, 2576 | 118.66629464285711 2577 | ] 2578 | ], 2579 | "lastCommittedPoint": null 2580 | }, 2581 | { 2582 | "id": "1R95eVfVsIRmoX_FC6KXC", 2583 | "type": "arrow", 2584 | "x": 960.5558035714286, 2585 | "y": 239.31361607142856, 2586 | "width": 16.72433035714289, 2587 | "height": 31.037946428571445, 2588 | "angle": 0, 2589 | "strokeColor": "#000000", 2590 | "backgroundColor": "transparent", 2591 | "fillStyle": "hachure", 2592 | "strokeWidth": 1, 2593 | "strokeStyle": "solid", 2594 | "roughness": 1, 2595 | "opacity": 100, 2596 | "seed": 366471749, 2597 | "version": 18, 2598 | "versionNonce": 962097701, 2599 | "isDeleted": false, 2600 | "groupIds": [], 2601 | "points": [ 2602 | [ 2603 | 0, 2604 | 0 2605 | ], 2606 | [ 2607 | -16.72433035714289, 2608 | 31.037946428571445 2609 | ] 2610 | ], 2611 | "lastCommittedPoint": null 2612 | }, 2613 | { 2614 | "id": "-yfddn6ykwyOaGNkoHXrj", 2615 | "type": "rectangle", 2616 | "x": 805.1877790178564, 2617 | "y": 386.98800223214295, 2618 | "width": 161.70703125, 2619 | "height": 52.98828125, 2620 | "angle": 0, 2621 | "strokeColor": "#000000", 2622 | "backgroundColor": "transparent", 2623 | "fillStyle": "hachure", 2624 | "strokeWidth": 1, 2625 | "strokeStyle": "solid", 2626 | "roughness": 1, 2627 | "opacity": 100, 2628 | "seed": 1540138149, 2629 | "version": 300, 2630 | "versionNonce": 2084236971, 2631 | "isDeleted": false, 2632 | "groupIds": [ 2633 | "q_VdfHkMwqdjqO5Xl1mZK" 2634 | ] 2635 | }, 2636 | { 2637 | "id": "qJxwuQ4LIkKcDJSWvNRGo", 2638 | "type": "text", 2639 | "x": 859.5412946428564, 2640 | "y": 400.1082589285714, 2641 | "width": 53, 2642 | "height": 26, 2643 | "angle": 0, 2644 | "strokeColor": "#000000", 2645 | "backgroundColor": "transparent", 2646 | "fillStyle": "hachure", 2647 | "strokeWidth": 1, 2648 | "strokeStyle": "solid", 2649 | "roughness": 1, 2650 | "opacity": 100, 2651 | "seed": 272180267, 2652 | "version": 372, 2653 | "versionNonce": 741401989, 2654 | "isDeleted": false, 2655 | "groupIds": [], 2656 | "text": "nest.js", 2657 | "fontSize": 20, 2658 | "fontFamily": 1, 2659 | "textAlign": "left", 2660 | "baseline": 21 2661 | }, 2662 | { 2663 | "id": "PYPRBrPSOtSdZU5p1-VqF", 2664 | "type": "arrow", 2665 | "x": 935.03125, 2666 | "y": 354.78794642857144, 2667 | "width": 19.65401785714289, 2668 | "height": 25.485491071428555, 2669 | "angle": 0, 2670 | "strokeColor": "#000000", 2671 | "backgroundColor": "transparent", 2672 | "fillStyle": "hachure", 2673 | "strokeWidth": 1, 2674 | "strokeStyle": "solid", 2675 | "roughness": 1, 2676 | "opacity": 100, 2677 | "seed": 456248811, 2678 | "version": 26, 2679 | "versionNonce": 1180953829, 2680 | "isDeleted": false, 2681 | "groupIds": [], 2682 | "points": [ 2683 | [ 2684 | 0, 2685 | 0 2686 | ], 2687 | [ 2688 | -19.65401785714289, 2689 | 25.485491071428555 2690 | ] 2691 | ], 2692 | "lastCommittedPoint": null 2693 | }, 2694 | { 2695 | "id": "SSuq-zZ0zk9OEF14JZpt3", 2696 | "type": "arrow", 2697 | "x": 1063.489955357143, 2698 | "y": 254.61941964285714, 2699 | "width": 171.34486607142867, 2700 | "height": 186.85267857142858, 2701 | "angle": 0, 2702 | "strokeColor": "#000000", 2703 | "backgroundColor": "transparent", 2704 | "fillStyle": "hachure", 2705 | "strokeWidth": 1, 2706 | "strokeStyle": "solid", 2707 | "roughness": 1, 2708 | "opacity": 100, 2709 | "seed": 368065669, 2710 | "version": 34, 2711 | "versionNonce": 868843499, 2712 | "isDeleted": false, 2713 | "groupIds": [], 2714 | "points": [ 2715 | [ 2716 | 0, 2717 | 0 2718 | ], 2719 | [ 2720 | 171.34486607142867, 2721 | 186.85267857142858 2722 | ] 2723 | ], 2724 | "lastCommittedPoint": null 2725 | }, 2726 | { 2727 | "id": "oN4JRSyQo3VNb1s6HbF1t", 2728 | "type": "arrow", 2729 | "x": 856.6205357142857, 2730 | "y": 167.43415178571428, 2731 | "width": 71.72433035714278, 2732 | "height": 17.578125, 2733 | "angle": 0, 2734 | "strokeColor": "#000000", 2735 | "backgroundColor": "transparent", 2736 | "fillStyle": "hachure", 2737 | "strokeWidth": 1, 2738 | "strokeStyle": "solid", 2739 | "roughness": 1, 2740 | "opacity": 100, 2741 | "seed": 951806597, 2742 | "version": 36, 2743 | "versionNonce": 1736378437, 2744 | "isDeleted": false, 2745 | "groupIds": [], 2746 | "points": [ 2747 | [ 2748 | 0, 2749 | 0 2750 | ], 2751 | [ 2752 | -71.72433035714278, 2753 | -17.578125 2754 | ] 2755 | ], 2756 | "lastCommittedPoint": null 2757 | }, 2758 | { 2759 | "id": "azBPB_dfrHahTJLjJqBqf", 2760 | "type": "rectangle", 2761 | "x": 328.4188058035718, 2762 | "y": -31.09793526785714, 2763 | "width": 161.70703125, 2764 | "height": 52.98828125, 2765 | "angle": 0, 2766 | "strokeColor": "#000000", 2767 | "backgroundColor": "transparent", 2768 | "fillStyle": "hachure", 2769 | "strokeWidth": 1, 2770 | "strokeStyle": "solid", 2771 | "roughness": 1, 2772 | "opacity": 100, 2773 | "seed": 1296450059, 2774 | "version": 275, 2775 | "versionNonce": 436750987, 2776 | "isDeleted": false, 2777 | "groupIds": [ 2778 | "pc54Ajfx0aWPnZgdnXpyR" 2779 | ] 2780 | }, 2781 | { 2782 | "id": "6yBvmze_ZXtMiP4-U8ysN", 2783 | "type": "text", 2784 | "x": 392.772321428572, 2785 | "y": -17.60379464285714, 2786 | "width": 33, 2787 | "height": 26, 2788 | "angle": 0, 2789 | "strokeColor": "#000000", 2790 | "backgroundColor": "transparent", 2791 | "fillStyle": "hachure", 2792 | "strokeWidth": 1, 2793 | "strokeStyle": "solid", 2794 | "roughness": 1, 2795 | "opacity": 100, 2796 | "seed": 1119811621, 2797 | "version": 338, 2798 | "versionNonce": 559921061, 2799 | "isDeleted": false, 2800 | "groupIds": [], 2801 | "text": "Jest", 2802 | "fontSize": 20, 2803 | "fontFamily": 1, 2804 | "textAlign": "left", 2805 | "baseline": 21 2806 | }, 2807 | { 2808 | "id": "TnMKNgeMHIkoWJS0Aghsr", 2809 | "type": "rectangle", 2810 | "x": 317.86077008928567, 2811 | "y": 49.577287946428555, 2812 | "width": 161.70703125, 2813 | "height": 52.98828125, 2814 | "angle": 0, 2815 | "strokeColor": "#000000", 2816 | "backgroundColor": "transparent", 2817 | "fillStyle": "hachure", 2818 | "strokeWidth": 1, 2819 | "strokeStyle": "solid", 2820 | "roughness": 1, 2821 | "opacity": 100, 2822 | "seed": 2021796325, 2823 | "version": 240, 2824 | "versionNonce": 1867825451, 2825 | "isDeleted": false, 2826 | "groupIds": [ 2827 | "GWioRiIbZQOHqsoUjPRoa" 2828 | ] 2829 | }, 2830 | { 2831 | "id": "EzZzDi_VHUEI-k4OvpRGy", 2832 | "type": "text", 2833 | "x": 335.71428571428567, 2834 | "y": 65.19754464285711, 2835 | "width": 126, 2836 | "height": 21, 2837 | "angle": 0, 2838 | "strokeColor": "#000000", 2839 | "backgroundColor": "transparent", 2840 | "fillStyle": "hachure", 2841 | "strokeWidth": 1, 2842 | "strokeStyle": "solid", 2843 | "roughness": 1, 2844 | "opacity": 100, 2845 | "seed": 1736020715, 2846 | "version": 323, 2847 | "versionNonce": 1848867589, 2848 | "isDeleted": false, 2849 | "groupIds": [], 2850 | "text": "React Testing Libary", 2851 | "fontSize": 16, 2852 | "fontFamily": 1, 2853 | "textAlign": "left", 2854 | "baseline": 17 2855 | }, 2856 | { 2857 | "id": "NAiG9AvcwuDZuxh_3RRq4", 2858 | "type": "arrow", 2859 | "x": 573.5636160714286, 2860 | "y": 127.4609375, 2861 | "width": 60.86495535714289, 2862 | "height": 30.284598214285722, 2863 | "angle": 0, 2864 | "strokeColor": "#000000", 2865 | "backgroundColor": "transparent", 2866 | "fillStyle": "hachure", 2867 | "strokeWidth": 1, 2868 | "strokeStyle": "solid", 2869 | "roughness": 1, 2870 | "opacity": 100, 2871 | "seed": 475128011, 2872 | "version": 24, 2873 | "versionNonce": 1561945035, 2874 | "isDeleted": false, 2875 | "groupIds": [], 2876 | "points": [ 2877 | [ 2878 | 0, 2879 | 0 2880 | ], 2881 | [ 2882 | -60.86495535714289, 2883 | -30.284598214285722 2884 | ] 2885 | ], 2886 | "lastCommittedPoint": null 2887 | }, 2888 | { 2889 | "id": "fngefTLK6IeyB-9t41ukR", 2890 | "type": "arrow", 2891 | "x": 633.8203125, 2892 | "y": 93.17522321428567, 2893 | "width": 121.99776785714289, 2894 | "height": 88.04129464285711, 2895 | "angle": 0, 2896 | "strokeColor": "#000000", 2897 | "backgroundColor": "transparent", 2898 | "fillStyle": "hachure", 2899 | "strokeWidth": 1, 2900 | "strokeStyle": "solid", 2901 | "roughness": 1, 2902 | "opacity": 100, 2903 | "seed": 1674794411, 2904 | "version": 34, 2905 | "versionNonce": 645386853, 2906 | "isDeleted": false, 2907 | "groupIds": [], 2908 | "points": [ 2909 | [ 2910 | 0, 2911 | 0 2912 | ], 2913 | [ 2914 | -121.99776785714289, 2915 | -88.04129464285711 2916 | ] 2917 | ], 2918 | "lastCommittedPoint": null 2919 | }, 2920 | { 2921 | "id": "LJag2p5OIopH2hXU6olvk", 2922 | "type": "rectangle", 2923 | "x": 1034.2826450892871, 2924 | "y": 599.9310825892856, 2925 | "width": 161.70703125, 2926 | "height": 52.98828125, 2927 | "angle": 0, 2928 | "strokeColor": "#000000", 2929 | "backgroundColor": "transparent", 2930 | "fillStyle": "hachure", 2931 | "strokeWidth": 1, 2932 | "strokeStyle": "solid", 2933 | "roughness": 1, 2934 | "opacity": 100, 2935 | "seed": 1756720101, 2936 | "version": 272, 2937 | "versionNonce": 2070983275, 2938 | "isDeleted": false, 2939 | "groupIds": [ 2940 | "Eop0NgHdoMwauIj3SyaNk" 2941 | ] 2942 | }, 2943 | { 2944 | "id": "UDQHwvEmCgQfBhCkgWdJL", 2945 | "type": "text", 2946 | "x": 1105.6361607142871, 2947 | "y": 613.4252232142856, 2948 | "width": 19, 2949 | "height": 26, 2950 | "angle": 0, 2951 | "strokeColor": "#000000", 2952 | "backgroundColor": "transparent", 2953 | "fillStyle": "hachure", 2954 | "strokeWidth": 1, 2955 | "strokeStyle": "solid", 2956 | "roughness": 1, 2957 | "opacity": 100, 2958 | "seed": 949186795, 2959 | "version": 350, 2960 | "versionNonce": 922369477, 2961 | "isDeleted": false, 2962 | "groupIds": [], 2963 | "text": "RN", 2964 | "fontSize": 20, 2965 | "fontFamily": 1, 2966 | "textAlign": "left", 2967 | "baseline": 21 2968 | }, 2969 | { 2970 | "id": "WWGqax3dmZGr_FfFDc4LO", 2971 | "type": "arrow", 2972 | "x": 1200.1640625, 2973 | "y": 538.2555803571429, 2974 | "width": 47.86272321428578, 2975 | "height": 39.609375, 2976 | "angle": 0, 2977 | "strokeColor": "#000000", 2978 | "backgroundColor": "transparent", 2979 | "fillStyle": "hachure", 2980 | "strokeWidth": 1, 2981 | "strokeStyle": "solid", 2982 | "roughness": 1, 2983 | "opacity": 100, 2984 | "seed": 2064829515, 2985 | "version": 22, 2986 | "versionNonce": 383270181, 2987 | "isDeleted": false, 2988 | "groupIds": [], 2989 | "points": [ 2990 | [ 2991 | 0, 2992 | 0 2993 | ], 2994 | [ 2995 | -47.86272321428578, 2996 | 39.609375 2997 | ] 2998 | ], 2999 | "lastCommittedPoint": null 3000 | }, 3001 | { 3002 | "id": "-MOtSiXcZo_rj9yEw_zlc", 3003 | "type": "rectangle", 3004 | "x": 1252.3909040178564, 3005 | "y": 638.708984375, 3006 | "width": 161.70703125, 3007 | "height": 52.98828125, 3008 | "angle": 0, 3009 | "strokeColor": "#000000", 3010 | "backgroundColor": "transparent", 3011 | "fillStyle": "hachure", 3012 | "strokeWidth": 1, 3013 | "strokeStyle": "solid", 3014 | "roughness": 1, 3015 | "opacity": 100, 3016 | "seed": 1805932747, 3017 | "version": 266, 3018 | "versionNonce": 941624133, 3019 | "isDeleted": false, 3020 | "groupIds": [ 3021 | "tQE8ku0g3fnHXRv8GJ4vM" 3022 | ] 3023 | }, 3024 | { 3025 | "id": "fmz3M1mq5GEIAfqg3UlM6", 3026 | "type": "text", 3027 | "x": 1316.376116071428, 3028 | "y": 651.8348214285716, 3029 | "width": 33, 3030 | "height": 26, 3031 | "angle": 0, 3032 | "strokeColor": "#000000", 3033 | "backgroundColor": "transparent", 3034 | "fillStyle": "hachure", 3035 | "strokeWidth": 1, 3036 | "strokeStyle": "solid", 3037 | "roughness": 1, 3038 | "opacity": 100, 3039 | "seed": 1375907173, 3040 | "version": 329, 3041 | "versionNonce": 1647114123, 3042 | "isDeleted": false, 3043 | "groupIds": [], 3044 | "text": "Taro", 3045 | "fontSize": 20, 3046 | "fontFamily": 1, 3047 | "textAlign": "left", 3048 | "baseline": 21 3049 | }, 3050 | { 3051 | "id": "eRZ3OkY1mJRbjbowoTY2r", 3052 | "type": "rectangle", 3053 | "x": 1465.1029575892867, 3054 | "y": 663.3909040178577, 3055 | "width": 161.70703125, 3056 | "height": 52.98828125, 3057 | "angle": 0, 3058 | "strokeColor": "#000000", 3059 | "backgroundColor": "transparent", 3060 | "fillStyle": "hachure", 3061 | "strokeWidth": 1, 3062 | "strokeStyle": "solid", 3063 | "roughness": 1, 3064 | "opacity": 100, 3065 | "seed": 1636605349, 3066 | "version": 265, 3067 | "versionNonce": 1769792395, 3068 | "isDeleted": false, 3069 | "groupIds": [ 3070 | "ruDiFDdhntW06pmNoZHoI" 3071 | ] 3072 | }, 3073 | { 3074 | "id": "tV9qXQoNzxkdQFJbkhpyS", 3075 | "type": "text", 3076 | "x": 1523.9564732142867, 3077 | "y": 676.8850446428577, 3078 | "width": 44, 3079 | "height": 26, 3080 | "angle": 0, 3081 | "strokeColor": "#000000", 3082 | "backgroundColor": "transparent", 3083 | "fillStyle": "hachure", 3084 | "strokeWidth": 1, 3085 | "strokeStyle": "solid", 3086 | "roughness": 1, 3087 | "opacity": 100, 3088 | "seed": 1095842603, 3089 | "version": 341, 3090 | "versionNonce": 601697957, 3091 | "isDeleted": false, 3092 | "groupIds": [], 3093 | "text": "Remax", 3094 | "fontSize": 20, 3095 | "fontFamily": 1, 3096 | "textAlign": "left", 3097 | "baseline": 21 3098 | }, 3099 | { 3100 | "id": "XDWuvgjzEKB68tjvmVYUD", 3101 | "type": "arrow", 3102 | "x": 1297.0669642857142, 3103 | "y": 551.84375, 3104 | "width": 24.799107142857338, 3105 | "height": 52.444196428571445, 3106 | "angle": 0, 3107 | "strokeColor": "#000000", 3108 | "backgroundColor": "transparent", 3109 | "fillStyle": "hachure", 3110 | "strokeWidth": 1, 3111 | "strokeStyle": "solid", 3112 | "roughness": 1, 3113 | "opacity": 100, 3114 | "seed": 477345125, 3115 | "version": 20, 3116 | "versionNonce": 1322802955, 3117 | "isDeleted": false, 3118 | "groupIds": [], 3119 | "points": [ 3120 | [ 3121 | 0, 3122 | 0 3123 | ], 3124 | [ 3125 | 24.799107142857338, 3126 | 52.444196428571445 3127 | ] 3128 | ], 3129 | "lastCommittedPoint": null 3130 | }, 3131 | { 3132 | "id": "F8zt6jQkL1r0ZK-ninZl3", 3133 | "type": "arrow", 3134 | "x": 1364.0145089285716, 3135 | "y": 529.9073660714286, 3136 | "width": 123.72209821428555, 3137 | "height": 102.0703125, 3138 | "angle": 0, 3139 | "strokeColor": "#000000", 3140 | "backgroundColor": "transparent", 3141 | "fillStyle": "hachure", 3142 | "strokeWidth": 1, 3143 | "strokeStyle": "solid", 3144 | "roughness": 1, 3145 | "opacity": 100, 3146 | "seed": 1890134821, 3147 | "version": 38, 3148 | "versionNonce": 1695703275, 3149 | "isDeleted": false, 3150 | "groupIds": [], 3151 | "points": [ 3152 | [ 3153 | 0, 3154 | 0 3155 | ], 3156 | [ 3157 | 123.72209821428555, 3158 | 102.0703125 3159 | ] 3160 | ], 3161 | "lastCommittedPoint": null 3162 | } 3163 | ], 3164 | "appState": { 3165 | "viewBackgroundColor": "#ffffff" 3166 | } 3167 | } --------------------------------------------------------------------------------