├── _config.yml ├── md ├── resource-analysis │ ├── vue3-render.md │ ├── vue3_renderer.md │ ├── vue3_vite.md │ ├── vue3_computed.md │ └── vue3_reactive_summary.md ├── img │ ├── cisu.png │ ├── https.png │ ├── jdk.png │ ├── meihong.jpg │ ├── widget.png │ ├── JsBridge.png │ ├── bianyiqi.png │ ├── bounding.png │ ├── common │ │ └── ewm.png │ ├── dart_loop.png │ ├── db │ │ └── indexes.jpg │ ├── event_loop.jpg │ ├── hot_loader.jpg │ ├── interweb.png │ ├── page_load.png │ ├── program.jpeg │ ├── prototype.png │ ├── security.png │ ├── vue_proxy.png │ ├── yufafenxi.png │ ├── cifadanyuan.png │ ├── flutter_GPU.png │ ├── algorithm │ │ ├── log.png │ │ ├── stack.png │ │ └── unshift.png │ ├── flutter_render.png │ ├── flutter_state.png │ ├── vue │ │ └── prerender.png │ └── zuoyongyulian.png ├── .vuepress │ ├── public │ │ ├── mh.jpg │ │ └── ewm.png │ └── index.html ├── algorithm │ └── jike-algorithm40.md ├── sse │ ├── microservice.md │ ├── smooth_site.md │ ├── scaffold.md │ ├── event_loop.md │ └── async_await.md ├── mvvm │ └── react_hoc.md ├── javascript │ ├── polyfill.md │ ├── touch.md │ ├── useful_features.md │ ├── animation.md │ └── iterator.md ├── todo │ └── todo.md ├── README.md ├── rxjs │ ├── Scheduler.md │ ├── Subject.md │ ├── Observable.md │ └── Operators.md ├── node │ ├── koa2.md │ └── NPM.md ├── other │ ├── GITHUB.md │ └── GIT.md ├── review │ └── js_promise.md ├── book │ ├── algorithm.md │ ├── js_core_analyze.md │ └── compilation.md ├── flutter │ ├── PRIMER.md │ ├── ISSUE.md │ ├── BRIEF.md │ ├── render.md │ ├── webview.md │ ├── SCENES.md │ └── navigator.md ├── dart │ ├── PRIMER.md │ ├── again.md │ └── base.md ├── browser │ ├── garbage_collection.md │ ├── http.md │ └── security_code.md ├── advance │ └── co_text.md └── css │ ├── EXPERIENCE.md │ └── mobile.md ├── docs ├── mh.jpg ├── ewm.png └── assets │ ├── img │ ├── cisu.a94b44ca.png │ ├── jdk.d05898a0.png │ ├── log.8762d8b3.png │ ├── https.5596ab39.png │ ├── indexes.d040eb02.jpg │ ├── stack.05aea686.png │ ├── unshift.2278dd9b.png │ ├── widget.8a01ecde.png │ ├── JsBridge.55672234.png │ ├── bianyiqi.2308f300.png │ ├── bounding.72490735.png │ ├── dart_loop.eb7484c9.png │ ├── interweb.40bd3632.png │ ├── page_load.b3dc0390.png │ ├── prerender.7af12b58.png │ ├── program.9f43aa42.jpeg │ ├── security.2d3c4c32.png │ ├── vue_proxy.5de7af21.png │ ├── yufafenxi.3605f4c2.png │ ├── cifadanyuan.7cb6265a.png │ ├── event_loop.c3f59522.jpg │ ├── flutter_GPU.9fd206d0.png │ ├── hot_loader.6949d4b0.jpg │ ├── flutter_render.92a1d12d.png │ ├── flutter_state.c6a2cef7.png │ ├── zuoyongyulian.cf7d6854.png │ └── search.83621669.svg │ └── js │ ├── 55.dd658087.js │ ├── 5.7bd620a8.js │ ├── 74.b3e3c021.js │ ├── 21.8a969975.js │ ├── 47.52c7c426.js │ ├── 43.cce6ec34.js │ ├── 60.76cb32da.js │ ├── 77.7f7a727a.js │ ├── 52.a265ba2e.js │ ├── 69.455158fe.js │ ├── 22.a4b7c25c.js │ ├── 65.7af8568e.js │ ├── 24.46de5072.js │ ├── 23.e5031cc2.js │ ├── 11.e99e6c41.js │ ├── 34.2fdbcc65.js │ ├── 51.01fef418.js │ ├── 33.123d1ce8.js │ ├── 26.7998ccbf.js │ ├── 4.3fab20f1.js │ ├── 38.de5a472c.js │ ├── 25.fdb7a3a3.js │ ├── 70.4d6d6d2f.js │ ├── 35.fe4d0657.js │ ├── 41.5b6af204.js │ ├── 36.9d8b1a51.js │ ├── 40.bac257c2.js │ ├── 37.b14f26e4.js │ ├── 71.ec8cfd97.js │ ├── 30.ca47500f.js │ ├── 8.0f83be65.js │ └── 42.aa7828a9.js ├── .gitignore ├── package.json ├── README.md └── LICENSE /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /md/resource-analysis/vue3-render.md: -------------------------------------------------------------------------------- 1 | # vue3 renderer 2 | -------------------------------------------------------------------------------- /docs/mh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/mh.jpg -------------------------------------------------------------------------------- /docs/ewm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/ewm.png -------------------------------------------------------------------------------- /md/img/cisu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/cisu.png -------------------------------------------------------------------------------- /md/img/https.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/https.png -------------------------------------------------------------------------------- /md/img/jdk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/jdk.png -------------------------------------------------------------------------------- /md/img/meihong.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/meihong.jpg -------------------------------------------------------------------------------- /md/img/widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/widget.png -------------------------------------------------------------------------------- /md/img/JsBridge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/JsBridge.png -------------------------------------------------------------------------------- /md/img/bianyiqi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/bianyiqi.png -------------------------------------------------------------------------------- /md/img/bounding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/bounding.png -------------------------------------------------------------------------------- /md/img/common/ewm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/common/ewm.png -------------------------------------------------------------------------------- /md/img/dart_loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/dart_loop.png -------------------------------------------------------------------------------- /md/img/db/indexes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/db/indexes.jpg -------------------------------------------------------------------------------- /md/img/event_loop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/event_loop.jpg -------------------------------------------------------------------------------- /md/img/hot_loader.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/hot_loader.jpg -------------------------------------------------------------------------------- /md/img/interweb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/interweb.png -------------------------------------------------------------------------------- /md/img/page_load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/page_load.png -------------------------------------------------------------------------------- /md/img/program.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/program.jpeg -------------------------------------------------------------------------------- /md/img/prototype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/prototype.png -------------------------------------------------------------------------------- /md/img/security.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/security.png -------------------------------------------------------------------------------- /md/img/vue_proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/vue_proxy.png -------------------------------------------------------------------------------- /md/img/yufafenxi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/yufafenxi.png -------------------------------------------------------------------------------- /md/img/cifadanyuan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/cifadanyuan.png -------------------------------------------------------------------------------- /md/img/flutter_GPU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/flutter_GPU.png -------------------------------------------------------------------------------- /md/.vuepress/public/mh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/.vuepress/public/mh.jpg -------------------------------------------------------------------------------- /md/img/algorithm/log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/algorithm/log.png -------------------------------------------------------------------------------- /md/img/algorithm/stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/algorithm/stack.png -------------------------------------------------------------------------------- /md/img/flutter_render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/flutter_render.png -------------------------------------------------------------------------------- /md/img/flutter_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/flutter_state.png -------------------------------------------------------------------------------- /md/img/vue/prerender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/vue/prerender.png -------------------------------------------------------------------------------- /md/img/zuoyongyulian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/zuoyongyulian.png -------------------------------------------------------------------------------- /md/.vuepress/public/ewm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/.vuepress/public/ewm.png -------------------------------------------------------------------------------- /md/img/algorithm/unshift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/md/img/algorithm/unshift.png -------------------------------------------------------------------------------- /md/algorithm/jike-algorithm40.md: -------------------------------------------------------------------------------- 1 | # 极客时间《法面试通关40讲》 2 | 3 | ### 如何练习算法? 4 | 5 | 1. 坚持、刻意练习 6 | 2. 练习缺点、弱点地方 7 | 3. 忍受枯燥 -------------------------------------------------------------------------------- /docs/assets/img/cisu.a94b44ca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/cisu.a94b44ca.png -------------------------------------------------------------------------------- /docs/assets/img/jdk.d05898a0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/jdk.d05898a0.png -------------------------------------------------------------------------------- /docs/assets/img/log.8762d8b3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/log.8762d8b3.png -------------------------------------------------------------------------------- /docs/assets/img/https.5596ab39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/https.5596ab39.png -------------------------------------------------------------------------------- /docs/assets/img/indexes.d040eb02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/indexes.d040eb02.jpg -------------------------------------------------------------------------------- /docs/assets/img/stack.05aea686.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/stack.05aea686.png -------------------------------------------------------------------------------- /docs/assets/img/unshift.2278dd9b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/unshift.2278dd9b.png -------------------------------------------------------------------------------- /docs/assets/img/widget.8a01ecde.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/widget.8a01ecde.png -------------------------------------------------------------------------------- /docs/assets/img/JsBridge.55672234.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/JsBridge.55672234.png -------------------------------------------------------------------------------- /docs/assets/img/bianyiqi.2308f300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/bianyiqi.2308f300.png -------------------------------------------------------------------------------- /docs/assets/img/bounding.72490735.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/bounding.72490735.png -------------------------------------------------------------------------------- /docs/assets/img/dart_loop.eb7484c9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/dart_loop.eb7484c9.png -------------------------------------------------------------------------------- /docs/assets/img/interweb.40bd3632.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/interweb.40bd3632.png -------------------------------------------------------------------------------- /docs/assets/img/page_load.b3dc0390.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/page_load.b3dc0390.png -------------------------------------------------------------------------------- /docs/assets/img/prerender.7af12b58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/prerender.7af12b58.png -------------------------------------------------------------------------------- /docs/assets/img/program.9f43aa42.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/program.9f43aa42.jpeg -------------------------------------------------------------------------------- /docs/assets/img/security.2d3c4c32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/security.2d3c4c32.png -------------------------------------------------------------------------------- /docs/assets/img/vue_proxy.5de7af21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/vue_proxy.5de7af21.png -------------------------------------------------------------------------------- /docs/assets/img/yufafenxi.3605f4c2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/yufafenxi.3605f4c2.png -------------------------------------------------------------------------------- /docs/assets/img/cifadanyuan.7cb6265a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/cifadanyuan.7cb6265a.png -------------------------------------------------------------------------------- /docs/assets/img/event_loop.c3f59522.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/event_loop.c3f59522.jpg -------------------------------------------------------------------------------- /docs/assets/img/flutter_GPU.9fd206d0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/flutter_GPU.9fd206d0.png -------------------------------------------------------------------------------- /docs/assets/img/hot_loader.6949d4b0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/hot_loader.6949d4b0.jpg -------------------------------------------------------------------------------- /docs/assets/img/flutter_render.92a1d12d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/flutter_render.92a1d12d.png -------------------------------------------------------------------------------- /docs/assets/img/flutter_state.c6a2cef7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/flutter_state.c6a2cef7.png -------------------------------------------------------------------------------- /docs/assets/img/zuoyongyulian.cf7d6854.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongmeizhi/fed-note/HEAD/docs/assets/img/zuoyongyulian.cf7d6854.png -------------------------------------------------------------------------------- /md/sse/microservice.md: -------------------------------------------------------------------------------- 1 | # 前端微服务 2 | 3 | 框架需要先加载 entry 资源,待 entry 资源加载完毕,确保子应用的路由系统注册进主框架之后后,再去由子应用的路由系统接管 url change 事件,同时在子应用路由切出时,主框架需要触发相应的 destroy 事件,子应用在监听到该事件时,调用自己的卸载方法卸载应用, -------------------------------------------------------------------------------- /md/mvvm/react_hoc.md: -------------------------------------------------------------------------------- 1 | # React 高阶组件 2 | 3 | ### 代理方式的高阶组件(优先考虑) 4 | 5 | 1. 操作 prop 6 | 2. 访问 ref 7 | 3. 抽取状态 8 | 4. 包装组件 9 | 10 | ### 继承方式的高阶组件(最后考虑) 11 | 12 | 1. 操作 prop 13 | 2. 操作 生命周期 14 | -------------------------------------------------------------------------------- /docs/assets/img/search.83621669.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | my-dist/ 4 | _book/ 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | test/unit/coverage 9 | test/e2e/reports 10 | selenium-debug.log 11 | 12 | # Editor directories and files 13 | .idea 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitbookFED", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "repository": "https://github.com/zhongmeizhi/gitbook-FED.git", 6 | "author": "zhongmeizhi <330447171@qq.com>", 7 | "license": "MIT", 8 | "scripts": { 9 | "dev": "vuepress dev md", 10 | "build": "vuepress build md" 11 | }, 12 | "devDependencies": { 13 | "vuepress": "^1.5.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /docs/assets/js/55.dd658087.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[55],{422:function(e,t,r){"use strict";r.r(t);var s=r(42),n=Object(s.a)({},(function(){var e=this.$createElement,t=this._self._c||e;return t("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[t("h1",{attrs:{id:"vue3-renderer"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#vue3-renderer"}},[this._v("#")]),this._v(" vue3 renderer")])])}),[],!1,null,null,null);t.default=n.exports}}]); -------------------------------------------------------------------------------- /md/.vuepress/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /docs/assets/js/5.7bd620a8.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[5],{317:function(t,e,n){},374:function(t,e,n){"use strict";var i=n(317);n.n(i).a},451:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(374),n(42)),a=Object(r.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=a.exports}}]); -------------------------------------------------------------------------------- /md/javascript/polyfill.md: -------------------------------------------------------------------------------- 1 | # polyfill 2 | 3 | ## Object.assign() 4 | 5 | ```js 6 | function merge(target) { 7 | for (let i = 1, j = arguments.length; i < j; i++) { 8 | let source = arguments[i] || {}; 9 | for (let prop in source) { 10 | if (source.hasOwnProperty(prop)) { 11 | let value = source[prop]; 12 | if (value !== undefined) { 13 | target[prop] = value; 14 | } 15 | } 16 | } 17 | } 18 | return target; 19 | } 20 | ``` -------------------------------------------------------------------------------- /md/todo/todo.md: -------------------------------------------------------------------------------- 1 | 2 | * [腾讯新闻前端周报](https://github.com/Tnfe/TNFE-Weekly) 3 | * [阿里语雀周刊][https://www.yuque.com/alibabaf2e/weekly] 4 | * [机器学习](https://github.com/apachecn/AiLearning) 5 | 6 | 工具 7 | * [网页 转 markdown](https://github.com/croqaz/clean-mark) 8 | 1. `npm install clean-mark --global` 9 | 2. `cd 承载目录` 10 | 3. `clean-mark url` 11 | * [markdown 在线免费转 html](https://mdnice.com/) 12 | * [备用](http://md.aclickall.com/) 13 | 14 | 同时启动 多个微信: 15 | * 利用 `.bat` 添加,运行命令,几行就几个。 16 | * `start/d "C:\Program Files (x86)\Tencent\WeChat\" Wechat.exe` 17 | -------------------------------------------------------------------------------- /md/resource-analysis/vue3_renderer.md: -------------------------------------------------------------------------------- 1 | # vue3 renderer 2 | 3 | # TODO 4 | 5 | vue3.0 渲染原理,源码解析系列(四) 6 | 7 | 1. 前言 8 | 1. 自我介绍 9 | 2. 工程化相关 10 | 2. vue3源码历史 11 | 1. 历史文章导读 12 | 2. 未完成事项 13 | 3. babel-react 实现 jsx 14 | 1. setup + template 对比 function + jsx 的优点 15 | 4. vite -> uuzpack 过程 16 | 1. vite 和 webpack 优点 17 | 2. 实现过程 18 | 3. 产生的结果 19 | 4. 后续展望 20 | 5. vue3 h函数 21 | 1. h函数的改进和优点 22 | 2. 多个h函数的分工 23 | 6. 实现一个 render 24 | 1. 从API匹配开始 25 | 2. 套上已有api 26 | 7. 后续规划 27 | 1. webComponent方案? 28 | 2. 编译器相关 29 | 3. 修复已有补丁 30 | 8. 为自己打卡 31 | 32 | -------------------------------------------------------------------------------- /docs/assets/js/74.b3e3c021.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[74],{442:function(t,s,e){"use strict";e.r(s);var r=e(42),n=Object(r.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"前端微服务"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#前端微服务"}},[this._v("#")]),this._v(" 前端微服务")]),this._v(" "),s("p",[this._v("框架需要先加载 entry 资源,待 entry 资源加载完毕,确保子应用的路由系统注册进主框架之后后,再去由子应用的路由系统接管 url change 事件,同时在子应用路由切出时,主框架需要触发相应的 destroy 事件,子应用在监听到该事件时,调用自己的卸载方法卸载应用,")])])}),[],!1,null,null,null);s.default=n.exports}}]); -------------------------------------------------------------------------------- /md/README.md: -------------------------------------------------------------------------------- 1 | # 《Mokou的小书房》 2 | 3 | > 因博客改动频繁,建议通过 star/watch 追更。 4 | 5 | ## 序言 6 | 7 | 从2019年3月份开始写读书笔记。主要是为了记录自己的学习轨迹和备忘,同时分享下技术心得。希望每年回顾上一年收获的时候,不会因为虚度光阴而悔恨。 8 | 9 | 喜欢请Star。 10 | 11 | 见解有限,如有描述不当之处,请帮忙及时指出,如有错误,会及时修正。 12 | 13 | 如果看完本文后,有看不懂的地方请回复我,一定是我写的不够清楚,我改。。。 14 | 15 | ## 2020阶段性感悟 16 | 17 | 学习应该学以致用,技术应该服务于业务。以后的学习会围绕下面主题: 18 | 19 | 1. 该xx有什么特点? 20 | 2. 该xx解决了什么问题? 21 | 3. xx和yy的对比优劣如何? 22 | 4. 具有什么应用场景? 23 | 24 | ### Vue3 源码深入浅出连载中... 25 | 26 | * mini版vue3源码地址:[uuz](https://github.com/zhongmeizhi/uuz) 27 | 28 | ## 最后 29 | 30 | * 更多精彩请关注微信公众号:**前端进阶课** 31 | 32 | ![微信公众号-前端进阶课](/fed-note/ewm.png) 33 | -------------------------------------------------------------------------------- /docs/assets/js/21.8a969975.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[21],{376:function(t,e,s){"use strict";s.r(e);var n=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],o={methods:{getMsg:function(){return n[Math.floor(Math.random()*n.length)]}}},i=s(42),h=Object(i.a)(o,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"theme-container"},[e("div",{staticClass:"theme-default-content"},[e("h1",[this._v("404")]),this._v(" "),e("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),e("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])}),[],!1,null,null,null);e.default=h.exports}}]); -------------------------------------------------------------------------------- /md/rxjs/Scheduler.md: -------------------------------------------------------------------------------- 1 | # RXJS学习 之 Scheduler 2 | 3 | > Scheduler允许定义Observable将哪些执行上下文传递给其Observer的通知 4 | 5 | ### 调度器:Scheduler 6 | 7 | 官网翻译: 8 | 9 | 什么是调度程序?调度程序控制订阅何时开始以及何时传递通知。它由三个部分组成。 10 | * 调度程序是一种数据结构。它知道如何根据优先级或其他标准存储和排队任务。 11 | * 调度程序是执行上下文。它表示执行任务的位置和时间(例如,立即执行,或者在另一个回调机制中,例如setTimeout或process.nextTick,或动画帧)。 12 | * 调度程序具有(虚拟)时钟。它通过now()调度程序上的getter方法提供了“时间”的概念。在特定调度程序上调度的任务将仅遵循该时钟表示的时间。 13 | 14 | 15 | ### 使用 Scheduler 16 | 17 | Scheduler一般在Operators中通过`observeOn(xxx)`使用,或者能接收`Scheduler`参数的方法(例如:of、from、interval、timer、concat、merge 等)中使用。 18 | 19 | 使用方法: 20 | ``` 21 | of(1, 2, 3, 4).pipe( 22 | observeOn(asyncScheduler), // 异步 23 | ).subscribe(console.log) 24 | ``` 25 | 26 | * asapScheduler // 同步 27 | * asyncScheduler // 异步 28 | * animationFrameScheduler // requestAnimationFrame -------------------------------------------------------------------------------- /md/node/koa2.md: -------------------------------------------------------------------------------- 1 | # koa2 2 | 3 | ## koa2 简介 4 | 5 | koa 和 koa2 的比较 6 | 1. `koa1` 使用 `co.js` 处理 `generator`。 7 | 2. `koa2` 使用 `async` 和 `await`,(node v7.6.0 才支持 async/await) 8 | 9 | 只提供了: context,request,response 以及 async/await 的中间件容器 10 | 11 | 简单的 koa2 中间件使用 12 | 13 | ```js 14 | const Koa = require('koa') // koa v2 15 | const loggerAsync = require('./middleware/logger-async') 16 | const app = new Koa() 17 | 18 | function log( ctx ) { 19 | console.log( ctx.method, ctx.header.host + ctx.url ) 20 | } 21 | 22 | function loggerAsync () { 23 | return async function ( ctx, next ) { 24 | log(ctx); 25 | await next() 26 | } 27 | } 28 | 29 | app.use(loggerAsync()) 30 | 31 | app.use(( ctx ) => { 32 | ctx.body = `hello ${ctx.request.url}` 33 | }) 34 | 35 | app.listen(3000) 36 | ``` 37 | 38 | ## 路由 39 | 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |

