├── .DS_Store ├── .babelrc ├── .gitignore ├── .md ├── 1.md ├── README.md ├── package-lock.json ├── package.json ├── public ├── bundle.html ├── bundle.js ├── bundle.js.map └── 双向数据绑定.html ├── rollup.config.js ├── src ├── .DS_Store ├── React │ ├── index.html │ ├── index.js │ ├── public │ │ ├── bundle.js │ │ └── bundle.js.map │ └── rollup.config.js ├── React技术揭秘 │ ├── babel │ │ └── babel.min.js │ ├── react │ │ ├── react-dom.development.js │ │ └── react.development.js │ └── reactDemo.html ├── assets │ └── img │ │ └── loading.gif ├── main.js ├── 手写系列 │ ├── .DS_Store │ ├── Promise │ │ ├── testPromise.js │ │ ├── 基本用法.js │ │ ├── 多次调用then.js │ │ ├── 异步事件.js │ │ └── 链式调用then.js │ ├── React diff │ │ └── index.js │ ├── React │ │ ├── .DS_Store │ │ ├── babel │ │ │ └── babel.min.js │ │ ├── react │ │ │ ├── react-dom.development.js │ │ │ └── react.development.js │ │ ├── reactDemo.html │ │ ├── reactDemo10.html │ │ ├── reactDemo11.html │ │ ├── reactDemo12.html │ │ ├── reactDemo2.html │ │ ├── reactDemo3.html │ │ ├── reactDemo4.html │ │ ├── reactDemo5.html │ │ ├── reactDemo6.html │ │ ├── reactDemo7.html │ │ ├── reactDemo8.html │ │ └── reactDemo9.html │ ├── 虚拟DOM │ │ ├── READ.md │ │ ├── index.html │ │ ├── public │ │ │ ├── bundle.js │ │ │ └── bundle.js.map │ │ ├── rollup.config.js │ │ └── src │ │ │ ├── index.js │ │ │ ├── lib-test │ │ │ ├── const.js │ │ │ ├── diff.js │ │ │ ├── patch.js │ │ │ └── util.js │ │ │ └── lib │ │ │ ├── diff.js │ │ │ ├── element.js │ │ │ ├── patch.js │ │ │ └── util.js │ └── 虚拟DOM实例 │ │ └── 分页 │ │ ├── 真实DOM │ │ ├── index.html │ │ ├── index.js │ │ ├── public │ │ │ ├── bundle.js │ │ │ └── bundle.js.map │ │ └── rollup.config.js │ │ └── 虚拟DOM │ │ ├── 1.json │ │ ├── index.html │ │ ├── index.js │ │ ├── public │ │ ├── bundle.js │ │ └── bundle.js.map │ │ └── rollup.config.js └── 设计模式 │ ├── .DS_Store │ ├── 代理模式 │ ├── .DS_Store │ ├── 分页 │ │ └── 缓存代理 │ │ │ └── index.js │ ├── 合并HTTP请求 │ │ └── 虚拟代理 │ │ │ ├── index.html │ │ │ └── index.js │ ├── 图片预加载 │ │ ├── .DS_Store │ │ ├── 普通 │ │ │ ├── .DS_Store │ │ │ ├── index.html │ │ │ └── index.js │ │ └── 虚拟代理 │ │ │ ├── .DS_Store │ │ │ ├── index.html │ │ │ └── index.js │ └── 小明送花给小白 │ │ ├── .DS_Store │ │ ├── 代理模式 │ │ ├── .DS_Store │ │ ├── index.html │ │ └── index.js │ │ └── 普通 │ │ ├── .DS_Store │ │ ├── index.html │ │ └── index.js │ ├── 单例模式 │ ├── .DS_Store │ ├── 代理实现单例模式 │ │ ├── index.html │ │ └── index.js │ ├── 实现单例模式 │ │ ├── .DS_Store │ │ ├── index.html │ │ └── 实现单例模式.js │ ├── 登录浮窗 │ │ ├── .DS_Store │ │ ├── 单例模式 │ │ │ ├── index.html │ │ │ └── index.js │ │ ├── 普通 │ │ │ ├── .DS_Store │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ └── index2.js │ │ └── 普通2 │ │ │ ├── .DS_Store │ │ │ ├── index.html │ │ │ └── index.js │ ├── 透明的单例模式 │ │ ├── .DS_Store │ │ ├── index.html │ │ └── 透明的单例模式.js │ └── 通用的惰性单例 │ │ ├── index.html │ │ └── index.js │ ├── 策略模式 │ ├── .DS_Store │ ├── 什么是快乐星球,什么是策略模式.md │ └── 表单校验 │ │ ├── .DS_Store │ │ ├── 普通 │ │ ├── .DS_Store │ │ ├── index.html │ │ └── index.js │ │ └── 策略 │ │ ├── .DS_Store │ │ ├── index.html │ │ ├── index.js │ │ └── index1.js │ ├── 职责链模式 │ └── 预售订单 │ │ ├── index.html │ │ └── index.js │ ├── 装饰器模式 │ ├── ajax参数.js │ ├── index.js │ ├── 数据上报.js │ └── 鸭子.js │ └── 观察者模式 │ ├── .DS_Store │ ├── 双向数据绑定 │ ├── .DS_Store │ ├── 完整版 │ │ ├── 2-way-binding.html │ │ ├── tbinding.js │ │ └── user.js │ └── 简单版 │ │ └── index.js │ └── 观察者模式函数 │ └── index.js └── 白帽子讲web安全 /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/.DS_Store -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"], 3 | "plugins": ["@babel/plugin-transform-runtime"] 4 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | .history 3 | package-lock.json 4 | 5 | index2.html -------------------------------------------------------------------------------- /.md: -------------------------------------------------------------------------------- 1 | # 一、什么是职责链模式 2 | 3 | 职责链模式就是当一个对象 `a`,有多种可能的请求对象 `b`、`c`、`d`、`e` 时,我们为 `b`、`c`、`d`、`e` 分别定义一个职责,组成一条职责链,这样 `a` 只需要找到 `b` 发起请求,然后沿着职责链继续请求,直到找到一个对象来处理 `a`。 4 | 5 | 女孩子们都喜欢结伴吃饭,我现在要找一个人一起吃饭,代码如下: 6 | 7 | > 嗯.....女程序员确实是这样,吃个饭也要写代码发请求的。 8 | 9 | ```javascript 10 | const [ astrid, brooke, calliope ] = [{ 11 | name: 'astrid', 12 | requirement: '我要吃湘菜' 13 | },{ 14 | name: 'brooke', 15 | requirement: '我要找10个人一起吃饭' 16 | },{ 17 | name: 'calliope', 18 | requirement: '我要和男朋友一起吃饭' 19 | }] 20 | 21 | // 是否满足 22 | function isSatisfyAstrid (user) { 23 | // ... 省略... 24 | } 25 | 26 | // 是否满足 27 | function isSatisfyBrooke (user) { 28 | // ... 省略... 29 | } 30 | 31 | // 是否满足 32 | function isSatisfyCalliope (user) { 33 | // ... 省略... 34 | } 35 | 36 | function eatDinner () { 37 | if (isSatisfyAstrid()) { 38 | console.log(`我可以和 astrid 一起吃晚饭啦`) 39 | } else if (isSatisfyBrooke()) { 40 | console.log(`我可以和 brooke 一起吃晚饭啦`) 41 | } else if (isSatisfyCalliope()) { 42 | console.log(`我可以和 calliope 一起吃晚饭啦`) 43 | } else { 44 | console.log(`哎呀,我要一个人吃晚饭啦`) 45 | } 46 | } 47 | ``` 48 | 49 | 由于 `astrid`、`brooke`、`calliope` 吃晚饭的要求不同,我需要一个个去问,直到找到答应和我一起吃晚饭的人。 50 | 51 | 在这里,我假设 `astrid` 的要求是要吃湘菜,`brooke` 的要求是要找 10 个人凑一桌一起吃,`calliope` 的要求是只想和男朋友一起吃饭。 52 | 53 | 用上述 `if-else` 太死板了,假如我又多了个朋友 `davi`,我必须再次修改 `eatDinner` 方法,违反了开放-封闭原则,不易于维护。 54 | 55 | 使用职责链来优化上述代码,代码如下: 56 | 57 | ```javascript 58 | // 给每个人定义一个职责 59 | const chainOrderA = new Chain(isSatisfyAstrid) 60 | const chainOrderB = new Chain(isSatisfyBrooke) 61 | const chainOrderC = new Chain(isSatisfyCalliope) 62 | 63 | // 设置一下职责链的顺序 64 | chainOrderA.setNextSuccessor(chainOrderB) 65 | chainOrderB.setNextSuccessor(chainOrderC) 66 | 67 | // 发起请求,这时我只需要向职责链上的第一个人请求 68 | 69 | 70 | 71 | ``` 72 | 73 | 74 | 75 | # 二、实际场景 76 | 77 | # 三、小结 -------------------------------------------------------------------------------- /1.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/1.md -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # web-learn-note 2 | 3 | ## 快速开始 4 | 5 | 1. git clone 6 | 7 | ``` 8 | git clone https://github.com/jiaozitang/web-learn-note 9 | ``` 10 | 11 | 2. 安装依赖 12 | 13 | ``` 14 | npm i 15 | 16 | ``` 17 | 18 | 3. 本地运行 19 | ``` 20 | npm run dev 21 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-learn-note", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "npm run watch", 9 | "push": "git add . && git commit -m '手写系列'", 10 | "watch": "rollup -c -w", 11 | "test:promise": "promises-aplus-tests ./src/手写系列/Promise/testPromise" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/jiaozitang/web-learn-note.git" 16 | }, 17 | "author": "", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/jiaozitang/web-learn-note/issues" 21 | }, 22 | "homepage": "https://github.com/jiaozitang/web-learn-note#readme", 23 | "devDependencies": { 24 | "@babel/core": "^7.14.3", 25 | "@babel/plugin-transform-runtime": "^7.14.3", 26 | "@babel/preset-env": "^7.14.4", 27 | "@babel/preset-react": "^7.14.5", 28 | "@rollup/plugin-babel": "^5.3.0", 29 | "@rollup/plugin-commonjs": "^19.0.0", 30 | "@rollup/plugin-node-resolve": "^13.0.0", 31 | "deepmerge": "^4.2.2", 32 | "is-module": "^1.0.0", 33 | "promises-aplus-tests": "^2.1.2", 34 | "rollup": "^2.50.5", 35 | "rollup-plugin-terser": "^7.0.2" 36 | }, 37 | "dependencies": { 38 | "list-diff2": "^0.1.4", 39 | "lodash": "^4.17.21", 40 | "simple-virtual-dom": "^0.1.10" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /public/bundle.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /public/bundle.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | function _typeof(obj) { 5 | "@babel/helpers - typeof"; 6 | 7 | if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { 8 | _typeof = function _typeof(obj) { 9 | return typeof obj; 10 | }; 11 | } else { 12 | _typeof = function _typeof(obj) { 13 | return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 14 | }; 15 | } 16 | 17 | return _typeof(obj); 18 | } 19 | 20 | function _classCallCheck(instance, Constructor) { 21 | if (!(instance instanceof Constructor)) { 22 | throw new TypeError("Cannot call a class as a function"); 23 | } 24 | } 25 | 26 | function _defineProperties(target, props) { 27 | for (var i = 0; i < props.length; i++) { 28 | var descriptor = props[i]; 29 | descriptor.enumerable = descriptor.enumerable || false; 30 | descriptor.configurable = true; 31 | if ("value" in descriptor) descriptor.writable = true; 32 | Object.defineProperty(target, descriptor.key, descriptor); 33 | } 34 | } 35 | 36 | function _createClass(Constructor, protoProps, staticProps) { 37 | if (protoProps) _defineProperties(Constructor.prototype, protoProps); 38 | if (staticProps) _defineProperties(Constructor, staticProps); 39 | return Constructor; 40 | } 41 | 42 | function _defineProperty(obj, key, value) { 43 | if (key in obj) { 44 | Object.defineProperty(obj, key, { 45 | value: value, 46 | enumerable: true, 47 | configurable: true, 48 | writable: true 49 | }); 50 | } else { 51 | obj[key] = value; 52 | } 53 | 54 | return obj; 55 | } 56 | 57 | var STATUS = { 58 | PENDING: 'pending', 59 | FULFILLED: 'fulfilled', 60 | REJECTED: 'rejected' 61 | }; 62 | 63 | var MyPromise = /*#__PURE__*/function () { 64 | function MyPromise(executor) { 65 | var _this = this; 66 | 67 | _classCallCheck(this, MyPromise); 68 | 69 | _defineProperty(this, "onFulfilledCallbacks", []); 70 | 71 | _defineProperty(this, "onRejectedCallbacks", []); 72 | 73 | _defineProperty(this, "status", STATUS.PENDING); 74 | 75 | _defineProperty(this, "value", null); 76 | 77 | _defineProperty(this, "resolve", null); 78 | 79 | _defineProperty(this, "resolve", function (value) { 80 | if (_this.status === STATUS.PENDING) { 81 | _this.status = STATUS.FULFILLED; 82 | _this.value = value; 83 | 84 | while (_this.onFulfilledCallbacks.length) { 85 | _this.onFulfilledCallbacks.shift()(value); 86 | } 87 | } 88 | }); 89 | 90 | _defineProperty(this, "reject", function (value) { 91 | if (_this.status === STATUS.PENDING) { 92 | _this.status = STATUS.REJECTED; 93 | _this.reason = value; 94 | 95 | while (_this.onRejectedCallbacks.length) { 96 | _this.onRejectedCallbacks.shift()(value); 97 | } 98 | } 99 | }); 100 | 101 | // 执行器 102 | try { 103 | executor(this.resolve, this.reject); 104 | } catch (error) { 105 | this.reject(error); 106 | } 107 | } // 成功回调 108 | 109 | 110 | _createClass(MyPromise, [{ 111 | key: "then", 112 | value: function then(onFulfilled, onRejected) { 113 | var _this2 = this; 114 | 115 | var realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) { 116 | return value; 117 | }; 118 | var realOnRejected = typeof onRejected === 'function' ? onRejected : function (error) { 119 | throw error; 120 | }; 121 | var promise2 = new MyPromise(function (resolve, reject) { 122 | var fulfilledMicrotask = function fulfilledMicrotask() { 123 | // 创建一个微任务等待 promise2 完成初始化 124 | queueMicrotask(function () { 125 | try { 126 | // 获取成功回调函数的执行结果 127 | var x = realOnFulfilled(_this2.value); // 传入 resolvePromise 集中处理 128 | 129 | resolvePromise(promise2, x, resolve, reject); 130 | } catch (error) { 131 | reject(error); 132 | } 133 | }); 134 | }; 135 | 136 | var rejectedMicrotask = function rejectedMicrotask() { 137 | // 创建一个微任务等待 promise2 完成初始化 138 | queueMicrotask(function () { 139 | try { 140 | // 调用失败回调,并且把原因返回 141 | var x = realOnRejected(_this2.reason); // 传入 resolvePromise 集中处理 142 | 143 | resolvePromise(promise2, x, resolve, reject); 144 | } catch (error) { 145 | reject(error); 146 | } 147 | }); 148 | }; 149 | 150 | if (_this2.status === STATUS.PENDING) { 151 | _this2.onFulfilledCallbacks.push(fulfilledMicrotask); 152 | 153 | _this2.onRejectedCallbacks.push(rejectedMicrotask); 154 | } else if (_this2.status === STATUS.FULFILLED) { 155 | fulfilledMicrotask(); 156 | } else if (_this2.status === STATUS.REJECTED) { 157 | rejectedMicrotask(); 158 | } 159 | }); 160 | return promise2; 161 | } 162 | }]); 163 | 164 | return MyPromise; 165 | }(); 166 | 167 | function resolvePromise(promise, x, resolve, reject) { 168 | // 如果 promise === x, 执行 reject,错误原因为 TypeError 169 | if (promise === x) { 170 | return reject(new TypeError('The promise and the return value are the same')); 171 | } // 如果 x 是对象或函数 172 | 173 | 174 | if (_typeof(x) === 'object' || typeof x === 'function') { 175 | if (x === null) { 176 | return resolve(x); 177 | } 178 | 179 | var then; 180 | 181 | try { 182 | then = x.then; 183 | } catch (error) { 184 | return reject(error); 185 | } // 如果 x.then 是函数 186 | 187 | 188 | if (typeof then === 'function') { 189 | var called = false; 190 | 191 | try { 192 | then.call(x, function (y) { 193 | // resolve的结果依旧是promise 那就继续解析 194 | if (called) return; 195 | called = true; 196 | resolvePromise(promise, y, resolve, reject); 197 | }, function (err) { 198 | if (called) return; 199 | called = true; 200 | reject(err); // 失败了 201 | }); 202 | } catch (error) { 203 | if (called) return; 204 | reject(error); 205 | } 206 | } else { 207 | // 如果 x.then 不是函数 208 | resolve(x); 209 | } 210 | } else { 211 | // 如果 x 不是 promise 实例 212 | resolve(x); 213 | } 214 | } 215 | 216 | var mypromise = new MyPromise(function (resolve, reject) { 217 | setTimeout(function () { 218 | return resolve('成功'); 219 | }, 1000); 220 | }); 221 | var mypromise2 = new MyPromise(function (resolve, reject) { 222 | setTimeout(function () { 223 | return resolve('成功2'); 224 | }, 1000); 225 | }); 226 | mypromise.then(function (data) { 227 | console.log(data, '1'); 228 | return mypromise2; 229 | }).then(function (data) { 230 | console.log(data, '2'); 231 | }); 232 | 233 | }()); 234 | //# sourceMappingURL=bundle.js.map 235 | -------------------------------------------------------------------------------- /public/bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bundle.js","sources":["../node_modules/@babel/runtime/helpers/esm/typeof.js","../node_modules/@babel/runtime/helpers/esm/classCallCheck.js","../node_modules/@babel/runtime/helpers/esm/createClass.js","../node_modules/@babel/runtime/helpers/esm/defineProperty.js","../src/手写系列/Promise/异步事件.js"],"sourcesContent":["export default function _typeof(obj) {\n \"@babel/helpers - typeof\";\n\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n _typeof = function _typeof(obj) {\n return typeof obj;\n };\n } else {\n _typeof = function _typeof(obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n\n return _typeof(obj);\n}","export default function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}","function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\n\nexport default function _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}","export default function _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}","const STATUS = {\n PENDING: 'pending',\n FULFILLED: 'fulfilled',\n REJECTED: 'rejected'\n}\n\nclass MyPromise {\n constructor (executor) {\n // 执行器\n try {\n executor(this.resolve, this.reject)\n } catch (error) {\n this.reject(error)\n }\n }\n\n // 成功回调\n onFulfilledCallbacks = []\n\n // 失败回调\n onRejectedCallbacks = []\n\n // 初始状态\n status = STATUS.PENDING\n \n // 成功返回值\n value = null\n \n // 失败返回值\n resolve = null\n \n // 修改 Promise 状态,并定义成功返回值\n resolve = value => {\n if (this.status === STATUS.PENDING) {\n this.status = STATUS.FULFILLED\n this.value = value\n\n while(this.onFulfilledCallbacks.length) {\n this.onFulfilledCallbacks.shift()(value)\n }\n }\n }\n \n // 修改 Promise 状态,并定义失败返回值\n reject = value => {\n if (this.status === STATUS.PENDING) {\n this.status = STATUS.REJECTED\n this.reason = value\n\n while(this.onRejectedCallbacks.length) {\n this.onRejectedCallbacks.shift()(value)\n }\n }\n }\n\n then (onFulfilled, onRejected) {\n const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value\n const realOnRejected = typeof onRejected === 'function' ? onRejected : error => { throw error }\n \n const promise2 = new MyPromise((resolve, reject) => {\n \n const fulfilledMicrotask = () => {\n // 创建一个微任务等待 promise2 完成初始化\n queueMicrotask(() => {\n try {\n // 获取成功回调函数的执行结果\n const x = realOnFulfilled(this.value);\n // 传入 resolvePromise 集中处理\n resolvePromise(promise2, x, resolve, reject);\n } catch (error) {\n reject(error)\n } \n }) \n }\n \n const rejectedMicrotask = () => { \n // 创建一个微任务等待 promise2 完成初始化\n queueMicrotask(() => {\n try {\n // 调用失败回调,并且把原因返回\n const x = realOnRejected(this.reason);\n // 传入 resolvePromise 集中处理\n resolvePromise(promise2, x, resolve, reject);\n } catch (error) {\n reject(error)\n } \n }) \n }\n\n if (this.status === STATUS.PENDING) {\n this.onFulfilledCallbacks.push(fulfilledMicrotask)\n this.onRejectedCallbacks.push(rejectedMicrotask)\n } else if (this.status === STATUS.FULFILLED) {\n fulfilledMicrotask()\n } else if (this.status === STATUS.REJECTED) {\n rejectedMicrotask()\n }\n }) \n\n return promise2\n }\n}\n\nfunction resolvePromise (promise, x, resolve, reject) {\n // 如果 promise === x, 执行 reject,错误原因为 TypeError\n if (promise === x) {\n return reject(new TypeError('The promise and the return value are the same'))\n }\n\n // 如果 x 是对象或函数\n if (typeof x === 'object' || typeof x === 'function') {\n\n if (x === null) {\n return resolve(x);\n }\n\n let then\n try {\n then = x.then\n } catch (error) {\n return reject(error)\n }\n\n // 如果 x.then 是函数\n if (typeof then === 'function') {\n let called = false;\n try {\n then.call(x, y => {\n // resolve的结果依旧是promise 那就继续解析\n if (called) return;\n called = true;\n resolvePromise(promise, y, resolve, reject);\n }, err => {\n if (called) return;\n called = true;\n reject(err);// 失败了\n })\n } catch (error) {\n if (called) return;\n reject(error)\n }\n } else {\n // 如果 x.then 不是函数\n resolve(x)\n }\n } else {\n // 如果 x 不是 promise 实例\n resolve(x)\n }\n\n}\n\nconst mypromise = new MyPromise((resolve, reject) => {\n setTimeout(() => resolve('成功'), 1000)\n})\n\nconst mypromise2 = new MyPromise((resolve, reject) => {\n setTimeout(() => resolve('成功2'), 1000)\n})\n\nmypromise.then(data => {\n console.log(data, '1')\n return mypromise2 \n}).then(data => {\n console.log(data, '2')\n})"],"names":["_typeof","obj","Symbol","iterator","constructor","prototype","_classCallCheck","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_createClass","protoProps","staticProps","_defineProperty","value","STATUS","PENDING","FULFILLED","REJECTED","MyPromise","executor","status","onFulfilledCallbacks","shift","reason","onRejectedCallbacks","resolve","reject","error","onFulfilled","onRejected","realOnFulfilled","realOnRejected","promise2","fulfilledMicrotask","queueMicrotask","x","resolvePromise","rejectedMicrotask","push","promise","then","called","call","y","err","mypromise","setTimeout","mypromise2","data","console","log"],"mappings":"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"} -------------------------------------------------------------------------------- /public/双向数据绑定.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 姓名:
10 | 年龄:
11 | 12 | 输入的姓名是
13 | 输入的年龄是
14 | 15 | 16 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import { terser } from 'rollup-plugin-terser'; 4 | import { babel } from '@rollup/plugin-babel'; 5 | 6 | // `npm run build` -> `production` is true 7 | // `npm run dev` -> `production` is false 8 | const production = !process.env.ROLLUP_WATCH; 9 | 10 | export default { 11 | input: 'src/main.js', 12 | output: { 13 | file: 'public/bundle.js', 14 | format: 'iife', // immediately-invoked function expression — suitable for 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/React/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const e = React.createElement; 4 | 5 | let start = 0 6 | let end = 0 7 | 8 | class LikeButton extends React.Component { 9 | constructor(props) { 10 | super(props); 11 | this.state = { 12 | data: [], // 分页数据 13 | time: 0 // 耗时 14 | } 15 | 16 | this.go({page: 1}) 17 | } 18 | 19 | componentWillUpdate () { 20 | start = new Date().getTime() 21 | } 22 | 23 | componentDidUpdate () { 24 | end = new Date().getTime() 25 | console.log(end - start) 26 | } 27 | 28 | // 跳转到某一页 29 | go ({page}) { 30 | const startTime = new Date().getTime() 31 | const data = this.getData({page}) 32 | this.handleDom(data) 33 | const endTime = new Date().getTime() 34 | const time = endTime - startTime 35 | this.showTimeOnPage(time) 36 | } 37 | 38 | showTimeOnPage (time) { 39 | this.setState({ 40 | time 41 | }) 42 | } 43 | 44 | handleDom (data) { 45 | this.setState({ 46 | data 47 | }) 48 | } 49 | 50 | // 获取某一页的数据 51 | getData ({page, pageSize = 20}) { 52 | const list = [] 53 | list.length = pageSize 54 | return list.fill(page) 55 | } 56 | 57 | // 在线babel转义 58 | render() { 59 | const { data, time } = this.state 60 | return ( 61 | e("div", null, 62 | e("p", null, "分页消耗时长:", 63 | e("span", null, time), "ms" 64 | ), 65 | e("div", null, 66 | e("button", { onClick: () => this.go({page: 1}) }, "第一页"), 67 | e("button", { onClick: () => this.go({page: 2}) }, "第二页") 68 | ), 69 | e("ul", null, data.map((dataItem, index) => { 70 | const key = `${index}-${dataItem}` 71 | return ( 72 | e("li", { key }, [`${index}-${dataItem}`, html]) 73 | ) 74 | })) 75 | ) 76 | ) 77 | } 78 | } 79 | 80 | const domContainer = document.querySelector('#container'); 81 | ReactDOM.render(e(LikeButton), domContainer); -------------------------------------------------------------------------------- /src/React/public/bundle.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | function _classCallCheck(instance, Constructor) { 5 | if (!(instance instanceof Constructor)) { 6 | throw new TypeError("Cannot call a class as a function"); 7 | } 8 | } 9 | 10 | function _defineProperties(target, props) { 11 | for (var i = 0; i < props.length; i++) { 12 | var descriptor = props[i]; 13 | descriptor.enumerable = descriptor.enumerable || false; 14 | descriptor.configurable = true; 15 | if ("value" in descriptor) descriptor.writable = true; 16 | Object.defineProperty(target, descriptor.key, descriptor); 17 | } 18 | } 19 | 20 | function _createClass(Constructor, protoProps, staticProps) { 21 | if (protoProps) _defineProperties(Constructor.prototype, protoProps); 22 | if (staticProps) _defineProperties(Constructor, staticProps); 23 | return Constructor; 24 | } 25 | 26 | function _setPrototypeOf(o, p) { 27 | _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { 28 | o.__proto__ = p; 29 | return o; 30 | }; 31 | 32 | return _setPrototypeOf(o, p); 33 | } 34 | 35 | function _inherits(subClass, superClass) { 36 | if (typeof superClass !== "function" && superClass !== null) { 37 | throw new TypeError("Super expression must either be null or a function"); 38 | } 39 | 40 | subClass.prototype = Object.create(superClass && superClass.prototype, { 41 | constructor: { 42 | value: subClass, 43 | writable: true, 44 | configurable: true 45 | } 46 | }); 47 | if (superClass) _setPrototypeOf(subClass, superClass); 48 | } 49 | 50 | function _typeof(obj) { 51 | "@babel/helpers - typeof"; 52 | 53 | if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { 54 | _typeof = function _typeof(obj) { 55 | return typeof obj; 56 | }; 57 | } else { 58 | _typeof = function _typeof(obj) { 59 | return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 60 | }; 61 | } 62 | 63 | return _typeof(obj); 64 | } 65 | 66 | function _assertThisInitialized(self) { 67 | if (self === void 0) { 68 | throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 69 | } 70 | 71 | return self; 72 | } 73 | 74 | function _possibleConstructorReturn(self, call) { 75 | if (call && (_typeof(call) === "object" || typeof call === "function")) { 76 | return call; 77 | } 78 | 79 | return _assertThisInitialized(self); 80 | } 81 | 82 | function _getPrototypeOf(o) { 83 | _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { 84 | return o.__proto__ || Object.getPrototypeOf(o); 85 | }; 86 | return _getPrototypeOf(o); 87 | } 88 | 89 | function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 90 | 91 | function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 92 | 93 | var e = React.createElement; 94 | var start = 0; 95 | var end = 0; 96 | 97 | var LikeButton = /*#__PURE__*/function (_React$Component) { 98 | _inherits(LikeButton, _React$Component); 99 | 100 | var _super = _createSuper(LikeButton); 101 | 102 | function LikeButton(props) { 103 | var _this; 104 | 105 | _classCallCheck(this, LikeButton); 106 | 107 | _this = _super.call(this, props); 108 | _this.state = { 109 | data: [], 110 | // 分页数据 111 | time: 0 // 耗时 112 | 113 | }; 114 | 115 | _this.go({ 116 | page: 1 117 | }); 118 | 119 | return _this; 120 | } 121 | 122 | _createClass(LikeButton, [{ 123 | key: "componentWillUpdate", 124 | value: function componentWillUpdate() { 125 | start = new Date().getTime(); 126 | } 127 | }, { 128 | key: "componentDidUpdate", 129 | value: function componentDidUpdate() { 130 | end = new Date().getTime(); 131 | console.log(end - start); 132 | } // 跳转到某一页 133 | 134 | }, { 135 | key: "go", 136 | value: function go(_ref) { 137 | var page = _ref.page; 138 | var startTime = new Date().getTime(); 139 | var data = this.getData({ 140 | page: page 141 | }); 142 | this.handleDom(data); 143 | var endTime = new Date().getTime(); 144 | var time = endTime - startTime; 145 | this.showTimeOnPage(time); 146 | } 147 | }, { 148 | key: "showTimeOnPage", 149 | value: function showTimeOnPage(time) { 150 | this.setState({ 151 | time: time 152 | }); 153 | } 154 | }, { 155 | key: "handleDom", 156 | value: function handleDom(data) { 157 | this.setState({ 158 | data: data 159 | }); 160 | } // 获取某一页的数据 161 | 162 | }, { 163 | key: "getData", 164 | value: function getData(_ref2) { 165 | var page = _ref2.page, 166 | _ref2$pageSize = _ref2.pageSize, 167 | pageSize = _ref2$pageSize === void 0 ? 20 : _ref2$pageSize; 168 | var list = []; 169 | list.length = pageSize; 170 | return list.fill(page); 171 | } // 在线babel转义 172 | 173 | }, { 174 | key: "render", 175 | value: function render() { 176 | var _this2 = this; 177 | 178 | var _this$state = this.state, 179 | data = _this$state.data, 180 | time = _this$state.time; 181 | return e("div", null, e("p", null, "分页消耗时长:", e("span", null, time), "ms"), e("div", null, e("button", { 182 | onClick: function onClick() { 183 | return _this2.go({ 184 | page: 1 185 | }); 186 | } 187 | }, "第一页"), e("button", { 188 | onClick: function onClick() { 189 | return _this2.go({ 190 | page: 2 191 | }); 192 | } 193 | }, "第二页")), e("ul", null, data.map(function (dataItem, index) { 194 | var key = "".concat(index, "-").concat(dataItem); 195 | return e("li", { 196 | key: key 197 | }, ["".concat(index, "-").concat(dataItem), html]); 198 | }))); 199 | } 200 | }]); 201 | 202 | return LikeButton; 203 | }(React.Component); 204 | 205 | var domContainer = document.querySelector('#container'); 206 | ReactDOM.render(e(LikeButton), domContainer); 207 | 208 | }()); 209 | //# sourceMappingURL=bundle.js.map 210 | -------------------------------------------------------------------------------- /src/React/public/bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bundle.js","sources":["../../../node_modules/@babel/runtime/helpers/esm/classCallCheck.js","../../../node_modules/@babel/runtime/helpers/esm/createClass.js","../../../node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","../../../node_modules/@babel/runtime/helpers/esm/inherits.js","../../../node_modules/@babel/runtime/helpers/esm/typeof.js","../../../node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js","../../../node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js","../../../node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js","../index.js"],"sourcesContent":["export default function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}","function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\n\nexport default function _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}","export default function _setPrototypeOf(o, p) {\n _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n\n return _setPrototypeOf(o, p);\n}","import setPrototypeOf from \"./setPrototypeOf.js\";\nexport default function _inherits(subClass, superClass) {\n if (typeof superClass !== \"function\" && superClass !== null) {\n throw new TypeError(\"Super expression must either be null or a function\");\n }\n\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n value: subClass,\n writable: true,\n configurable: true\n }\n });\n if (superClass) setPrototypeOf(subClass, superClass);\n}","export default function _typeof(obj) {\n \"@babel/helpers - typeof\";\n\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n _typeof = function _typeof(obj) {\n return typeof obj;\n };\n } else {\n _typeof = function _typeof(obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n\n return _typeof(obj);\n}","export default function _assertThisInitialized(self) {\n if (self === void 0) {\n throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n }\n\n return self;\n}","import _typeof from \"@babel/runtime/helpers/typeof\";\nimport assertThisInitialized from \"./assertThisInitialized.js\";\nexport default function _possibleConstructorReturn(self, call) {\n if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) {\n return call;\n }\n\n return assertThisInitialized(self);\n}","export default function _getPrototypeOf(o) {\n _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {\n return o.__proto__ || Object.getPrototypeOf(o);\n };\n return _getPrototypeOf(o);\n}","'use strict';\n\nconst e = React.createElement;\n\nlet start = 0\nlet end = 0\n\nclass LikeButton extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n data: [], // 分页数据\n time: 0 // 耗时\n }\n\n this.go({page: 1})\n }\n\n componentWillUpdate () {\n start = new Date().getTime()\n }\n\n componentDidUpdate () {\n end = new Date().getTime()\n console.log(end - start)\n }\n\n // 跳转到某一页\n go ({page}) {\n const startTime = new Date().getTime()\n const data = this.getData({page})\n this.handleDom(data)\n const endTime = new Date().getTime()\n const time = endTime - startTime\n this.showTimeOnPage(time)\n }\n\n showTimeOnPage (time) {\n this.setState({\n time\n })\n }\n\n handleDom (data) {\n this.setState({\n data\n })\n }\n\n // 获取某一页的数据\n getData ({page, pageSize = 20}) {\n const list = []\n list.length = pageSize\n return list.fill(page)\n }\n\n // 在线babel转义\n render() {\n const { data, time } = this.state\n return (\n e(\"div\", null, \n e(\"p\", null, \"分页消耗时长:\", \n e(\"span\", null, time), \"ms\"\n ), \n e(\"div\", null, \n e(\"button\", { onClick: () => this.go({page: 1}) }, \"第一页\"), \n e(\"button\", { onClick: () => this.go({page: 2}) }, \"第二页\")\n ), \n e(\"ul\", null, data.map((dataItem, index) => {\n const key = `${index}-${dataItem}`\n return (\n e(\"li\", { key }, [`${index}-${dataItem}`, html])\n )\n }))\n )\n )\n }\n}\n\nconst domContainer = document.querySelector('#container');\nReactDOM.render(e(LikeButton), domContainer);"],"names":["_classCallCheck","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_createClass","protoProps","staticProps","prototype","_setPrototypeOf","o","p","setPrototypeOf","__proto__","_inherits","subClass","superClass","create","constructor","value","_typeof","obj","Symbol","iterator","_assertThisInitialized","self","ReferenceError","_possibleConstructorReturn","call","assertThisInitialized","_getPrototypeOf","getPrototypeOf","e","React","createElement","start","end","LikeButton","state","data","time","go","page","Date","getTime","console","log","startTime","getData","handleDom","endTime","showTimeOnPage","setState","pageSize","list","fill","onClick","map","dataItem","index","html","Component","domContainer","document","querySelector","ReactDOM","render"],"mappings":"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"} -------------------------------------------------------------------------------- /src/React/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import { terser } from 'rollup-plugin-terser'; 4 | import { babel } from '@rollup/plugin-babel'; 5 | 6 | // `npm run build` -> `production` is true 7 | // `npm run dev` -> `production` is false 8 | const production = !process.env.ROLLUP_WATCH; 9 | 10 | export default { 11 | input: 'index.js', 12 | output: { 13 | file: 'public/bundle.js', 14 | format: 'iife', // immediately-invoked function expression — suitable for 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 26 | 27 | -------------------------------------------------------------------------------- /src/assets/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/assets/img/loading.gif -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // import './设计模式/代理模式/分页/缓存代理' 2 | 3 | // import './设计模式/观察者模式/观察者模式函数' 4 | 5 | // import './设计模式/观察者模式/双向数据绑定/简单版' 6 | 7 | // import './设计模式/装饰器模式' 8 | 9 | // import './设计模式/装饰器模式/index4' 10 | 11 | // import './设计模式/职责链模式/预售订单/index' 12 | 13 | // import './手写系列/Promise/demo.js' 14 | 15 | // import './手写系列/Promise/多次调用then' 16 | 17 | import './手写系列/Promise/异步事件' 18 | 19 | // import './手写系列/Promise/链式调用then' -------------------------------------------------------------------------------- /src/手写系列/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/手写系列/.DS_Store -------------------------------------------------------------------------------- /src/手写系列/Promise/testPromise.js: -------------------------------------------------------------------------------- 1 | const STATUS = { 2 | PENDING: 'pending', 3 | FULFILLED: 'fulfilled', 4 | REJECTED: 'rejected' 5 | } 6 | 7 | class MyPromise { 8 | constructor (executor) { 9 | // 执行器 10 | try { 11 | executor(this.resolve, this.reject) 12 | } catch (error) { 13 | this.reject(error) 14 | } 15 | } 16 | 17 | // 成功回调 18 | onFulfilledCallbacks = [] 19 | 20 | // 失败回调 21 | onRejectedCallbacks = [] 22 | 23 | // 初始状态 24 | status = STATUS.PENDING 25 | 26 | // 成功返回值 27 | value = null 28 | 29 | // 失败返回值 30 | resolve = null 31 | 32 | // 修改 Promise 状态,并定义成功返回值 33 | resolve = value => { 34 | if (this.status === STATUS.PENDING) { 35 | this.status = STATUS.FULFILLED 36 | this.value = value 37 | 38 | while(this.onFulfilledCallbacks.length) { 39 | this.onFulfilledCallbacks.shift()(value) 40 | } 41 | } 42 | } 43 | 44 | // 修改 Promise 状态,并定义失败返回值 45 | reject = value => { 46 | if (this.status === STATUS.PENDING) { 47 | this.status = STATUS.REJECTED 48 | this.reason = value 49 | 50 | while(this.onRejectedCallbacks.length) { 51 | this.onRejectedCallbacks.shift()(value) 52 | } 53 | } 54 | } 55 | 56 | then (onFulfilled, onRejected) { 57 | const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value 58 | const realOnRejected = typeof onRejected === 'function' ? onRejected : error => { throw error } 59 | 60 | const promise2 = new MyPromise((resolve, reject) => { 61 | 62 | const fulfilledMicrotask = () => { 63 | // 创建一个微任务等待 promise2 完成初始化 64 | queueMicrotask(() => { 65 | try { 66 | // 获取成功回调函数的执行结果 67 | const x = realOnFulfilled(this.value); 68 | // 传入 resolvePromise 集中处理 69 | resolvePromise(promise2, x, resolve, reject); 70 | } catch (error) { 71 | reject(error) 72 | } 73 | }) 74 | } 75 | 76 | const rejectedMicrotask = () => { 77 | // 创建一个微任务等待 promise2 完成初始化 78 | queueMicrotask(() => { 79 | try { 80 | // 调用失败回调,并且把原因返回 81 | const x = realOnRejected(this.reason); 82 | // 传入 resolvePromise 集中处理 83 | resolvePromise(promise2, x, resolve, reject); 84 | } catch (error) { 85 | reject(error) 86 | } 87 | }) 88 | } 89 | 90 | if (this.status === STATUS.PENDING) { 91 | this.onFulfilledCallbacks.push(fulfilledMicrotask) 92 | this.onRejectedCallbacks.push(rejectedMicrotask) 93 | } else if (this.status === STATUS.FULFILLED) { 94 | fulfilledMicrotask() 95 | } else if (this.status === STATUS.REJECTED) { 96 | rejectedMicrotask() 97 | } 98 | }) 99 | 100 | return promise2 101 | } 102 | } 103 | 104 | function resolvePromise (promise, x, resolve, reject) { 105 | // 如果 promise === x, 执行 reject,错误原因为 TypeError 106 | if (promise === x) { 107 | return reject(new TypeError('The promise and the return value are the same')) 108 | } 109 | 110 | // 如果 x 是 promise 实例 111 | if (typeof x === 'object' || typeof x === 'function') { 112 | 113 | if (x === null) { 114 | return resolve(x); 115 | } 116 | 117 | let then 118 | try { 119 | then = x.then 120 | } catch (error) { 121 | return reject(error) 122 | } 123 | 124 | // 如果 x.then 是函数 125 | if (typeof then === 'function') { 126 | let called = false; 127 | try { 128 | then.call(x, y => { 129 | // resolve的结果依旧是promise 那就继续解析 130 | if (called) return; 131 | called = true; 132 | resolvePromise(promise, y, resolve, reject); 133 | }, err => { 134 | if (called) return; 135 | called = true; 136 | reject(err);// 失败了 137 | }) 138 | } catch (error) { 139 | if (called) return; 140 | reject(error) 141 | } 142 | } else { 143 | // 如果 x.then 不是函数 144 | resolve(x) 145 | } 146 | } else { 147 | // 如果 x 不是 promise 实例 148 | resolve(x) 149 | } 150 | 151 | } 152 | 153 | MyPromise.deferred = function () { 154 | var result = {}; 155 | result.promise = new MyPromise(function (resolve, reject) { 156 | result.resolve = resolve; 157 | result.reject = reject; 158 | }); 159 | 160 | return result; 161 | } 162 | 163 | 164 | module.exports = MyPromise 165 | 166 | 167 | -------------------------------------------------------------------------------- /src/手写系列/Promise/基本用法.js: -------------------------------------------------------------------------------- 1 | // Promise 的 3 种状态 2 | const STATUS = { 3 | PENDING: 'pending', 4 | FULFILLED: 'fulfilled', 5 | REJECTED: 'rejected' 6 | } 7 | 8 | export default class MyPromise { 9 | constructor (executor) { 10 | // 执行器 11 | executor(this.resolve, this.reject) 12 | } 13 | // 初始状态 14 | status = STATUS.PENDING 15 | 16 | // 成功返回值 17 | value = null 18 | 19 | // 失败返回值 20 | reason = null 21 | 22 | // 修改 Promise 状态,并定义成功返回值 23 | resolve = value => { 24 | if (this.status === STATUS.PENDING) { 25 | this.status = STATUS.FULFILLED 26 | this.value = value 27 | } 28 | } 29 | 30 | // 修改 Promise 状态,并定义失败返回值 31 | reject = () => { 32 | if (this.status === STATUS.PENDING) { 33 | this.status = STATUS.REJECTED 34 | this.reason = value 35 | } 36 | } 37 | 38 | then = function (onFulfilled, onRejected) { 39 | if (this.status === STATUS.FULFILLED) { 40 | onFulfilled(this.value) 41 | } else if (this.status === STATUS.REJECTED) { 42 | onRejected(this.reason) 43 | } 44 | } 45 | } 46 | 47 | const mypromise = new MyPromise((resolve, reject) => { 48 | resolve('成功') 49 | }) 50 | 51 | mypromise.then(data => { 52 | console.log(data, '请求成功') // 成功打印“成功 请求成功” 53 | }, err => { 54 | console.log(err, '请求失败') 55 | }) -------------------------------------------------------------------------------- /src/手写系列/Promise/多次调用then.js: -------------------------------------------------------------------------------- 1 | // Promise 的 3 种状态 2 | const STATUS = { 3 | PENDING: 'pending', 4 | FULFILLED: 'fulfilled', 5 | REJECTED: 'rejected' 6 | } 7 | 8 | class MyPromise { 9 | constructor (executor) { 10 | // 执行器 11 | try { 12 | executor(this.resolve, this.reject) 13 | } catch (reason) { 14 | this.reject(reason) 15 | } 16 | } 17 | 18 | // 成功回调 19 | onFulfilledCallback = [] 20 | 21 | // 失败回调 22 | onRejectedCallback = [] 23 | 24 | // 初始状态为 pending 25 | status = STATUS.PENDING 26 | 27 | // 请求成功时的返回值 28 | value = null 29 | 30 | // 请求失败的原因 31 | reason = null 32 | 33 | // 修改 Promise 状态,并定义成功返回值 34 | resolve = value => { 35 | if (this.status === STATUS.PENDING) { 36 | this.status = STATUS.FULFILLED 37 | this.value = value 38 | 39 | while(this.onFulfilledCallback.length) { 40 | this.onFulfilledCallback.shift()(value) 41 | } 42 | } 43 | } 44 | 45 | // 修改 Promise 状态,并定义失败返回值 46 | reject = value => { 47 | if (this.status === STATUS.PENDING) { 48 | this.status = STATUS.REJECTED 49 | this.reason = value 50 | 51 | while(this.onRejectedCallback.length) { 52 | this.onRejectedCallback.shift()(value) 53 | } 54 | } 55 | } 56 | 57 | then = function (onFulfilled, onRejected) { 58 | onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value 59 | onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason } 60 | if (this.status === STATUS.PENDING) { 61 | this.onFulfilledCallback.push(onFulfilled) 62 | this.onRejectedCallback.push(onRejected) 63 | } else if (this.status === STATUS.FULFILLED) { 64 | onFulfilled(this.value) 65 | } else if (this.status === STATUS.REJECTED) { 66 | onRejected(this.reason) 67 | } 68 | } 69 | } 70 | 71 | const mypromise = new MyPromise((resolve, reject) => { 72 | resolve('成功') 73 | }) 74 | 75 | mypromise.then(data => { 76 | console.log(data, '1') 77 | }) 78 | 79 | mypromise.then(data => { 80 | console.log(data, '2') 81 | }) 82 | -------------------------------------------------------------------------------- /src/手写系列/Promise/异步事件.js: -------------------------------------------------------------------------------- 1 | const STATUS = { 2 | PENDING: 'pending', 3 | FULFILLED: 'fulfilled', 4 | REJECTED: 'rejected' 5 | } 6 | 7 | class MyPromise { 8 | constructor (executor) { 9 | // 执行器 10 | try { 11 | executor(this.resolve, this.reject) 12 | } catch (error) { 13 | this.reject(error) 14 | } 15 | } 16 | 17 | // 成功回调 18 | onFulfilledCallbacks = [] 19 | 20 | // 失败回调 21 | onRejectedCallbacks = [] 22 | 23 | // 初始状态 24 | status = STATUS.PENDING 25 | 26 | // 成功返回值 27 | value = null 28 | 29 | // 失败返回值 30 | resolve = null 31 | 32 | // 修改 Promise 状态,并定义成功返回值 33 | resolve = value => { 34 | if (this.status === STATUS.PENDING) { 35 | this.status = STATUS.FULFILLED 36 | this.value = value 37 | 38 | while(this.onFulfilledCallbacks.length) { 39 | this.onFulfilledCallbacks.shift()(value) 40 | } 41 | } 42 | } 43 | 44 | // 修改 Promise 状态,并定义失败返回值 45 | reject = value => { 46 | if (this.status === STATUS.PENDING) { 47 | this.status = STATUS.REJECTED 48 | this.reason = value 49 | 50 | while(this.onRejectedCallbacks.length) { 51 | this.onRejectedCallbacks.shift()(value) 52 | } 53 | } 54 | } 55 | 56 | then (onFulfilled, onRejected) { 57 | const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value 58 | const realOnRejected = typeof onRejected === 'function' ? onRejected : error => { throw error } 59 | 60 | const promise2 = new MyPromise((resolve, reject) => { 61 | 62 | const fulfilledMicrotask = () => { 63 | // 创建一个微任务等待 promise2 完成初始化 64 | queueMicrotask(() => { 65 | try { 66 | // 获取成功回调函数的执行结果 67 | const x = realOnFulfilled(this.value); 68 | // 传入 resolvePromise 集中处理 69 | resolvePromise(promise2, x, resolve, reject); 70 | } catch (error) { 71 | reject(error) 72 | } 73 | }) 74 | } 75 | 76 | const rejectedMicrotask = () => { 77 | // 创建一个微任务等待 promise2 完成初始化 78 | queueMicrotask(() => { 79 | try { 80 | // 调用失败回调,并且把原因返回 81 | const x = realOnRejected(this.reason); 82 | // 传入 resolvePromise 集中处理 83 | resolvePromise(promise2, x, resolve, reject); 84 | } catch (error) { 85 | reject(error) 86 | } 87 | }) 88 | } 89 | 90 | if (this.status === STATUS.PENDING) { 91 | this.onFulfilledCallbacks.push(fulfilledMicrotask) 92 | this.onRejectedCallbacks.push(rejectedMicrotask) 93 | } else if (this.status === STATUS.FULFILLED) { 94 | fulfilledMicrotask() 95 | } else if (this.status === STATUS.REJECTED) { 96 | rejectedMicrotask() 97 | } 98 | }) 99 | 100 | return promise2 101 | } 102 | } 103 | 104 | function resolvePromise (promise, x, resolve, reject) { 105 | // 如果 promise === x, 执行 reject,错误原因为 TypeError 106 | if (promise === x) { 107 | return reject(new TypeError('The promise and the return value are the same')) 108 | } 109 | 110 | // 如果 x 是对象或函数 111 | if (typeof x === 'object' || typeof x === 'function') { 112 | 113 | if (x === null) { 114 | return resolve(x); 115 | } 116 | 117 | let then 118 | try { 119 | then = x.then 120 | } catch (error) { 121 | return reject(error) 122 | } 123 | 124 | // 如果 x.then 是函数 125 | if (typeof then === 'function') { 126 | let called = false; 127 | try { 128 | then.call(x, y => { 129 | // resolve的结果依旧是promise 那就继续解析 130 | if (called) return; 131 | called = true; 132 | resolvePromise(promise, y, resolve, reject); 133 | }, err => { 134 | if (called) return; 135 | called = true; 136 | reject(err);// 失败了 137 | }) 138 | } catch (error) { 139 | if (called) return; 140 | reject(error) 141 | } 142 | } else { 143 | // 如果 x.then 不是函数 144 | resolve(x) 145 | } 146 | } else { 147 | // 如果 x 不是 promise 实例 148 | resolve(x) 149 | } 150 | 151 | } 152 | 153 | const mypromise = new MyPromise((resolve, reject) => { 154 | setTimeout(() => resolve('成功'), 1000) 155 | }) 156 | 157 | const mypromise2 = new MyPromise((resolve, reject) => { 158 | setTimeout(() => resolve('成功2'), 1000) 159 | }) 160 | 161 | mypromise.then(data => { 162 | console.log(data, '1') 163 | return mypromise2 164 | }).then(data => { 165 | console.log(data, '2') 166 | }) -------------------------------------------------------------------------------- /src/手写系列/Promise/链式调用then.js: -------------------------------------------------------------------------------- 1 | const STATUS = { 2 | PENDING: 'pending', 3 | FULFILLED: 'fulfilled', 4 | REJECTED: 'rejected' 5 | } 6 | 7 | class MyPromise { 8 | constructor (executor) { 9 | // 执行器 10 | try { 11 | executor(this.resolve, this.reject) 12 | } catch (error) { 13 | this.reject(error) 14 | } 15 | } 16 | 17 | // 成功回调 18 | onFulfilledCallback = [] 19 | 20 | // 失败回调 21 | onRejectedCallback = [] 22 | 23 | // 初始状态 24 | status = STATUS.PENDING 25 | 26 | // 成功返回值 27 | value = null 28 | 29 | // 失败返回值 30 | resolve = null 31 | 32 | // 修改 Promise 状态,并定义成功返回值 33 | resolve = value => { 34 | if (this.status === STATUS.PENDING) { 35 | this.status = STATUS.FULFILLED 36 | this.value = value 37 | 38 | while(this.onFulfilledCallback.length) { 39 | this.onFulfilledCallback.shift()(value) 40 | } 41 | } 42 | } 43 | 44 | // 修改 Promise 状态,并定义失败返回值 45 | reject = value => { 46 | if (this.status === STATUS.PENDING) { 47 | this.status = STATUS.REJECTED 48 | this.reason = value 49 | 50 | while(this.onRejectedCallback.length) { 51 | this.onRejectedCallback.shift()(value) 52 | } 53 | } 54 | } 55 | 56 | then = function (onFulfilled, onRejected) { 57 | onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value 58 | onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error } 59 | 60 | const promise2 = new MyPromise((resolve, reject) => { 61 | if (this.status === STATUS.PENDING) { 62 | this.onFulfilledCallback.push(() => { 63 | try { 64 | const x = onFulfilled(this.value) 65 | resolvePromise(promise2, x, resolve, reject) 66 | } catch (error) { 67 | reject(error) 68 | } 69 | }) 70 | this.onRejectedCallback.push(() => { 71 | try { 72 | const x = onRejected(this.value) 73 | resolvePromise(promise2, x, resolve, reject) 74 | } catch (error) { 75 | reject(error) 76 | } 77 | }) 78 | } else if (this.status === STATUS.FULFILLED) { 79 | try { 80 | const x = onFulfilled(this.value) 81 | resolvePromise(promise2, x, resolve, reject) 82 | } catch (error) { 83 | reject(error) 84 | } 85 | } else if (this.status === STATUS.REJECTED) { 86 | try { 87 | const x = onRejected(this.reason) 88 | resolvePromise(promise2, x, resolve, reject) 89 | } catch (error) { 90 | reject(error) 91 | } 92 | } 93 | }) 94 | 95 | return promise2 96 | } 97 | } 98 | 99 | function resolvePromise (promise2, x, resolve, reject) { 100 | // 如果 promise2 === x, 执行 reject,错误原因为 TypeError 101 | if (promise2 === x) { 102 | reject(new TypeError('The promise and the return value are the same')) 103 | } 104 | 105 | // 如果 x 是 promise 实例 106 | if (typeof x === 'object' || typeof x === 'function') { 107 | let then 108 | try { 109 | then = x.then 110 | } catch (error) { 111 | reject(error) 112 | } 113 | 114 | // 如果 x.then 是函数 115 | if (typeof then === 'function') { 116 | then.call(x, y => { 117 | // resolve的结果依旧是promise 那就继续解析 118 | resolvePromise(promise2, y, resolve, reject); 119 | }, err => { 120 | reject(err);// 失败了 121 | }) 122 | } else { 123 | // 如果 x.then 不是函数 124 | resolve(x) 125 | } 126 | } else { 127 | // 如果 x 不是 promise 实例 128 | resolve(x) 129 | } 130 | } 131 | 132 | const mypromise = new MyPromise((resolve, reject) => { 133 | resolve('成功') 134 | }) 135 | 136 | const mypromise2 = new MyPromise((resolve, reject) => { 137 | resolve('成功2') 138 | }) 139 | 140 | mypromise.then(data => { 141 | console.log(data, '1') 142 | return mypromise2 143 | }).then(data => { 144 | console.log(data, '2') 145 | }) -------------------------------------------------------------------------------- /src/手写系列/React diff/index.js: -------------------------------------------------------------------------------- 1 | var svd = require('simple-virtual-dom') 2 | 3 | var el = svd.el 4 | var diff = svd.diff 5 | var patch = svd.patch 6 | 7 | // 1. use `el(tagName, [propeties], children)` to create a virtual dom tree 8 | var tree = el('div', {'id': 'container'}, [ 9 | el('h1', {style: 'color: blue'}, ['simple virtal dom']), 10 | el('p', ['Hello, virtual-dom']), 11 | el('ul', [el('li')]) 12 | ]) 13 | 14 | // 2. generate a real dom from virtual dom. `root` is a `div` element 15 | var root = tree.render() 16 | 17 | // 3. generate another different virtual dom tree 18 | var newTree = el('div', {'id': 'container'}, [ 19 | el('h1', {style: 'color: red'}, ['simple virtal dom']), 20 | el('p', ['Hello, virtual-dom']), 21 | el('ul', [el('li'), el('li')]) 22 | ]) 23 | 24 | // 4. diff two virtual dom trees and get patches 25 | var patches = diff(tree, newTree) 26 | 27 | // 5. apply patches to real dom 28 | patch(root, patches) 29 | 30 | // now the `root` dom is updated 31 | -------------------------------------------------------------------------------- /src/手写系列/React/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/手写系列/React/.DS_Store -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 20 | 33 | 34 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 |
13 | 277 | 278 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo11.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 |
13 | 322 | 323 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo12.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 |
13 | 324 | 325 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World 6 | 7 | 8 |
9 | 25 | 26 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 |
14 | 48 | 49 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 50 | 51 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 68 | 69 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 87 | 88 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 139 | 140 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 153 | 154 | -------------------------------------------------------------------------------- /src/手写系列/React/reactDemo9.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 |
13 | 257 | 258 | -------------------------------------------------------------------------------- /src/手写系列/虚拟DOM/READ.md: -------------------------------------------------------------------------------- 1 | 快速开始 2 | 3 | 1. 安装依赖 4 | npm i 5 | 6 | 2. rollup 打包 7 | rollup -c -w -------------------------------------------------------------------------------- /src/手写系列/虚拟DOM/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/手写系列/虚拟DOM/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import { terser } from 'rollup-plugin-terser'; 4 | import { babel } from '@rollup/plugin-babel'; 5 | 6 | // `npm run build` -> `production` is true 7 | // `npm run dev` -> `production` is false 8 | const production = !process.env.ROLLUP_WATCH; 9 | 10 | export default { 11 | input: 'src/index.js', 12 | output: { 13 | file: 'public/bundle.js', 14 | format: 'iife', // immediately-invoked function expression — suitable for 71 | 72 | -------------------------------------------------------------------------------- /src/手写系列/虚拟DOM实例/分页/真实DOM/index.js: -------------------------------------------------------------------------------- 1 | // 全局对象 2 | const _ = {} 3 | 4 | window.onload = function () { 5 | // ul 节点 6 | _.oUl = document.getElementById('list') 7 | // 按钮 节点 8 | _.oButton = document.getElementById('btn') 9 | // 消耗时间 节点 10 | _.oTime = document.getElementById('time') 11 | // 文章模拟 节点 12 | _.oHtml = document.getElementById('html') 13 | const btnList = _.oButton.getElementsByTagName('button') 14 | 15 | Array.from(btnList).forEach((btn, index) => { 16 | // 为按钮添加事件 17 | btn.addEventListener('click', () => { 18 | go({page: index + 1}) 19 | }) 20 | }) 21 | 22 | // 默认加载第一页数据 23 | go({page: 1}) 24 | } 25 | 26 | // 跳转到某一页 27 | function go ({page}) { 28 | const startTime = new Date().getTime() 29 | const data = getData({page}) 30 | handleDom(data) 31 | const endTime = new Date().getTime() 32 | const time = endTime - startTime 33 | showTimeOnPage(time) 34 | } 35 | 36 | function showTimeOnPage (time) { 37 | _.oTime.innerHTML = time 38 | } 39 | 40 | function handleDom (data) { 41 | const ulChildren = _.oUl.getElementsByTagName('li') 42 | Array.from(ulChildren).forEach(item => { 43 | _.oUl.removeChild(item) 44 | }) 45 | 46 | data.forEach((dataItem, index) => { 47 | const li = document.createElement('li') 48 | li.innerHTML = `${index}-${dataItem}${_.oHtml}` 49 | _.oUl.appendChild(li) 50 | }) 51 | } 52 | 53 | // 获取某一页的数据 54 | function getData ({page, pageSize = 20}) { 55 | const list = [] 56 | list.length = pageSize 57 | return list.fill(page) 58 | } -------------------------------------------------------------------------------- /src/手写系列/虚拟DOM实例/分页/真实DOM/public/bundle.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | // 全局对象 5 | var _ = {}; 6 | 7 | window.onload = function () { 8 | // ul 节点 9 | _.oUl = document.getElementById('list'); // 按钮 节点 10 | 11 | _.oButton = document.getElementById('btn'); // 消耗时间 节点 12 | 13 | _.oTime = document.getElementById('time'); // 文章模拟 节点 14 | 15 | _.oHtml = document.getElementById('html'); 16 | 17 | var btnList = _.oButton.getElementsByTagName('button'); 18 | 19 | Array.from(btnList).forEach(function (btn, index) { 20 | // 为按钮添加事件 21 | btn.addEventListener('click', function () { 22 | go({ 23 | page: index + 1 24 | }); 25 | }); 26 | }); // 默认加载第一页数据 27 | 28 | go({ 29 | page: 1 30 | }); 31 | }; // 跳转到某一页 32 | 33 | 34 | function go(_ref) { 35 | var page = _ref.page; 36 | var startTime = new Date().getTime(); 37 | var data = getData({ 38 | page: page 39 | }); 40 | handleDom(data); 41 | var endTime = new Date().getTime(); 42 | var time = endTime - startTime; 43 | showTimeOnPage(time); 44 | } 45 | 46 | function showTimeOnPage(time) { 47 | _.oTime.innerHTML = time; 48 | } 49 | 50 | function handleDom(data) { 51 | var ulChildren = _.oUl.getElementsByTagName('li'); 52 | 53 | Array.from(ulChildren).forEach(function (item) { 54 | _.oUl.removeChild(item); 55 | }); 56 | data.forEach(function (dataItem, index) { 57 | var li = document.createElement('li'); 58 | li.innerHTML = "".concat(index, "-").concat(dataItem).concat(_.oHtml); 59 | 60 | _.oUl.appendChild(li); 61 | }); 62 | } // 获取某一页的数据 63 | 64 | 65 | function getData(_ref2) { 66 | var page = _ref2.page, 67 | _ref2$pageSize = _ref2.pageSize, 68 | pageSize = _ref2$pageSize === void 0 ? 20 : _ref2$pageSize; 69 | var list = []; 70 | list.length = pageSize; 71 | return list.fill(page); 72 | } 73 | 74 | }()); 75 | //# sourceMappingURL=bundle.js.map 76 | -------------------------------------------------------------------------------- /src/手写系列/虚拟DOM实例/分页/真实DOM/public/bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bundle.js","sources":["../index.js"],"sourcesContent":["// 全局对象\nconst _ = {}\n\nwindow.onload = function () {\n // ul 节点\n _.oUl = document.getElementById('list')\n // 按钮 节点\n _.oButton = document.getElementById('btn')\n // 消耗时间 节点\n _.oTime = document.getElementById('time')\n // 文章模拟 节点\n _.oHtml = document.getElementById('html')\n const btnList = _.oButton.getElementsByTagName('button')\n\n Array.from(btnList).forEach((btn, index) => {\n // 为按钮添加事件\n btn.addEventListener('click', () => {\n go({page: index + 1})\n })\n })\n\n // 默认加载第一页数据\n go({page: 1})\n}\n\n// 跳转到某一页\nfunction go ({page}) {\n const startTime = new Date().getTime()\n const data = getData({page})\n handleDom(data)\n const endTime = new Date().getTime()\n const time = endTime - startTime\n showTimeOnPage(time)\n}\n\nfunction showTimeOnPage (time) {\n _.oTime.innerHTML = time\n}\n\nfunction handleDom (data) {\n const ulChildren = _.oUl.getElementsByTagName('li')\n Array.from(ulChildren).forEach(item => {\n _.oUl.removeChild(item)\n })\n\n data.forEach((dataItem, index) => {\n const li = document.createElement('li')\n li.innerHTML = `${index}-${dataItem}${_.oHtml}`\n _.oUl.appendChild(li)\n })\n}\n\n// 获取某一页的数据\nfunction getData ({page, pageSize = 20}) {\n const list = []\n list.length = pageSize\n return list.fill(page)\n}"],"names":["_","window","onload","oUl","document","getElementById","oButton","oTime","oHtml","btnList","getElementsByTagName","Array","from","forEach","btn","index","addEventListener","go","page","startTime","Date","getTime","data","getData","handleDom","endTime","time","showTimeOnPage","innerHTML","ulChildren","item","removeChild","dataItem","li","createElement","appendChild","pageSize","list","length","fill"],"mappings":";;;IAAA;IACA,IAAMA,CAAC,GAAG,EAAV;;IAEAC,MAAM,CAACC,MAAP,GAAgB,YAAY;IACxB;IACAF,EAAAA,CAAC,CAACG,GAAF,GAAQC,QAAQ,CAACC,cAAT,CAAwB,MAAxB,CAAR,CAFwB;;IAIxBL,EAAAA,CAAC,CAACM,OAAF,GAAYF,QAAQ,CAACC,cAAT,CAAwB,KAAxB,CAAZ,CAJwB;;IAMxBL,EAAAA,CAAC,CAACO,KAAF,GAAUH,QAAQ,CAACC,cAAT,CAAwB,MAAxB,CAAV,CANwB;;IAQxBL,EAAAA,CAAC,CAACQ,KAAF,GAAUJ,QAAQ,CAACC,cAAT,CAAwB,MAAxB,CAAV;;IACA,MAAMI,OAAO,GAAGT,CAAC,CAACM,OAAF,CAAUI,oBAAV,CAA+B,QAA/B,CAAhB;;IAEAC,EAAAA,KAAK,CAACC,IAAN,CAAWH,OAAX,EAAoBI,OAApB,CAA4B,UAACC,GAAD,EAAMC,KAAN,EAAgB;IACxC;IACAD,IAAAA,GAAG,CAACE,gBAAJ,CAAqB,OAArB,EAA8B,YAAM;IAChCC,MAAAA,EAAE,CAAC;IAACC,QAAAA,IAAI,EAAEH,KAAK,GAAG;IAAf,OAAD,CAAF;IACH,KAFD;IAGH,GALD,EAXwB;;IAmBxBE,EAAAA,EAAE,CAAC;IAACC,IAAAA,IAAI,EAAE;IAAP,GAAD,CAAF;IACH,CApBD;;;IAuBA,SAASD,EAAT,OAAqB;IAAA,MAAPC,IAAO,QAAPA,IAAO;IACjB,MAAMC,SAAS,GAAG,IAAIC,IAAJ,GAAWC,OAAX,EAAlB;IACA,MAAMC,IAAI,GAAGC,OAAO,CAAC;IAACL,IAAAA,IAAI,EAAJA;IAAD,GAAD,CAApB;IACAM,EAAAA,SAAS,CAACF,IAAD,CAAT;IACA,MAAMG,OAAO,GAAG,IAAIL,IAAJ,GAAWC,OAAX,EAAhB;IACA,MAAMK,IAAI,GAAGD,OAAO,GAAGN,SAAvB;IACAQ,EAAAA,cAAc,CAACD,IAAD,CAAd;IACH;;IAED,SAASC,cAAT,CAAyBD,IAAzB,EAA+B;IAC3B1B,EAAAA,CAAC,CAACO,KAAF,CAAQqB,SAAR,GAAoBF,IAApB;IACH;;IAED,SAASF,SAAT,CAAoBF,IAApB,EAA0B;IACtB,MAAMO,UAAU,GAAG7B,CAAC,CAACG,GAAF,CAAMO,oBAAN,CAA2B,IAA3B,CAAnB;;IACAC,EAAAA,KAAK,CAACC,IAAN,CAAWiB,UAAX,EAAuBhB,OAAvB,CAA+B,UAAAiB,IAAI,EAAI;IACnC9B,IAAAA,CAAC,CAACG,GAAF,CAAM4B,WAAN,CAAkBD,IAAlB;IACH,GAFD;IAIAR,EAAAA,IAAI,CAACT,OAAL,CAAa,UAACmB,QAAD,EAAWjB,KAAX,EAAqB;IAC9B,QAAMkB,EAAE,GAAG7B,QAAQ,CAAC8B,aAAT,CAAuB,IAAvB,CAAX;IACAD,IAAAA,EAAE,CAACL,SAAH,aAAkBb,KAAlB,cAA2BiB,QAA3B,SAAsChC,CAAC,CAACQ,KAAxC;;IACAR,IAAAA,CAAC,CAACG,GAAF,CAAMgC,WAAN,CAAkBF,EAAlB;IACH,GAJD;IAKH;;;IAGD,SAASV,OAAT,QAAyC;IAAA,MAAtBL,IAAsB,SAAtBA,IAAsB;IAAA,6BAAhBkB,QAAgB;IAAA,MAAhBA,QAAgB,+BAAL,EAAK;IACrC,MAAMC,IAAI,GAAG,EAAb;IACAA,EAAAA,IAAI,CAACC,MAAL,GAAcF,QAAd;IACA,SAAOC,IAAI,CAACE,IAAL,CAAUrB,IAAV,CAAP;IACH;;;;;;"} -------------------------------------------------------------------------------- /src/手写系列/虚拟DOM实例/分页/真实DOM/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import { terser } from 'rollup-plugin-terser'; 4 | import { babel } from '@rollup/plugin-babel'; 5 | 6 | // `npm run build` -> `production` is true 7 | // `npm run dev` -> `production` is false 8 | const production = !process.env.ROLLUP_WATCH; 9 | 10 | export default { 11 | input: 'index.js', 12 | output: { 13 | file: 'public/bundle.js', 14 | format: 'iife', // immediately-invoked function expression — suitable for 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/手写系列/虚拟DOM实例/分页/虚拟DOM/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const e = React.createElement; 4 | 5 | let start = 0 6 | let end = 0 7 | 8 | const html = e("div", { 9 | "data-v-791421da": "", 10 | class: "content-box" 11 | }, e("div", { 12 | "data-v-791421da": "", 13 | class: "meta-container" 14 | }, e("div", { 15 | "data-v-791421da": "", 16 | class: "user-message" 17 | }, e("a", { 18 | "data-v-791421da": "", 19 | href: "/user/4300945218607197", 20 | target: "_blank", 21 | rel: "", 22 | name: "user", 23 | state: "4300945218607197", 24 | class: "userbox" 25 | }, e("div", { 26 | "data-v-1d25c2a8": "", 27 | "data-v-791421da": "", 28 | block: "userPopover", 29 | state: "4300945218607197", 30 | class: "user-popover-box" 31 | }, "\u6E05\u6C64\u997A\u5B50"))), e("div", { 32 | "data-v-791421da": "", 33 | class: "dividing" 34 | }), e("div", { 35 | "data-v-791421da": "", 36 | class: "date" 37 | }, "4\u5929\u524D"), e("div", { 38 | "data-v-791421da": "", 39 | class: "dividing" 40 | }), e("div", { 41 | "data-v-791421da": "", 42 | class: "tag_list" 43 | }, e("div", { 44 | "data-v-791421da": "", 45 | class: "tag" 46 | }, e("a", { 47 | "data-v-791421da": "", 48 | href: "/tag/JavaScript", 49 | target: "_blank", 50 | rel: "", 51 | name: "tag", 52 | state: "6809640398105870343", 53 | class: "tag" 54 | }, " JavaScript "), e("i", { 55 | "data-v-791421da": "", 56 | class: "point" 57 | })), e("div", { 58 | "data-v-791421da": "", 59 | class: "tag" 60 | }, e("a", { 61 | "data-v-791421da": "", 62 | href: "/tag/%E5%89%8D%E7%AB%AF", 63 | target: "_blank", 64 | rel: "", 65 | name: "tag", 66 | state: "6809640407484334093", 67 | class: "tag" 68 | }, " \u524D\u7AEF "), e("i", { 69 | "data-v-791421da": "", 70 | class: "point" 71 | })))), e("div", { 72 | "data-v-791421da": "", 73 | class: "content-wrapper" 74 | }, e("div", { 75 | "data-v-791421da": "", 76 | class: "content-main" 77 | }, e("div", { 78 | "data-v-791421da": "", 79 | class: "title-row" 80 | }, e("a", { 81 | "data-v-791421da": "", 82 | href: "/post/6973155726302642206", 83 | target: "_blank", 84 | rel: "", 85 | name: "title", 86 | title: "\u624B\u5199\u7CFB\u5217-\u8FD9\u4E00\u6B21\uFF0C\u5F7B\u5E95\u641E\u61C2 Promise", 87 | class: "title" 88 | }, " \u624B\u5199\u7CFB\u5217-\u8FD9\u4E00\u6B21\uFF0C\u5F7B\u5E95\u641E\u61C2 Promise ")), e("div", { 89 | "data-v-791421da": "", 90 | class: "abstract" 91 | }, e("a", { 92 | "data-v-791421da": "", 93 | href: "/post/6973155726302642206", 94 | target: "_blank", 95 | rel: "" 96 | }, " \u672C\u6587\u5B9E\u73B0\u4E86\u4E00\u4E2A\u7B26\u5408Promises/A+ \u89C4\u8303\u7684 Promise\uFF0C\u6211\u4EEC\u53EF\u4EE5\u7EE7\u7EED\u81EA\u5DF1\u52A8\u624B\uFF0C\u53C2\u8003 ES6 \u7684 Promise \u65B9\u6CD5\u5BF9 MyPromise \u8FDB\u884C\u62D3\u5C55\u7EC3\u4E60\u3002 ")), e("ul", { 97 | "data-v-791421da": "", 98 | class: "action-list jh-timeline-action-area" 99 | }, e("li", { 100 | "data-v-791421da": "", 101 | name: "commentBtn", 102 | class: "item view" 103 | }, e("i", { 104 | "data-v-791421da": "" 105 | }), " ", e("span", { 106 | "data-v-791421da": "" 107 | }, "2393")), e("li", { 108 | "data-v-791421da": "", 109 | name: "likeBtn", 110 | class: "item like active" 111 | }, e("i", { 112 | "data-v-791421da": "" 113 | }), " ", e("span", { 114 | "data-v-791421da": "" 115 | }, " 18 ")), e("li", { 116 | "data-v-791421da": "", 117 | name: "commentBtn", 118 | class: "item comment" 119 | }, e("i", { 120 | "data-v-791421da": "" 121 | }), " ", e("span", { 122 | "data-v-791421da": "" 123 | }, " 5 ")), e("li", { 124 | "data-v-791421da": "", 125 | name: "moreBtn", 126 | class: "item more" 127 | }, e("i", { 128 | "data-v-791421da": "" 129 | }), e("ul", { 130 | "data-v-791421da": "", 131 | silent: "silent", 132 | class: "more-list" 133 | }, e("li", { 134 | "data-v-791421da": "", 135 | class: "item" 136 | }, " \u7F16\u8F91 "), e("li", { 137 | "data-v-791421da": "", 138 | class: "item" 139 | }, "\u5220\u9664"))))), e("img", { 140 | "data-v-fd37d0ac": "", 141 | "data-v-791421da": "", 142 | src: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/596c26911f3342ea86adcc94c441332d~tplv-k3u1fbpfcp-zoom-mark-crop-v2:0:0:360:240.awebp", 143 | alt: "\u624B\u5199\u7CFB\u5217-\u8FD9\u4E00\u6B21\uFF0C\u5F7B\u5E95\u641E\u61C2 Promise", 144 | class: "lazy thumb", 145 | "data-src": "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/596c26911f3342ea86adcc94c441332d~tplv-k3u1fbpfcp-zoom-mark-crop-v2:0:0:360:240.awebp" 146 | }))) 147 | 148 | class LikeButton extends React.Component { 149 | constructor(props) { 150 | super(props); 151 | this.state = { 152 | data: [], // 分页数据 153 | time: 0 // 耗时 154 | } 155 | 156 | this.go({page: 1}) 157 | } 158 | 159 | componentWillUpdate () { 160 | start = new Date().getTime() 161 | } 162 | 163 | componentDidUpdate () { 164 | end = new Date().getTime() 165 | console.log(end - start) 166 | } 167 | 168 | // 跳转到某一页 169 | go ({page}) { 170 | const startTime = new Date().getTime() 171 | const data = this.getData({page}) 172 | this.handleDom(data) 173 | const endTime = new Date().getTime() 174 | const time = endTime - startTime 175 | this.showTimeOnPage(time) 176 | } 177 | 178 | showTimeOnPage (time) { 179 | this.setState({ 180 | time 181 | }) 182 | } 183 | 184 | handleDom (data) { 185 | this.setState({ 186 | data 187 | }) 188 | } 189 | 190 | // 获取某一页的数据 191 | getData ({page, pageSize = 20}) { 192 | const list = [] 193 | list.length = pageSize 194 | return list.fill(page) 195 | } 196 | 197 | // 在线babel转义 198 | render() { 199 | const { data, time } = this.state 200 | console.log(e("div", { 201 | className: 'box' 202 | }, 203 | e("p", null, "文本") 204 | )) 205 | return (e("div", { 206 | className: 'box' 207 | }, 208 | e("p", null, "文本") 209 | )) 210 | return ( 211 | e("div", null, 212 | e("p", null, "分页消耗时长:", 213 | e("span", null, time), "ms" 214 | ), 215 | e("div", null, 216 | e("button", { onClick: () => this.go({page: 1}) }, "第一页"), 217 | e("button", { onClick: () => this.go({page: 2}) }, "第二页") 218 | ), 219 | e("ul", null, data.map((dataItem, index) => { 220 | const key = `${index}-${dataItem}` 221 | return ( 222 | e("li", { key }, [`${index}-${dataItem}`, html]) 223 | ) 224 | })) 225 | ) 226 | ) 227 | } 228 | } 229 | 230 | const domContainer = document.querySelector('#container'); 231 | ReactDOM.render(e(LikeButton), domContainer); -------------------------------------------------------------------------------- /src/手写系列/虚拟DOM实例/分页/虚拟DOM/public/bundle.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | function _classCallCheck(instance, Constructor) { 5 | if (!(instance instanceof Constructor)) { 6 | throw new TypeError("Cannot call a class as a function"); 7 | } 8 | } 9 | 10 | function _defineProperties(target, props) { 11 | for (var i = 0; i < props.length; i++) { 12 | var descriptor = props[i]; 13 | descriptor.enumerable = descriptor.enumerable || false; 14 | descriptor.configurable = true; 15 | if ("value" in descriptor) descriptor.writable = true; 16 | Object.defineProperty(target, descriptor.key, descriptor); 17 | } 18 | } 19 | 20 | function _createClass(Constructor, protoProps, staticProps) { 21 | if (protoProps) _defineProperties(Constructor.prototype, protoProps); 22 | if (staticProps) _defineProperties(Constructor, staticProps); 23 | return Constructor; 24 | } 25 | 26 | function _setPrototypeOf(o, p) { 27 | _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { 28 | o.__proto__ = p; 29 | return o; 30 | }; 31 | 32 | return _setPrototypeOf(o, p); 33 | } 34 | 35 | function _inherits(subClass, superClass) { 36 | if (typeof superClass !== "function" && superClass !== null) { 37 | throw new TypeError("Super expression must either be null or a function"); 38 | } 39 | 40 | subClass.prototype = Object.create(superClass && superClass.prototype, { 41 | constructor: { 42 | value: subClass, 43 | writable: true, 44 | configurable: true 45 | } 46 | }); 47 | if (superClass) _setPrototypeOf(subClass, superClass); 48 | } 49 | 50 | function _typeof(obj) { 51 | "@babel/helpers - typeof"; 52 | 53 | if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { 54 | _typeof = function _typeof(obj) { 55 | return typeof obj; 56 | }; 57 | } else { 58 | _typeof = function _typeof(obj) { 59 | return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 60 | }; 61 | } 62 | 63 | return _typeof(obj); 64 | } 65 | 66 | function _assertThisInitialized(self) { 67 | if (self === void 0) { 68 | throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 69 | } 70 | 71 | return self; 72 | } 73 | 74 | function _possibleConstructorReturn(self, call) { 75 | if (call && (_typeof(call) === "object" || typeof call === "function")) { 76 | return call; 77 | } 78 | 79 | return _assertThisInitialized(self); 80 | } 81 | 82 | function _getPrototypeOf(o) { 83 | _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { 84 | return o.__proto__ || Object.getPrototypeOf(o); 85 | }; 86 | return _getPrototypeOf(o); 87 | } 88 | 89 | function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 90 | 91 | function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 92 | 93 | var e = React.createElement; 94 | var start = 0; 95 | var end = 0; 96 | e("div", { 97 | "data-v-791421da": "", 98 | "class": "content-box" 99 | }, e("div", { 100 | "data-v-791421da": "", 101 | "class": "meta-container" 102 | }, e("div", { 103 | "data-v-791421da": "", 104 | "class": "user-message" 105 | }, e("a", { 106 | "data-v-791421da": "", 107 | href: "/user/4300945218607197", 108 | target: "_blank", 109 | rel: "", 110 | name: "user", 111 | state: "4300945218607197", 112 | "class": "userbox" 113 | }, e("div", { 114 | "data-v-1d25c2a8": "", 115 | "data-v-791421da": "", 116 | block: "userPopover", 117 | state: "4300945218607197", 118 | "class": "user-popover-box" 119 | }, "\u6E05\u6C64\u997A\u5B50"))), e("div", { 120 | "data-v-791421da": "", 121 | "class": "dividing" 122 | }), e("div", { 123 | "data-v-791421da": "", 124 | "class": "date" 125 | }, "4\u5929\u524D"), e("div", { 126 | "data-v-791421da": "", 127 | "class": "dividing" 128 | }), e("div", { 129 | "data-v-791421da": "", 130 | "class": "tag_list" 131 | }, e("div", { 132 | "data-v-791421da": "", 133 | "class": "tag" 134 | }, e("a", { 135 | "data-v-791421da": "", 136 | href: "/tag/JavaScript", 137 | target: "_blank", 138 | rel: "", 139 | name: "tag", 140 | state: "6809640398105870343", 141 | "class": "tag" 142 | }, " JavaScript "), e("i", { 143 | "data-v-791421da": "", 144 | "class": "point" 145 | })), e("div", { 146 | "data-v-791421da": "", 147 | "class": "tag" 148 | }, e("a", { 149 | "data-v-791421da": "", 150 | href: "/tag/%E5%89%8D%E7%AB%AF", 151 | target: "_blank", 152 | rel: "", 153 | name: "tag", 154 | state: "6809640407484334093", 155 | "class": "tag" 156 | }, " \u524D\u7AEF "), e("i", { 157 | "data-v-791421da": "", 158 | "class": "point" 159 | })))), e("div", { 160 | "data-v-791421da": "", 161 | "class": "content-wrapper" 162 | }, e("div", { 163 | "data-v-791421da": "", 164 | "class": "content-main" 165 | }, e("div", { 166 | "data-v-791421da": "", 167 | "class": "title-row" 168 | }, e("a", { 169 | "data-v-791421da": "", 170 | href: "/post/6973155726302642206", 171 | target: "_blank", 172 | rel: "", 173 | name: "title", 174 | title: "\u624B\u5199\u7CFB\u5217-\u8FD9\u4E00\u6B21\uFF0C\u5F7B\u5E95\u641E\u61C2 Promise", 175 | "class": "title" 176 | }, " \u624B\u5199\u7CFB\u5217-\u8FD9\u4E00\u6B21\uFF0C\u5F7B\u5E95\u641E\u61C2 Promise ")), e("div", { 177 | "data-v-791421da": "", 178 | "class": "abstract" 179 | }, e("a", { 180 | "data-v-791421da": "", 181 | href: "/post/6973155726302642206", 182 | target: "_blank", 183 | rel: "" 184 | }, " \u672C\u6587\u5B9E\u73B0\u4E86\u4E00\u4E2A\u7B26\u5408Promises/A+ \u89C4\u8303\u7684 Promise\uFF0C\u6211\u4EEC\u53EF\u4EE5\u7EE7\u7EED\u81EA\u5DF1\u52A8\u624B\uFF0C\u53C2\u8003 ES6 \u7684 Promise \u65B9\u6CD5\u5BF9 MyPromise \u8FDB\u884C\u62D3\u5C55\u7EC3\u4E60\u3002 ")), e("ul", { 185 | "data-v-791421da": "", 186 | "class": "action-list jh-timeline-action-area" 187 | }, e("li", { 188 | "data-v-791421da": "", 189 | name: "commentBtn", 190 | "class": "item view" 191 | }, e("i", { 192 | "data-v-791421da": "" 193 | }), " ", e("span", { 194 | "data-v-791421da": "" 195 | }, "2393")), e("li", { 196 | "data-v-791421da": "", 197 | name: "likeBtn", 198 | "class": "item like active" 199 | }, e("i", { 200 | "data-v-791421da": "" 201 | }), " ", e("span", { 202 | "data-v-791421da": "" 203 | }, " 18 ")), e("li", { 204 | "data-v-791421da": "", 205 | name: "commentBtn", 206 | "class": "item comment" 207 | }, e("i", { 208 | "data-v-791421da": "" 209 | }), " ", e("span", { 210 | "data-v-791421da": "" 211 | }, " 5 ")), e("li", { 212 | "data-v-791421da": "", 213 | name: "moreBtn", 214 | "class": "item more" 215 | }, e("i", { 216 | "data-v-791421da": "" 217 | }), e("ul", { 218 | "data-v-791421da": "", 219 | silent: "silent", 220 | "class": "more-list" 221 | }, e("li", { 222 | "data-v-791421da": "", 223 | "class": "item" 224 | }, " \u7F16\u8F91 "), e("li", { 225 | "data-v-791421da": "", 226 | "class": "item" 227 | }, "\u5220\u9664"))))), e("img", { 228 | "data-v-fd37d0ac": "", 229 | "data-v-791421da": "", 230 | src: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/596c26911f3342ea86adcc94c441332d~tplv-k3u1fbpfcp-zoom-mark-crop-v2:0:0:360:240.awebp", 231 | alt: "\u624B\u5199\u7CFB\u5217-\u8FD9\u4E00\u6B21\uFF0C\u5F7B\u5E95\u641E\u61C2 Promise", 232 | "class": "lazy thumb", 233 | "data-src": "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/596c26911f3342ea86adcc94c441332d~tplv-k3u1fbpfcp-zoom-mark-crop-v2:0:0:360:240.awebp" 234 | }))); 235 | 236 | var LikeButton = /*#__PURE__*/function (_React$Component) { 237 | _inherits(LikeButton, _React$Component); 238 | 239 | var _super = _createSuper(LikeButton); 240 | 241 | function LikeButton(props) { 242 | var _this; 243 | 244 | _classCallCheck(this, LikeButton); 245 | 246 | _this = _super.call(this, props); 247 | _this.state = { 248 | data: [], 249 | // 分页数据 250 | time: 0 // 耗时 251 | 252 | }; 253 | 254 | _this.go({ 255 | page: 1 256 | }); 257 | 258 | return _this; 259 | } 260 | 261 | _createClass(LikeButton, [{ 262 | key: "componentWillUpdate", 263 | value: function componentWillUpdate() { 264 | start = new Date().getTime(); 265 | } 266 | }, { 267 | key: "componentDidUpdate", 268 | value: function componentDidUpdate() { 269 | end = new Date().getTime(); 270 | console.log(end - start); 271 | } // 跳转到某一页 272 | 273 | }, { 274 | key: "go", 275 | value: function go(_ref) { 276 | var page = _ref.page; 277 | var startTime = new Date().getTime(); 278 | var data = this.getData({ 279 | page: page 280 | }); 281 | this.handleDom(data); 282 | var endTime = new Date().getTime(); 283 | var time = endTime - startTime; 284 | this.showTimeOnPage(time); 285 | } 286 | }, { 287 | key: "showTimeOnPage", 288 | value: function showTimeOnPage(time) { 289 | this.setState({ 290 | time: time 291 | }); 292 | } 293 | }, { 294 | key: "handleDom", 295 | value: function handleDom(data) { 296 | this.setState({ 297 | data: data 298 | }); 299 | } // 获取某一页的数据 300 | 301 | }, { 302 | key: "getData", 303 | value: function getData(_ref2) { 304 | var page = _ref2.page, 305 | _ref2$pageSize = _ref2.pageSize, 306 | pageSize = _ref2$pageSize === void 0 ? 20 : _ref2$pageSize; 307 | var list = []; 308 | list.length = pageSize; 309 | return list.fill(page); 310 | } // 在线babel转义 311 | 312 | }, { 313 | key: "render", 314 | value: function render() { 315 | 316 | var _this$state = this.state; 317 | _this$state.data; 318 | _this$state.time; 319 | console.log(e("div", { 320 | className: 'box' 321 | }, e("p", null, "文本"))); 322 | return e("div", { 323 | className: 'box' 324 | }, e("p", null, "文本")); 325 | } 326 | }]); 327 | 328 | return LikeButton; 329 | }(React.Component); 330 | 331 | var domContainer = document.querySelector('#container'); 332 | ReactDOM.render(e(LikeButton), domContainer); 333 | 334 | }()); 335 | //# sourceMappingURL=bundle.js.map 336 | -------------------------------------------------------------------------------- /src/手写系列/虚拟DOM实例/分页/虚拟DOM/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import { terser } from 'rollup-plugin-terser'; 4 | import { babel } from '@rollup/plugin-babel'; 5 | 6 | // `npm run build` -> `production` is true 7 | // `npm run dev` -> `production` is false 8 | const production = !process.env.ROLLUP_WATCH; 9 | 10 | export default { 11 | input: 'index.js', 12 | output: { 13 | file: 'public/bundle.js', 14 | format: 'iife', // immediately-invoked function expression — suitable for 14 | 15 | -------------------------------------------------------------------------------- /src/设计模式/代理模式/合并HTTP请求/虚拟代理/index.js: -------------------------------------------------------------------------------- 1 | const synchronousFile = cache => { 2 | console.log('开始同步文件,id为:'+ cache.join('/')) 3 | } 4 | 5 | const proxySynchronousFile = (() => { 6 | const cache = [] 7 | 8 | let timer 9 | 10 | return id => { 11 | console.log(id) 12 | cache.push(id) 13 | 14 | if (timer) { 15 | return 16 | } 17 | 18 | timer = setTimeout(() => { 19 | synchronousFile(cache) 20 | clearTimeout(timer) 21 | timer = null 22 | cache.length = 0 23 | }, 2000) 24 | } 25 | })() 26 | 27 | const checkbox = document.getElementsByTagName('input') 28 | 29 | Array.from(checkbox).forEach(i => { 30 | console.log(i) 31 | i.onclick = () => { 32 | if (i.checked) { 33 | proxySynchronousFile(i.value) 34 | } 35 | } 36 | }) 37 | 38 | -------------------------------------------------------------------------------- /src/设计模式/代理模式/图片预加载/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/代理模式/图片预加载/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/代理模式/图片预加载/普通/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/代理模式/图片预加载/普通/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/代理模式/图片预加载/普通/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /src/设计模式/代理模式/图片预加载/普通/index.js: -------------------------------------------------------------------------------- 1 | const myImage = (() => { 2 | const imgNode = document.createElement('img') 3 | document.body.appendChild(imgNode) 4 | 5 | return { 6 | setSrc: src => { 7 | imgNode.src = src 8 | } 9 | } 10 | })() 11 | 12 | myImage.setSrc('https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fa98e67c4708449eb6894c7133d93774~tplv-k3u1fbpfcp-watermark.image') -------------------------------------------------------------------------------- /src/设计模式/代理模式/图片预加载/虚拟代理/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/代理模式/图片预加载/虚拟代理/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/代理模式/图片预加载/虚拟代理/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /src/设计模式/代理模式/图片预加载/虚拟代理/index.js: -------------------------------------------------------------------------------- 1 | const myImage = (() => { 2 | const imgNode = document.createElement('img') 3 | document.body.appendChild(imgNode) 4 | 5 | return { 6 | setSrc: src => { 7 | imgNode.src = src 8 | } 9 | } 10 | })() 11 | 12 | const loadingSrc = '../../../../img/loading.gif' 13 | const imgSrc = 'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fa98e67c4708449eb6894c7133d93774~tplv-k3u1fbpfcp-watermark.image' 14 | 15 | const proxyImage = (function () { 16 | const img = new Image() 17 | img.onload = () => { 18 | myImage.setSrc(img.src) 19 | } 20 | 21 | return { 22 | setSrc: src => { 23 | myImage.setSrc(loadingSrc) 24 | img.src = src 25 | } 26 | } 27 | })() 28 | 29 | proxyImage.setSrc(imgSrc) 30 | 31 | -------------------------------------------------------------------------------- /src/设计模式/代理模式/小明送花给小白/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/代理模式/小明送花给小白/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/代理模式/小明送花给小白/代理模式/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/代理模式/小明送花给小白/代理模式/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/代理模式/小明送花给小白/代理模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /src/设计模式/代理模式/小明送花给小白/代理模式/index.js: -------------------------------------------------------------------------------- 1 | const Flower = function () { 2 | return '玫瑰🌹' 3 | } 4 | 5 | const xiaoming = { 6 | sendFlower: target => { 7 | const flower = new Flower() 8 | target.receiveFlower(flower) 9 | } 10 | } 11 | 12 | const xiaodai = { 13 | receiveFlower: flower => { 14 | xiaobai.listenGoodMood().then(() => { 15 | xiaobai.receiveFlower(flower) 16 | }) 17 | } 18 | } 19 | 20 | const xiaobai = { 21 | receiveFlower: flower => { 22 | console.log('收到花', flower) 23 | }, 24 | listenGoodMood: fn => { 25 | return new Promise((reslove, reject) => { 26 | // 10秒后,心情变好 27 | reslove() 28 | }) 29 | } 30 | } 31 | 32 | xiaoming.sendFlower(xiaodai) -------------------------------------------------------------------------------- /src/设计模式/代理模式/小明送花给小白/普通/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/代理模式/小明送花给小白/普通/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/代理模式/小明送花给小白/普通/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /src/设计模式/代理模式/小明送花给小白/普通/index.js: -------------------------------------------------------------------------------- 1 | const Flower = function () { 2 | return '玫瑰🌹' 3 | } 4 | 5 | const xiaoming = { 6 | sendFlower: target => { 7 | const flower = new Flower() 8 | target.receiveFlower(flower) 9 | } 10 | } 11 | 12 | const xiaobai = { 13 | receiveFlower: flower => { 14 | console.log('收到花', flower) 15 | } 16 | } 17 | 18 | xiaoming.sendFlower(xiaobai) -------------------------------------------------------------------------------- /src/设计模式/单例模式/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/单例模式/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/单例模式/代理实现单例模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/设计模式/单例模式/代理实现单例模式/index.js: -------------------------------------------------------------------------------- 1 | let CreateDiv = function (html) { 2 | this.html = html 3 | this.init() 4 | console.log(html) 5 | } 6 | 7 | CreateDiv.prototype.init = function () { 8 | let div = document.createElement('div') 9 | div.innerHTML = this.html 10 | document.body.appendChild(div) 11 | } 12 | 13 | let ProxySingleTonCreateDiv = function (html) { 14 | let instance; 15 | 16 | return html => { 17 | if (!instance) { 18 | instance = new CreateDiv(html) 19 | console.log(instance.html) 20 | } 21 | return instance 22 | } 23 | } 24 | 25 | let a = new ProxySingleTonCreateDiv('a')() 26 | let b = new ProxySingleTonCreateDiv('b')() 27 | 28 | console.log(a === b, a, b) -------------------------------------------------------------------------------- /src/设计模式/单例模式/实现单例模式/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/单例模式/实现单例模式/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/单例模式/实现单例模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/设计模式/单例模式/实现单例模式/实现单例模式.js: -------------------------------------------------------------------------------- 1 | let Singleton = function (name) { 2 | this.name = name 3 | this.instance = null 4 | } 5 | 6 | Singleton.prototype.getName = () => { 7 | console.log(this.name) 8 | } 9 | 10 | Singleton.getInstance = name => { 11 | if (!this.instance) { 12 | this.instance = new Singleton(name) 13 | } 14 | return this.instance 15 | } 16 | 17 | // Singleton.getInstance = (() => { 18 | // let instance = null 19 | // return name => { 20 | // if (!instance) { 21 | // instance = new Singleton(name) 22 | // } 23 | // return instance 24 | // } 25 | // })() 26 | 27 | let a = Singleton.getInstance('b') 28 | let b = Singleton.getInstance('c') 29 | 30 | console.log(a === b, a, b) -------------------------------------------------------------------------------- /src/设计模式/单例模式/登录浮窗/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/单例模式/登录浮窗/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/单例模式/登录浮窗/单例模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /src/设计模式/单例模式/登录浮窗/单例模式/index.js: -------------------------------------------------------------------------------- 1 | const createLoginLayer = () => { 2 | const div = document.createElement('div') 3 | div.innerHTML = '我是登录弹窗' 4 | div.style.display = 'none' 5 | console.log(123) 6 | 7 | document.body.appendChild(div) 8 | return div 9 | } 10 | 11 | const createSingle = (function () { 12 | let instance = {} 13 | return function (fn) { 14 | if (!instance[fn.name]) { 15 | instance[fn.name] = fn.apply(this, arguments) 16 | } 17 | return instance[fn.name] 18 | } 19 | })() 20 | 21 | function createIframe() { 22 | const iframe = document.createElement('iframe') 23 | document.body.appendChild(iframe) 24 | iframe.style.display = 'none' 25 | return iframe 26 | } 27 | 28 | const createSingleLoginLayer = createSingle(createLoginLayer) 29 | const createSingleIframe = createSingle(createIframe) 30 | 31 | document.getElementById('loginBtn').onclick = () => { 32 | const loginLayer = createSingleLoginLayer 33 | const iframe = createSingleIframe 34 | loginLayer.style.display = 'block' 35 | iframe.style.display = 'block' 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/设计模式/单例模式/登录浮窗/普通/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/单例模式/登录浮窗/普通/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/单例模式/登录浮窗/普通/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /src/设计模式/单例模式/登录浮窗/普通/index.js: -------------------------------------------------------------------------------- 1 | let loginLayer = (() => { 2 | let div = document.createElement('div') 3 | div.innerHTML = '我是登录弹窗' 4 | div.style.display = 'none' 5 | 6 | document.body.appendChild(div) 7 | 8 | return div 9 | })() 10 | 11 | document.getElementById('loginBtn').onclick = () => { 12 | loginLayer.style.display = 'block' 13 | } -------------------------------------------------------------------------------- /src/设计模式/单例模式/登录浮窗/普通/index2.js: -------------------------------------------------------------------------------- 1 | let createLoginLayer = () => { 2 | let div = document.createElement('div') 3 | div.innerHTML = '我是登录弹窗' 4 | div.style.display = 'none' 5 | 6 | document.body.appendChild(div) 7 | 8 | return div 9 | } 10 | 11 | document.getElementById('loginBtn').onclick = () => { 12 | const loginLayer = createLoginLayer() 13 | loginLayer.style.display = 'block' 14 | } -------------------------------------------------------------------------------- /src/设计模式/单例模式/登录浮窗/普通2/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/单例模式/登录浮窗/普通2/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/单例模式/登录浮窗/普通2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /src/设计模式/单例模式/登录浮窗/普通2/index.js: -------------------------------------------------------------------------------- 1 | let createLoginLayer = () => { 2 | let div = document.createElement('div') 3 | div.innerHTML = '我是登录弹窗' 4 | div.style.display = 'none' 5 | 6 | document.body.appendChild(div) 7 | 8 | return div 9 | } 10 | 11 | document.getElementById('loginBtn').onclick = () => { 12 | const loginLayer = createLoginLayer() 13 | loginLayer.style.display = 'block' 14 | } -------------------------------------------------------------------------------- /src/设计模式/单例模式/透明的单例模式/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/单例模式/透明的单例模式/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/单例模式/透明的单例模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/设计模式/单例模式/透明的单例模式/透明的单例模式.js: -------------------------------------------------------------------------------- 1 | let createDiv = (() => { 2 | let instance 3 | 4 | let createDiv = (html) => { 5 | if (instance) { 6 | return instance 7 | } 8 | this.html = html 9 | this.init() 10 | return instance = this 11 | } 12 | 13 | createDiv.prototype.init = () => { 14 | let div = document.createElement('div') 15 | div.innerHTML = this.html 16 | document.body.appendChild(div) 17 | } 18 | 19 | return createDiv 20 | }) -------------------------------------------------------------------------------- /src/设计模式/单例模式/通用的惰性单例/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
123123
9 | 10 | 11 | -------------------------------------------------------------------------------- /src/设计模式/单例模式/通用的惰性单例/index.js: -------------------------------------------------------------------------------- 1 | let getSingle = fn => { 2 | let result 3 | 4 | return function () { 5 | result || (result = fn.apply(this, arguments)) 6 | } 7 | } 8 | 9 | let createSingleIframe = getSingle(function () { 10 | let iframe = document.createElement('iframe') 11 | document.body.appendChild(iframe) 12 | console.log(iframe) 13 | return iframe 14 | }) 15 | 16 | const iDiv = document.getElementsByTagName('div')[0] 17 | iDiv.onclick = function () { 18 | let a = createSingleIframe('a') 19 | let b = createSingleIframe('b') 20 | console.log(a, b, a=== b) 21 | } 22 | console.log(iDiv, 1111) -------------------------------------------------------------------------------- /src/设计模式/策略模式/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/策略模式/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/策略模式/什么是快乐星球,什么是策略模式.md: -------------------------------------------------------------------------------- 1 | > 当我们计划国庆出去游玩时,在交通方式上,我们可以选择贵而快的飞机/价格中等但稍慢的动车/便宜但超级慢的火车,根据不同的人,选择对应的交通方式,且可以更换交通方式,这就是策略模式。 2 | 3 | 策略模式的定义是,定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。 4 | 5 | 另外一个场景,给员工发放年终奖,假设,绩效为s的员工年终奖是4倍工资,绩效为a的员工年终奖是3倍工资,绩效为b的员工年终奖是2倍工资,下面我们来计算员工的年终奖。 6 | 7 | ``` 8 | let calculateBonus = function(performanceLevel, salary) {

 9 | if (performanceLevel === 'S') {
 10 | return salary * 4;
 11 | }

 12 | if (performanceLevel === 'A') {
 13 | return salary * 3;
 14 | }

 15 | if (performanceLevel === 'B') {
 16 | return salary * 2;
 17 | }

 18 | };

 19 | 20 | calculateBonus('B', 20000); // 输出:40000
 21 | calculateBonus( 'S', 6000 ); // 输出:24000 22 | 23 | ``` 24 | 25 | 上述代码有以下缺点: 26 | 1. 使用if-else语句描述逻辑 27 | 2. 缺乏弹性,如果需要修改绩效s的奖金系数,必须修改calculateBonus函数,违法了开放-封闭原则 28 | 3. 无法再次复用,当其他地方需要用到这套逻辑,只能再复制一份 29 | 30 | 31 | 使用策略模式改良后 32 | 33 | 34 | ``` 35 | let strategies = { 36 | s: salary => { 37 | return salary * 4 38 | }, 39 | a: salary => { 40 | return salary * 3 41 | }, 42 | b: salary => { 43 | return salary * 2 44 | } 45 | } 46 | 47 | const calculateBonus = (level, salary) => { 48 | return strtegies[level](salary) 49 | } 50 | 51 | console.log(calculateBonus('s', 20000)) 52 | console.log(calculateBonus('a', 10000)) 53 | ``` -------------------------------------------------------------------------------- /src/设计模式/策略模式/表单校验/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/策略模式/表单校验/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/策略模式/表单校验/普通/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/策略模式/表单校验/普通/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/策略模式/表单校验/普通/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 用户名: 10 | 密码: 11 | 手机号: 12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /src/设计模式/策略模式/表单校验/普通/index.js: -------------------------------------------------------------------------------- 1 | let registerForm = document.getElementById('registerForm') 2 | 3 | registerForm.onsubmit = () => { 4 | if (registerForm.userName.value) { 5 | alert('用户名不能为空') 6 | return false 7 | } 8 | 9 | if (registerForm.password.value.length < 6) { 10 | alert('密码长度不能少于6') 11 | return false 12 | } 13 | 14 | if (!/(^1[3|5|8][0-9]$)/.test(registerForm.phone.value)) { 15 | alert('手机号码格式不正确') 16 | return false 17 | } 18 | } -------------------------------------------------------------------------------- /src/设计模式/策略模式/表单校验/策略/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/策略模式/表单校验/策略/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/策略模式/表单校验/策略/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 请输入用户名: 11 | 12 | 请输入密码: 13 | 14 | 请输入手机号码: 15 | 16 | 19 |
20 | 23 | 24 | -------------------------------------------------------------------------------- /src/设计模式/策略模式/表单校验/策略/index.js: -------------------------------------------------------------------------------- 1 | /***********************策略对象**************************/ 2 | 3 | let strategies = {
 4 | isNonEmpty: function(value, errorMsg) {
 5 | if (value === '') {
 6 | return errorMsg;
 7 | }
 8 | }, 9 | 
minLength: function(value, length, errorMsg) {
 10 | if (value.length < length) {
 11 | return errorMsg;
 12 | }
 13 | }, 14 | 
isMobile: function(value, errorMsg) {
 15 | if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
 16 | return errorMsg;
 17 | }
 18 | }
 19 | };

 20 | 21 | /***********************Validator类**************************/ 22 | 

 23 | let Validator = function() {
 24 | this.cache = [];
 25 | };

 26 | 27 | Validator.prototype.add = function(dom, rules) {

 28 | rules.forEach(rule => { 29 | const { strategy, errorMsg } = rule 30 | const [ strategyName, strategyCondition ] = strategy.split(':') 31 | const { value } = dom 32 | this.cache.push(strategies[strategyName].bind(dom, value, errorMsg)) 33 | }) 34 | };

 35 | 36 | Validator.prototype.start = function() {
 37 | let errorMsg 38 | this.cache.some(cacheItem => { 39 | const _errorMsg = cacheItem() 40 | if (_errorMsg) { 41 | errorMsg = _errorMsg 42 | return true 43 | } else { 44 | return false 45 | } 46 | }) 47 | return errorMsg 48 | };

 49 | 50 | let validataFunc = () => { 51 | let validator = new Validator() 52 | validator.add(registerForm.userName, [{ 53 | strategy: 'isNonEmpty', 54 | errorMsg: '用户名不能为空' 55 | },{ 56 | strategy: 'minLength:10', 57 | errorMsg: '用户名长度不能小于10位' 58 | }]); 59 | validator.add(registerForm.password, [{ 60 | strategy: 'minLength:6', 61 | errorMsg: '密码长度不能小于6位' 62 | }]); 63 | validator.add(registerForm.phoneNumber, [{ 64 | strategy: 'isMobile', 65 | errorMsg: '手机号码格式不正确' 66 | }]); 67 | 68 | const errorMsg = validator.start() 69 | return errorMsg 70 | } 71 | /***********************客户调用代码**************************/ 72 | 

 73 | let registerForm = document.getElementById('registerForm');

 74 | 75 | 76 | registerForm.onsubmit = function() {
 77 | let errorMsg = validataFunc();

 78 | if (errorMsg) {
 79 | alert(errorMsg);
 80 | return false;
 81 | }
 82 | };

 -------------------------------------------------------------------------------- /src/设计模式/策略模式/表单校验/策略/index1.js: -------------------------------------------------------------------------------- 1 | // 表单dom 2 | const registerForm = document.getElementById('registerForm') 3 | 4 | // 表单规则 5 | const rules = { 6 | userName: [ 7 | { 8 | strategy: 'isNonEmpty', 9 | errorMsg: '用户名不能为空' 10 | }, 11 | { 12 | strategy: 'minLength:10', 13 | errorMsg: '用户名长度不能小于10位' 14 | } 15 | ], 16 | password: [ 17 | { 18 | strategy: 'minLength:6', 19 | errorMsg: '密码长度不能小于6位' 20 | } 21 | ], 22 | phoneNumber: [ 23 | { 24 | strategy: 'isMobile', 25 | errorMsg: '手机号码格式不正确' 26 | } 27 | ] 28 | } 29 | 30 | // 策略类 31 | let strategies = { 32 | isNonEmpty: function(value, errorMsg) { 33 | if (value === '') { 34 | return errorMsg; 35 | } 36 | }, 37 | minLength: function(value, errorMsg, length) { 38 | console.log(length) 39 | if (value.length < length) { 40 | return errorMsg; 41 | } 42 | }, 43 | isMobile: function(value, errorMsg) { 44 | if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) { 45 | return errorMsg; 46 | } 47 | } 48 | }; 49 | 50 | // 验证类 51 | const Validator = function () { 52 | this.cache = [] 53 | } 54 | 55 | // 添加验证方法 56 | Validator.prototype.add = function ({ dom, rules}) { 57 | rules.forEach(rule => { 58 | const { strategy, errorMsg } = rule 59 | console.log(rule) 60 | const [ strategyName, strategyCondition ] = strategy.split(':') 61 | console.log(strategyName) 62 | const { value } = dom 63 | this.cache.push(strategies[strategyName].bind(dom, value, errorMsg, strategyCondition)) 64 | }) 65 | } 66 | 67 | // 开始验证 68 | Validator.prototype.start = function () { 69 | let errorMsg 70 | this.cache.some(cacheItem => { 71 | const _errorMsg = cacheItem() 72 | if (_errorMsg) { 73 | errorMsg = _errorMsg 74 | return true 75 | } else { 76 | return false 77 | } 78 | }) 79 | 80 | return errorMsg 81 | } 82 | 83 | // 验证函数 84 | const validatorFn = () => { 85 | const validator = new Validator() 86 | console.log(validator.add) 87 | 88 | Object.keys(rules).forEach(key => { 89 | console.log(2222222, rules[key]) 90 | validator.add({ 91 | dom: registerForm[key], 92 | rules: rules[key] 93 | }) 94 | }) 95 | 96 | const errorMsg = validator.start() 97 | return errorMsg 98 | } 99 | 100 | 101 | // 表单提交 102 | registerForm.onsubmit = () => { 103 | const errorMsg = validatorFn() 104 | if (errorMsg) { 105 | alert(errorMsg) 106 | return false 107 | } 108 | return false 109 | } -------------------------------------------------------------------------------- /src/设计模式/职责链模式/预售订单/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/设计模式/职责链模式/预售订单/index.js: -------------------------------------------------------------------------------- 1 | ;const Chain = function(fn) { 2 | this.fn = fn; 3 | this.successor = null; 4 | }; 5 | 6 | Chain.prototype.setNextSuccessor = function(successor) { 7 | return this.successor = successor; 8 | } 9 | 10 | Chain.prototype.passRequest = function() { 11 | const ret = this.fn.apply(this, arguments) 12 | if (ret === 'nextSuccessor') { 13 | return this.successor && this.successor.passRequest.apply(this.successor, arguments); 14 | } 15 | return ret; 16 | }; 17 | 18 | const order500 = function (orderType) { 19 | if (orderType === 500) { 20 | console.log('已预付500定金,享有100优惠券') 21 | } else { 22 | return 'nextSuccessor' 23 | } 24 | } 25 | 26 | const order200 = function (orderType) { 27 | if (orderType === 200) { 28 | console.log('已预付200定金,享有50元优惠券') 29 | } else { 30 | return 'nextSuccessor' 31 | } 32 | } 33 | 34 | const chainOrder500 = new Chain(order500) 35 | 36 | const chainOrder200 = new Chain(order200) 37 | 38 | chainOrder500.setNextSuccessor(chainOrder200) 39 | 40 | chainOrder500.passRequest(200) -------------------------------------------------------------------------------- /src/设计模式/装饰器模式/ajax参数.js: -------------------------------------------------------------------------------- 1 | const before = function (fn, beforeFn) { 2 | return function () { 3 | beforeFn.apply(this, arguments) 4 | return fn.apply(this, arguments) 5 | } 6 | } 7 | 8 | let ajax = function (type, url, param) { 9 | console.log(arguments) 10 | // ...ajax请求...省略 11 | } 12 | 13 | ajax = before(ajax, function (type, url, param) { 14 | console.log(param) 15 | param.token = 'xxx' 16 | }) 17 | 18 | ajax('type', 'url', {name: 'tj'}) -------------------------------------------------------------------------------- /src/设计模式/装饰器模式/index.js: -------------------------------------------------------------------------------- 1 | const before = function (fn, beforeFn) { 2 | return function () { 3 | beforeFn.apply(this, arguments) 4 | return fn.apply(this, arguments) 5 | } 6 | } 7 | 8 | const after = function (fn, afterFn) { 9 | return function () { 10 | const __ = fn.apply(this, arguments) 11 | afterFn.apply(this, arguments) 12 | return __ 13 | } 14 | } 15 | 16 | // let a = before( 17 | // function() { 18 | // alert(1) 19 | // }, 20 | // function() { 21 | // alert(2) 22 | // } 23 | // ) 24 | 25 | // a = before(a, function() { 26 | // alert(3) 27 | // }) 28 | 29 | // a() 30 | 31 | let b = after( 32 | function() { 33 | alert(1) 34 | }, 35 | function() { 36 | alert(2) 37 | } 38 | ) 39 | 40 | b = after(b, function() { 41 | alert(3) 42 | }) 43 | 44 | b() -------------------------------------------------------------------------------- /src/设计模式/装饰器模式/数据上报.js: -------------------------------------------------------------------------------- 1 | const after = function (fn, afterFn) { 2 | return function () { 3 | const __ = fn.apply(this, arguments) 4 | afterFn.apply(this, arguments) 5 | return __ 6 | } 7 | } 8 | 9 | const showLogin = function () { 10 | console.log('去登录') 11 | } 12 | 13 | const log = function () { 14 | console.log('去上报') 15 | } 16 | 17 | const loginBtnClick = after(showLogin, log) 18 | 19 | loginBtnClick() -------------------------------------------------------------------------------- /src/设计模式/装饰器模式/鸭子.js: -------------------------------------------------------------------------------- 1 | const before = function (fn, beforeFn) { 2 | return function () { 3 | beforeFn.apply(this, arguments) 4 | return fn.apply(this, arguments) 5 | } 6 | } 7 | 8 | const after = function (fn, afterFn) { 9 | return function () { 10 | const __ = fn.apply(this, arguments) 11 | afterFn.apply(this, arguments) 12 | return __ 13 | } 14 | } 15 | 16 | const duck = { 17 | makeVoice: function () { 18 | console.log('我会嘎嘎嘎啦') 19 | }, 20 | sleep: function () { 21 | console.log('谁又不会睡觉呢') 22 | }, 23 | walk: function () { 24 | console.log('哈哈哈,我会走路啦') 25 | }, 26 | init: function () { 27 | this.makeVoice() 28 | this.sleep() 29 | this.walk() 30 | } 31 | } 32 | 33 | after(duck.init, function egg () { 34 | console.log('生蛋快乐~') 35 | }).apply(duck) -------------------------------------------------------------------------------- /src/设计模式/观察者模式/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/观察者模式/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/观察者模式/双向数据绑定/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiaozitang/web-learn-note/d9fcfbc68277332a9be0ac85d2a137f51be14060/src/设计模式/观察者模式/双向数据绑定/.DS_Store -------------------------------------------------------------------------------- /src/设计模式/观察者模式/双向数据绑定/完整版/2-way-binding.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 2-way-binding 6 | 7 | 8 |
9 |
10 | User info form: 11 | Name:
12 |
13 | Age:
14 | 15 | 16 | 17 |
18 | Gender:
19 | 24 |
25 |
26 | 27 | 28 |
29 | 30 |

User info

31 | 32 | Name: 33 | 34 |
35 | 36 | Age: 37 | 38 |
39 | 40 | Gender: 41 | 42 |
43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/设计模式/观察者模式/双向数据绑定/完整版/tbinding.js: -------------------------------------------------------------------------------- 1 | 2 | var Pubsub = { 3 | subscrib: function(ev, callback) { 4 | this._callbacks || (this._callbacks = {}); 5 | (this._callbacks[ev] || (this._callbacks[ev] = [])).push(callback); 6 | 7 | return this; 8 | }, 9 | 10 | publish: function() { 11 | var args = Array.prototype.slice.call(arguments); 12 | 13 | var ev = args.shift(); 14 | 15 | if(!this._callbacks) return this; 16 | if(!this._callbacks[ev]) return this; 17 | 18 | for(var i = 0; i < this._callbacks[ev].length; i++) { 19 | this._callbacks[ev][i].apply(this, args); 20 | } 21 | 22 | return this; 23 | } 24 | } 25 | 26 | 27 | var TBinding = (function(){ 28 | // element keyup and change callback 29 | function pageElementEventHandler(e) { 30 | var target = e.target || e.srcElemnt; 31 | var fullPropName = target.getAttribute('t-binding'); 32 | 33 | if(fullPropName && fullPropName !== '') { 34 | Pubsub.publish('ui-update-event', fullPropName, target.value); 35 | } 36 | 37 | } 38 | 39 | // add keyup and change event listener 40 | if(document.addEventListener) { 41 | document.addEventListener('keyup', pageElementEventHandler, false); 42 | document.addEventListener('change', pageElementEventHandler, false); 43 | } else { 44 | document.attachEvent('onkeyup', pageElementEventHandler); 45 | document.attachEvent('onchange', pageElementEventHandler); 46 | } 47 | 48 | // subscrib model-update-event, handle model change, then update UI 49 | Pubsub.subscrib('model-update-event', function(fullPropName, propValue) { 50 | var elements = document.querySelectorAll('[t-binding="' + fullPropName + '"]'); 51 | 52 | for(var i = 0, len =elements.length; i < len; i++){ 53 | var elementType = elements[i].tagName.toLowerCase(); 54 | 55 | if(elementType === 'input' || elementType === 'textarea' || elementType === 'select') { 56 | elements[i].value = propValue; 57 | } else { 58 | elements[i].innerHTML = propValue; 59 | } 60 | 61 | } 62 | }); 63 | 64 | 65 | return { 66 | 'modelName': '', 67 | 68 | 'initModel': function(modelName) { 69 | 70 | var self = this; 71 | 72 | self.modelName = modelName; 73 | 74 | // subscrib ui-update-event, handle ui change then update model 75 | Pubsub.subscrib('ui-update-event', function(fullPropName, propValue) { 76 | var propPathArr = fullPropName.split('.'); 77 | self.updateModelData(propPathArr[1], propValue); 78 | }); 79 | 80 | return Object.create(this); 81 | }, 82 | 83 | 'loadModelData': function(modelData) { 84 | for(prop in modelData) { 85 | this.updateModelData(prop, modelData[prop]) 86 | } 87 | }, 88 | 89 | 'updateModelData': function(propName, propValue) { 90 | eval(this.modelName)[propName] =propValue; 91 | Pubsub.publish('model-update-event', this.modelName + '.' + propName, propValue); 92 | } 93 | } 94 | 95 | })(); 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /src/设计模式/观察者模式/双向数据绑定/完整版/user.js: -------------------------------------------------------------------------------- 1 | 2 | var user = TBinding.initModel('user'); 3 | 4 | user.loadModelData({ 5 | 'name': 'wilber', 6 | 'age': 29, 7 | 'gender': 2 8 | }) 9 | 10 | user.incAge = function() { 11 | this.updateModelData('age', user.age + 1); 12 | } 13 | 14 | user.decAge = function() { 15 | this.updateModelData('age', user.age - 1); 16 | } 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/设计模式/观察者模式/双向数据绑定/简单版/index.js: -------------------------------------------------------------------------------- 1 | // 可发布可订阅的对象 2 | const Pubsub = { 3 | subscrib: function (ev, callback) { 4 | this._callbacks || (this._callbacks = {}); 5 | (this._callbacks[ev] || (this._callbacks[ev] = [])).push(callback); 6 | }, 7 | 8 | publish: function () { 9 | const args = [...arguments] 10 | const ev = args.shift() 11 | 12 | if (!this._callbacks) return 13 | if (!this._callbacks[ev]) return 14 | 15 | this._callbacks[ev].forEach(callback => { 16 | callback(...args) 17 | }) 18 | } 19 | } 20 | 21 | // 订阅model更新消息,更新后所有符合条件的dom节点都会收到通知,进行更新 22 | Pubsub.subscrib('model-update-event', function ({propNameWhole, propValue}) { 23 | const elements = document.querySelectorAll(`[data-bind="${propNameWhole}"]`) 24 | 25 | elements.forEach(element => { 26 | const elementTagName = element.tagName.toLowerCase() 27 | const formTypeTagNames = ['input', 'select', 'textarea'] 28 | if (formTypeTagNames.includes(elementTagName)) { 29 | element.value = propValue 30 | } else { 31 | element.innerHTML = propValue 32 | } 33 | }) 34 | }) 35 | 36 | // 添加onchange/onkeyup事件,触发时,发布ui更新消息 start 37 | function eventHander (e) { 38 | const { target } = e 39 | const { value: propValue } = target 40 | 41 | const propNameWhole = target.getAttribute('data-bind') 42 | if (propNameWhole) { 43 | console.log(propNameWhole, 123) 44 | // 发布ui更新消息 45 | Pubsub.publish('ui-update-event', { propNameWhole, propValue }) 46 | } 47 | } 48 | 49 | document.addEventListener('change', eventHander, false) 50 | document.addEventListener('keyup', eventHander, false) 51 | 52 | // end 53 | 54 | class Bind { 55 | constructor () { 56 | this.modelName = '' 57 | } 58 | 59 | initModal ({ modelName }) { 60 | this.modelName = modelName 61 | 62 | // 订阅ui更新消息 63 | Pubsub.subscrib('ui-update-event', ({propNameWhole, propValue}) => { 64 | const [ , _propName] = propNameWhole.split('.') 65 | this.updateModalData(_propName, propValue) 66 | }) 67 | } 68 | 69 | loadModalData (modelData) { 70 | for (let propName in modelData) { 71 | this.updateModalData(propName, modelData[propName]) 72 | } 73 | } 74 | 75 | updateModalData (propName, propValue) { 76 | const propNameWhole = `${this.modelName}.${propName}` 77 | // 发布model更新消息 78 | Pubsub.publish('model-update-event', { propNameWhole, propValue }); 79 | } 80 | 81 | } 82 | 83 | const user = new Bind() 84 | 85 | user.initModal({ 86 | modelName: 'user' 87 | }) 88 | 89 | user.loadModalData({ 90 | name: 'tj', 91 | age: '18' 92 | }) -------------------------------------------------------------------------------- /src/设计模式/观察者模式/观察者模式函数/index.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | const Event = function () { 3 | this.clientList = [] 4 | this.listen = function (key, fn) { 5 | if (!this.clientList[key]) { 6 | this.clientList[key] = [] 7 | } 8 | 9 | this.clientList[key].push(fn) 10 | } 11 | this.trigger = function (key, params) { 12 | const fns = this.clientList[key] 13 | if (!fns || fns.length === 0) { 14 | return false 15 | } 16 | 17 | fns.forEach(fn => { 18 | fn(params) 19 | }) 20 | } 21 | this.remove = function (key, fn) { 22 | const fns = this.clientList[key] 23 | 24 | if (!fns) { 25 | return false 26 | } 27 | 28 | const index = fns.findIndex(i => i === fn) 29 | fns.splice(index, 1) 30 | } 31 | } 32 | 33 | const salesOffices = new Event() 34 | 35 | console.log(salesOffices) 36 | 37 | const fn1 = ({price, squareMeter}) => { 38 | console.log(`价格`, price) 39 | console.log(`平方米=`, squareMeter) 40 | } 41 | 42 | // 订阅消息 43 | salesOffices.listen('square88', fn1) 44 | 45 | // 订阅消息 46 | salesOffices.listen('square110', fn1) 47 | 48 | // 发布消息 49 | salesOffices.trigger('square88', { price: 2000, squareMeter: 88 }) 50 | 51 | salesOffices.remove('square88', fn1) 52 | 53 | salesOffices.trigger('square88', { price: 3000, squareMeter: 88 }) 54 | 55 | salesOffices.trigger('square110', { price: 5000, squareMeter: 110 }) 56 | 57 | })() -------------------------------------------------------------------------------- /白帽子讲web安全: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------