Mokou的小书房

6 | 7 | ## 序言 8 | 9 | 从2019年3月份开始写读书笔记。主要是为了记录自己的学习轨迹和备忘,同时分享下技术心得。希望每年回顾上一年收获的时候,不会因为虚度光阴而悔恨。 10 | 11 | 喜欢请Star。 12 | 13 | 见解有限,如有描述不当之处,请帮忙及时指出,如有错误,会及时修正。 14 | 15 | 如果看完本文后,有看不懂的地方请回复我,一定是我写的不够清楚,我改。。。 16 | 17 | 18 | ## 本博客链接: 19 | 20 | 因为博客改动频繁,收藏时最好通过本 github 收藏。 21 | 22 | * [https://zhongmeizhi.github.io/fed-note/](https://zhongmeizhi.github.io/fed-note/) 23 | * [备用链接](https://env-sursrwlb-1302583115.tcloudbaseapp.com/fed-note/) 24 | 25 | 26 | ### Vue3 源码深入浅出连载中... 27 | 28 | * 源码解析文章请去[个人博客](https://zhongmeizhi.github.io/fed-note/) 29 | * mini版vue3源码地址:[uuz](https://github.com/zhongmeizhi/uuz) 30 | 31 | ## 最后 32 | 33 | * 更多精彩请关注微信公众号:**前端进阶课** 34 | 35 | ![微信公众号-前端进阶课](/md/img/common/ewm.png) 36 | -------------------------------------------------------------------------------- /md/other/GITHUB.md: -------------------------------------------------------------------------------- 1 | # GitHub的Host和Key 2 | 3 | ### 解决GitHub不能访问的问题 4 | 5 | 1. 修改Host 6 | 7 | ``` 8 | # github 9 | 204.232.175.78 https://documentcloud.github.com 10 | 207.97.227.239 https://github.com 11 | 204.232.175.94 https://gist.github.com 12 | 107.21.116.220 https://help.github.com 13 | 207.97.227.252 https://nodeload.github.com 14 | 199.27.76.130 https://raw.github.com 15 | 107.22.3.110 https://status.github.com 16 | 204.232.175.78 https://training.github.com 17 | 207.97.227.243 https://www.github.com 18 | ``` 19 | 20 | 2. 刷新DNS:控制台输入`ipconfig/flushdns` 21 | 22 | ### Git Key获取 23 | 24 | 1. 在git bash中运行`ssh-keygen -t rsa -C "git user"` 25 | 2. 此时会在`C:\Users\jack\.ssh`文件夹内生成`id_rsa.pub`和`id_rsa` 26 | 3. 复制`id_rsa.pub`的内容(就是key) 27 | 4. 放置于github -> setting -> SSH keys中(title随意) 28 | 29 | 30 | -------------------------------------------------------------------------------- /md/review/js_promise.md: -------------------------------------------------------------------------------- 1 | # Promise 2 | 3 | > Promise 是一个对象,它代表了一个异步操作的最终完成或者失败。 4 | 5 | ### Promise 概念 6 | 7 | 一个 Promise有以下几种状态: 8 | * `pending`: 初始状态,既不是成功,也不是失败状态。 9 | * `fulfilled`: 意味着操作成功完成。 10 | * `rejected`: 意味着操作失败。 11 | 12 | 13 | 不同于“老式”的传入回调,在使用 Promise 时,会有以下约定: 14 | * 在 本轮 `Javascript event loop`(事件循环)运行完成 之前,回调函数是不会被调用。 15 | * 通过 `then()` 添加的回调函数总会被调用,即便它是在异步操作完成之后才被添加的函数。 16 | * 通过多次调用 `then()`,可以添加多个回调函数,它们会按照插入顺序一个接一个独立执行。 17 | 18 | 因为 Promise.prototype.then 和 Promise.prototype.catch 方法返回promise 对象, 所以它们可以被链式调用。 19 | 20 | 21 | Promise的 4 个方法 22 | 1. Promise.all(iterable) 23 | 2. Promise.race(iterable) 24 | 3. Promise.resolve(value) 25 | 4. Promise.reject(reason) 26 | 27 | Promise的 prototype 28 | 1. Promise.prototype.catch(onRejected) 29 | 2. Promise.prototype.then(onFulfilled, onRejected) 30 | 3. Promise.prototype.finally(onFinally) 31 | 32 | -------------------------------------------------------------------------------- /md/javascript/touch.md: -------------------------------------------------------------------------------- 1 | # 移动端touch 2 | 3 | touch 4 | touchstart 5 | touchmove 6 | touchend 7 | 8 | 9 | 手势难点 10 | 1. 手势识别 11 | 缩放,旋转 12 | 2. 方向锁定 13 | 3. 14 | 15 | touch的事件有,event.targetTouchs,数组,目标dom的触摸数。 16 | 如果是多指代表最中间点 17 | 拖拽时要在touchstart事件中 e.preventDefault()来阻止页面的滚动效果, 18 | 每个touch都有 identifier表示ID 19 | 20 | 21 | 22 | 23 | 单点触摸,使用 event.targetTouchs[0] 24 | 25 | 多点触摸: 26 | 目标dom的event.targetTouchs表示目标的触摸手指数组 27 | 多点触摸有在touchend触发时当前dom的所有touch事件都remove掉 28 | 需要使用event.changedTouches来寻找离开的手指的 identifier来判断是否离开 29 | 30 | 31 | 32 | 原生的额touch 和 websocket很难用 33 | 分别用 iscroll 、 hammer 和 socketio 34 | 35 | 36 | 37 | 拖拽方向锁定 38 | 。上下拖的时候阻止左右拖,左右同理 39 | 40 | 41 | 获取transform属性基本上不能,因为通过js获取到的是矩阵, 42 | 但是获得一个矩阵的transform可以有多个,比如scale+skew可以等于rotate 43 | 44 | 45 | 46 | 调试手机端可以用 browser-sync完成多端同步(利用socket.io完成的) 47 | 48 | 49 | 在if里面放函数是很不好的行为,因为在不同的浏览器执行的结果可能不一样, 50 | 在严格模式还会报错 51 | 52 | 53 | -------------------------------------------------------------------------------- /md/book/algorithm.md: -------------------------------------------------------------------------------- 1 | # 《算法导论》 第三版 2 | 3 | 4 | ### 算法的作用 5 | 6 | > 算法就是求良解的计算过程 7 | 8 | 数据结构是一种`存储`和`组织`数据的方式,旨在便于访问和修改。 9 | 10 | 11 | ### 算法的效率问题: 12 | 13 | 为求解相同的问题而设计的不同算法在效率方面有显著的差别。 14 | 15 | 拿排序举例,排序 `n` 项 16 | * 插入排序:所花时间大致等于 `cn^2` 17 | * 并归排序:所花时间大致等于 `cnlgn` 18 | 19 | 其中 `c` 为不依赖 `n` 的常数当 n = 1000 时, lgn 大致为 10,当 n 等于 100万 时,lgn 大致为 20。对于小规模的排序:插入排序通常比并归排序要快,超过一定点,并归排序更快。 20 | 21 | 22 | ### 分治策略 23 | 24 | 1. 分解:分解成多个子问题 25 | 2. 解决:分别解决每个子问题 26 | 3. 合并: 将解决的结果合并 27 | 28 | 举例:一段时间(n天)内做一次股票交易怎样获益最大?也就是获取一个数组中值相加最大的子数组 29 | 30 | 解法1:暴力解决 31 | 1. 只要卖出日期在买入日期之后即可,n天共有 `n^2` 种组合 32 | 33 | 解法2:分治策略 34 | 1. 获取数组的中点 `n/2` (n/2需要取整) 35 | 2. 分解:一共 3 种情况 36 | 1. 子数组在 0 至 n/2 之间(在左边) -> (n^2)/4 37 | 2. 子数组在 n/2 至 n 之间(在右边) -> (n^2)/4 38 | 3. 子数组在 跨越了中点 n/2(就是在中点两边) -> 2n 39 | 3. 一共需要 (n^2)/2 + 2n 次计算 40 | 41 | 42 | ### 算法 43 | 44 | 1. 矩阵的 Strassen 算法 45 | 2. 代入法求解递归式 46 | 3. 递归树求解递归式 47 | 4. 主方法求解递归式 48 | 49 | 概率分析 和 随机算法 50 | -------------------------------------------------------------------------------- /md/sse/smooth_site.md: -------------------------------------------------------------------------------- 1 | # 如果让网页更流畅 2 | 3 | 4 | # TODO 5 | 6 | 60Hz,16.7ms 7 | 8 | 9 | 如何避免长任务 10 | * Web Worker 11 | * Time Slicing(时间切片),比如React的`fiber` 12 | 13 | 时间分片 14 | 15 | ``` 16 | function init({ sliceList, callback }) { 17 | if (!isFunction(callback)) { 18 | return new Error('不是function'); 19 | } 20 | // 添加切片队列 21 | this.generator = this.sliceQueue({ 22 | sliceList, 23 | callback 24 | }); 25 | // 开始切片 26 | this.next(); 27 | } 28 | 29 | function* sliceQueue({ sliceList, callback }) { 30 | let listOrNum = (isNum(sliceList) && sliceList) || (isArray(sliceList) && sliceList.length); 31 | for (let i = 0; i < listOrNum; ++i) { 32 | const start = performance.now(); 33 | callback(i); 34 | while (performance.now() - start < 16.7) { 35 | yield; 36 | } 37 | } 38 | } 39 | ``` -------------------------------------------------------------------------------- /docs/assets/js/47.52c7c426.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[47],{412:function(t,a,r){"use strict";r.r(a);var e=r(42),s=Object(e.a)({},(function(){var t=this,a=t.$createElement,r=t._self._c||a;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"react-高阶组件"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#react-高阶组件"}},[t._v("#")]),t._v(" React 高阶组件")]),t._v(" "),r("h3",{attrs:{id:"代理方式的高阶组件(优先考虑)"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#代理方式的高阶组件(优先考虑)"}},[t._v("#")]),t._v(" 代理方式的高阶组件(优先考虑)")]),t._v(" "),r("ol",[r("li",[t._v("操作 prop")]),t._v(" "),r("li",[t._v("访问 ref")]),t._v(" "),r("li",[t._v("抽取状态")]),t._v(" "),r("li",[t._v("包装组件")])]),t._v(" "),r("h3",{attrs:{id:"继承方式的高阶组件(最后考虑)"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#继承方式的高阶组件(最后考虑)"}},[t._v("#")]),t._v(" 继承方式的高阶组件(最后考虑)")]),t._v(" "),r("ol",[r("li",[t._v("操作 prop")]),t._v(" "),r("li",[t._v("操作 生命周期")])])])}),[],!1,null,null,null);a.default=s.exports}}]); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 zhongmeizhi 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. -------------------------------------------------------------------------------- /md/flutter/PRIMER.md: -------------------------------------------------------------------------------- 1 | # 适配 2 | 3 | Flutter借鉴的是React思想,使用的是Widget组件 4 | 5 | 本文只写`官网很难找到`或者`官网压根没有的`Fluter日常踩坑。 6 | 7 | ### 静态文件引入 8 | 1. 打开根目录中的`pubspec.yaml`文件 9 | ``` 10 | // 配置 assets 11 | 12 | assets: 13 | - assets/images/xxx.jpg 14 | ``` 15 | 2. 在Widget中使用即可 16 | ``` 17 | Image.asset('assets/images/xxx.jpg', 18 | ``` 19 | 20 | ### 屏幕适配 21 | 1. 打开根目录中的`pubspec.yaml`文件 22 | > 添加 flutter_screenutil 插件 23 | ``` 24 | dependencies: 25 | flutter: 26 | sdk: flutter 27 | flutter_screenutil: ^0.4.2 28 | ``` 29 | 2. 在所有的使用处引入插件(肯定的咯) 30 | ``` 31 | import 'package:flutter_screenutil/flutter_screenutil.dart'; 32 | ``` 33 | 3. 在`MaterialApp`的`home`的Widget中确认设计稿宽高 34 | > 拟定宽高 width=750; height=1334; 35 | ``` 36 | // Widget build(BuildContext context) { 后面添加 37 | 38 | ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context); 39 | ``` 40 | 4. 使用 41 | ``` 42 | width: ScreenUtil().setWidth(750) 43 | ``` 44 | 45 | ### 字体适配 46 | > 适配方案大致同上,略有不同 47 | ``` 48 | ScreenUtil().setSp(28) 49 | ``` 50 | 51 | ### 颜色使用 52 | * 自带颜色 `Colors.red` 53 | * 自义颜色 `Color(0xFF333333)` 54 | * 0xFF表示透明度16进制, 之后的333333代表RGB色值 55 | 56 | 57 | -------------------------------------------------------------------------------- /md/book/js_core_analyze.md: -------------------------------------------------------------------------------- 1 | # JavaScript核心原理解析 2 | 3 | > 学习要“知味”,你一旦从这个过程中得到了收获,你就如同食髓,乐此不疲了。所以,不要气馁,放松心态,坚持就好了。 4 | 5 | 语言最核心的部分也有两个,第一个是语言的构成,第二个是如何构成。 6 | 7 | ### 赋值案例分析 8 | 9 | > JavaScript 总是严格按照从左至右的顺序来计算表达式 by.《JavaScript 权威指南》 10 | 11 | 以下代码分析,为何 `a.x == undefined` 12 | 13 | ```js 14 | var a = {n:1}; 15 | a.x = a = {n:2}; 16 | alert(a.x); // --> undefined 17 | ``` 18 | 19 | 包含知识点 20 | 21 | 1. JS 表达式严格按照从左往右的顺序进行计算 22 | 2. `a.x` 在 JS 中属于表达式(中 a 中获取 x) 23 | 3. `a` 是引用类型 24 | 25 | 运算过程 26 | 27 | 1. 因为是 `a.x` 所以先获取到 `a` 的引用, 28 | 2. 通过 `a` 取值,获取到 `a.x` 29 | 3. 通过赋值覆盖原始变量 `a` 30 | 4. 因为 `a.x` 已经取值,将 `a` 原始值覆盖后,已被取值的 `a` 被**空悬** 31 | 5. 而赋值 `a.x` 其实是无意义的 32 | 33 | 34 | ### 水平一般? 35 | 36 | > 什么叫“水平一般”呢? by. 周爱民 37 | 38 | 因为他学的东西,别人也都学;会的东西,别人也都会;他强的东西,别人一样也强。即使别人今天不如他学得多、会得多,又或者不比他强多少,但是只要花点时间、下点功夫,也就一样儿也不会比他差。他十几年的一线开发,把自己做成了熟手、熟练工,东西会得再多,技巧再熟练,也不过是卖油翁的“但手熟尔”。 39 | 40 | 我在面试里面,确实问了他几个偏向核心的问题,他也确实知道,很清晰、很准确。但再进一步问原理时,他却是一无所知。所以,我又引导、设问,说:“如果现在让你来考虑这个问题,你会从哪儿入手呢?”那位候选人想了好几个招数,中规中矩,然而无一可用。这就是关键所在。 41 | 42 | “核心原理”不是一些招数技法,不是拿来多练多用就行了的。所谓“核心”呢,不见得是大家都知道的——一眼望去,万千条路径之中,找到最正确的那一条,才是核心。但是这个东西可以教,也可以记,下次看见这个路,照着走就是了。所以,大公司里有所谓的“核心团队”,新人进去,不消半年工夫,功力就大增了,出来能带一个团队了。咦,带团队做什么呢?冲锋陷阵啊,杀敌交人头啊!反正,和上面说的“吃”一样,还是劳力活。 43 | 44 | 所以,就算是在“核心团队”里,他们也只是帮你指出核心之所在,最多教你会一些套路,让人净增功力。但是这样的核心只是“死东西”,不懂得核心的原理,就如同上面说过的那位面试候选人一样,出的都是些中规中矩的招数。 45 | -------------------------------------------------------------------------------- /docs/assets/js/43.cce6ec34.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[43],{411:function(t,e,o){"use strict";o.r(e);var n=o(42),v=Object(n.a)({},(function(){var t=this,e=t.$createElement,o=t._self._c||e;return o("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[o("h1",{attrs:{id:"移动端touch"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#移动端touch"}},[t._v("#")]),t._v(" 移动端touch")]),t._v(" "),o("p",[t._v("touch\ntouchstart\ntouchmove\ntouchend")]),t._v(" "),o("p",[t._v("手势难点")]),t._v(" "),o("ol",[o("li",[t._v("手势识别\n缩放,旋转")]),t._v(" "),o("li",[t._v("方向锁定")]),t._v(" "),o("li")]),t._v(" "),o("p",[t._v("touch的事件有,event.targetTouchs,数组,目标dom的触摸数。\n如果是多指代表最中间点\n拖拽时要在touchstart事件中 e.preventDefault()来阻止页面的滚动效果,\n每个touch都有 identifier表示ID")]),t._v(" "),o("p",[t._v("单点触摸,使用 event.targetTouchs[0]")]),t._v(" "),o("p",[t._v("多点触摸:\n目标dom的event.targetTouchs表示目标的触摸手指数组\n多点触摸有在touchend触发时当前dom的所有touch事件都remove掉\n需要使用event.changedTouches来寻找离开的手指的 identifier来判断是否离开")]),t._v(" "),o("p",[t._v("原生的额touch 和 websocket很难用\n分别用 iscroll 、 hammer 和 socketio")]),t._v(" "),o("p",[t._v("拖拽方向锁定\n。上下拖的时候阻止左右拖,左右同理")]),t._v(" "),o("p",[t._v("获取transform属性基本上不能,因为通过js获取到的是矩阵,\n但是获得一个矩阵的transform可以有多个,比如scale+skew可以等于rotate")]),t._v(" "),o("p",[t._v("调试手机端可以用 browser-sync完成多端同步(利用socket.io完成的)")]),t._v(" "),o("p",[t._v("在if里面放函数是很不好的行为,因为在不同的浏览器执行的结果可能不一样,\n在严格模式还会报错")])])}),[],!1,null,null,null);e.default=v.exports}}]); -------------------------------------------------------------------------------- /md/dart/PRIMER.md: -------------------------------------------------------------------------------- 1 | # dart2 入门 2 | 3 | ### 简介 4 | * 由Google开发 5 | * 可运行在移动端、浏览器、服务端 6 | * fuchsia && flutter 的亲儿子 7 | * 单进程(isolate隔离区多线程) 8 | * 可以在没有锁的情况下进行对象分配和垃圾回收(像JavaScript一样) 9 | * 拥有虚拟机 DartVM 10 | * 开发时使用:JIT(Just In Time)编译 11 | * 运行时使用:AOT(Ahead Of Time)编译 12 | * 静态作用域、 13 | * 大括号里面定义的变量就 只能在大括号里面访问 14 | 15 | ### 特点 16 | * 强类型语言,支持类型推断 17 | * 所有对象都继承自`Object`类 18 | * 程序有统一的程序入口:`main()` 19 | * 类TypeScript函数 20 | * mixins的实现`with` 21 | * `future`和`async await` 22 | * 在Dart 2中,`new`可选的(类不需要new了) 23 | 24 | ### 语法 25 | 26 | 可以⽤ var 来声明变量, Dart 会⾃推导出数据类型, var实际上是`编译期`的“语法糖”。 27 | 28 | Dart 中所有的基础类型、类 等都继承 Object ,默认值是`null`, ⾃带 getter 和 setter,⽽如果是 final 或者 const 的话,那么它只有⼀个 getter ⽅法。其中 const 的值在编译期确定,final 的值要到运⾏时才确定。 29 | 30 | 31 | 支持异步 32 | ``` 33 | ///模拟等待两秒,返回OK 34 | request() async { 35 | await Future.delayed(Duration(seconds: 1)); 36 | return "ok!"; 37 | } 38 | 39 | ///得到"ok!"后,将"ok!"修改为"ok from request" 40 | doSomeThing() async { 41 | String data = await request(); 42 | data = "ok from request"; 43 | return data; 44 | } 45 | 46 | ///打印结果 47 | renderSome() { 48 | doSomeThing().then((value) { 49 | print(value); 50 | ///输出ok from request 51 | }); 52 | } 53 | ``` 54 | 55 | ### Dart运行机制 56 | 57 | > Dart和Javascript的运行机制类似(都是单线程) 58 | 59 | 见下图: 60 | 61 | ![Event_Loop](../img/dart_loop.png) 62 | 63 | 其中:`Future`是微任务(当然,Future几乎就是Promise) -------------------------------------------------------------------------------- /md/other/GIT.md: -------------------------------------------------------------------------------- 1 | # git 使用 2 | 3 | Git是分布式版本控制系统 4 | 5 | ### 常用命令 6 | 7 | 代码暂存 8 | * 代码暂存`git stash save 'message'` 9 | * 恢复最新的进度到工作区`git stash pop [–index] [stash_id]` 10 | * 删除所有存储的进度`git stash clear` 11 | 12 | 克隆 `git clone http://xxx.git dirname` 13 | 14 | fork代码到本地 `fork remote add https://xxx.git` 15 | 16 | 添加文件 `git add [ -a ]` 17 | 18 | 查看 19 | * 查看分支 `git branch [ -a | -r ]` 20 | * 查看状态 `git status` 21 | * 查看远程代码地址 `git remote -v` 22 | * 对比 `git diff` 23 | 24 | 拉取 25 | * 拉取远程代码 `git fetch [ --all ]` 26 | * 拉取远程代码并合并 `git pull origin name` 27 | 28 | 提交代码 29 | * 提交到本地 `git commit -m 'remark'` 30 | * 整理commit记录 `git rebase branch` 31 | * 提交到远程 `git push origin name` 32 | * 合并分支 `git merge branch` 33 | 34 | 创建子分支 `git checkout -b name` 35 | 36 | 删除分支 37 | * 删除本地分支 `git branch -d name` 38 | * 删除远程分支 `git push origin --delete name` 39 | * 删除本地可见但远程已经删除的分支 `git remote prune origin` 40 | 41 | 42 | 同步fork代码 43 | 1. `git fetch upstream` 44 | 2. `git checkout master` 45 | 3. `git merge upstream/master` 46 | 4. `git push` 47 | 48 | 回撤提交 `git revert HEAD` 49 | 50 | 回滚到特定版本 51 | * `git reset --hard 5dc29bebe8` 52 | * 有多个选项[soft、mixed、hard] 53 | * hard = mixed + revert 54 | * 回滚完成后只是在本地reset,需要覆盖远程节点 55 | * `git push --force` 强制push 56 | 57 | 修补commit(用于代码提交错分支的情况) 58 | * 生成最近的4次(^数量)commit的patch `git format-patch HEAD^^^^` 59 | * 检查patch:如果没有任何输出,则说明无冲突`git apply --check 某提交.patch` 60 | * 将名字为 "某提交.patch" 的patch打上`git am 某提交.patch` 61 | 62 | -------------------------------------------------------------------------------- /docs/assets/js/60.76cb32da.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[60],{428:function(v,_,e){"use strict";e.r(_);var l=e(42),t=Object(l.a)({},(function(){var v=this,_=v.$createElement,e=v._self._c||_;return e("ContentSlotsDistributor",{attrs:{"slot-key":v.$parent.slotKey}},[e("h1",{attrs:{id:"vue3-renderer"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#vue3-renderer"}},[v._v("#")]),v._v(" vue3 renderer")]),v._v(" "),e("h1",{attrs:{id:"todo"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#todo"}},[v._v("#")]),v._v(" TODO")]),v._v(" "),e("p",[v._v("vue3.0 渲染原理,源码解析系列(四)")]),v._v(" "),e("ol",[e("li",[v._v("前言\n"),e("ol",[e("li",[v._v("自我介绍")]),v._v(" "),e("li",[v._v("工程化相关")])])]),v._v(" "),e("li",[v._v("vue3源码历史\n"),e("ol",[e("li",[v._v("历史文章导读")]),v._v(" "),e("li",[v._v("未完成事项")])])]),v._v(" "),e("li",[v._v("babel-react 实现 jsx\n"),e("ol",[e("li",[v._v("setup + template 对比 function + jsx 的优点")])])]),v._v(" "),e("li",[v._v("vite -> uuzpack 过程\n"),e("ol",[e("li",[v._v("vite 和 webpack 优点")]),v._v(" "),e("li",[v._v("实现过程")]),v._v(" "),e("li",[v._v("产生的结果")]),v._v(" "),e("li",[v._v("后续展望")])])]),v._v(" "),e("li",[v._v("vue3 h函数\n"),e("ol",[e("li",[v._v("h函数的改进和优点")]),v._v(" "),e("li",[v._v("多个h函数的分工")])])]),v._v(" "),e("li",[v._v("实现一个 render\n"),e("ol",[e("li",[v._v("从API匹配开始")]),v._v(" "),e("li",[v._v("套上已有api")])])]),v._v(" "),e("li",[v._v("后续规划\n"),e("ol",[e("li",[v._v("webComponent方案?")]),v._v(" "),e("li",[v._v("编译器相关")]),v._v(" "),e("li",[v._v("修复已有补丁")])])]),v._v(" "),e("li",[v._v("为自己打卡")])])])}),[],!1,null,null,null);_.default=t.exports}}]); -------------------------------------------------------------------------------- /md/flutter/ISSUE.md: -------------------------------------------------------------------------------- 1 | # Flutter 使用经验 2 | 3 | > 自己mark一下 4 | 5 | 6 | ## 更改 Flutter 桌面项目名 7 | 8 | * Android 是在 AndroidManifest.xml 中修改 9 | * flutter_ui\android\app\src\main\AndroidManifest.xml 10 | * 修改 `android:label="蘑菇碳"` 11 | * iOS 则是在 Info.plist 中修改的 12 | * flutter_ui\ios\Runner\Info.plist 13 | * 修改`CFBundleName`下面的`蘑菇碳` 14 | 15 | 16 | ## 更改 Flutter 桌面项目图片 17 | 18 | * Android 在 flutter_ui\android\app\src\main\res 下各种规格图片 19 | * ios 在 flutter_ui\ios\Runner\Assets.xcassets\AppIcon.appiconset 下配置 20 | 21 | 22 | ## 版本升级 23 | 24 | Flutter的版本升级通过`flutter_downloader`(包下载) + `permission_handler`(权限管理) + `path_provider`(下载路径管理)协助完成 25 | 26 | PS: flutter_downloader 插件有毒,推使用 1.1.9版本。后面的版本有各种BUG(虽然功能也多了点) 27 | 28 | 29 | ## 配置不同的运行环境 30 | 31 | > 区分开发、测试、生产环境 32 | 33 | * 运行:`flutter run -target lib/main_dev.dart` (`-target` 可以缩小为 `-t`) 34 | * 打包:`flutter build apk -t lib/main_prod.dart` (ios同理) 35 | 36 | 当然`:)`如果通过编辑器/.bat来配置就更完美了。 37 | 38 | 39 | ## Android 打包后不能访问网络问题 40 | 41 | > 需要配置:使用权限申请 42 | 43 | 分别在`android/src/profile/AndroidManifest.xml`和`android/src/main/AndroidManifest.xml`添加配置 44 | 45 | ``` 46 | // 47 | 48 | 49 | 50 | 51 | // 52 | ``` 53 | 然后就能访问网络了 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /docs/assets/js/77.7f7a727a.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[77],{448:function(t,n,e){"use strict";e.r(n);var s=e(42),i=Object(s.a)({},(function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"如果让网页更流畅"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#如果让网页更流畅"}},[t._v("#")]),t._v(" 如果让网页更流畅")]),t._v(" "),e("h1",{attrs:{id:"todo"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#todo"}},[t._v("#")]),t._v(" TODO")]),t._v(" "),e("p",[t._v("60Hz,16.7ms")]),t._v(" "),e("p",[t._v("如何避免长任务")]),t._v(" "),e("ul",[e("li",[t._v("Web Worker")]),t._v(" "),e("li",[t._v("Time Slicing(时间切片),比如React的"),e("code",[t._v("fiber")])])]),t._v(" "),e("p",[t._v("时间分片")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v(" function init({ sliceList, callback }) {\n if (!isFunction(callback)) {\n return new Error('不是function');\n }\n // 添加切片队列\n this.generator = this.sliceQueue({\n sliceList,\n callback\n });\n // 开始切片\n this.next();\n }\n\n function* sliceQueue({ sliceList, callback }) {\n let listOrNum = (isNum(sliceList) && sliceList) || (isArray(sliceList) && sliceList.length);\n for (let i = 0; i < listOrNum; ++i) {\n const start = performance.now();\n callback(i);\n while (performance.now() - start < 16.7) {\n yield;\n }\n }\n }\n")])])])])}),[],!1,null,null,null);n.default=i.exports}}]); -------------------------------------------------------------------------------- /md/flutter/BRIEF.md: -------------------------------------------------------------------------------- 1 | # flutter 2 | 3 | ### Flutter 简介 4 | 5 | > Flutter是Google的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 6 | 7 | Flutter使用自绘UI+原生实现(使用自己的Skia引擎来绘 制 widget)。 8 | * Flutter借鉴的是React思想,页面使用Widget搭建 9 | * Widget就相当于一个UI库 10 | 11 | Flutter中有四⼤线程,Platform Task Runner 、UI Task Runner、GPU Task Runner 和 IO Task Runner。运行机制和JS类似。 12 | 13 | 对于 Flutter ⽽⾔,整个屏幕都是⼀块画布,我们通过各种 Offset 和 Rect 确定了位置,然后通过 PaintingContext 的 Canvas 绘制上去,⽬标是整个屏幕区域,整个屏幕就是⼀帧,每次改变都是重新绘制。 14 | 15 | ### 优势: 16 | * 对外提供了完全不依赖系统平台的 Widget 的能力 17 | * 只通过自绘图形的方式工作(Skia),而 Android 自带 Skia 18 | * 因此具有极其优秀的跨平台性(iOS和Android的效果基本完全一致) 19 | * 目前已经支持了 iOS、Android、Fuchsia 20 | * Dart支持JIT和AOT 21 | * 支持热重载 22 | * 应用程序速度快。 23 | 24 | ### 环境搭建 25 | [https://flutter.dev/](https://flutter.dev/) 26 | 27 | ### Widget 28 | 29 | 在 Flutter 中,⼀切的显示都是 Widget 。Widget 是通过 state 跨帧实现管理数据状态的,(类似于React) 30 | 31 | 渲染经历了从 Widget 到 Element 再到 RenderObject 的过程。 32 | 33 | Flutter 中的根Widget 是`RenderObjectToWidgetAdapter`,根 Widget 的 child 就是我们在void runApp(Widget app)中传入的自定义 Widget。 34 | 35 |
36 | 37 | ![widget](../img/widget.png) 38 | 39 |
40 | 41 | 42 | Widget 分为 有状态(`StatefulWidget`)和 ⽆状态(`StatelessWidget`)两种,在 Flutter 中每个⻚⾯都是⼀帧,⽆状态就是保持在那⼀帧,⽽有状态的 Widget 当数据更新时,其实是绘制了新的 Widget,只是 State 实现了跨帧的数据同步保存。 43 | 44 | State 中主要的生命周期: 45 | * `initState` :初始化,理论上只有初始化⼀次,第⼆篇中会说特殊情况下。 46 | * `didChangeDependencies`:在 initState 之后调⽤,此时可以获取其他 State 。 47 | * `dispose` :销毁,只会调⽤⼀次。* 48 | 49 | 在Flutter中,要主动改变⼦控件的状态,还可以使⽤ `GlobalKey` 。 50 | 51 | 52 | 具体每个Widget的使用方式和展现:[Flutter-UI](https://github.com/zhongmeizhi/flutter-UI) 53 | 54 | 55 | # Flutter 实现原理 56 | 57 | 渲染 58 | ![渲染](../img/flutter_render.png) 59 | 60 | 状态 61 | ![状态](../img/flutter_state.png) 62 | 63 | GPU 64 | ![GPU](../img/flutter_GPU.png) 65 | 66 | -------------------------------------------------------------------------------- /docs/assets/js/52.a265ba2e.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[52],{420:function(t,s,e){"use strict";e.r(s);var i=e(42),a=Object(i.a)({},(function(){var t=this,s=t.$createElement,e=t._self._c||s;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"github的host和key"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#github的host和key"}},[t._v("#")]),t._v(" GitHub的Host和Key")]),t._v(" "),e("h3",{attrs:{id:"解决github不能访问的问题"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#解决github不能访问的问题"}},[t._v("#")]),t._v(" 解决GitHub不能访问的问题")]),t._v(" "),e("ol",[e("li",[e("p",[t._v("修改Host")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v(" # github\n 204.232.175.78 https://documentcloud.github.com\n 207.97.227.239 https://github.com\n 204.232.175.94 https://gist.github.com\n 107.21.116.220 https://help.github.com\n 207.97.227.252 https://nodeload.github.com\n 199.27.76.130 https://raw.github.com\n 107.22.3.110 https://status.github.com\n 204.232.175.78 https://training.github.com\n 207.97.227.243 https://www.github.com\n")])])])]),t._v(" "),e("li",[e("p",[t._v("刷新DNS:控制台输入"),e("code",[t._v("ipconfig/flushdns")])])])]),t._v(" "),e("h3",{attrs:{id:"git-key获取"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#git-key获取"}},[t._v("#")]),t._v(" Git Key获取")]),t._v(" "),e("ol",[e("li",[t._v("在git bash中运行"),e("code",[t._v('ssh-keygen -t rsa -C "git user"')])]),t._v(" "),e("li",[t._v("此时会在"),e("code",[t._v("C:\\Users\\jack\\.ssh")]),t._v("文件夹内生成"),e("code",[t._v("id_rsa.pub")]),t._v("和"),e("code",[t._v("id_rsa")])]),t._v(" "),e("li",[t._v("复制"),e("code",[t._v("id_rsa.pub")]),t._v("的内容(就是key)")]),t._v(" "),e("li",[t._v("放置于github -> setting -> SSH keys中(title随意)")])])])}),[],!1,null,null,null);s.default=a.exports}}]); -------------------------------------------------------------------------------- /docs/assets/js/69.455158fe.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[69],{438:function(e,r,s){"use strict";s.r(r);var t=s(42),a=Object(t.a)({},(function(){var e=this,r=e.$createElement,s=e._self._c||r;return s("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[s("h1",{attrs:{id:"rxjs学习-之-scheduler"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#rxjs学习-之-scheduler"}},[e._v("#")]),e._v(" RXJS学习 之 Scheduler")]),e._v(" "),s("blockquote",[s("p",[e._v("Scheduler允许定义Observable将哪些执行上下文传递给其Observer的通知")])]),e._v(" "),s("h3",{attrs:{id:"调度器:scheduler"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#调度器:scheduler"}},[e._v("#")]),e._v(" 调度器:Scheduler")]),e._v(" "),s("p",[e._v("官网翻译:")]),e._v(" "),s("p",[e._v("什么是调度程序?调度程序控制订阅何时开始以及何时传递通知。它由三个部分组成。")]),e._v(" "),s("ul",[s("li",[e._v("调度程序是一种数据结构。它知道如何根据优先级或其他标准存储和排队任务。")]),e._v(" "),s("li",[e._v("调度程序是执行上下文。它表示执行任务的位置和时间(例如,立即执行,或者在另一个回调机制中,例如setTimeout或process.nextTick,或动画帧)。")]),e._v(" "),s("li",[e._v("调度程序具有(虚拟)时钟。它通过now()调度程序上的getter方法提供了“时间”的概念。在特定调度程序上调度的任务将仅遵循该时钟表示的时间。")])]),e._v(" "),s("h3",{attrs:{id:"使用-scheduler"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#使用-scheduler"}},[e._v("#")]),e._v(" 使用 Scheduler")]),e._v(" "),s("p",[e._v("Scheduler一般在Operators中通过"),s("code",[e._v("observeOn(xxx)")]),e._v("使用,或者能接收"),s("code",[e._v("Scheduler")]),e._v("参数的方法(例如:of、from、interval、timer、concat、merge 等)中使用。")]),e._v(" "),s("p",[e._v("使用方法:")]),e._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[e._v(" of(1, 2, 3, 4).pipe(\n observeOn(asyncScheduler), // 异步\n ).subscribe(console.log)\n")])])]),s("ul",[s("li",[e._v("asapScheduler // 同步")]),e._v(" "),s("li",[e._v("asyncScheduler // 异步")]),e._v(" "),s("li",[e._v("animationFrameScheduler // requestAnimationFrame")])])])}),[],!1,null,null,null);r.default=a.exports}}]); -------------------------------------------------------------------------------- /md/browser/garbage_collection.md: -------------------------------------------------------------------------------- 1 | # JS垃圾回收机制 2 | 3 | > 垃圾回收是靠平台实现的,如:JVM,V8。所以c++和c就没有垃圾回收机制。 4 | 5 | 会讲述以下内容 6 | 1. 垃圾回收概念 7 | 2. V8引擎的垃圾回收过程 8 | 3. 各种垃圾回收算法 9 | 4. 内存泄露 10 | 11 | ### 为什么JS会有垃圾回收机制? 12 | 13 | 一个软件系统最重要的就是:快速、经济、可靠 14 | 15 | 类型检查是一种有效的,被充分研究的技术(成熟),它可以被用于捕捉程序中的不一致性,它可以用来检测一些错误(可靠)。 16 | 17 | 垃圾收集机制是:在`效率`和`易编程`及软件`可靠性`之间进行的`折中处理`的极好方式 18 | 19 | 出自:《编译原理》 20 | 21 | ### JS 垃圾回收 22 | 23 | 首先涉及2个概念:栈和堆。 24 | 25 | * 栈(stack) 26 | * 存放原始值,引用 27 | * 后进后出 28 | * 连续的储存空间,空间小,读写快 29 | * 堆(heap) 30 | * 存放引用的值 31 | * 先进先出 32 | * 散列的储存空间,空间大,读写慢 33 | 34 | 题外话:JS的.unshift()会比.pop()要慢,见(JS语言精粹) 35 | 36 | 堆的内存由特定的垃圾回收算法进行。 37 | 38 | ### V8引擎 的垃圾回收过程 39 | 40 | 首先采用**分代算法**将堆中对象分为2类:新生代 和 老生代 41 | 42 | **新生代** 43 | 44 | > 新生代中存放新的对象。可用空间为老生代的1/40。 45 | 46 | 新生代使用**复制收集算法** 47 | * 分割新生代空间 48 | * 使用中的空间称为From,闲置的空间为To。 49 | * 可达对象会被复制到To空间或晋升老生代 50 | * 对象复制完毕 From空间会被清理,然后和To空间将进行角色反转 51 | 52 | **老生代** 53 | 54 | 进入老生代的规则 55 | * 新生代复制时,To空间已使用25% 56 | * 新生代复制时,已经历过复制算法的可达对象 57 | * 大对象(具体多大?反正我不知道) 58 | 59 | 老生代 -> 三种算法 60 | 1. **标记清除** 61 | * 由于老生代大部分对象是存活的,所以采用:存活对象标记,未标记对象清除 62 | 2. **标记整理** / 压缩算法 63 | * 由于标记清除会产生大量的内存碎片,内存碎片不一定能容纳大对象。所以需要标记整理 64 | * 标记整理方法是:将所有存活对象往一端移动 65 | 3. **增量标记** 66 | * 将标记阶段分为若干小步骤,解决垃圾回收时可能的卡顿问题 67 | 68 | ### 如何判断对象是否存活? 69 | 70 | 判断堆内存是否存活使用的是**可达性算法** 71 | 72 | 可达性:通过一系列的GC Roots的对象作为起始点,从这些根节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。 -> 即对象是否在自上而下的引用链中 73 | 74 | ### WeakSet 和 WeakMap 75 | 76 | 弱引用:对于值的引用都是不计入垃圾回收机制 77 | 78 | 见 http://www.ruanyifeng.com/blog/2017/04/memory-leak.html 79 | 80 | ### 内存泄露 81 | 82 | > 内存泄露就是垃圾未被回收 83 | 84 | 如: 85 | 1. 古老的**引用计数算法**,在处理循环引用是会出现内存泄露 86 | * 引用计数即:计算引用次数是否为 0 87 | 2. 事件线程中未清理的事件 88 | 89 | **内存泄露的查询** 90 | 91 | Chrome浏览器 -> Performance 勾选 Memory -> 录制 -> 会展示Heap占用情况 92 | 93 | -------------------------------------------------------------------------------- /docs/assets/js/22.a4b7c25c.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[22],{377:function(t,a,r){"use strict";r.r(a);var e=r(42),v=Object(e.a)({},(function(){var t=this,a=t.$createElement,r=t._self._c||a;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"《mokou的小书房》"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#《mokou的小书房》"}},[t._v("#")]),t._v(" 《Mokou的小书房》")]),t._v(" "),r("blockquote",[r("p",[t._v("因博客改动频繁,建议通过 star/watch 追更。")])]),t._v(" "),r("h2",{attrs:{id:"序言"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#序言"}},[t._v("#")]),t._v(" 序言")]),t._v(" "),r("p",[t._v("从2019年3月份开始写读书笔记。主要是为了记录自己的学习轨迹和备忘,同时分享下技术心得。希望每年回顾上一年收获的时候,不会因为虚度光阴而悔恨。")]),t._v(" "),r("p",[t._v("喜欢请Star。")]),t._v(" "),r("p",[t._v("见解有限,如有描述不当之处,请帮忙及时指出,如有错误,会及时修正。")]),t._v(" "),r("p",[t._v("如果看完本文后,有看不懂的地方请回复我,一定是我写的不够清楚,我改。。。")]),t._v(" "),r("h2",{attrs:{id:"_2020阶段性感悟"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#_2020阶段性感悟"}},[t._v("#")]),t._v(" 2020阶段性感悟")]),t._v(" "),r("p",[t._v("学习应该学以致用,技术应该服务于业务。以后的学习会围绕下面主题:")]),t._v(" "),r("ol",[r("li",[t._v("该xx有什么特点?")]),t._v(" "),r("li",[t._v("该xx解决了什么问题?")]),t._v(" "),r("li",[t._v("xx和yy的对比优劣如何?")]),t._v(" "),r("li",[t._v("具有什么应用场景?")])]),t._v(" "),r("h3",{attrs:{id:"vue3-源码深入浅出连载中"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#vue3-源码深入浅出连载中"}},[t._v("#")]),t._v(" Vue3 源码深入浅出连载中...")]),t._v(" "),r("ul",[r("li",[t._v("mini版vue3源码地址:"),r("a",{attrs:{href:"https://github.com/zhongmeizhi/uuz",target:"_blank",rel:"noopener noreferrer"}},[t._v("uuz"),r("OutboundLink")],1)])]),t._v(" "),r("h2",{attrs:{id:"最后"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#最后"}},[t._v("#")]),t._v(" 最后")]),t._v(" "),r("ul",[r("li",[t._v("更多精彩请关注微信公众号:"),r("strong",[t._v("前端进阶课")])])]),t._v(" "),r("p",[r("img",{attrs:{src:"/fed-note/ewm.png",alt:"微信公众号-前端进阶课"}})])])}),[],!1,null,null,null);a.default=v.exports}}]); -------------------------------------------------------------------------------- /docs/assets/js/65.7af8568e.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[65],{435:function(e,o,t){"use strict";t.r(o);var v=t(42),r=Object(v.a)({},(function(){var e=this,o=e.$createElement,t=e._self._c||o;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"promise"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#promise"}},[e._v("#")]),e._v(" Promise")]),e._v(" "),t("blockquote",[t("p",[e._v("Promise 是一个对象,它代表了一个异步操作的最终完成或者失败。")])]),e._v(" "),t("h3",{attrs:{id:"promise-概念"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#promise-概念"}},[e._v("#")]),e._v(" Promise 概念")]),e._v(" "),t("p",[e._v("一个 Promise有以下几种状态:")]),e._v(" "),t("ul",[t("li",[t("code",[e._v("pending")]),e._v(": 初始状态,既不是成功,也不是失败状态。")]),e._v(" "),t("li",[t("code",[e._v("fulfilled")]),e._v(": 意味着操作成功完成。")]),e._v(" "),t("li",[t("code",[e._v("rejected")]),e._v(": 意味着操作失败。")])]),e._v(" "),t("p",[e._v("不同于“老式”的传入回调,在使用 Promise 时,会有以下约定:")]),e._v(" "),t("ul",[t("li",[e._v("在 本轮 "),t("code",[e._v("Javascript event loop")]),e._v("(事件循环)运行完成 之前,回调函数是不会被调用。")]),e._v(" "),t("li",[e._v("通过 "),t("code",[e._v("then()")]),e._v(" 添加的回调函数总会被调用,即便它是在异步操作完成之后才被添加的函数。")]),e._v(" "),t("li",[e._v("通过多次调用 "),t("code",[e._v("then()")]),e._v(",可以添加多个回调函数,它们会按照插入顺序一个接一个独立执行。")])]),e._v(" "),t("p",[e._v("因为 Promise.prototype.then 和 Promise.prototype.catch 方法返回promise 对象, 所以它们可以被链式调用。")]),e._v(" "),t("p",[e._v("Promise的 4 个方法")]),e._v(" "),t("ol",[t("li",[e._v("Promise.all(iterable)")]),e._v(" "),t("li",[e._v("Promise.race(iterable)")]),e._v(" "),t("li",[e._v("Promise.resolve(value)")]),e._v(" "),t("li",[e._v("Promise.reject(reason)")])]),e._v(" "),t("p",[e._v("Promise的 prototype")]),e._v(" "),t("ol",[t("li",[e._v("Promise.prototype.catch(onRejected)")]),e._v(" "),t("li",[e._v("Promise.prototype.then(onFulfilled, onRejected)")]),e._v(" "),t("li",[e._v("Promise.prototype.finally(onFinally)")])])])}),[],!1,null,null,null);o.default=r.exports}}]); -------------------------------------------------------------------------------- /md/advance/co_text.md: -------------------------------------------------------------------------------- 1 | # JS 执行上下文 2 | 3 | 1. 宿主(浏览器和node)和v8的关系 4 | 1. node和浏览器事件循环系统不一致 5 | 2. dom操作会很慢? 6 | 2. v8的执行过程 编译 执行 热代码 7 | 3. 声明、 if、严格模式 8 | 1. 为什么会有变量提升? 9 | 1. 因为js代码解析的结果会放到内存中 10 | 2. 所以v8的js代码采用惰性解析 11 | 2. 为什么let和const有暂时性的死区? 12 | 1. 在预解析阶段并没有提前声明 13 | 2. let、const存放在上下文的词法环境中 14 | 1. 由于该变量在词法环境中,所以可以做成块级作用域 15 | 4. 堆栈结构、执行上下文,执行上下文的垃圾回收 16 | 1. 为什么采用堆栈结构? 17 | 1. 方便移交控制权 18 | 2. 执行上下文不同ES版本会不一样 19 | 3. 堆栈结构的栈溢出和异常提示 20 | 4. 解决栈溢出问题,协程和尾递归(部分没有) 21 | 5. 调用栈的垃圾回收 22 | 1. esp寄存器保存栈顶指针 23 | 2. 当调用栈执行完成后,挪动栈顶指针, 24 | 3. 下一次入栈时从指针开始进行覆盖 25 | 5. 变量环境和作用域链寻址 26 | 6. 块状结构、词法环境 27 | 7. 堆内存和栈内存 28 | 1. 栈内存的好处(快)是线性结构的连续空间,堆内存(慢)是非连续空间 29 | 2. 同理,计算机中有cpu的寄存器,内存,硬盘都可以存放数据,而硬盘存放的量最大,为什么不把数据都放到硬盘中? 30 | 8. 对象的字典结构和链式结构,快属性和慢属性 31 | 9. unshift 和 push 32 | 10. 函数和为什么基于原形而不是基于类 33 | 11. 闭包 colsure,编译阶段,垃圾回收 34 | 12. 自执行函数anonymous 和(小括号) 35 | 36 | 全局执行上下文在 V8 的生存周期内是不会被销毁 37 | 38 | ## 为什么会出现变量提升? 39 | 40 | 讲变量提升之前先介绍下编程语言的有2种编译方式:`JIT` 和 `AOT`。 41 | 42 | * AOT (Ahead-Of-Time - 预先编译) 43 | * 编译步骤:词法分析 -> 语法分析 -> 语义检查 -> 代码优化和字节码生成 44 | * JIT(Just-In-Time - 实时编译) 45 | * 编译步骤:词法分析 -> 语法分析 -> 语法树 -> 解释执行 46 | 47 | ps:具体js的语法分析结果可以查看:[JS语法分析成语法树](https://esprima.org/demo/parse.html#) 48 | 49 | 每种编译方式都有各自的优缺点,这里以js为例,js属于jit编译,这样的好处是可以做到动态的代码生成,也不会出现在引入js文件时出现长时间的编译操作。 50 | 51 | ### js解释执行 52 | 53 | js解释执行严格按照js作用域链(scope chain)机制执行的, 54 | 55 | 56 | 57 | 58 | 59 | ### 调用栈 60 | 61 | 栈也是一种数据结构,它是一种运算受限的线性表,限定在表尾进行插入和删除。向栈顶插入元素叫`入栈`,从栈顶删除元素叫`出栈` 62 | 63 | 而调用栈是计算机科学中存储有关正在运行的子程序的消息的栈,几乎所有计算机程序都依赖于调用栈。调用栈的主要功能是**存放返回地址** 64 | 65 | 举一个递归调用栈的栗子 66 | 67 | ```js 68 | function fact(x) { 69 | if (x == 1) return 1; 70 | return x * fact(x - 1); 71 | } 72 | ``` 73 | 74 | 使用一个图解算法中的案例:(灵魂画手正在路上) 75 | 76 | ![stack](../img/algorithm/stack.png) 77 | 78 | 79 | 注意:调用栈中每个函数都有自己的变量: 80 | 81 | 既然说到了调用栈,这里就再举一反三谈谈js的作用域。 82 | 83 | 84 | 调用栈的用处: 85 | 86 | 1. 异常捕获:由于是堆栈的形式,当一个函数出错时很方便的可以追溯到调用它的函数和一些其他出错信息。 87 | -------------------------------------------------------------------------------- /md/sse/scaffold.md: -------------------------------------------------------------------------------- 1 | # 搭建一个自己的前端项目 2 | 3 | 项目相关 4 | 5 | ### 搭建脚手架 6 | 7 | 案例:[https://www.npmjs.com/package/create-fv-cli](https://www.npmjs.com/package/create-fv-cli) 8 | 9 | 脚手架重点: 10 | 11 | 1. 脚手架名称不能有冲突(可以在 npm 官网查询) 12 | 2. 脚手架入口 `package.json` -> `bin` 13 | 3. 脚手架如果名称为 `create-fv-cli` 那么 `npm init fv-cli` 可以指到 `create-fv-cli` 地址。 14 | 4. 脚手架的依赖包要放在 `dependencies` 中(否则会提示没有module) 15 | 16 | 脚手架的几种思路: 17 | 18 | 1. 最好的当然是 yyx 的利用 `fs-extra` 估计目录执行 `copy` 19 | 2. 也可以使用 commander 通过 git clone 安装 20 | 21 | 22 | ### PrerenderSPAPlugin 启动预渲染 23 | 24 | 预渲染采用 vue 推荐的 `PrerenderSPAPlugin` 插件,放入 `webpack` 就可以使用 25 | 26 | PrerenderSPAPlugin 使用 27 | 28 | ```js 29 | new PrerenderSPAPlugin({ 30 | staticDir: path.join(__dirname, 'dist'), 31 | routes: [ '/', '/about'], 32 | renderer: new PrerenderSPAPlugin.PuppeteerRenderer({ 33 | renderAfterDocumentEvent: 'render-event', 34 | // renderAfterTime: 5000 35 | }) 36 | }) 37 | ``` 38 | 39 | 在 vue 文件中通过 `renderAfterDocumentEvent` 告知 `PrerenderSPAPlugin` render 时间点,当然多个 route 需要弄多个 event 40 | 41 | ```js 42 | document.dispatchEvent(new Event('render-active')) 43 | ``` 44 | 45 | 工作流程 46 | 47 | ![prerender](../img/vue/prerender.png) 48 | 49 | 50 | ### nuxt.js 搭建 ssr 或 预渲染 51 | 52 | 直接通过 ![https://www.nuxtjs.cn/](https://www.nuxtjs.cn/) 官网就可以使用了。 53 | 54 | 55 | ### 微服务基础 single-spa 56 | 57 | 子项目: 58 | * 在开发或者单独部署时,按照各自风格编写。 59 | * 如果要集成微服务架构,需要再设置单独的打包方式,以引入`single-spa-vue`或者其他单页面插件的js文件作为入口。 60 | * 需要打包为 `library`,target可以是umd或者其他方式。 61 | ``` 62 | libraryTarget: 'umd', 63 | library: 'app1' 64 | ``` 65 | 66 | 根项目: 67 | * 引入`single-spa` 68 | * 通过`spa.registerApplication`的方式,在遇到特定`href`时加载不同的打包子项目入口文件 69 | * 在开发环境,通过代理来实现不同的遇到特定`href`代理不同的子项目。 70 | 71 | 72 | ### 阿里 qiankun 实现微服务 73 | 74 | qiankun 是基于 single-spa 的微服务框架。实现了几乎包含所有构建微前端系统时所需要的基本能力,如 样式隔离、js 沙箱、预加载等。 75 | 76 | 使用 自带的 example 77 | 78 | ``` 79 | $ git clone https://github.com/umijs/qiankun.git 80 | $ cd qiankun 81 | $ yarn install 82 | $ yarn examples:install 83 | $ yarn examples:start 84 | ``` 85 | 86 | 使用 qiankun 可以无缝兼容已有的项目...真棒呢 87 | 88 | -------------------------------------------------------------------------------- /md/flutter/render.md: -------------------------------------------------------------------------------- 1 | # Widget 渲染策略 2 | 3 | 主要讲述: 4 | * Stateful和Stateless 5 | * Key 6 | * buildContext 7 | * setState 8 | * InheritedWidget 9 | * Element 10 | * RenderObject 11 | * SteamBuilder 12 | 13 | ### Widget 14 | 15 | * 为Element提供配置信息,通过State管理状态 16 | * `StatefulWidget`通过 `key` 和 `runtimeType` 来判断是否`canUpdate` 17 | * `StatelessWidget`是不变的,不能多次渲染,只能被替换 18 | 19 | Stateful的Widget可以多次绘制更新。(运行时和setState时都会调用build方法) 20 | 21 | 每次绘制都会进入更新算法`canUpdate`:会比较`runtimeType (组件的类型和子元素的引用)` 和 `key` 22 | 23 | ``` 24 | static bool canUpdate(Widget oldWidget, Widget newWidget) { 25 | return oldWidget.runtimeType == newWidget.runtimeType 26 | && oldWidget.key == newWidget.key; 27 | } 28 | ``` 29 | 30 | key的种类(功能和名字一致) 31 | * ValueKey 32 | * ObjectKey 33 | * UniqueKey 34 | * PageStorageKey 35 | * GlobalKey 36 | 37 | 38 | 如果要重绘`Stateless`的Widget,那么必须创建新的实例。当然在`Stateless`中也并不需要使用`key`, 39 | 40 | 41 | 每个widget都有自己的context。这个context是父组件通过build方法给他返回的。比如context不匹配时调用`showSnackBar`方法会提示:`Scaffold.of() called with a context that does not contain a Scaffold`。 42 | 43 | 解决方法: 44 | 1. 可以通过 `new Builder(builder: (context) {...})` 获得context。 45 | 2. 或者将不能使用获取context的方法使用widget单独build 46 | 3. 使用`GlobalKey()`,通过key来调用 47 | 48 | 49 | 因为每个build的context不一样,所以每个不同的页面数据无法共享。(InheritedWidget 等除外) 50 | 51 | 52 | 然后,官方提出了`InheritedWidget`的类,**共享的State放在一个继承InheritedWidget的类中**,随之社区推出了[scoped_model](https://pub.dartlang.org/packages/scoped_model)的库(比Redux方便) 53 | 54 | 但是还是会存在整棵树的Widget都会更新,虽然在`ScopedModelDescendant`中有`rebuildOnChange`来阻止重新渲染(类似React的shouldComponentUpdate,当然它有竞态的问题) 55 | 56 | 不过,Scope model 使用起来很方便,如果不是复杂项目,使用 Scope model 会**容易上手**。 57 | 58 | 59 | 60 | 61 | ### Element: 62 | 63 | * `管理`底层渲染树 64 | * 最重要的属性:`dirty` 是否渲染的关键 65 | * 调用`setState({})`会执行`markNeedsBuild`标记自身为`dirty = true`, 66 | * `dirty = true`意味着会在系统下一个事件周期中重绘,会调用`build`方法 67 | 68 | 69 | 70 | ### RenderObject: 71 | 72 | * 主要负责`渲染`工作 73 | * 相当于 render树上的 一个节点 74 | 75 | 76 | 77 | ### SteamBuilder() 78 | 79 | BloC即(Business Logic Component),是一种利用reactive programming方式构建应用的方法,这是一个由流构成的完全异步的世界。 80 | 81 | * 用StreamBuilder包裹有状态的部件,streambuilder将会监听一个流 82 | * 这个流来自于BLoC 83 | * 有状态小部件中的数据来自于监听的流。 84 | * 用户交互手势被检测到,产生了事件。例如按了一下按钮。 85 | * 调用bloc的功能来处理这个事件 86 | * 在bloc中处理完毕后将会吧最新的数据add进流的sink中 87 | * StreamBuilder监听到新的数据,产生一个新的snapshot,并重新调用build方法 88 | * Widget被重新构建 89 | 90 | [参考链接](https://juejin.im/post/5bb6f344f265da0aa664d68a) -------------------------------------------------------------------------------- /md/flutter/webview.md: -------------------------------------------------------------------------------- 1 | # Flutter WebView使用 2 | 3 | > 一个完整的WebView要有与JS交互和拦截URL的功能 4 | 5 | 6 | 使用过人气很高的[flutter_webview_plugin](https://github.com/fluttercommunity/flutter_webview_plugin),但是缺少2个重要的功能。也在打开多个WebView时会出错。 7 | * 不能在JS中调用Flutter方法 8 | * 不能在H5进入某个URL之前拦截 9 | 10 | 虽然该插件不够完整,但是使用起来很方便,封装了很多功能。如果交互不多可以用该插件。 11 | 12 | ### 官方的 webview_flutter 13 | 14 | 之后使用官方的[webview_flutter](https://pub.dev/packages/webview_flutter)插件。 15 | 16 | 附: 17 | 18 | 在老版本的 Flutter WebView有在Android中无法调弹出键盘的问题,在`webview_flutter Version 0.3.10+2`中已经修复该BUG,使用最新版的Flutter SDK (`flutter _v1.7.8+hotfix.3-stable`) 19 | 20 | 见GitHub Issue:[issues/19718](https://github.com/flutter/flutter/issues/19718) 21 | 22 | 真的很好用。官方的Example也很到位哈。 23 | 24 | 25 | ### JS调用Flutter 26 | 27 | 使用实例: 28 | 29 | ``` 30 | // 定义方法 31 | JavascriptChannel _toasterJavascriptChannel(BuildContext context) { 32 | return JavascriptChannel( 33 | name: 'Toaster', 34 | onMessageReceived: (JavascriptMessage message) { 35 | Scaffold.of(context).showSnackBar( 36 | SnackBar(content: Text(message.message)), 37 | ); 38 | }); 39 | } 40 | 41 | // 暴露给WebView 42 | WebView( 43 | // ... 略 44 | javascriptChannels: [ 45 | _toasterJavascriptChannel(context), 46 | ].toSet(), 47 | ) 48 | 49 | // JS调用方法 50 | Toaster.postMessage('弹弹乐'); 51 | ``` 52 | 53 | ### Flutter调用JS 54 | 55 | ``` 56 | WebViewController _webViewController; 57 | 58 | WebView( 59 | // ... 略 60 | javascriptMode: JavascriptMode.unrestricted, // 使用JS没限制 61 | onWebViewCreated: (WebViewController webViewController) { 62 | // 在WebView创建完成后会产生一个 webViewController 63 | _webViewController = webViewController; 64 | }, 65 | ) 66 | 67 | // 之后可以调用 _webViewController 的 evaluateJavascript 属性来注入JS 68 | _webViewController.evaluateJavascript("Toaster.postMessage('弹弹乐');"); 69 | ``` 70 | 71 | ### 拦截URL 72 | 73 | ``` 74 | WebView( 75 | navigationDelegate: (NavigationRequest request) { 76 | // 判断URL 77 | if (request.url.startsWith('https://www.baidu.com')) { 78 | // 做一些事情 79 | // 阻止进入登录页面 80 | return NavigationDecision.prevent; 81 | } 82 | return NavigationDecision.navigate; 83 | }, 84 | ); 85 | ``` -------------------------------------------------------------------------------- /md/css/EXPERIENCE.md: -------------------------------------------------------------------------------- 1 | # 静态页面 细节 2 | 3 | ### box-shadow细节 4 | 5 | /* x偏移量 | y偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影颜色 */ 6 | * 可以同时定义多个阴影 7 | * 阴影扩散半径可以为负数(向内扩散) 8 | * (可以弄出很多特效) 9 | 10 | ``` 11 | box-shadow: 0 13px 0px -6px rebeccapurple, 14px 0px 0px -5px grey; 12 | ``` 13 | 14 | ### 关于层级 15 | 16 | 1. `z-index` 支持为负 17 | 2. `block` 块状盒子 18 | 3. `float` 浮动元素 19 | 4. `inline`/`inline-block` 水平盒子 20 | 5. `z-index` 支持且为正 21 | 22 | ps: 子元素的 `z-index` 只作用于父元素内部。 23 | 24 | ### flex 25 | 26 | 1. 主轴 -> `justify-content` 27 | 2. 交叉轴 -> `align-items`(单项) + `align-content`(多项) 28 | 3. 顺序 -> `order` 29 | 4. flex-grow 放大比例,默认为 0 (不放大) 30 | 5. flex-shrink 缩小比例,默认 1 (空间不足自动缩小) 31 | * 剩余空间按照 空间 * 元素放大值 / 总放大值 32 | 6. flex-basis 计算剩余空间时的元素大小,auto 表示原本大小 33 | 7. flex [flex-grow、 flex-shrink、 flex-basis],默认 [0 1 auto] 34 | 8. align-self 当前项的 align-items 35 | 36 | ### 可替换元素(img、input、select 等)伪类细节 37 | 38 | 以 `img` 标签的 `before`, `after` 为例: 39 | 1. 替换元素标准并没有清晰定义,这也导致了浏览器实现的差异性。 40 | 2. 在大多数浏览器中替换元素的 `before`, `after` 是无效的 41 | 3. 对于 `img` 这种自闭合标签,似乎不存在 `content` 42 | 43 | 44 | ### p标签 细节 45 | 46 | p标签是无法包裹块状标签的(不注意如果产生BUG) 47 | 48 | ```html 49 |

50 |

asaaa

51 | xxx 52 |
yyy
53 |

54 | ``` 55 | 56 | ### canvas有锯齿 57 | 58 | canvas具有外部画布宽高,还有内部画布宽高(canvas基础) 59 | 1. 如果内外的宽高不匹配就会产生锯齿。 60 | 2. 就算宽高等比例,因为不同手机像素问题,还是会产生锯齿。 61 | 62 | 63 | 解决方案:百度echarts框架抗锯齿实现 64 | ```js 65 | // 获取像素比 66 | const ratio = window.devicePixelRatio; 67 | 68 | // 内部画布大小 按像素比扩大 69 | context.canvas.width = _width * ratio; 70 | context.canvas.height = _height * ratio; 71 | // 外部展示 72 | $ele.width = _width; 73 | $ele.height = _height; 74 | 75 | // ps 先定内部,再定外部,顺序不能乱 76 | ``` 77 | 78 | 79 | ### 文本省略... 80 | ``` 81 | /*单行*/ 82 | .dot{ 83 | display:block /*这里设置inline-block或者block;根据使用情况来定(行内元素需要加这个,块级元素和行内块级可以不用)*/ 84 | white-space:nowrap; 85 | overflow:hidden; 86 | text-overflow:ellipsis; 87 | } 88 | 89 | /*多行*/ 90 | .dot{ 91 | text-overflow:ellipsis; 92 | overflow:hidden; 93 | display:-webkit-box; 94 | -webkit-line-clamp:2; /*这个数字是设置要显示省略号的行数*/ 95 | -webkit-box-orient:vertical; 96 | } 97 | ``` 98 | 99 | ### 改变图片背景色 100 | 101 | ``` 102 | background: url('xx'); 103 | background-blend-mode: multiply; 104 | background-color: #F6F6F6; 105 | ``` 106 | 107 | -------------------------------------------------------------------------------- /docs/assets/js/24.46de5072.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[24],{380:function(v,_,t){"use strict";t.r(_);var n=t(42),a=Object(n.a)({},(function(){var v=this,_=v.$createElement,t=v._self._c||_;return t("ContentSlotsDistributor",{attrs:{"slot-key":v.$parent.slotKey}},[t("h1",{attrs:{id:"《算法导论》-第三版"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#《算法导论》-第三版"}},[v._v("#")]),v._v(" 《算法导论》 第三版")]),v._v(" "),t("h3",{attrs:{id:"算法的作用"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#算法的作用"}},[v._v("#")]),v._v(" 算法的作用")]),v._v(" "),t("blockquote",[t("p",[v._v("算法就是求良解的计算过程")])]),v._v(" "),t("p",[v._v("数据结构是一种"),t("code",[v._v("存储")]),v._v("和"),t("code",[v._v("组织")]),v._v("数据的方式,旨在便于访问和修改。")]),v._v(" "),t("h3",{attrs:{id:"算法的效率问题:"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#算法的效率问题:"}},[v._v("#")]),v._v(" 算法的效率问题:")]),v._v(" "),t("p",[v._v("为求解相同的问题而设计的不同算法在效率方面有显著的差别。")]),v._v(" "),t("p",[v._v("拿排序举例,排序 "),t("code",[v._v("n")]),v._v(" 项")]),v._v(" "),t("ul",[t("li",[v._v("插入排序:所花时间大致等于 "),t("code",[v._v("cn^2")])]),v._v(" "),t("li",[v._v("并归排序:所花时间大致等于 "),t("code",[v._v("cnlgn")])])]),v._v(" "),t("p",[v._v("其中 "),t("code",[v._v("c")]),v._v(" 为不依赖 "),t("code",[v._v("n")]),v._v(" 的常数当 n = 1000 时, lgn 大致为 10,当 n 等于 100万 时,lgn 大致为 20。对于小规模的排序:插入排序通常比并归排序要快,超过一定点,并归排序更快。")]),v._v(" "),t("h3",{attrs:{id:"分治策略"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#分治策略"}},[v._v("#")]),v._v(" 分治策略")]),v._v(" "),t("ol",[t("li",[v._v("分解:分解成多个子问题")]),v._v(" "),t("li",[v._v("解决:分别解决每个子问题")]),v._v(" "),t("li",[v._v("合并: 将解决的结果合并")])]),v._v(" "),t("p",[v._v("举例:一段时间(n天)内做一次股票交易怎样获益最大?也就是获取一个数组中值相加最大的子数组")]),v._v(" "),t("p",[v._v("解法1:暴力解决")]),v._v(" "),t("ol",[t("li",[v._v("只要卖出日期在买入日期之后即可,n天共有 "),t("code",[v._v("n^2")]),v._v(" 种组合")])]),v._v(" "),t("p",[v._v("解法2:分治策略")]),v._v(" "),t("ol",[t("li",[v._v("获取数组的中点 "),t("code",[v._v("n/2")]),v._v(" (n/2需要取整)")]),v._v(" "),t("li",[v._v("分解:一共 3 种情况\n"),t("ol",[t("li",[v._v("子数组在 0 至 n/2 之间(在左边) -> (n^2)/4")]),v._v(" "),t("li",[v._v("子数组在 n/2 至 n 之间(在右边) -> (n^2)/4")]),v._v(" "),t("li",[v._v("子数组在 跨越了中点 n/2(就是在中点两边) -> 2n")])])]),v._v(" "),t("li",[v._v("一共需要 (n^2)/2 + 2n 次计算")])]),v._v(" "),t("h3",{attrs:{id:"算法"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#算法"}},[v._v("#")]),v._v(" 算法")]),v._v(" "),t("ol",[t("li",[v._v("矩阵的 Strassen 算法")]),v._v(" "),t("li",[v._v("代入法求解递归式")]),v._v(" "),t("li",[v._v("递归树求解递归式")]),v._v(" "),t("li",[v._v("主方法求解递归式")])]),v._v(" "),t("p",[v._v("概率分析 和 随机算法")])])}),[],!1,null,null,null);_.default=a.exports}}]); -------------------------------------------------------------------------------- /md/rxjs/Subject.md: -------------------------------------------------------------------------------- 1 | # RXJS学习 之 Subject 2 | 3 | > Subject是一种特殊类型的Observable,它允许将值多播到许多观察者。 4 | 5 | Subject继承自Observable:`declare class Subject extends Observable implements SubscriptionLike` 6 | 7 | Subject和多个Observable订阅不同点: 8 | * 多个Observable订阅,每个Observable都是独立的 9 | * Subject 的状态是统一的 10 | 11 | 12 | ### Subject 实现 13 | 14 | Subject实现起来就像EventEmitters。 15 | 16 | `Subject`自己实现了`next、error、complete、subscribe、unsubscribe`其他方法都是继承自`Observable`的 17 | ``` 18 | var subject = { 19 | observers: [], 20 | subscribe: function(observer) { 21 | this.observers.push(observer) 22 | }, 23 | next: function(value) { 24 | this.observers.forEach(o => o.next(value)) 25 | }, 26 | error: function(error){ 27 | this.observers.forEach(o => o.error(error)) 28 | }, 29 | complete: function() { 30 | this.observers.forEach(o => o.complete()) 31 | } 32 | } 33 | ``` 34 | 35 | ### Subject 36 | 37 | ``` 38 | import { Subject, from } from "rxjs"; 39 | 40 | const subject = new Subject(); 41 | 42 | // 多个订阅 43 | subject.subscribe({ 44 | next: (v) => console.log('observerA: ' + v) 45 | }) 46 | subject.subscribe({ 47 | next: (v) => console.log('observerB: ' + v) 48 | }) 49 | 50 | // Observable 51 | var observable = from([1,2,3]); 52 | 53 | // 使用Subject订阅 54 | observable.subscribe(subject); 55 | ``` 56 | 57 | ### BehaviorSubject 58 | 59 | 在开始订阅时,就尝试获取并使用最后一次发送的元素。 60 | 61 | ``` 62 | var subject = new BehaviorSubject(0); // 0 为起始值 63 | var observerA = { 64 | ... 65 | } 66 | 67 | var observerB = { 68 | ... 69 | } 70 | 71 | subject.subscribe(observerA); 72 | subject.next(1); 73 | subject.next(2); 74 | 75 | setTimeout(() => { 76 | subject.subscribe(observerB); 77 | subject.next(3); 78 | },3000) 79 | 80 | // 0 1 2 81 | // 3秒后 2 3 3 82 | ``` 83 | 84 | ### ReplaySubject 85 | 86 | 使用方法同上,`ReplaySubject(bufferSize, windowTime)`,一般用来缓存bufferSize个元素 87 | 88 | 89 | ### AsyncSubject 90 | 91 | 使用方法同上,AsyncSubject() 只返回最后一个值。类似于`last()`操作符 92 | 93 | 94 | ### Observable转换Subject 95 | 96 | * multicast:用来挂载 subject,返回具有connect方法的observable 97 | * connect() 后才会真的用 subject 订阅 98 | * refCount:可以建立一个只要有订阅就会自动 connect 的 observable 99 | * publish = `multicast(new Rx.Subject())` 100 | * share = `publish + refCount` -------------------------------------------------------------------------------- /md/javascript/useful_features.md: -------------------------------------------------------------------------------- 1 | # 好用的新特性 2 | 3 | ### offsetParent 各种偏移系列 4 | 5 | > 能获取到定位父元素,也很方便的获取到偏移值 6 | 7 | PS: PC端兼容不错,获取偏移很方便 8 | 9 | `HTMLElement.offsetParent` 是一个只读属性,返回一个指向最近的(指包含层级上的最近)`包含该元素的定位元素`或者最近的 table,td,th,body元素。 10 | * `offsetParent` 是要有定位的父元素 (position不等于static),或者 table/td/th/body。 11 | * `offsetParent` 如果自身是 `display: fixed;` 那么其定位父元素为视窗 12 | * 当元素的 `style.display` 设置为 `none` 时,offsetParent 返回 `null` 13 | * `offsetTop` 和 `offsetLeft` 都是相对于其内边距边界的。 14 | 15 | 16 | ### getBoundingClientRect: 获取边界框客户矩形 17 | 18 | > Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。 19 | 20 | PS: PC端兼容不错,获取相对视口位置很方便 21 | 22 | left、top、right、bottom,单位为像素,位置都是**相对于视口的左上角**位置而言的 23 | 24 | ![bounding](../img/bounding.png) 25 | 26 | [参考 MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect) 27 | 28 | 29 | 30 | ### getComputedStyle: 获取元素样式 31 | 32 | > 方法返回一个对象,该对象在应用活动样式表并解析这些值可能包含的任何基本计算后报告元素的所有CSS属性的值。(能获取伪元素的值) 33 | 34 | PC端兼容不错,优势:可以获取到伪元素。 35 | 36 | `let style = window.getComputedStyle(element, [pseudoElt]);` pseudoElt指:伪元素 37 | 38 | [参考 MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/getComputedStyle) 39 | 40 | 41 | 42 | ### IntersectionObserverEntry:交叉点监听条目 43 | 44 | > 描述了 目标元素 与其 根元素容器 在某一特定过渡时刻的交叉状态. 45 | 46 | PS: 兼容性堪忧 47 | 48 | [参考1 MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserverEntry) 49 | [参考2 阮一峰大佬](http://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html) 50 | 51 | 52 | ### window.requestIdleCallback() 请求懒回调 53 | 54 | > 将在浏览器的空闲时段内调用的函数排队. 55 | 56 | PS: 兼容性堪忧 57 | 58 | 这使开发人员能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应。函数一般会按先进先调用的顺序执行,然而,如果回调函数指定了执行超时时间timeout,则有可能为了在超时前执行函数而打乱执行顺序。 59 | 60 | [参考 MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback) 61 | 62 | 63 | ### css 属性 scroll-snap-align 64 | 65 | PS:PC端兼容性一般,移动端兼容性很差 66 | 67 | 滚动的对齐方式,对做轮播图什么的很方便 68 | 69 | 70 | ### MutationObserver 71 | 72 | 监听DOM的变化,(是个微任务) 73 | 74 | ps: 大部分浏览器都能用,包括IE11。。。 75 | 76 | [参考](https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver) 77 | 78 | 79 | ### shadow DOM 80 | 81 | > 一个可以隔离样式的 DOM 元素,可以配合 Web Components 使用 82 | 83 | 原生 input 使用了该属性。 84 | 85 | ps: 兼容性就这样吧 86 | 87 | [参考](https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_shadow_DOM) 88 | 89 | 90 | ### customElements 91 | 92 | > Web Components 标准非常重要的一个特性是,它使开发者能够将HTML页面的功能封装为 custom elements 93 | 94 | ps: 兼容性就这样吧 95 | 96 | [参考](https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_custom_elements) 97 | -------------------------------------------------------------------------------- /md/flutter/SCENES.md: -------------------------------------------------------------------------------- 1 | # 环境问题 2 | 3 | ### Flutter 找不到虚拟机 4 | 5 | 解决方案 6 | 1. 检查ADB 环境 7 | 2. 检查SDK PATH 8 | 3. 清除缓存 9 | 10 | . 11 | 12 | ### Windows开发环境 访问localhost 13 | 14 | 访问会报错:SocketException: OS Error: Connection refused 15 | 16 | > android模拟器中使用 localhost会指向模拟机本机 17 | 18 | 解决方案: 在控制台运行:`adb reverse tcp:8080 tcp:8080` 19 | 20 | 解决方案2: 直接访问自己的IP 如: `http://10.93.157.10:2333` 21 | 22 | . 23 | 24 | ### android无法联网问题 25 | 26 | > emulator -avd 虚拟机名称 -dns-server 8.8.8.8,114.114.114.114 27 | 28 | 1. 进入 C:\Users\zmz\.android\avd 查看虚拟机名称 29 | 2. 进入 C:\Users\zmz\AppData\Local\Android\Sdk\emulator 打开控制台 30 | 3. 运行`emulator -avd 虚拟机名称 -dns-server 8.8.8.8,114.114.114.114` 31 | 32 | . 33 | 34 | ### Flutter Resolving dependencies... 卡住的问题 35 | 36 | > 感谢伟大的中国长城防火墙 37 | 38 | 解决方案: 39 | 40 | 配置用户环境变量,使用中国的Flutter镜像包: 41 | ``` 42 | PUB_HOSTED_URL ==> https://pub.flutter-io.cn 43 | 44 | FLUTTER_STORAGE_BASE_URL ==> https://storage.flutter-io.cn 45 | ``` 46 | 47 | 修改android/build.gradle默认的配置: 48 | ``` 49 | buildscript { 50 | repositories { 51 | // maven 阿里镜像地址 52 | maven{ url 'https://maven.aliyun.com/repository/google'} 53 | maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'} 54 | maven{ url 'https://maven.aliyun.com/repository/public'} 55 | maven{ url 'https://maven.aliyun.com/repository/jcenter'} 56 | google() 57 | jcenter() 58 | } 59 | 60 | dependencies { 61 | classpath 'com.android.tools.build:gradle:3.2.1' 62 | } 63 | } 64 | 65 | allprojects { 66 | repositories { 67 | // maven 阿里镜像地址 68 | maven{ url 'https://maven.aliyun.com/repository/google'} 69 | maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'} 70 | maven{ url 'https://maven.aliyun.com/repository/public'} 71 | maven{ url 'https://maven.aliyun.com/repository/jcenter'} 72 | google() 73 | jcenter() 74 | } 75 | } 76 | ``` 77 | 78 | 修改flutter\packages\flutter_tools\gradle\flutter.gradle配置 79 | ``` 80 | buildscript { 81 | repositories { 82 | // maven 阿里镜像地址 83 | maven{ url 'https://maven.aliyun.com/repository/google'} 84 | maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'} 85 | maven{ url 'https://maven.aliyun.com/repository/public'} 86 | maven{ url 'https://maven.aliyun.com/repository/jcenter'} 87 | google() 88 | jcenter() 89 | } 90 | dependencies { 91 | classpath 'com.android.tools.build:gradle:3.2.1' 92 | } 93 | } 94 | ``` 95 | 96 | -------------------------------------------------------------------------------- /docs/assets/js/23.e5031cc2.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[23],{381:function(t,s,a){"use strict";a.r(s);var n=a(42),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"《图解算法》-读书笔记"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#《图解算法》-读书笔记"}},[t._v("#")]),t._v(" 《图解算法》 读书笔记")]),t._v(" "),a("h2",{attrs:{id:"二分法"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#二分法"}},[t._v("#")]),t._v(" 二分法")]),t._v(" "),a("blockquote",[a("p",[t._v("对有序元素列表(必须是有序列表),每次都从中间查找,找到某个元素的位置。")])]),t._v(" "),a("p",[t._v("二分法的时间复杂度是 "),a("code",[t._v("O(log n)")])]),t._v(" "),a("p",[t._v("用 js 实现一个二分法查找:// TODO: 自己写一个吧")]),t._v(" "),a("div",{staticClass:"language-js extra-class"},[a("pre",{pre:!0,attrs:{class:"language-js"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 二分法")]),t._v("\n\n")])])]),a("h2",{attrs:{id:"选择排序"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#选择排序"}},[t._v("#")]),t._v(" 选择排序")]),t._v(" "),a("p",[t._v("比如现在有一个列表,里面记录了歌曲名称和播放次数,现在需要根据歌曲的播放次数进行排序。")]),t._v(" "),a("p",[t._v("有如下歌曲")]),t._v(" "),a("div",{staticClass:"language-js extra-class"},[a("pre",{pre:!0,attrs:{class:"language-js"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" musicList "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'歌曲1'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n num"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("123")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'歌曲2'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n num"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("13")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...略")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n")])])]),a("p",[t._v("如果使用冒泡法,需要时间为 O(n^2)")]),t._v(" "),a("p",[t._v("// TODO: 55页:分治")])])}),[],!1,null,null,null);s.default=e.exports}}]); -------------------------------------------------------------------------------- /md/javascript/animation.md: -------------------------------------------------------------------------------- 1 | # 关于前端动画效果 2 | 3 | ### 动画注意点 4 | 5 | 浏览器可以生成多个图层(普通文档流也是一个图层)。不同的图层渲染互不影响,所以对于需要频繁渲染的操作,最好单独生成一个新图层。 6 | 7 | 生成新图层的方式 8 | * will-change 9 | * 3D 变换:translate3d、translateZ 10 | * 通过动画实现的 opacity 动画转换 11 | * position: fixed 12 | * video、iframe 标签 13 | 14 | ### requestAnimateFrame 15 | 16 | > window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画 17 | 18 | 回调函数执行次数通常与浏览器屏幕刷新次数相匹配,通常是每秒60次。 19 | 20 | 和setTimeout的区别 21 | 1. 当requestAnimationFrame() 运行在后台标签页或者隐藏的` 66 | 67 | // JS 68 | // 由于没有同源策略的限制,钓鱼网站可以直接拿到别的网站的Dom 69 | // 所以 饼夕夕.com 可以在 拼多多.com 输入账号密码处埋点 70 | 71 | const $iframe = window.frames['pinduoduo']; 72 | const $pwd = $iframe.document.getElementById('password'); 73 | console.log(`你的密码已泄露: ${$pwd}`) 74 | ``` 75 | 76 | ##### 解决方案(主流) 77 | 78 | **1. JSONP -> get请求跨域** 79 | 80 | 原理:script和img等标签没有跨域限制 81 | 82 | 具体实现: 83 | ``` 84 | // HTML 插入标签 85 | 86 | 87 | // JS 88 | function say(name, age) { 89 | console.log(`${name}, ${age} 岁`) 90 | } 91 | 92 | // 服务器返回response 93 | say('zmz', 18) 94 | 95 | // 那么客户端在script onload时会执行say方法 96 | 97 | // 结束 98 | ``` 99 | 100 | **2. iframe+form实现post请求跨域** 101 | 102 | 原理:利用form表单target属性,将post请求提交给隐藏的iframe,使页面不跳转 103 | 104 | 具体实现: 105 | ``` 106 | var data = { 107 | name: 'zmz', 108 | age: 18 109 | } 110 | var url = 'http://localhost/say'; 111 | 112 | var $iframe = document.createElement('iframe'); 113 | $iframe.name = 'iframePost'; 114 | $iframe.style.display = 'none'; 115 | document.body.appendChild($iframe); 116 | 117 | $iframe.addEventListener('load', function(e) { 118 | console.log($iframe.contentWindow) 119 | }) 120 | 121 | const form = document.createElement('form'); 122 | const ipt = document.createElement('input'); 123 | form.action = url; 124 | form.enctype = 'application/json;' 125 | form.method = 'post'; 126 | 127 | // 最核心的一行代码 128 | // 在指定的iframe中执行form 129 | form.target = $iframe.name; 130 | 131 | for (var name in data) { 132 | ipt.name = name; 133 | ipt.value = data[name]; 134 | form.appendChild(ipt.cloneNode()); 135 | } 136 | form.style.display = 'none'; 137 | document.body.appendChild(form); 138 | form.submit(); 139 | 140 | document.body.removeChild(form) 141 | ``` 142 | 143 | **3. CORS 跨源资源共享** 144 | 145 | 原理:新版XMLHttpRequest(ajax2.0)特性,服务器白名单 146 | 147 | 服务器端设置`response.setHeader("Access-Control-Allow-xxx...` 148 | 149 | 附:ajax2.0新特性 150 | * 可以设置HTTP请求的时限`xhr.timeout` 151 | * 可以使用`FormData`对象管理表单数据 152 | * 可以上传文件 >> 同上 153 | * 可以请求不同域名下的数据(跨域请求) 154 | * 可以获取服务器端的二进制数据`xhr.responseType = 'blob'` 155 | * 可以获得数据传输的进度信息 `xhr.upload.process` 156 | 157 | CORS分类 158 | * 简单请求(自行搜索) 159 | * 在请求头信息中指定`Origin` 160 | * 非简单请求 161 | * 会发送预检请求(options),返回状态码204 162 | 163 | 164 | **5. 代理** 165 | 166 | 原理:服务器之间没有跨域限制 167 | 168 | 具体实现: 169 | ``` 170 | // Nginx配置 171 | server{ 172 | # 监听9099端口 173 | listen 9099; 174 | # 域名是localhost 175 | server_name localhost; 176 | # 匹配到都转发到http://localhost:9871 177 | location ^~ /api { 178 | proxy_pass http://localhost:9871; 179 | } 180 | } 181 | ``` 182 | 183 | **5. postMessage** 184 | 185 | 原理:postMessage可以处理各种浏览器窗口之间的通信问题。 186 | 187 | 具体实现: 188 | ``` 189 | // 发送方 190 | window.frames['crossDomainIframe'] 191 | iframe.postMessage('我想要数据', 'http://localhost:8088') 192 | 193 | window.addEventListener('message', function () { 194 | if (e.origin === 'http://localhost:2333') { 195 | console.log('收到', e.data) 196 | } 197 | } 198 | 199 | // 接收方 200 | window.addEventListener('message', (e) => { 201 | if (e.origin === 'http://localhost:8088') { 202 | console.log(e.data) 203 | e.source.postMessage('给,你要的数据', e.origin); 204 | } 205 | }) 206 | ``` 207 | 208 | **6. WebSocket** 209 | 210 | 原理:新协议(socket) 211 | 212 | 具体实现:类似postMessage 213 | 214 | 附: 215 | * socket.io框架能解决兼容性问题 216 | 217 | 218 | ##### 各种方式对比 219 | * JSONP和iframe+from兼容性很好 220 | * 但是错误处理和RESTful接口统一是个问题 221 | * CORS最简单粗暴 222 | * 和Vue兼容性类似。 223 | * 代理 224 | * 肯定会慢一丢丢咯,而且要找运维配 225 | * postMessage 226 | * 处理窗口间通信,- -。不嫌麻烦可以用来跨域 227 | * WebSocket 228 | * 处理长连接,附带跨域 229 | 230 | 231 | -------------------------------------------------------------------------------- /docs/assets/js/42.aa7828a9.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[42],{407:function(t,s,a){"use strict";a.r(s);var n=a(42),r=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"polyfill"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#polyfill"}},[t._v("#")]),t._v(" polyfill")]),t._v(" "),a("h2",{attrs:{id:"object-assign"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#object-assign"}},[t._v("#")]),t._v(" Object.assign()")]),t._v(" "),a("div",{staticClass:"language-js extra-class"},[a("pre",{pre:!0,attrs:{class:"language-js"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("merge")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("target")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" j "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" arguments"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" source "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" arguments"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" prop "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" source"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("source"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("hasOwnProperty")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("prop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" value "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" source"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("prop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("undefined")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n target"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("prop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" target"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=r.exports}}]); --------------------------------------------------------------------------------