blog-hexo/db.json
2023-11-17 13:12:11 +08:00

1 line
1.6 MiB
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"meta":{"version":1,"warehouse":"4.0.2"},"models":{"Asset":[{"_id":"themes/hexo-theme-cosy/source/css/0c63d269.css","path":"css/0c63d269.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/3a4a90d1.css","path":"css/3a4a90d1.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/3efc6cb5.css","path":"css/3efc6cb5.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/5bfc518f.css","path":"css/5bfc518f.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/5c728363.css","path":"css/5c728363.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/68d4249e.css","path":"css/68d4249e.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/69c863a0.css","path":"css/69c863a0.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/80d65618.css","path":"css/80d65618.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/82dd7e5a.css","path":"css/82dd7e5a.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/c080db9c.css","path":"css/c080db9c.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/dba23209.css","path":"css/dba23209.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/de5de8fb.css","path":"css/de5de8fb.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/e7914205.css","path":"css/e7914205.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/efca006a.css","path":"css/efca006a.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/css/f3729dde.css","path":"css/f3729dde.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/favicon.svg","path":"img/favicon.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon-arrow-left.svg","path":"img/icon-arrow-left.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon-book.svg","path":"img/icon-book.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon-click.svg","path":"img/icon-click.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon-layout.svg","path":"img/icon-layout.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon-date.svg","path":"img/icon-date.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon-link.svg","path":"img/icon-link.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon-moon.svg","path":"img/icon-moon.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon-sun.svg","path":"img/icon-sun.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon1.svg","path":"img/icon1.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon2.svg","path":"img/icon2.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/icon3.svg","path":"img/icon3.svg","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/logo.png","path":"img/logo.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/31d6cfe0.js","path":"js/31d6cfe0.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/3cf4fd98.js","path":"js/3cf4fd98.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/58c91c4e.js","path":"js/58c91c4e.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/9f1cd854.js","path":"js/9f1cd854.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/ae2a0e7b.js","path":"js/ae2a0e7b.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/b9c2be9c.js.LICENSE.txt","path":"js/b9c2be9c.js.LICENSE.txt","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/b9c2be9c.js","path":"js/b9c2be9c.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/c413ebaa.js","path":"js/c413ebaa.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/ca6b30b5.js","path":"js/ca6b30b5.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/d3872ea1.js","path":"js/d3872ea1.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/cdca7001.js","path":"js/cdca7001.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/js/f8b20eb9.js","path":"js/f8b20eb9.js","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/font/linear.woff2","path":"font/linear.woff2","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/font/motto.woff","path":"font/motto.woff","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/100.png","path":"img/qweather-color-icon/100.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/101.png","path":"img/qweather-color-icon/101.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/102.png","path":"img/qweather-color-icon/102.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/103.png","path":"img/qweather-color-icon/103.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/104.png","path":"img/qweather-color-icon/104.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/150.png","path":"img/qweather-color-icon/150.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/151.png","path":"img/qweather-color-icon/151.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/152.png","path":"img/qweather-color-icon/152.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/153.png","path":"img/qweather-color-icon/153.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/300.png","path":"img/qweather-color-icon/300.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/301.png","path":"img/qweather-color-icon/301.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/302.png","path":"img/qweather-color-icon/302.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/303.png","path":"img/qweather-color-icon/303.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/304.png","path":"img/qweather-color-icon/304.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/305.png","path":"img/qweather-color-icon/305.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/306.png","path":"img/qweather-color-icon/306.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/307.png","path":"img/qweather-color-icon/307.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/308.png","path":"img/qweather-color-icon/308.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/309.png","path":"img/qweather-color-icon/309.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/310.png","path":"img/qweather-color-icon/310.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/311.png","path":"img/qweather-color-icon/311.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/312.png","path":"img/qweather-color-icon/312.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/313.png","path":"img/qweather-color-icon/313.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/315.png","path":"img/qweather-color-icon/315.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/314.png","path":"img/qweather-color-icon/314.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/316.png","path":"img/qweather-color-icon/316.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/317.png","path":"img/qweather-color-icon/317.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/318.png","path":"img/qweather-color-icon/318.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/350.png","path":"img/qweather-color-icon/350.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/351.png","path":"img/qweather-color-icon/351.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/399.png","path":"img/qweather-color-icon/399.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/400.png","path":"img/qweather-color-icon/400.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/402.png","path":"img/qweather-color-icon/402.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/401.png","path":"img/qweather-color-icon/401.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/403.png","path":"img/qweather-color-icon/403.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/406.png","path":"img/qweather-color-icon/406.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/404.png","path":"img/qweather-color-icon/404.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/407.png","path":"img/qweather-color-icon/407.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/408.png","path":"img/qweather-color-icon/408.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/409.png","path":"img/qweather-color-icon/409.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/410.png","path":"img/qweather-color-icon/410.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/456.png","path":"img/qweather-color-icon/456.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/457.png","path":"img/qweather-color-icon/457.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/499.png","path":"img/qweather-color-icon/499.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/500.png","path":"img/qweather-color-icon/500.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/501.png","path":"img/qweather-color-icon/501.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/502.png","path":"img/qweather-color-icon/502.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/503.png","path":"img/qweather-color-icon/503.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/504.png","path":"img/qweather-color-icon/504.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/507.png","path":"img/qweather-color-icon/507.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/508.png","path":"img/qweather-color-icon/508.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/509.png","path":"img/qweather-color-icon/509.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/510.png","path":"img/qweather-color-icon/510.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/511.png","path":"img/qweather-color-icon/511.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/512.png","path":"img/qweather-color-icon/512.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/513.png","path":"img/qweather-color-icon/513.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/514.png","path":"img/qweather-color-icon/514.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/515.png","path":"img/qweather-color-icon/515.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/900.png","path":"img/qweather-color-icon/900.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/901.png","path":"img/qweather-color-icon/901.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/999.png","path":"img/qweather-color-icon/999.png","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/lib/prism/one-dark.css","path":"lib/prism/one-dark.css","modified":1,"renderable":1},{"_id":"themes/hexo-theme-cosy/source/lib/prism/one-light.css","path":"lib/prism/one-light.css","modified":1,"renderable":1},{"_id":"source/img/bolt.png","path":"img/bolt.png","modified":1,"renderable":0},{"_id":"source/img/avatar.png","path":"img/avatar.png","modified":1,"renderable":0},{"_id":"source/img/cvpilot.png","path":"img/cvpilot.png","modified":1,"renderable":0},{"_id":"source/img/grid_1.png","path":"img/grid_1.png","modified":1,"renderable":0},{"_id":"source/img/hexo-theme-linear-dark.png","path":"img/hexo-theme-linear-dark.png","modified":1,"renderable":0},{"_id":"source/img/mz10nq.png","path":"img/mz10nq.png","modified":1,"renderable":0},{"_id":"source/img/shader_1.png","path":"img/shader_1.png","modified":1,"renderable":0},{"_id":"source/img/shader_10.png","path":"img/shader_10.png","modified":1,"renderable":0},{"_id":"source/img/shader_11.png","path":"img/shader_11.png","modified":1,"renderable":0},{"_id":"source/img/shader_12.png","path":"img/shader_12.png","modified":1,"renderable":0},{"_id":"source/img/shader_13.png","path":"img/shader_13.png","modified":1,"renderable":0},{"_id":"source/img/shader_14.png","path":"img/shader_14.png","modified":1,"renderable":0},{"_id":"source/img/algolia-api-keys.png","path":"img/algolia-api-keys.png","modified":1,"renderable":0},{"_id":"source/img/shader_15.png","path":"img/shader_15.png","modified":1,"renderable":0},{"_id":"source/img/shader_16.png","path":"img/shader_16.png","modified":1,"renderable":0},{"_id":"source/img/shader_17.png","path":"img/shader_17.png","modified":1,"renderable":0},{"_id":"source/img/shader_18.png","path":"img/shader_18.png","modified":1,"renderable":0},{"_id":"source/img/shader_2.png","path":"img/shader_2.png","modified":1,"renderable":0},{"_id":"source/img/shader_20.png","path":"img/shader_20.png","modified":1,"renderable":0},{"_id":"source/img/shader_19.png","path":"img/shader_19.png","modified":1,"renderable":0},{"_id":"source/img/shader_21.png","path":"img/shader_21.png","modified":1,"renderable":0},{"_id":"source/img/shader_22.png","path":"img/shader_22.png","modified":1,"renderable":0},{"_id":"source/img/shader_23.png","path":"img/shader_23.png","modified":1,"renderable":0},{"_id":"source/img/shader_24.png","path":"img/shader_24.png","modified":1,"renderable":0},{"_id":"source/img/shader_25.png","path":"img/shader_25.png","modified":1,"renderable":0},{"_id":"source/img/shader_26.png","path":"img/shader_26.png","modified":1,"renderable":0},{"_id":"source/img/shader_27.png","path":"img/shader_27.png","modified":1,"renderable":0},{"_id":"source/img/shader_28.png","path":"img/shader_28.png","modified":1,"renderable":0},{"_id":"source/img/shader_3.png","path":"img/shader_3.png","modified":1,"renderable":0},{"_id":"source/img/shader_29.png","path":"img/shader_29.png","modified":1,"renderable":0},{"_id":"source/img/shader_30.png","path":"img/shader_30.png","modified":1,"renderable":0},{"_id":"source/img/shader_5.png","path":"img/shader_5.png","modified":1,"renderable":0},{"_id":"source/img/shader_4.png","path":"img/shader_4.png","modified":1,"renderable":0},{"_id":"source/img/shader_6.png","path":"img/shader_6.png","modified":1,"renderable":0},{"_id":"source/img/shader_7.png","path":"img/shader_7.png","modified":1,"renderable":0},{"_id":"source/img/shader_8.png","path":"img/shader_8.png","modified":1,"renderable":0},{"_id":"source/img/shader_9.png","path":"img/shader_9.png","modified":1,"renderable":0}],"Cache":[{"_id":"source/.DS_Store","hash":"7f1dadbc3bded867e8dcd5a0b7bf8cf97fea026c","modified":1699344729323},{"_id":"source/_posts/A Guide to Effective Dialogue.md","hash":"6b921148f345d387426eda1d8f8b2329d9b78194","modified":1699248300499},{"_id":"source/_posts/Markdown Sample.md","hash":"474ccea7a7fc40113e81c6ac17d332299f9a61ab","modified":1699409281242},{"_id":"source/_posts/Cosy-Starter-Guide.md","hash":"2e850ac0f61d4e22ab165280ee4f6489f993ce7c","modified":1700189823295},{"_id":"source/resume/index.md","hash":"b585667730d961c1fca9317763f3220a9df32371","modified":1698981341632},{"_id":"source/img/avatar.png","hash":"7c2da2939b1a36315c45489fbc9930bac73f0880","modified":1698729532245},{"_id":"source/img/grid_1.png","hash":"c464cd495e7b9fca7ea2eca75e8f3ba0376301ec","modified":1699405771999},{"_id":"source/img/shader_10.png","hash":"b680ce28ce113c09dc89aee5cf7b82efbb3d0feb","modified":1699247573640},{"_id":"source/img/.DS_Store","hash":"df2fbeb1400acda0909a32c1cf6bf492f1121e07","modified":1698730015110},{"_id":"source/img/shader_18.png","hash":"fd93d1fb5b4a7f1c3884bb8592bc4ecbeee75d2f","modified":1699247573643},{"_id":"source/img/shader_20.png","hash":"b5900021cd88644a8902d24aa04b2e940f766547","modified":1699247573645},{"_id":"source/img/shader_19.png","hash":"d5d252b8f676d9f6a81f9fdb1dbf869827294060","modified":1699247573643},{"_id":"source/img/shader_23.png","hash":"53456d8475ed2d70180de00e1869534369bf8ddb","modified":1699247573646},{"_id":"source/img/shader_4.png","hash":"5a6b452396cc87aadc4a03b1c44482a1d4ee2f0f","modified":1699247573656},{"_id":"source/roadmap/index.md","hash":"fd571d7ff1b43a7905438f4a36710bc153fda7c6","modified":1700196759950},{"_id":"source/_posts/finance/付鹏:逆全球化下的全球资产配置.md","hash":"9d2db9097826fd7549ebb1831488ee927782c1df","modified":1699247867196},{"_id":"source/_posts/front-end/jquery.md","hash":"c9a96157a671867e444d806d0dbbcaf85d1dd926","modified":1699257755529},{"_id":"source/_posts/front-end/Unity Shader入门精要.md","hash":"2533731c1e134f7d97160ccc531f458c3de5c9c6","modified":1699258090905},{"_id":"source/_posts/front-end/ddd.md","hash":"2983b3e1398ca9d0e41939cf31be4f130a562eaa","modified":1699257759167},{"_id":"source/_posts/front-end/css奇技淫巧.md","hash":"305722194038130992e33ecacbc4d6434dbfea65","modified":1699407210288},{"_id":"source/_posts/front-end/git.md","hash":"eae431c353fdeeb919b12005db09dcf7453c86ac","modified":1699257754511},{"_id":"source/_posts/front-end/verdaccio.md","hash":"50453d3e60c7e63e31bc9f3efcebc241d317fae0","modified":1699257759971},{"_id":"source/_posts/social/内部循环与产出意识.md","hash":"88fdb3f9b6e5d4b432a7011ee8bba3f6b41e6f83","modified":1699247971986},{"_id":"source/_posts/front-end/码场悟道.md","hash":"aba1107b1b90f852294f895e7f9bf20f410404e5","modified":1699339688822},{"_id":"source/_posts/finance/付鹏展望2023年下半年全球经济格局异常的利差意味着什么.md","hash":"4976b314cd7932e8e1333688491e506442900a37","modified":1699248127164},{"_id":"source/_posts/front-end/wsl2.md","hash":"628674ee566a260abf5e6090435feb822a43be96","modified":1699257758239},{"_id":"source/_posts/social/改掉选择困难症.md","hash":"98dfb13d9c9771ecdb1648dae778d83bfc1dc869","modified":1699248014555},{"_id":"source/_posts/social/非暴力沟通.md","hash":"629439b58652484c61fbda33103ae89437929fb7","modified":1699247939336},{"_id":"source/_posts/social/烦恼的原因.md","hash":"477a662420ffb2e51136ac59712cb5375eef20ea","modified":1699247993454},{"_id":"source/_posts/social/走神.md","hash":"86869ea38150a552128649f3aa5fd7a0b6a9c90e","modified":1699248013780},{"_id":"source/_posts/we-media/douyin.md","hash":"3bf6d9d1d658d534a40f51cddad5a7ca39b6154a","modified":1699947197858},{"_id":"source/_posts/social/有效对话指南.md","hash":"d20ec18cf5f8929d6af14b12a1c296bef007bc2b","modified":1699247891496},{"_id":"themes/hexo-theme-cosy/source/js/31d6cfe0.js","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1700187362835},{"_id":"source/img/bolt.png","hash":"9f178950034e1ad5c5248b9caaca36e2f784225d","modified":1698730006343},{"_id":"source/img/cvpilot.png","hash":"e10abaca3fd20488b0889a4da84d65312e5ac3ad","modified":1698730476343},{"_id":"source/img/shader_11.png","hash":"954022f8fb580fce66b491db72df770591746362","modified":1699247573640},{"_id":"source/img/shader_12.png","hash":"9d303ac8621c91088f97834733aa7903c70eaa43","modified":1699247573640},{"_id":"source/img/shader_15.png","hash":"c3feca0caadb737da89ad5a5a509057d379952c7","modified":1699247573642},{"_id":"source/img/shader_17.png","hash":"6274e99ab2e3d2053bdf2c0b9e3cc9b2b786f086","modified":1699247573643},{"_id":"source/img/shader_16.png","hash":"9bec75831c21d063f23502612f106bfa86a0b100","modified":1699247573642},{"_id":"source/img/shader_14.png","hash":"bde142cb701d1f17cc8733b66cdc8166b8334f32","modified":1699247573641},{"_id":"source/img/shader_2.png","hash":"767fe07c2ff75bdb58e1bd5487f373ea7b33a163","modified":1699247573644},{"_id":"source/img/shader_22.png","hash":"610a67538d93eb8c81da6c99b90fe751657f9266","modified":1699247573646},{"_id":"source/img/shader_28.png","hash":"079730db179a7b1f9539b929c33fc2be2b4a5bb5","modified":1699247573653},{"_id":"source/img/shader_3.png","hash":"1260a52b8fc6351c62c3bf9f1e2907f495dd2f4e","modified":1699247573655},{"_id":"source/img/shader_8.png","hash":"ebe473df6f8f19aec27a1e97301c533d82653096","modified":1699247573659},{"_id":"themes/hexo-theme-cosy/.DS_Store","hash":"6971f3f5a01e146585c1e8391a78a45b241e724f","modified":1700190143861},{"_id":"themes/hexo-theme-cosy/_config.yml","hash":"ab20fa95bf33f63416ecbb780fc1cee9ad413ab9","modified":1700014848699},{"_id":"themes/hexo-theme-cosy/languages/ar.yml","hash":"c5bf5f32d55971bc27ceec59357bd0ba9c06dd3a","modified":1700187362872},{"_id":"themes/hexo-theme-cosy/languages/de.yml","hash":"b93ab51f36fa62193caf7101c4f4ba3b81e10da7","modified":1700187362872},{"_id":"themes/hexo-theme-cosy/languages/en.yml","hash":"ef659dc0692fc269cabc224dcfc4c72aac3e3861","modified":1700187362871},{"_id":"themes/hexo-theme-cosy/languages/ja.yml","hash":"dff9e0bddce6d4846829b3995115e829e4faa2c2","modified":1700187362871},{"_id":"themes/hexo-theme-cosy/languages/fr.yml","hash":"9ecddd8cc6755a8e07e75066b7a4001963250106","modified":1700187362871},{"_id":"themes/hexo-theme-cosy/languages/ko.yml","hash":"e38a9692cc247ea21f06e383b47cf85f0d287b50","modified":1700187362871},{"_id":"themes/hexo-theme-cosy/languages/zh-CN.yml","hash":"3bbda115a0a4113fa06906c3f888585ad5b9be39","modified":1700187362870},{"_id":"themes/hexo-theme-cosy/languages/ru.yml","hash":"7571248b920136f7c58e3da045650857eb3cff14","modified":1700187362870},{"_id":"themes/hexo-theme-cosy/languages/es.yml","hash":"21f4d88855f6afd785268da57e5762bddf9667a9","modified":1700187362871},{"_id":"themes/hexo-theme-cosy/languages/zh-TW.yml","hash":"cb42a35cc73a8233b40a0afb612ec15fb714edea","modified":1700187362870},{"_id":"themes/hexo-theme-cosy/layout/archive.ejs","hash":"c6e3c47c195dc1b7551e25d6c6ccf22489a5abec","modified":1700187362869},{"_id":"themes/hexo-theme-cosy/layout/breadcrumb.ejs","hash":"81c91ad7b618a760b901741ff0d87333acddf60c","modified":1700187362869},{"_id":"themes/hexo-theme-cosy/layout/airplane.ejs","hash":"28521fce0f5dbd1fd62c612ae68b78ba254faef3","modified":1700187362870},{"_id":"themes/hexo-theme-cosy/layout/homebar.ejs","hash":"603903d1ac644e1a4500599d51aa7404dc64b4ab","modified":1700187362869},{"_id":"themes/hexo-theme-cosy/layout/category.ejs","hash":"c2653f82add02705f350edd193715b4872a6411c","modified":1700187362869},{"_id":"themes/hexo-theme-cosy/layout/navigation.ejs","hash":"d5bee071deb56ad28dcc4523f425705ce1967510","modified":1700187362868},{"_id":"themes/hexo-theme-cosy/layout/index.ejs","hash":"42af2e637dc5e2148199ef4f13d58932d690ccd5","modified":1700187362869},{"_id":"themes/hexo-theme-cosy/layout/post.ejs","hash":"1d755a0a1eefb6a59c6a53115f6f729167611732","modified":1700187362868},{"_id":"themes/hexo-theme-cosy/layout/postCopyright.ejs","hash":"499a9f2fae167592caf9f03f7988bbbb61481acb","modified":1700187362868},{"_id":"themes/hexo-theme-cosy/layout/resume.ejs","hash":"4ecb48cb1e9bd5c2134b8e4e82ed0ef9df2d4b67","modified":1700187362868},{"_id":"themes/hexo-theme-cosy/layout/layout.ejs","hash":"5dd45c1b25e2a658c5901d9ec33f7abfcadcbb0e","modified":1700187362868},{"_id":"themes/hexo-theme-cosy/layout/roadmap.ejs","hash":"e16ef0b34e2f285c3cfd7733e61aae75894a8394","modified":1700187362867},{"_id":"themes/hexo-theme-cosy/scripts/generate_category.js","hash":"03af36ba93e3ee17572e3f826430989119b1772a","modified":1700187362866},{"_id":"themes/hexo-theme-cosy/scripts/generate_excerpt.js","hash":"a7cfe46e7e389b1654c81f3e9a8a934dd80d735a","modified":1700187362866},{"_id":"themes/hexo-theme-cosy/scripts/generate_nav.js","hash":"3d58530838daf9e6225b4474b9ac230a55f1e0d4","modified":1700187362866},{"_id":"themes/hexo-theme-cosy/scripts/mermaid_tag.js","hash":"bc74c79cf41709da1993597acaebae96d6b3761d","modified":1700187362865},{"_id":"themes/hexo-theme-cosy/scripts/post_counter.js","hash":"62aaa594dafcffe5aa457628eaf183075cabe159","modified":1700187362865},{"_id":"themes/hexo-theme-cosy/scripts/sort_posts.js","hash":"16818ebbeb612f34d07cf9e285d42645eac31805","modified":1700187362865},{"_id":"themes/hexo-theme-cosy/layout/welcome.ejs","hash":"ce7419f61089411de4cea72165a4ce89c4d55fbd","modified":1700187362867},{"_id":"themes/hexo-theme-cosy/scripts/road-to-json.js","hash":"7fddd6117979d983e2172a04dd8764459a9c626b","modified":1700187362865},{"_id":"themes/hexo-theme-cosy/layout/search.ejs","hash":"f3faa8ba2d4e12e615e9554079c8465b68f3b495","modified":1700187362867},{"_id":"themes/hexo-theme-cosy/scripts/postIcon.js","hash":"73362a6570b00613681425b59a30903be671cd91","modified":1700187362865},{"_id":"themes/hexo-theme-cosy/layout/weather.ejs","hash":"04052e95f80ac11765b90019b149d7fb1bb68bab","modified":1700187362867},{"_id":"themes/hexo-theme-cosy/source/css/0c63d269.css","hash":"6b9b9796cf8ff9349b724f4b789f1347eaa0d476","modified":1700187362864},{"_id":"themes/hexo-theme-cosy/source/css/5bfc518f.css","hash":"4b7c03f245b3d60c366321e6cad11ceee7c0a131","modified":1700187362863},{"_id":"themes/hexo-theme-cosy/source/css/3efc6cb5.css","hash":"1f1958bfd921ac3eea83a1e14ed97e8e83b31fb6","modified":1700187362863},{"_id":"themes/hexo-theme-cosy/source/css/3a4a90d1.css","hash":"4ffc2c5e9f1afd4fa74d7d9b785e0697cd7fb770","modified":1700187362864},{"_id":"themes/hexo-theme-cosy/source/css/5c728363.css","hash":"715635cbd3ce46fd0b82117bc757fab6d2277070","modified":1700187362863},{"_id":"themes/hexo-theme-cosy/source/css/69c863a0.css","hash":"9047a6d26295eb0245c3e1dd9db3de600e0e4bda","modified":1700187362862},{"_id":"themes/hexo-theme-cosy/source/css/80d65618.css","hash":"3928a4a222e7353ed86a540aac9c9b6448ea9ff5","modified":1700187362862},{"_id":"themes/hexo-theme-cosy/source/css/82dd7e5a.css","hash":"c9561c3c190498369201f1ed27b6c17d255e0314","modified":1700187362862},{"_id":"themes/hexo-theme-cosy/source/css/68d4249e.css","hash":"1e3c7c24bbac6eb2b9377e318e6ffb7bc4b90ee1","modified":1700187362863},{"_id":"themes/hexo-theme-cosy/source/css/c080db9c.css","hash":"7caf9f961e4c0a26c53e1e37ce3d88d93d0be5ff","modified":1700187362862},{"_id":"themes/hexo-theme-cosy/source/css/dba23209.css","hash":"c03ff22c4a332f16b5f4ce22e3394ee05010027a","modified":1700187362861},{"_id":"themes/hexo-theme-cosy/source/css/de5de8fb.css","hash":"a05682caa4e0b8a106578468f795dad472ee75da","modified":1700187362861},{"_id":"themes/hexo-theme-cosy/source/css/e7914205.css","hash":"121b14a58b519c3fc538173189372800dea0d3de","modified":1700187362861},{"_id":"themes/hexo-theme-cosy/source/css/f3729dde.css","hash":"2a7faa0c3816e3b653fb4540fa63504a26b2051f","modified":1700187362861},{"_id":"themes/hexo-theme-cosy/source/img/icon-arrow-left.svg","hash":"a36362d2555e8b836fcec1f7eeeae4588a871bdd","modified":1700187362859},{"_id":"themes/hexo-theme-cosy/source/img/favicon.svg","hash":"6e88f8a231bb0a7ae4cc4598f85b6d346a286095","modified":1700187362859},{"_id":"themes/hexo-theme-cosy/source/img/icon-book.svg","hash":"d5e4064468dde477bf9a630c3fababec41316708","modified":1700187362859},{"_id":"themes/hexo-theme-cosy/source/css/efca006a.css","hash":"97972d1b7ca177983b39a67e772736f661637468","modified":1700187362861},{"_id":"themes/hexo-theme-cosy/source/img/icon-click.svg","hash":"b10df8b886a8b2d44293b26f42b440c9aedb66a7","modified":1700187362859},{"_id":"themes/hexo-theme-cosy/source/img/icon-layout.svg","hash":"108ef43073a5b92552dc00744a9f11db8e5ac0a2","modified":1700187362858},{"_id":"themes/hexo-theme-cosy/source/img/icon-date.svg","hash":"b391e34adafed83ef52d836fd6f81618494c4c6b","modified":1700187362858},{"_id":"themes/hexo-theme-cosy/source/img/icon-link.svg","hash":"436b5ee7ef2d28766e86ac1e65a567d1e786c1b3","modified":1700187362858},{"_id":"themes/hexo-theme-cosy/source/img/icon-sun.svg","hash":"57a0ce52ecce7188eaac5e06eab54609a8e572c8","modified":1700187362857},{"_id":"themes/hexo-theme-cosy/source/img/icon-moon.svg","hash":"032be7ed3d2320f22069e2efb2fb7f60592d6212","modified":1700187362858},{"_id":"themes/hexo-theme-cosy/source/img/icon2.svg","hash":"cc598540651110d977afd26dc0a1f01bbc95bf21","modified":1700187362857},{"_id":"themes/hexo-theme-cosy/source/img/icon3.svg","hash":"a1a9dcee7703ec48f2d92b0d533b62fef16097fc","modified":1700187362857},{"_id":"themes/hexo-theme-cosy/source/img/icon1.svg","hash":"f15fbcecbaa00db99aeaca9807922514f6452d02","modified":1700187362857},{"_id":"themes/hexo-theme-cosy/source/js/3cf4fd98.js","hash":"0d51155f6dc08d1d8c693d210c1407b2e26b5685","modified":1700187362835},{"_id":"themes/hexo-theme-cosy/source/js/9f1cd854.js","hash":"070029c5073bc3e67d98f1ac377d12f585bb4a2f","modified":1700187362834},{"_id":"themes/hexo-theme-cosy/source/js/58c91c4e.js","hash":"1935dee981143040a708a1144fd2a57894ce3137","modified":1700187362835},{"_id":"themes/hexo-theme-cosy/source/js/b9c2be9c.js.LICENSE.txt","hash":"a8820a0de0a074d43cb1f7db8eee78c8dbfd4d87","modified":1700187362834},{"_id":"themes/hexo-theme-cosy/source/js/c413ebaa.js","hash":"dd282af849c44345ad3e577efc8fa291468de653","modified":1700187362833},{"_id":"themes/hexo-theme-cosy/source/js/b9c2be9c.js","hash":"c03c1885896b368caf85bf273a8148428e649f59","modified":1700187362834},{"_id":"themes/hexo-theme-cosy/source/js/ca6b30b5.js","hash":"481a8f20c3d4e565c1ea5dafe4218597d051a9fc","modified":1700187362833},{"_id":"themes/hexo-theme-cosy/source/js/cdca7001.js","hash":"cd27e408febd15a99bafdf9da8a834bb1b6902c3","modified":1700187362833},{"_id":"themes/hexo-theme-cosy/source/js/d3872ea1.js","hash":"2c81c164e89dddf76fcee864da25ecf8e074248e","modified":1700187362832},{"_id":"themes/hexo-theme-cosy/source/js/f8b20eb9.js","hash":"86cff2cb169c614dedd464b373d94322328cb185","modified":1700187362832},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/100.png","hash":"ad42001979a0dbb8807c128b871dc28161b8c191","modified":1700187362856},{"_id":"themes/hexo-theme-cosy/source/font/motto.woff","hash":"755620f3bad3ebdf683c074043104d4c11f8d23e","modified":1700187362860},{"_id":"themes/hexo-theme-cosy/source/font/linear.woff2","hash":"57cac19ad34a50d5a4da5e471e08174c950ce5fb","modified":1700187362860},{"_id":"themes/hexo-theme-cosy/source/js/ae2a0e7b.js","hash":"d71a6f691ba45862066ad15bb7f8b3bd2ad9f5f5","modified":1700187362834},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/101.png","hash":"890888efd8db7a3f29427e476ce3433f4a564321","modified":1700187362855},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/102.png","hash":"74d7cfa4f23850a456c16d0e0956264e920f7a85","modified":1700187362855},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/103.png","hash":"656d81bd50728c7ba62572e838db7c355d522e51","modified":1700187362855},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/150.png","hash":"572b4a6e56271b89208daa538f02416d50249347","modified":1700187362854},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/104.png","hash":"36add97ed90d57e691e6e15d3456898a42dccb16","modified":1700187362855},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/152.png","hash":"3ec0a1ac063ae068cc9d728eef88a9a6d7859153","modified":1700187362854},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/151.png","hash":"8041e428fc369be40f9e993f4f718ae99c7662fa","modified":1700187362854},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/153.png","hash":"3eb50d325ec84e1248585d347471b1093a83909c","modified":1700187362854},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/301.png","hash":"cc616d4c7ae6abbe0338f418fe35acce93c46164","modified":1700187362853},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/302.png","hash":"371fa4d79b6a93573fde068f179829ed97c8f4f8","modified":1700187362852},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/303.png","hash":"453442f93e62ac98884aae173530f26272d97ad6","modified":1700187362852},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/304.png","hash":"3669eb04ee87dca604f70f7404c0ecb303d17af4","modified":1700187362852},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/306.png","hash":"69b55e71e8da4e0fe223ff76b9a68f98e4134b3d","modified":1700187362851},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/307.png","hash":"02a08e002d21a10e0854b1036556fb81b0308be3","modified":1700187362850},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/309.png","hash":"c5140be49b8936e5d30380f14f7dce49a7be7cb5","modified":1700187362849},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/305.png","hash":"618e18bf06b5d12d64269b30d6f044fc356d24b0","modified":1700187362851},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/300.png","hash":"bd67445ff764f3f1d4eeb81625372585bb537b07","modified":1700187362853},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/313.png","hash":"afa70386816623e847c09f51032212d2520d1740","modified":1700187362848},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/310.png","hash":"9315203066fa97a7d10f2a6fb0fd3ce5b7805126","modified":1700187362849},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/311.png","hash":"ab5c5059f354da2f9525b30ee81312fbfa4749bf","modified":1700187362848},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/312.png","hash":"c672d7373fce89803b5e8d06420e158f11ea346f","modified":1700187362848},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/315.png","hash":"2100a23ee6d584227715164263c43875e8d8946c","modified":1700187362847},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/314.png","hash":"110f9fe81f80b8f372b7472fbcfd9c0071b33151","modified":1700187362847},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/316.png","hash":"4de1ac0254507c5509fc4d04e208fd81d2af7b34","modified":1700187362846},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/317.png","hash":"7e60725abd3b91b9ba388ad9b9f642690c39ff9e","modified":1700187362846},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/318.png","hash":"7a042920165671cdbfef6c58596a80f9a1f6f016","modified":1700187362845},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/350.png","hash":"f29c1aa55c4afd3df17aef7885a35b0bd177d771","modified":1700187362845},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/400.png","hash":"79444a48a0e416e4cac1eb319496f495091f4c86","modified":1700187362844},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/351.png","hash":"3ab30470a65acb8fe879aa7adc9064284abd8407","modified":1700187362845},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/399.png","hash":"993ddcd386480d211ec9b2e56656d659bb6c453b","modified":1700187362844},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/402.png","hash":"033fc236885a2bf7007d97eb054b0c5885035be5","modified":1700187362843},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/401.png","hash":"279c8bc00b4e57db9b1095df64044ec80b37edb0","modified":1700187362844},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/406.png","hash":"b9cd0421518e0a76041285e5bf0c1666a93428a5","modified":1700187362842},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/403.png","hash":"dfad1a525c4467c3e95e281befdf813e145620df","modified":1700187362843},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/407.png","hash":"82223792a5e3e556148b4663f195ef22044c143a","modified":1700187362842},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/408.png","hash":"02b34a66020c9f3e5173702d30e5a7b69139bade","modified":1700187362841},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/404.png","hash":"112e73e641d1a30712993b5dca681a5e033831ee","modified":1700187362843},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/409.png","hash":"aed269911d0249a700b4f3890c424f00f4a27e1e","modified":1700187362841},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/410.png","hash":"9170b32d6b7f644ce49116f3e35d35558bae6536","modified":1700187362841},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/456.png","hash":"dd16b957cc544730afab8d2712821dd6c77f5167","modified":1700187362840},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/308.png","hash":"ace460a40174aa90dde6c2ef71663f30cec24193","modified":1700187362850},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/500.png","hash":"ddb4712d8f19bb8c197e600000dd2d51049f970d","modified":1700187362840},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/501.png","hash":"ddb4712d8f19bb8c197e600000dd2d51049f970d","modified":1700187362839},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/503.png","hash":"9415147c4bcebadd7f3089339064b8120c8d4089","modified":1700187362839},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/502.png","hash":"4146081a2635ff88fa14e38ed8d360d3b4fa74dd","modified":1700187362839},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/504.png","hash":"defba93520719f72b217583062ccc79abd5b445e","modified":1700187362839},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/499.png","hash":"2b51631144a7c0f813b6425d4daa30c4d4e8bd38","modified":1700187362840},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/507.png","hash":"426d5a73a482ac5721e7da2141e4fe704f50b608","modified":1700187362839},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/457.png","hash":"5dffe7e9139bfb697b046c427b9ef0ed6ffa95c7","modified":1700187362840},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/509.png","hash":"3bc779bfbcab94a79c91b26288e2e7b67412d15e","modified":1700187362838},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/510.png","hash":"524131e401d0b150dab2733af336f4649b8ade74","modified":1700187362838},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/512.png","hash":"64e11f225c35caa6ef2612d613026c52cfd3557e","modified":1700187362837},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/508.png","hash":"ae98a3217df26021ec2f667f099d27575c912bf4","modified":1700187362838},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/511.png","hash":"e2efe07a29446ebecd313ccd8a2c7d57a670f203","modified":1700187362838},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/513.png","hash":"ceff3dfd109a990c9595276ad6b56061bb662e5e","modified":1700187362837},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/514.png","hash":"fdf992021ff20e1ffe1b19f0b918aa35204f22e7","modified":1700187362837},{"_id":"themes/hexo-theme-cosy/source/lib/prism/one-dark.css","hash":"5967bad8dd34b1eb244956064ae7870f62e6cd75","modified":1700187362831},{"_id":"themes/hexo-theme-cosy/source/lib/prism/one-light.css","hash":"dd7660b35884866eee48f069e876f1c29661a150","modified":1700187362831},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/999.png","hash":"74e4fa5bdd815d988b55525d4e7f6d40bf1080d4","modified":1700187362836},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/900.png","hash":"6eacf8df641c6096feb746c7544a825d3c65bf47","modified":1700187362836},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/901.png","hash":"f6b3f1cd64e9c325e9dc3ab42469baa5c5119c2d","modified":1700187362836},{"_id":"themes/hexo-theme-cosy/source/img/qweather-color-icon/515.png","hash":"fdf992021ff20e1ffe1b19f0b918aa35204f22e7","modified":1700187362837},{"_id":"source/img/shader_1.png","hash":"559caf74cb63637b58483773f72b7589408ceaf9","modified":1699247573639},{"_id":"source/img/hexo-theme-linear-dark.png","hash":"758aef1e3d9a83844d2871e8ceaccf6767e78284","modified":1698730623818},{"_id":"source/img/shader_13.png","hash":"e1eb1a13ffe9ed74b2f79f2e97c4134f10988657","modified":1699247573641},{"_id":"source/img/shader_21.png","hash":"a381d25344aaf2da7e29a7f157f3c2d1b0a8f813","modified":1699247573645},{"_id":"source/img/shader_27.png","hash":"285b22fb20437acaf07a9a3aa37770802d1b7202","modified":1699247573653},{"_id":"source/img/shader_5.png","hash":"07822798c3008fe841798993f75b50f104de5e11","modified":1699247573657},{"_id":"source/img/shader_6.png","hash":"7f96d58b93a0149993a7aa02d1d27c75e0ce0936","modified":1699247573657},{"_id":"source/img/shader_30.png","hash":"35610b6e8877b16bc2140ec1e13a104188ac2f6b","modified":1699247573656},{"_id":"source/img/shader_9.png","hash":"601cd60bc9837dc0603f82991334e084e7074aec","modified":1699247573660},{"_id":"source/img/shader_29.png","hash":"17acdcaa715bc68eb654b1e6db4fe0b4364d6394","modified":1699247573654},{"_id":"source/img/shader_7.png","hash":"23388d247c00f832e544954f4fa6956c03fec16d","modified":1699247573658},{"_id":"themes/hexo-theme-cosy/source/img/logo.png","hash":"05730ab0dadd5036509f942834278eef683994dd","modified":1700187362856},{"_id":"source/img/algolia-api-keys.png","hash":"8b2f85a93b52f0590e9b8fe2d2405427c99e2280","modified":1697779286767},{"_id":"source/img/shader_24.png","hash":"8eba8647f182532ac37462c15aa11a6e2d4ee196","modified":1699247573648},{"_id":"source/img/shader_25.png","hash":"9be25a68c628071e583e3985929c321ebe6d13cb","modified":1699247573651},{"_id":"source/img/shader_26.png","hash":"3433565461d058e381b1c5a13db978d6f470025a","modified":1699247573652},{"_id":"source/img/mz10nq.png","hash":"e26097f94ae54967e68f36b13b6aca80c4d173de","modified":1699247796443},{"_id":"public/roadmap/index.html","hash":"ce48322328308e7423e9655badb9c50051019f49","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58r000v4cz3bm2ichic/index.html","hash":"247e8baa1150d66683a9b69dee8de931f5bed1bf","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58r000t4cz30eqvd8xz/index.html","hash":"5afceef43689ac6bb5035ccd67ef4af0fbb2cecf","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58r000q4cz30t6927bz/index.html","hash":"785616c0324c293a799748d00e83f95bd51bbd6f","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58t001c4cz3hsj15usi/index.html","hash":"4d6b4de5762457940db4cbe43e4c491471cdeb06","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58q000m4cz3dxv034l1/index.html","hash":"18e08a8aef4d8eeac736b9880958d99354ce9580","modified":1700197927774},{"_id":"public/categories/Hexo/index.html","hash":"d6bc8ab3f5d7cb7236637b840f4bc95f2380b6ff","modified":1700197927774},{"_id":"public/categories/Finance/index.html","hash":"fe13c72b55c717ddd5fccac29d2ba0b1260c6666","modified":1700197927774},{"_id":"public/categories/自媒体/index.html","hash":"8121627e0fd95ecb5dc6cd11c9e2d86d4666ed59","modified":1700197927774},{"_id":"public/resume/index.html","hash":"c733037a1e28d5735428eca3183b86ebe48f212b","modified":1700197927774},{"_id":"public/2023/11/14/clp25y58t001b4cz30xaoer0h/index.html","hash":"4608e6cd55d40f8fabd642b32b343f15d3cc7132","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58n00094cz3bshsgix4/index.html","hash":"e68278005fc2bd8ef918e3de80210c197368c23a","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58o000e4cz3ffa9d2ke/index.html","hash":"c6a6ce42c34793516b73893dd6b6069404339d07","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58o000d4cz39b94fqx5/index.html","hash":"119bea628508e70d8e1d6d90d9523d272f7b3e70","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58m00074cz31y3lcvvy/index.html","hash":"4a088544adf053d19f8a332b57e5997239782d1d","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58q000p4cz3gxzl7mxo/index.html","hash":"22061a4352d268c88a50b02f43c8a71a16a0b5c8","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58n000a4cz39b6r5kmh/index.html","hash":"1b9530311c1ec336d4939614464f36cc93debd4c","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58i00014cz3goob8drj/index.html","hash":"e5d9c24f7222f298c13d6e9ff51f206cbb3c9ee9","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58q000i4cz39r1m7266/index.html","hash":"79ff27b627a4a2ff01096979890384ba5e9ad76d","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58q000l4cz31hnu8sy9/index.html","hash":"1744ff1721c56a6552e36402aab36567cba6ff30","modified":1700197927774},{"_id":"public/2023/11/06/clp25y58m00064cz35salcgt5/index.html","hash":"38447d216d4664d16ade2669db6e5ba6bbab625f","modified":1700197927774},{"_id":"public/2023/10/24/clp25y58t001e4cz330le440v/index.html","hash":"11322282ccfb10942cb46dc56eb7c57397ac51f6","modified":1700197927774},{"_id":"public/2023/10/23/clp25y58k00034cz3f1qn2ems/index.html","hash":"ba4b1500e00ff701795f9a78acd12e359b798df3","modified":1700197927774},{"_id":"public/2023/10/23/clp25y58l00054cz36gn8061p/index.html","hash":"665784c5d0bd228f4d73a258f63f4418bff97daf","modified":1700197927774},{"_id":"public/2023/10/20/clp25y58p000h4cz3305y5675/index.html","hash":"7ea19af2e3e2d07ab3697ef63b0f445f6ad9db2a","modified":1700197927774},{"_id":"public/archives/index.html","hash":"b6b01a09c5e4db54d908049c69d7c6e24b50431a","modified":1700197927774},{"_id":"public/archives/page/2/index.html","hash":"b6b01a09c5e4db54d908049c69d7c6e24b50431a","modified":1700197927774},{"_id":"public/archives/2023/index.html","hash":"b6b01a09c5e4db54d908049c69d7c6e24b50431a","modified":1700197927774},{"_id":"public/archives/2023/page/2/index.html","hash":"b6b01a09c5e4db54d908049c69d7c6e24b50431a","modified":1700197927774},{"_id":"public/archives/2023/10/index.html","hash":"b6b01a09c5e4db54d908049c69d7c6e24b50431a","modified":1700197927774},{"_id":"public/archives/2023/11/index.html","hash":"b6b01a09c5e4db54d908049c69d7c6e24b50431a","modified":1700197927774},{"_id":"public/archives/2023/11/page/2/index.html","hash":"b6b01a09c5e4db54d908049c69d7c6e24b50431a","modified":1700197927774},{"_id":"public/categories/EQ/index.html","hash":"7a8739ed2224238a9a08592818dc37f4655f5fdb","modified":1700197927774},{"_id":"public/categories/Front-End/index.html","hash":"eb0ba3f6fb4b88d30a25d387438c73bb8c1faee5","modified":1700197927774},{"_id":"public/index.html","hash":"3a05379f9e93559d39a1825630f463f360341f3c","modified":1700197927774},{"_id":"public/page/2/index.html","hash":"3a05379f9e93559d39a1825630f463f360341f3c","modified":1700197927774},{"_id":"public/img/icon-layout.svg","hash":"108ef43073a5b92552dc00744a9f11db8e5ac0a2","modified":1700197927774},{"_id":"public/img/icon-arrow-left.svg","hash":"a36362d2555e8b836fcec1f7eeeae4588a871bdd","modified":1700197927774},{"_id":"public/img/favicon.svg","hash":"6e88f8a231bb0a7ae4cc4598f85b6d346a286095","modified":1700197927774},{"_id":"public/img/icon-click.svg","hash":"b10df8b886a8b2d44293b26f42b440c9aedb66a7","modified":1700197927774},{"_id":"public/img/icon-book.svg","hash":"d5e4064468dde477bf9a630c3fababec41316708","modified":1700197927774},{"_id":"public/img/icon-sun.svg","hash":"57a0ce52ecce7188eaac5e06eab54609a8e572c8","modified":1700197927774},{"_id":"public/img/icon-moon.svg","hash":"032be7ed3d2320f22069e2efb2fb7f60592d6212","modified":1700197927774},{"_id":"public/img/icon1.svg","hash":"f15fbcecbaa00db99aeaca9807922514f6452d02","modified":1700197927774},{"_id":"public/img/icon-date.svg","hash":"b391e34adafed83ef52d836fd6f81618494c4c6b","modified":1700197927774},{"_id":"public/img/icon-link.svg","hash":"436b5ee7ef2d28766e86ac1e65a567d1e786c1b3","modified":1700197927774},{"_id":"public/js/b9c2be9c.js.LICENSE.txt","hash":"a8820a0de0a074d43cb1f7db8eee78c8dbfd4d87","modified":1700197927774},{"_id":"public/img/icon2.svg","hash":"cc598540651110d977afd26dc0a1f01bbc95bf21","modified":1700197927774},{"_id":"public/img/icon3.svg","hash":"a1a9dcee7703ec48f2d92b0d533b62fef16097fc","modified":1700197927774},{"_id":"public/font/motto.woff","hash":"755620f3bad3ebdf683c074043104d4c11f8d23e","modified":1700197927774},{"_id":"public/img/qweather-color-icon/101.png","hash":"890888efd8db7a3f29427e476ce3433f4a564321","modified":1700197927774},{"_id":"public/img/qweather-color-icon/103.png","hash":"656d81bd50728c7ba62572e838db7c355d522e51","modified":1700197927774},{"_id":"public/img/qweather-color-icon/102.png","hash":"74d7cfa4f23850a456c16d0e0956264e920f7a85","modified":1700197927774},{"_id":"public/img/qweather-color-icon/100.png","hash":"ad42001979a0dbb8807c128b871dc28161b8c191","modified":1700197927774},{"_id":"public/img/qweather-color-icon/104.png","hash":"36add97ed90d57e691e6e15d3456898a42dccb16","modified":1700197927774},{"_id":"public/font/linear.woff2","hash":"57cac19ad34a50d5a4da5e471e08174c950ce5fb","modified":1700197927774},{"_id":"public/img/qweather-color-icon/152.png","hash":"3ec0a1ac063ae068cc9d728eef88a9a6d7859153","modified":1700197927774},{"_id":"public/img/qweather-color-icon/151.png","hash":"8041e428fc369be40f9e993f4f718ae99c7662fa","modified":1700197927774},{"_id":"public/img/qweather-color-icon/300.png","hash":"bd67445ff764f3f1d4eeb81625372585bb537b07","modified":1700197927774},{"_id":"public/img/qweather-color-icon/150.png","hash":"572b4a6e56271b89208daa538f02416d50249347","modified":1700197927774},{"_id":"public/img/qweather-color-icon/302.png","hash":"371fa4d79b6a93573fde068f179829ed97c8f4f8","modified":1700197927774},{"_id":"public/img/qweather-color-icon/153.png","hash":"3eb50d325ec84e1248585d347471b1093a83909c","modified":1700197927774},{"_id":"public/img/qweather-color-icon/303.png","hash":"453442f93e62ac98884aae173530f26272d97ad6","modified":1700197927774},{"_id":"public/img/qweather-color-icon/304.png","hash":"3669eb04ee87dca604f70f7404c0ecb303d17af4","modified":1700197927774},{"_id":"public/img/qweather-color-icon/305.png","hash":"618e18bf06b5d12d64269b30d6f044fc356d24b0","modified":1700197927774},{"_id":"public/img/qweather-color-icon/306.png","hash":"69b55e71e8da4e0fe223ff76b9a68f98e4134b3d","modified":1700197927774},{"_id":"public/img/qweather-color-icon/301.png","hash":"cc616d4c7ae6abbe0338f418fe35acce93c46164","modified":1700197927774},{"_id":"public/img/qweather-color-icon/307.png","hash":"02a08e002d21a10e0854b1036556fb81b0308be3","modified":1700197927774},{"_id":"public/img/qweather-color-icon/308.png","hash":"ace460a40174aa90dde6c2ef71663f30cec24193","modified":1700197927774},{"_id":"public/img/qweather-color-icon/310.png","hash":"9315203066fa97a7d10f2a6fb0fd3ce5b7805126","modified":1700197927774},{"_id":"public/img/qweather-color-icon/312.png","hash":"c672d7373fce89803b5e8d06420e158f11ea346f","modified":1700197927774},{"_id":"public/img/qweather-color-icon/313.png","hash":"afa70386816623e847c09f51032212d2520d1740","modified":1700197927774},{"_id":"public/img/qweather-color-icon/315.png","hash":"2100a23ee6d584227715164263c43875e8d8946c","modified":1700197927774},{"_id":"public/img/qweather-color-icon/309.png","hash":"c5140be49b8936e5d30380f14f7dce49a7be7cb5","modified":1700197927774},{"_id":"public/img/qweather-color-icon/314.png","hash":"110f9fe81f80b8f372b7472fbcfd9c0071b33151","modified":1700197927774},{"_id":"public/img/qweather-color-icon/318.png","hash":"7a042920165671cdbfef6c58596a80f9a1f6f016","modified":1700197927774},{"_id":"public/img/qweather-color-icon/350.png","hash":"f29c1aa55c4afd3df17aef7885a35b0bd177d771","modified":1700197927774},{"_id":"public/img/qweather-color-icon/399.png","hash":"993ddcd386480d211ec9b2e56656d659bb6c453b","modified":1700197927774},{"_id":"public/img/qweather-color-icon/317.png","hash":"7e60725abd3b91b9ba388ad9b9f642690c39ff9e","modified":1700197927774},{"_id":"public/img/qweather-color-icon/311.png","hash":"ab5c5059f354da2f9525b30ee81312fbfa4749bf","modified":1700197927774},{"_id":"public/img/qweather-color-icon/351.png","hash":"3ab30470a65acb8fe879aa7adc9064284abd8407","modified":1700197927774},{"_id":"public/img/qweather-color-icon/400.png","hash":"79444a48a0e416e4cac1eb319496f495091f4c86","modified":1700197927774},{"_id":"public/img/qweather-color-icon/402.png","hash":"033fc236885a2bf7007d97eb054b0c5885035be5","modified":1700197927774},{"_id":"public/img/qweather-color-icon/403.png","hash":"dfad1a525c4467c3e95e281befdf813e145620df","modified":1700197927774},{"_id":"public/img/qweather-color-icon/404.png","hash":"112e73e641d1a30712993b5dca681a5e033831ee","modified":1700197927774},{"_id":"public/img/qweather-color-icon/316.png","hash":"4de1ac0254507c5509fc4d04e208fd81d2af7b34","modified":1700197927774},{"_id":"public/img/qweather-color-icon/407.png","hash":"82223792a5e3e556148b4663f195ef22044c143a","modified":1700197927774},{"_id":"public/img/qweather-color-icon/408.png","hash":"02b34a66020c9f3e5173702d30e5a7b69139bade","modified":1700197927774},{"_id":"public/img/qweather-color-icon/406.png","hash":"b9cd0421518e0a76041285e5bf0c1666a93428a5","modified":1700197927774},{"_id":"public/img/qweather-color-icon/409.png","hash":"aed269911d0249a700b4f3890c424f00f4a27e1e","modified":1700197927774},{"_id":"public/img/qweather-color-icon/410.png","hash":"9170b32d6b7f644ce49116f3e35d35558bae6536","modified":1700197927774},{"_id":"public/img/qweather-color-icon/456.png","hash":"dd16b957cc544730afab8d2712821dd6c77f5167","modified":1700197927774},{"_id":"public/img/qweather-color-icon/457.png","hash":"5dffe7e9139bfb697b046c427b9ef0ed6ffa95c7","modified":1700197927774},{"_id":"public/img/qweather-color-icon/499.png","hash":"2b51631144a7c0f813b6425d4daa30c4d4e8bd38","modified":1700197927774},{"_id":"public/img/qweather-color-icon/500.png","hash":"ddb4712d8f19bb8c197e600000dd2d51049f970d","modified":1700197927774},{"_id":"public/img/qweather-color-icon/501.png","hash":"ddb4712d8f19bb8c197e600000dd2d51049f970d","modified":1700197927774},{"_id":"public/img/qweather-color-icon/502.png","hash":"4146081a2635ff88fa14e38ed8d360d3b4fa74dd","modified":1700197927774},{"_id":"public/img/qweather-color-icon/504.png","hash":"defba93520719f72b217583062ccc79abd5b445e","modified":1700197927774},{"_id":"public/img/qweather-color-icon/503.png","hash":"9415147c4bcebadd7f3089339064b8120c8d4089","modified":1700197927774},{"_id":"public/img/qweather-color-icon/507.png","hash":"426d5a73a482ac5721e7da2141e4fe704f50b608","modified":1700197927774},{"_id":"public/img/qweather-color-icon/508.png","hash":"ae98a3217df26021ec2f667f099d27575c912bf4","modified":1700197927774},{"_id":"public/img/qweather-color-icon/509.png","hash":"3bc779bfbcab94a79c91b26288e2e7b67412d15e","modified":1700197927774},{"_id":"public/img/qweather-color-icon/510.png","hash":"524131e401d0b150dab2733af336f4649b8ade74","modified":1700197927774},{"_id":"public/img/qweather-color-icon/512.png","hash":"64e11f225c35caa6ef2612d613026c52cfd3557e","modified":1700197927774},{"_id":"public/img/qweather-color-icon/513.png","hash":"ceff3dfd109a990c9595276ad6b56061bb662e5e","modified":1700197927774},{"_id":"public/img/qweather-color-icon/515.png","hash":"fdf992021ff20e1ffe1b19f0b918aa35204f22e7","modified":1700197927774},{"_id":"public/img/qweather-color-icon/514.png","hash":"fdf992021ff20e1ffe1b19f0b918aa35204f22e7","modified":1700197927774},{"_id":"public/img/qweather-color-icon/900.png","hash":"6eacf8df641c6096feb746c7544a825d3c65bf47","modified":1700197927774},{"_id":"public/img/qweather-color-icon/511.png","hash":"e2efe07a29446ebecd313ccd8a2c7d57a670f203","modified":1700197927774},{"_id":"public/img/qweather-color-icon/999.png","hash":"74e4fa5bdd815d988b55525d4e7f6d40bf1080d4","modified":1700197927774},{"_id":"public/img/qweather-color-icon/901.png","hash":"f6b3f1cd64e9c325e9dc3ab42469baa5c5119c2d","modified":1700197927774},{"_id":"public/img/qweather-color-icon/401.png","hash":"279c8bc00b4e57db9b1095df64044ec80b37edb0","modified":1700197927774},{"_id":"public/img/avatar.png","hash":"7c2da2939b1a36315c45489fbc9930bac73f0880","modified":1700197927774},{"_id":"public/img/grid_1.png","hash":"c464cd495e7b9fca7ea2eca75e8f3ba0376301ec","modified":1700197927774},{"_id":"public/img/shader_10.png","hash":"b680ce28ce113c09dc89aee5cf7b82efbb3d0feb","modified":1700197927774},{"_id":"public/img/shader_18.png","hash":"fd93d1fb5b4a7f1c3884bb8592bc4ecbeee75d2f","modified":1700197927774},{"_id":"public/img/shader_19.png","hash":"d5d252b8f676d9f6a81f9fdb1dbf869827294060","modified":1700197927774},{"_id":"public/img/shader_20.png","hash":"b5900021cd88644a8902d24aa04b2e940f766547","modified":1700197927774},{"_id":"public/img/shader_23.png","hash":"53456d8475ed2d70180de00e1869534369bf8ddb","modified":1700197927774},{"_id":"public/img/shader_4.png","hash":"5a6b452396cc87aadc4a03b1c44482a1d4ee2f0f","modified":1700197927774},{"_id":"public/css/0c63d269.css","hash":"6b9b9796cf8ff9349b724f4b789f1347eaa0d476","modified":1700197927774},{"_id":"public/css/3a4a90d1.css","hash":"4ffc2c5e9f1afd4fa74d7d9b785e0697cd7fb770","modified":1700197927774},{"_id":"public/css/68d4249e.css","hash":"1e3c7c24bbac6eb2b9377e318e6ffb7bc4b90ee1","modified":1700197927774},{"_id":"public/css/5bfc518f.css","hash":"4b7c03f245b3d60c366321e6cad11ceee7c0a131","modified":1700197927774},{"_id":"public/css/69c863a0.css","hash":"9047a6d26295eb0245c3e1dd9db3de600e0e4bda","modified":1700197927774},{"_id":"public/css/3efc6cb5.css","hash":"1f1958bfd921ac3eea83a1e14ed97e8e83b31fb6","modified":1700197927774},{"_id":"public/css/5c728363.css","hash":"715635cbd3ce46fd0b82117bc757fab6d2277070","modified":1700197927774},{"_id":"public/css/80d65618.css","hash":"3928a4a222e7353ed86a540aac9c9b6448ea9ff5","modified":1700197927774},{"_id":"public/css/82dd7e5a.css","hash":"c9561c3c190498369201f1ed27b6c17d255e0314","modified":1700197927774},{"_id":"public/css/c080db9c.css","hash":"7caf9f961e4c0a26c53e1e37ce3d88d93d0be5ff","modified":1700197927774},{"_id":"public/css/dba23209.css","hash":"c03ff22c4a332f16b5f4ce22e3394ee05010027a","modified":1700197927774},{"_id":"public/css/de5de8fb.css","hash":"a05682caa4e0b8a106578468f795dad472ee75da","modified":1700197927774},{"_id":"public/css/efca006a.css","hash":"97972d1b7ca177983b39a67e772736f661637468","modified":1700197927774},{"_id":"public/css/f3729dde.css","hash":"2a7faa0c3816e3b653fb4540fa63504a26b2051f","modified":1700197927774},{"_id":"public/css/e7914205.css","hash":"121b14a58b519c3fc538173189372800dea0d3de","modified":1700197927774},{"_id":"public/js/31d6cfe0.js","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1700197927774},{"_id":"public/js/58c91c4e.js","hash":"1935dee981143040a708a1144fd2a57894ce3137","modified":1700197927774},{"_id":"public/js/9f1cd854.js","hash":"070029c5073bc3e67d98f1ac377d12f585bb4a2f","modified":1700197927774},{"_id":"public/js/ae2a0e7b.js","hash":"d71a6f691ba45862066ad15bb7f8b3bd2ad9f5f5","modified":1700197927774},{"_id":"public/js/3cf4fd98.js","hash":"0d51155f6dc08d1d8c693d210c1407b2e26b5685","modified":1700197927774},{"_id":"public/js/d3872ea1.js","hash":"2c81c164e89dddf76fcee864da25ecf8e074248e","modified":1700197927774},{"_id":"public/js/f8b20eb9.js","hash":"86cff2cb169c614dedd464b373d94322328cb185","modified":1700197927774},{"_id":"public/lib/prism/one-dark.css","hash":"5967bad8dd34b1eb244956064ae7870f62e6cd75","modified":1700197927774},{"_id":"public/js/ca6b30b5.js","hash":"481a8f20c3d4e565c1ea5dafe4218597d051a9fc","modified":1700197927774},{"_id":"public/lib/prism/one-light.css","hash":"dd7660b35884866eee48f069e876f1c29661a150","modified":1700197927774},{"_id":"public/js/c413ebaa.js","hash":"dd282af849c44345ad3e577efc8fa291468de653","modified":1700197927774},{"_id":"public/js/b9c2be9c.js","hash":"c03c1885896b368caf85bf273a8148428e649f59","modified":1700197927774},{"_id":"public/js/cdca7001.js","hash":"cd27e408febd15a99bafdf9da8a834bb1b6902c3","modified":1700197927774},{"_id":"public/img/bolt.png","hash":"9f178950034e1ad5c5248b9caaca36e2f784225d","modified":1700197927774},{"_id":"public/img/cvpilot.png","hash":"e10abaca3fd20488b0889a4da84d65312e5ac3ad","modified":1700197927774},{"_id":"public/img/shader_11.png","hash":"954022f8fb580fce66b491db72df770591746362","modified":1700197927774},{"_id":"public/img/shader_12.png","hash":"9d303ac8621c91088f97834733aa7903c70eaa43","modified":1700197927774},{"_id":"public/img/shader_14.png","hash":"bde142cb701d1f17cc8733b66cdc8166b8334f32","modified":1700197927774},{"_id":"public/img/shader_15.png","hash":"c3feca0caadb737da89ad5a5a509057d379952c7","modified":1700197927774},{"_id":"public/img/shader_16.png","hash":"9bec75831c21d063f23502612f106bfa86a0b100","modified":1700197927774},{"_id":"public/img/shader_17.png","hash":"6274e99ab2e3d2053bdf2c0b9e3cc9b2b786f086","modified":1700197927774},{"_id":"public/img/shader_2.png","hash":"767fe07c2ff75bdb58e1bd5487f373ea7b33a163","modified":1700197927774},{"_id":"public/img/shader_22.png","hash":"610a67538d93eb8c81da6c99b90fe751657f9266","modified":1700197927774},{"_id":"public/img/shader_28.png","hash":"079730db179a7b1f9539b929c33fc2be2b4a5bb5","modified":1700197927774},{"_id":"public/img/shader_3.png","hash":"1260a52b8fc6351c62c3bf9f1e2907f495dd2f4e","modified":1700197927774},{"_id":"public/img/shader_8.png","hash":"ebe473df6f8f19aec27a1e97301c533d82653096","modified":1700197927774},{"_id":"public/img/logo.png","hash":"05730ab0dadd5036509f942834278eef683994dd","modified":1700197927774},{"_id":"public/img/shader_1.png","hash":"559caf74cb63637b58483773f72b7589408ceaf9","modified":1700197927774},{"_id":"public/img/hexo-theme-linear-dark.png","hash":"758aef1e3d9a83844d2871e8ceaccf6767e78284","modified":1700197927774},{"_id":"public/img/shader_13.png","hash":"e1eb1a13ffe9ed74b2f79f2e97c4134f10988657","modified":1700197927774},{"_id":"public/img/shader_21.png","hash":"a381d25344aaf2da7e29a7f157f3c2d1b0a8f813","modified":1700197927774},{"_id":"public/img/shader_27.png","hash":"285b22fb20437acaf07a9a3aa37770802d1b7202","modified":1700197927774},{"_id":"public/img/shader_30.png","hash":"35610b6e8877b16bc2140ec1e13a104188ac2f6b","modified":1700197927774},{"_id":"public/img/shader_5.png","hash":"07822798c3008fe841798993f75b50f104de5e11","modified":1700197927774},{"_id":"public/img/shader_6.png","hash":"7f96d58b93a0149993a7aa02d1d27c75e0ce0936","modified":1700197927774},{"_id":"public/img/shader_9.png","hash":"601cd60bc9837dc0603f82991334e084e7074aec","modified":1700197927774},{"_id":"public/img/shader_7.png","hash":"23388d247c00f832e544954f4fa6956c03fec16d","modified":1700197927774},{"_id":"public/img/shader_29.png","hash":"17acdcaa715bc68eb654b1e6db4fe0b4364d6394","modified":1700197927774},{"_id":"public/img/algolia-api-keys.png","hash":"8b2f85a93b52f0590e9b8fe2d2405427c99e2280","modified":1700197927774},{"_id":"public/img/shader_24.png","hash":"8eba8647f182532ac37462c15aa11a6e2d4ee196","modified":1700197927774},{"_id":"public/img/shader_25.png","hash":"9be25a68c628071e583e3985929c321ebe6d13cb","modified":1700197927774},{"_id":"public/img/shader_26.png","hash":"3433565461d058e381b1c5a13db978d6f470025a","modified":1700197927774},{"_id":"public/img/mz10nq.png","hash":"e26097f94ae54967e68f36b13b6aca80c4d173de","modified":1700197927774}],"Category":[{"name":"EQ","_id":"clp25y58l00044cz306yca7vp"},{"name":"Hexo","_id":"clp25y58m00084cz3cojwdpah"},{"name":"Finance","_id":"clp25y58p000f4cz31o7a47jo"},{"name":"Front-End","_id":"clp25y58q000k4cz311896all"},{"name":"自媒体","_id":"clp25y58t001d4cz35av6hd5e"}],"Data":[],"Page":[{"title":"简历 · 陈不渡Mozzie","layout":"resume","avatar":"/img/avatar.png","name":"Hi! Mozzie","role":"Full Stack","email":"himozzie@gmail.com","phone":"+86 180-xxxx-xxx","birth":"Jan 21, 1994","location":"Nanjing, China","social":[{"name":"github","link":"https://github.com/17px","icon":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"><path d=\"M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2c2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 0 0-1.3-3.2a4.2 4.2 0 0 0-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3 0 0 0-6.2 0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2 0 0 0-.1 3.2A4.6 4.6 0 0 0 4 9.5c0 4.6 2.7 5.7 5.5 6c-.6.6-.6 1.2-.5 2V21\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg>"}],"about":["熟练掌握Vue和React全家桶包括状态管理和组件库如ElementPlus 和 AntDesign。在前端工程化方面有 Webpack 和 Vite 的配置经验。具备 SpringBoot、Egg、Koa2 和 Midway 的项目经验,并在微服务架构下使用 Nestjs。熟悉Linux基础命令和Nginx、Docker的使用。","在3D图形和医疗前端方面具有 three.js 和 Vtk.js 的实践经验"],"skill":["熟悉常见的数据结构和算法,熟悉设计模式","熟悉前端基础 HTML5、CSS3、JS、ES6+、TypeScript 语法","熟悉 Vue2、Vue3 全家桶,熟悉 ElementPlus、NaiveUI熟悉 Vue 原理","熟悉 React 技术栈,熟悉 Hooks 语法,熟悉 AntDesign熟悉 React 原理","熟悉微信小程序开发,熟悉 Taro 框架的使用","熟悉 Webpack、Vite 常见配置,以及性能优化配置","熟悉 Node具备后端开发能力SpringBoot、Egg、Koa2、Midway 单体应用项目经验Nestjs 微服务应用项目经验","有 Monorepo 工程化经验,具备单体前后端分离应用 DevOps 能力","熟悉 three.js、了解 Vtk.js具备医疗 3D 前端、图形学相关的开发经验","掌握 Linux 基本命令,了解 Nginx、Docker 基本使用"],"education":[{"school":"南京信息工程大学滨江学院 / 本科","time":"2012-2016"}],"workExp":[{"inc":"拓微摹心数据科技(南京)有限公司 · 全栈","time":"2021.09 ~ 至今"},{"inc":"南京寻鹿网络科技有限公司 · 前端","time":"2016.09 ~ 2019.06"}],"projectExp":[{"name":"CVPilot算法、标注数据中台","desc":"具备高精度数据标注、强大的数据管理、算法集成、多级用户权限、标注流程协作、算法模型版本、训练测试、API接口和数据可视化等功能全面支持公司内部医疗影像分析和诊断","list":["使用 Pnpm workspace 实现 Monorepo 多个代码仓库管理,支持多个框架并存,可共享公共组件库和能力","自行使用 rollup 沉淀了部分可复用基础模块UI 组件库、对象存储、邮件、短信、企业微信机器人通知","使用 Nest.js 开发,基于事件驱动架构,重构后端服务体系","基于 rbac 设计了认证中心,解决业务应用中用户统一授权、鉴权的问题","使用 orthanc 搭建 Pacs 影像、并且基于标注、业务流程设计了影像上层的标签系统","使用 pdf.js 实现 3Mensio、FluoroCT 医疗报告关键字段的自动解析Cover了 80%+ 的字段","设计了前后端一体开发的领域驱动设计DDD项目架构并成功实践"]},{"name":"TAVR手术辅助决策系统 Tavigator™","desc":"系统实现了对CT影像主动脉根部解剖结构的全自动化、全流程手术规划测量为瓣膜选型、术中并发症风险预测","list":["基于容器,解决算法输出 stl 模型增加血管壁厚等后处理需求","在 OHIF 基础上重新规划项目结构工程化相关优化构建速度提升8倍","对 orthanc 配置进行了优化,使用 postgreSQL 存储影像数据","实践了 threejs 替换了 vtk.js 的默认三维渲染引擎,节省了某些场景下 Vtk.js占用内存过大的问题","使用了 chrome的 snapshot、调用栈优化页面内存 3GB+,使用 Indexdb 与 Webworker 对 Dicom 读片速度优化了3倍以上","使用 webworker、请求队列实现了在 http1.1 环境下,提升用户上传 Dicom影像 74% 上传效率。同时针对不同大小、类型的文件,设计了不同的 Hash 切片方案,提升了文件完整性验证速度提升","使用了 Http3 和 nginx-quic使用 Brotli 替换 gzip实现了静载资源传输速度提升 17% - 25%"]},{"name":"Bolt 组件库、文档设计系统","desc":"前端基建Bolt 用于构建快速组件库、文档。你可以在开发react组件库的同时, 无缝地编写组件文档, 实时热更新","list":["React 组件的 Props 解析,自动生成组件的 API 表格","组件的开发阶段,实施更新,所见即所得","依赖 vite 插件机制200+ 以上组件,开发阶段秒级热更新","智能生成组件说明文档,构建产物分离组件库、文档静态站,支持全局、局部引入"]},{"name":"瓣侣 - 微信小程序","desc":"一款支持医生、病人查看算法分割后数字孪生心脏模型的小程序","list":["使用 taro 对小程序端实现3d模型展示进行了技术选型移植了STLloader 到 three-platformize 中,解决了 stl 模型加载的问题","解决小程序内存占用过大,导致部分机型崩溃的问题","使用包围盒对多个分割模型组合及位置修正、空间测量计算,实现瓣环样条绘制、空间拾取高亮等功能"]}],"portfolio":[{"name":"CVPilot (原Tavigator)","desc":"TAVR手术辅助决策系统","iconSVG":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\"><path d=\"M21 10h-4V6h-2v4h-4v2h4v4h2v-4h4v-2z\" fill=\"currentColor\"></path><path d=\"M28 10h-2V4a2.002 2.002 0 0 0-2-2H8a2.002 2.002 0 0 0-2 2v6H4a2.002 2.002 0 0 0-2 2v18h28V12a2.002 2.002 0 0 0-2-2zM14 28v-6h4v6zm6 0v-7a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v7H4V12h4V4h16v8h4v16z\" fill=\"currentColor\"></path></svg>","link":"https://www.tavi.fit"},{"name":"Bolt Design","desc":"基于 Vite 开发的 React 组件、文档一体化系统","iconSVG":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"><g fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6.357 9C3.72 9.68 2 10.845 2 12.175C2 14.282 6.405 16 11.85 16c.74 0 1.26-.039 1.95-.097\"></path><path d=\"M9.837 15.9c-.413-.596-.806-1.133-1.18-1.8c-2.751-4.9-3.488-9.77-1.63-10.873c1.15-.697 3.047.253 4.974 2.254\"></path><path d=\"M6.429 15.387c-.702 2.688-.56 4.716.56 5.395c1.783 1.08 5.387-1.958 8.043-6.804c.36-.67.683-1.329.968-1.978\"></path><path d=\"M12 18.52c1.928 2 3.817 2.95 4.978 2.253c1.85-1.102 1.121-5.972-1.633-10.873c-.384-.677-.777-1.204-1.18-1.8\"></path><path d=\"M17.66 15c2.612-.687 4.34-1.85 4.34-3.176C22 9.714 17.592 8 12.155 8c-.747 0-1.266.029-1.955.087\"></path><path d=\"M8 12c.285-.66.607-1.308.968-1.978c2.647-4.844 6.253-7.89 8.046-6.801c1.11.679 1.262 2.706.56 5.393\"></path><path d=\"M12.26 12.015h-.01c-.01.13-.12.24-.26.24a.263.263 0 0 1-.25-.26c0-.14.11-.25.24-.25h-.01c.13-.01.25.11.25.24\"></path></g></svg>","link":"https://amo.mozzie.cn/"},{"name":"hexo-theme-cosy","desc":"Minimalist, pursuing the ultimate loading speed for a Hexo theme","iconSVG":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"><path d=\"M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2c2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 0 0-1.3-3.2a4.2 4.2 0 0 0-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3 0 0 0-6.2 0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2 0 0 0-.1 3.2A4.6 4.6 0 0 0 4 9.5c0 4.6 2.7 5.7 5.5 6c-.6.6-.6 1.2-.5 2V21\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg>","link":"https://github.com/17px/hexo-theme-cosy"}],"_content":"","source":"resume/index.md","raw":"---\ntitle: 简历 · 陈不渡Mozzie\nlayout: resume\navatar: /img/avatar.png\nname: Hi! Mozzie\nrole: Full Stack\nemail: himozzie@gmail.com\nphone: +86 180-xxxx-xxx\nbirth: Jan 21, 1994\nlocation: Nanjing, China\nsocial:\n - name: github\n link: https://github.com/17px\n icon: <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"><path d=\"M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2c2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 0 0-1.3-3.2a4.2 4.2 0 0 0-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3 0 0 0-6.2 0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2 0 0 0-.1 3.2A4.6 4.6 0 0 0 4 9.5c0 4.6 2.7 5.7 5.5 6c-.6.6-.6 1.2-.5 2V21\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg>\nabout:\n - 熟练掌握Vue和React全家桶包括状态管理和组件库如ElementPlus 和 AntDesign。在前端工程化方面有 Webpack 和 Vite 的配置经验。具备 SpringBoot、Egg、Koa2 和 Midway 的项目经验,并在微服务架构下使用 Nestjs。熟悉Linux基础命令和Nginx、Docker的使用。\n - 在3D图形和医疗前端方面具有 three.js 和 Vtk.js 的实践经验\n\nskill:\n - 熟悉常见的数据结构和算法,熟悉设计模式\n - 熟悉前端基础 HTML5、CSS3、JS、ES6+、TypeScript 语法\n - 熟悉 Vue2、Vue3 全家桶,熟悉 ElementPlus、NaiveUI熟悉 Vue 原理\n - 熟悉 React 技术栈,熟悉 Hooks 语法,熟悉 AntDesign熟悉 React 原理\n - 熟悉微信小程序开发,熟悉 Taro 框架的使用\n - 熟悉 Webpack、Vite 常见配置,以及性能优化配置\n - 熟悉 Node具备后端开发能力SpringBoot、Egg、Koa2、Midway 单体应用项目经验Nestjs 微服务应用项目经验\n - 有 Monorepo 工程化经验,具备单体前后端分离应用 DevOps 能力\n - 熟悉 three.js、了解 Vtk.js具备医疗 3D 前端、图形学相关的开发经验\n - 掌握 Linux 基本命令,了解 Nginx、Docker 基本使用\n\neducation:\n - school: 南京信息工程大学滨江学院 / 本科\n time: 2012-2016\n\nworkExp:\n - inc: 拓微摹心数据科技(南京)有限公司 · 全栈\n time: 2021.09 ~ 至今\n - inc: 南京寻鹿网络科技有限公司 · 前端\n time: 2016.09 ~ 2019.06\n\nprojectExp:\n - name: CVPilot算法、标注数据中台\n desc: 具备高精度数据标注、强大的数据管理、算法集成、多级用户权限、标注流程协作、算法模型版本、训练测试、API接口和数据可视化等功能全面支持公司内部医疗影像分析和诊断\n list:\n - 使用 Pnpm workspace 实现 Monorepo 多个代码仓库管理,支持多个框架并存,可共享公共组件库和能力\n - 自行使用 rollup 沉淀了部分可复用基础模块UI 组件库、对象存储、邮件、短信、企业微信机器人通知\n - 使用 Nest.js 开发,基于事件驱动架构,重构后端服务体系\n - 基于 rbac 设计了认证中心,解决业务应用中用户统一授权、鉴权的问题\n - 使用 orthanc 搭建 Pacs 影像、并且基于标注、业务流程设计了影像上层的标签系统\n - 使用 pdf.js 实现 3Mensio、FluoroCT 医疗报告关键字段的自动解析Cover了 80%+ 的字段\n - 设计了前后端一体开发的领域驱动设计DDD项目架构并成功实践\n\n - name: TAVR手术辅助决策系统 Tavigator™\n desc: 系统实现了对CT影像主动脉根部解剖结构的全自动化、全流程手术规划测量为瓣膜选型、术中并发症风险预测\n list:\n - 基于容器,解决算法输出 stl 模型增加血管壁厚等后处理需求\n - 在 OHIF 基础上重新规划项目结构工程化相关优化构建速度提升8倍\n - 对 orthanc 配置进行了优化,使用 postgreSQL 存储影像数据\n - 实践了 threejs 替换了 vtk.js 的默认三维渲染引擎,节省了某些场景下 Vtk.js占用内存过大的问题\n - 使用了 chrome的 snapshot、调用栈优化页面内存 3GB+,使用 Indexdb 与 Webworker 对 Dicom 读片速度优化了3倍以上\n - 使用 webworker、请求队列实现了在 http1.1 环境下,提升用户上传 Dicom影像 74% 上传效率。同时针对不同大小、类型的文件,设计了不同的 Hash 切片方案,提升了文件完整性验证速度提升\n - 使用了 Http3 和 nginx-quic使用 Brotli 替换 gzip实现了静载资源传输速度提升 17% - 25%\n\n - name: Bolt 组件库、文档设计系统\n desc: 前端基建Bolt 用于构建快速组件库、文档。你可以在开发react组件库的同时, 无缝地编写组件文档, 实时热更新\n list:\n - React 组件的 Props 解析,自动生成组件的 API 表格\n - 组件的开发阶段,实施更新,所见即所得\n - 依赖 vite 插件机制200+ 以上组件,开发阶段秒级热更新\n - 智能生成组件说明文档,构建产物分离组件库、文档静态站,支持全局、局部引入\n\n - name: 瓣侣 - 微信小程序\n desc: 一款支持医生、病人查看算法分割后数字孪生心脏模型的小程序\n list:\n - 使用 taro 对小程序端实现3d模型展示进行了技术选型移植了STLloader 到 three-platformize 中,解决了 stl 模型加载的问题\n - 解决小程序内存占用过大,导致部分机型崩溃的问题\n - 使用包围盒对多个分割模型组合及位置修正、空间测量计算,实现瓣环样条绘制、空间拾取高亮等功能\n\nportfolio:\n - name: CVPilot (原Tavigator)\n desc: TAVR手术辅助决策系统\n iconSVG: <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\"><path d=\"M21 10h-4V6h-2v4h-4v2h4v4h2v-4h4v-2z\" fill=\"currentColor\"></path><path d=\"M28 10h-2V4a2.002 2.002 0 0 0-2-2H8a2.002 2.002 0 0 0-2 2v6H4a2.002 2.002 0 0 0-2 2v18h28V12a2.002 2.002 0 0 0-2-2zM14 28v-6h4v6zm6 0v-7a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v7H4V12h4V4h16v8h4v16z\" fill=\"currentColor\"></path></svg>\n link: https://www.tavi.fit\n\n - name: Bolt Design\n desc: 基于 Vite 开发的 React 组件、文档一体化系统\n iconSVG: <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"><g fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6.357 9C3.72 9.68 2 10.845 2 12.175C2 14.282 6.405 16 11.85 16c.74 0 1.26-.039 1.95-.097\"></path><path d=\"M9.837 15.9c-.413-.596-.806-1.133-1.18-1.8c-2.751-4.9-3.488-9.77-1.63-10.873c1.15-.697 3.047.253 4.974 2.254\"></path><path d=\"M6.429 15.387c-.702 2.688-.56 4.716.56 5.395c1.783 1.08 5.387-1.958 8.043-6.804c.36-.67.683-1.329.968-1.978\"></path><path d=\"M12 18.52c1.928 2 3.817 2.95 4.978 2.253c1.85-1.102 1.121-5.972-1.633-10.873c-.384-.677-.777-1.204-1.18-1.8\"></path><path d=\"M17.66 15c2.612-.687 4.34-1.85 4.34-3.176C22 9.714 17.592 8 12.155 8c-.747 0-1.266.029-1.955.087\"></path><path d=\"M8 12c.285-.66.607-1.308.968-1.978c2.647-4.844 6.253-7.89 8.046-6.801c1.11.679 1.262 2.706.56 5.393\"></path><path d=\"M12.26 12.015h-.01c-.01.13-.12.24-.26.24a.263.263 0 0 1-.25-.26c0-.14.11-.25.24-.25h-.01c.13-.01.25.11.25.24\"></path></g></svg>\n link: https://amo.mozzie.cn/\n\n - name: hexo-theme-cosy\n desc: Minimalist, pursuing the ultimate loading speed for a Hexo theme\n iconSVG: <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"><path d=\"M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2c2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 0 0-1.3-3.2a4.2 4.2 0 0 0-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3 0 0 0-6.2 0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2 0 0 0-.1 3.2A4.6 4.6 0 0 0 4 9.5c0 4.6 2.7 5.7 5.5 6c-.6.6-.6 1.2-.5 2V21\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg>\n link: https://github.com/17px/hexo-theme-cosy\n---\n","date":"2023-11-03T03:15:41.632Z","updated":"2023-11-03T03:15:41.632Z","path":"resume/index.html","comments":1,"_id":"clp25y58h00004cz37e1j1vhv","content":"","site":{"data":{}},"excerpt":"","more":""},{"title":"陈不渡 - roadmap","layout":"roadmap","initYear":2023,"years":{"2022":[{"title":"读书","start":"01-01","end":"1-5"},{"title":"还是读书","start":"02-01","end":"05-30"}],"2023":[{"title":"⛵️ 开发hexo-theme-cosy主题","start":"09-03","end":"10-03","content":"基本功能基本迭代完成目前稳定在1.2.4版本"},{"title":"✅ 视频AI无闪烁转绘","start":"10-25","end":"11-04","content":"stable diffusion + Ebsynth 插帧"},{"title":"✅ 成为一名飞手","start":"11-04","end":"11-09","content":"UTC无人驾驶航空器系统操作手合格证"},{"title":"✅ hexo-theme-cosy 发包到 npm","start":"11-14","end":"11-16","content":"人生中第一个正儿八经的 npm 包,使用 github 的 action 白嫖一手 ci 资源"},{"title":"抖音千粉","start":"11-06","end":"12-30","content":"粉丝量突破1000预算投入¥3000每天至少生产1个小姐姐舞蹈 AI转绘 视频"},{"title":"📚 付鹏《见证逆潮》","start":"11-25","end":"12-30","content":"笔录书中核心观点,写一篇读后感"}]},"_content":"","source":"roadmap/index.md","raw":"---\ntitle: 陈不渡 - roadmap\nlayout: roadmap\ninitYear: 2023\nyears:\n 2022:\n - title: 读书\n start: 01-01\n end: 1-5\n - title: 还是读书\n start: 02-01\n end: 05-30\n\n 2023:\n - title: ⛵️ 开发hexo-theme-cosy主题\n start: 09-03\n end: 10-03\n content: 基本功能基本迭代完成目前稳定在1.2.4版本\n\n - title: ✅ 视频AI无闪烁转绘\n start: 10-25\n end: 11-04\n content: stable diffusion + Ebsynth 插帧\n\n - title: ✅ 成为一名飞手\n start: 11-04\n end: 11-09\n content: UTC无人驾驶航空器系统操作手合格证\n\n - title: ✅ hexo-theme-cosy 发包到 npm\n start: 11-14\n end: 11-16\n content: 人生中第一个正儿八经的 npm 包,使用 github 的 action 白嫖一手 ci 资源\n\n - title: 抖音千粉\n start: 11-06\n end: 12-30\n content: 粉丝量突破1000预算投入¥3000每天至少生产1个小姐姐舞蹈 AI转绘 视频\n\n - title: 📚 付鹏《见证逆潮》\n start: 11-25\n end: 12-30\n content: 笔录书中核心观点,写一篇读后感\n---","date":"2023-11-17T04:52:39.950Z","updated":"2023-11-17T04:52:39.950Z","path":"roadmap/index.html","comments":1,"_id":"clp25y58k00024cz3f1eg6jgd","content":"","site":{"data":{}},"excerpt":"","more":""}],"Post":[{"title":"有效对话指南","top":0,"status":"done","_content":"\n卡耐基说过要说服别人同意你的观点你就要让他觉得这是他自己的观点。也就是说本质上没有人真正被别人说服听或者不听都是他们自己的主动选择\n\n# 目的\n\n沟通目的无非两个\n\n- 让对方认同我们的观点\n- 或者按我们说的做\n\n# 搞定情绪\n\n大多数人的立场和行为是由情绪决定的对方不喜欢你你再怎么努力也很难说服他只有他认可你这个人你的话他才会听。所以动之以理之前要先小之以轻你把他情绪搞定了沟通也就成功了一半\n\n## 夸 - 细节\n\n不吝赞美就一个字“夸”具体怎么夸呢\n\n细节就是不要太笼统\n\n- 😭 你穿的真好看 \n- 😊 今天的上衣显得你很白,太美了\n\n## 夸 - 对比\n\n- 😭 你今天穿的真好看\n- 😊 你今天穿的真好看,一般人可传不出这种气质\n\n## 我能理解你,换我也生气\n\n接纳对方的负面情绪把双方情绪拉回到安全范围内。\n\n## 肢体同步\n\n如果你的肢体动作跟对方同步它会产生一种被共情的感觉\n\n- 对方说的火热,身体前倾,伺机凑近\n- 思考一到两秒钟再反馈,这个简单的停顿\n\n# 只陈述不评论\n\n事实不会引起争议\n\n比如孩子考试没及格是事实说他笨死了就是评论了。\n\n再比如你这周上班迟到两次这是事实说你经常迟到就是评论了。\n\n## 评论副词\n\n尽量规避一些跟评论相关的糊的频率副词比如\n- 笨\n- 懒\n- 坏\n- 总是\n- 永远\n- 每次\n\n# 保持开放性\n\n还拿上面的例子这些话对方只能回答好或者不好然后结束沟通\n\n- 孩子没及格,老爸说下次必须及格。\n- 你上班迟到,老板说再迟到扣薪水。\n\n如果换成开放式沟通\n\n- 老爸说咱们聊聊哪些题没有搞清楚\n- 老板说生活上是不是遇到了什么问题,没着我可以帮你\n\n# 反馈事实\n\n这些话对方不仅听着舒服而且能给你反馈事实。具体怎么开放呢咱们只需要记住两个关键词\n\n- 问题开放:不要让对方只能回答是或否,例如:像愿闻其详、展开说说、欢迎补充之类\n- 让出话语权:真正的沟通高手,是让对方觉得自己很牛,主导聊天的往往是能提出问题的人,或者让别人多说的人\n\n","source":"_posts/A Guide to Effective Dialogue.md","raw":"---\ntitle: 有效对话指南\ntop: 0\ncategories:\n - EQ\nstatus: done\n---\n\n卡耐基说过要说服别人同意你的观点你就要让他觉得这是他自己的观点。也就是说本质上没有人真正被别人说服听或者不听都是他们自己的主动选择\n\n# 目的\n\n沟通目的无非两个\n\n- 让对方认同我们的观点\n- 或者按我们说的做\n\n# 搞定情绪\n\n大多数人的立场和行为是由情绪决定的对方不喜欢你你再怎么努力也很难说服他只有他认可你这个人你的话他才会听。所以动之以理之前要先小之以轻你把他情绪搞定了沟通也就成功了一半\n\n## 夸 - 细节\n\n不吝赞美就一个字“夸”具体怎么夸呢\n\n细节就是不要太笼统\n\n- 😭 你穿的真好看 \n- 😊 今天的上衣显得你很白,太美了\n\n## 夸 - 对比\n\n- 😭 你今天穿的真好看\n- 😊 你今天穿的真好看,一般人可传不出这种气质\n\n## 我能理解你,换我也生气\n\n接纳对方的负面情绪把双方情绪拉回到安全范围内。\n\n## 肢体同步\n\n如果你的肢体动作跟对方同步它会产生一种被共情的感觉\n\n- 对方说的火热,身体前倾,伺机凑近\n- 思考一到两秒钟再反馈,这个简单的停顿\n\n# 只陈述不评论\n\n事实不会引起争议\n\n比如孩子考试没及格是事实说他笨死了就是评论了。\n\n再比如你这周上班迟到两次这是事实说你经常迟到就是评论了。\n\n## 评论副词\n\n尽量规避一些跟评论相关的糊的频率副词比如\n- 笨\n- 懒\n- 坏\n- 总是\n- 永远\n- 每次\n\n# 保持开放性\n\n还拿上面的例子这些话对方只能回答好或者不好然后结束沟通\n\n- 孩子没及格,老爸说下次必须及格。\n- 你上班迟到,老板说再迟到扣薪水。\n\n如果换成开放式沟通\n\n- 老爸说咱们聊聊哪些题没有搞清楚\n- 老板说生活上是不是遇到了什么问题,没着我可以帮你\n\n# 反馈事实\n\n这些话对方不仅听着舒服而且能给你反馈事实。具体怎么开放呢咱们只需要记住两个关键词\n\n- 问题开放:不要让对方只能回答是或否,例如:像愿闻其详、展开说说、欢迎补充之类\n- 让出话语权:真正的沟通高手,是让对方觉得自己很牛,主导聊天的往往是能提出问题的人,或者让别人多说的人\n\n","slug":"A Guide to Effective Dialogue","published":1,"date":"2023-11-06T05:25:00.499Z","updated":"2023-11-06T05:25:00.499Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58i00014cz3goob8drj","content":"<p>卡耐基说过:要说服别人同意你的观点,你就要让他觉得这是他自己的观点。也就是说,本质上没有人真正被别人说服,听或者不听都是他们自己的主动选择</p>\n<h1 id=\"目的\"><a href=\"#目的\" class=\"headerlink\" title=\"目的\"></a>目的</h1><p>沟通目的无非两个:</p>\n<ul>\n<li>让对方认同我们的观点</li>\n<li>或者按我们说的做</li>\n</ul>\n<h1 id=\"搞定情绪\"><a href=\"#搞定情绪\" class=\"headerlink\" title=\"搞定情绪\"></a>搞定情绪</h1><p>大多数人的立场和行为,是由情绪决定的,对方不喜欢你,你再怎么努力也很难说服他,只有他认可你这个人你的话他才会听。所以动之以理之前要先小之以轻,你把他情绪搞定了,沟通也就成功了一半</p>\n<h2 id=\"夸-细节\"><a href=\"#夸-细节\" class=\"headerlink\" title=\"夸 - 细节\"></a>夸 - 细节</h2><p>不吝赞美,就一个字“夸”,具体怎么夸呢?</p>\n<p>细节就是不要太笼统:</p>\n<ul>\n<li>😭 你穿的真好看 </li>\n<li>😊 今天的上衣显得你很白,太美了</li>\n</ul>\n<h2 id=\"夸-对比\"><a href=\"#夸-对比\" class=\"headerlink\" title=\"夸 - 对比\"></a>夸 - 对比</h2><ul>\n<li>😭 你今天穿的真好看</li>\n<li>😊 你今天穿的真好看,一般人可传不出这种气质</li>\n</ul>\n<h2 id=\"我能理解你,换我也生气\"><a href=\"#我能理解你,换我也生气\" class=\"headerlink\" title=\"我能理解你,换我也生气\"></a>我能理解你,换我也生气</h2><p>接纳对方的负面情绪,把双方情绪拉回到安全范围内。</p>\n<h2 id=\"肢体同步\"><a href=\"#肢体同步\" class=\"headerlink\" title=\"肢体同步\"></a>肢体同步</h2><p>如果你的肢体动作跟对方同步,它会产生一种被共情的感觉</p>\n<ul>\n<li>对方说的火热,身体前倾,伺机凑近</li>\n<li>思考一到两秒钟再反馈,这个简单的停顿</li>\n</ul>\n<h1 id=\"只陈述不评论\"><a href=\"#只陈述不评论\" class=\"headerlink\" title=\"只陈述不评论\"></a>只陈述不评论</h1><p>事实不会引起争议</p>\n<p>比如:孩子考试没及格是事实,说他笨死了就是评论了。</p>\n<p>再比如:你这周上班迟到两次,这是事实,说你经常迟到就是评论了。</p>\n<h2 id=\"评论副词\"><a href=\"#评论副词\" class=\"headerlink\" title=\"评论副词\"></a>评论副词</h2><p>尽量规避一些跟评论相关的糊的频率副词,比如</p>\n<ul>\n<li>笨</li>\n<li>懒</li>\n<li>坏</li>\n<li>总是</li>\n<li>永远</li>\n<li>每次</li>\n</ul>\n<h1 id=\"保持开放性\"><a href=\"#保持开放性\" class=\"headerlink\" title=\"保持开放性\"></a>保持开放性</h1><p>还拿上面的例子,这些话对方只能回答好或者不好,然后结束沟通</p>\n<ul>\n<li>孩子没及格,老爸说下次必须及格。</li>\n<li>你上班迟到,老板说再迟到扣薪水。</li>\n</ul>\n<p>如果换成开放式沟通:</p>\n<ul>\n<li>老爸说咱们聊聊哪些题没有搞清楚</li>\n<li>老板说生活上是不是遇到了什么问题,没着我可以帮你</li>\n</ul>\n<h1 id=\"反馈事实\"><a href=\"#反馈事实\" class=\"headerlink\" title=\"反馈事实\"></a>反馈事实</h1><p>这些话对方不仅听着舒服,而且能给你反馈事实。具体怎么开放呢?咱们只需要记住两个关键词</p>\n<ul>\n<li>问题开放:不要让对方只能回答是或否,例如:像愿闻其详、展开说说、欢迎补充之类</li>\n<li>让出话语权:真正的沟通高手,是让对方觉得自己很牛,主导聊天的往往是能提出问题的人,或者让别人多说的人</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<p>卡耐基说过:要说服别人同意你的观点,你就要让他觉得这是他自己的观点。也就是说,本质上没有人真正被别人说服,听或者不听都是他们自己的主动选择</p>\n<h1 id=\"目的\"><a href=\"#目的\" class=\"headerlink\" title=\"目的\"></a>目的</h1><p>沟通目的无非两个:</p>\n<ul>\n<li>让对方认同我们的观点</li>\n<li>或者按我们说的做</li>\n</ul>\n<h1 id=\"搞定情绪\"><a href=\"#搞定情绪\" class=\"headerlink\" title=\"搞定情绪\"></a>搞定情绪</h1><p>大多数人的立场和行为,是由情绪决定的,对方不喜欢你,你再怎么努力也很难说服他,只有他认可你这个人你的话他才会听。所以动之以理之前要先小之以轻,你把他情绪搞定了,沟通也就成功了一半</p>\n<h2 id=\"夸-细节\"><a href=\"#夸-细节\" class=\"headerlink\" title=\"夸 - 细节\"></a>夸 - 细节</h2><p>不吝赞美,就一个字“夸”,具体怎么夸呢?</p>\n<p>细节就是不要太笼统:</p>\n<ul>\n<li>😭 你穿的真好看 </li>\n<li>😊 今天的上衣显得你很白,太美了</li>\n</ul>\n<h2 id=\"夸-对比\"><a href=\"#夸-对比\" class=\"headerlink\" title=\"夸 - 对比\"></a>夸 - 对比</h2><ul>\n<li>😭 你今天穿的真好看</li>\n<li>😊 你今天穿的真好看,一般人可传不出这种气质</li>\n</ul>\n<h2 id=\"我能理解你,换我也生气\"><a href=\"#我能理解你,换我也生气\" class=\"headerlink\" title=\"我能理解你,换我也生气\"></a>我能理解你,换我也生气</h2><p>接纳对方的负面情绪,把双方情绪拉回到安全范围内。</p>\n<h2 id=\"肢体同步\"><a href=\"#肢体同步\" class=\"headerlink\" title=\"肢体同步\"></a>肢体同步</h2><p>如果你的肢体动作跟对方同步,它会产生一种被共情的感觉</p>\n<ul>\n<li>对方说的火热,身体前倾,伺机凑近</li>\n<li>思考一到两秒钟再反馈,这个简单的停顿</li>\n</ul>\n<h1 id=\"只陈述不评论\"><a href=\"#只陈述不评论\" class=\"headerlink\" title=\"只陈述不评论\"></a>只陈述不评论</h1><p>事实不会引起争议</p>\n<p>比如:孩子考试没及格是事实,说他笨死了就是评论了。</p>\n<p>再比如:你这周上班迟到两次,这是事实,说你经常迟到就是评论了。</p>\n<h2 id=\"评论副词\"><a href=\"#评论副词\" class=\"headerlink\" title=\"评论副词\"></a>评论副词</h2><p>尽量规避一些跟评论相关的糊的频率副词,比如</p>\n<ul>\n<li>笨</li>\n<li>懒</li>\n<li>坏</li>\n<li>总是</li>\n<li>永远</li>\n<li>每次</li>\n</ul>\n<h1 id=\"保持开放性\"><a href=\"#保持开放性\" class=\"headerlink\" title=\"保持开放性\"></a>保持开放性</h1><p>还拿上面的例子,这些话对方只能回答好或者不好,然后结束沟通</p>\n<ul>\n<li>孩子没及格,老爸说下次必须及格。</li>\n<li>你上班迟到,老板说再迟到扣薪水。</li>\n</ul>\n<p>如果换成开放式沟通:</p>\n<ul>\n<li>老爸说咱们聊聊哪些题没有搞清楚</li>\n<li>老板说生活上是不是遇到了什么问题,没着我可以帮你</li>\n</ul>\n<h1 id=\"反馈事实\"><a href=\"#反馈事实\" class=\"headerlink\" title=\"反馈事实\"></a>反馈事实</h1><p>这些话对方不仅听着舒服,而且能给你反馈事实。具体怎么开放呢?咱们只需要记住两个关键词</p>\n<ul>\n<li>问题开放:不要让对方只能回答是或否,例如:像愿闻其详、展开说说、欢迎补充之类</li>\n<li>让出话语权:真正的沟通高手,是让对方觉得自己很牛,主导聊天的往往是能提出问题的人,或者让别人多说的人</li>\n</ul>\n"},{"title":"Cosy 入门","top":2,"status":"doing","_content":"\n# 安装\n\n## 使用 npm 安装\n\n在主题的根目录\n\n```yml\nnpm i hexo-theme-cosy\n```\n\n此外需要新建一个 `_config.cosy.yml`,同时修改 `_config.yml`\n\n```yml\ntheme: cosy\n\nalgolia:\n appId: 你的\n apiKey: 你的\n adminApiKey: 你的\n SearchOnlyAPIKey: 你的\n chunkSize: 5000\n indexName: 你的algolia的index\n fields:\n - content\n - excerpt:strip\n - categories\n - title\n - permalink\n - slug\n - tags\n - title\n```\n\n## 传统安装 Hexo 安装主题\n\n将主题 `Hexo-theme-cosy` 文件夹复制目录的 `themes` 目录下,然后在 `Hexo` 的 `_config.yml` 中修改下主题配置即可\n\n```yml\n# 找到 theme 配置项\ntheme: Hexo-theme-cosy\n```\n\n## 获取 Cosy\n\n- 进入 [Cosy 代码仓库](https://github.com/17px/hexo-theme-cosy/tree/main),了解最新的主题开发进度\n- 在 [发布页面](https://github.com/17px/hexo-theme-cosy/releases) 下载 `hexo-theme-cosy.zip`\n- 解压至站点的 `themes` 目录下\n- 在 Hexo 的 `_config.yml` 中启用\n\n# hexo配置\n\n在 `Hexo` 的 `_config.yml` 中调整\n\n## 基础配置\n\n```yml\n# 网页标题\ntitle: 17px blog\n# 侧边栏顶部显示\nsubtitle: \"Mozzie\"\n# 用于SEO的html元描述\ndescription: \"\"\n# 用于SEO的html关键字\nkeywords:\n# 文章版权声明显示作者名称\nauthor: Mozzie\n\n# 在此处设置您的网站url\nurl: https://mozzie.cn\n```\n\n## 语言\n\n你可以在 `hexo-theme-cosy/languages` 中找到不同的语言文件,如果想切换语言,在配置文件中,填入 `yml` 的文件名\n\n```yml\nlanguage: en\n```\n\n## 文章语法高亮\n\n关闭hexo默认的highlight.js语法高亮\n\n```yml\nhighlight:\n enable: false\n line_number: true\n auto_detect: false\n tab_replace: \"\"\n wrap: true\n hljs: false\n\nprismjs:\n enable: true\n preprocess: true\n line_number: true\n line_threshold: 0\n tab_replace: \"\"\n```\n\n# Cosy 主题配置\n\n下面的配置基于 `Hexo-theme-cosy` 下的 `_config.yml` \n\n## 文章分类图标\n\n> 可以在 [xicon](https://www.xicons.org/) 获取丰富的图标\n\n在`主题_config.yml`文件中,添加`分类名称`和`图标svg`的映射,如值设置为 `false`,代表不显示该分类\n\n```yml\ncategory_meta:\n foo: <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"><g fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1\"></path><path d=\"M8 16h8\"></path><path d=\"M8.322 12.582l7.956.836\"></path><path d=\"M8.787 9.168l7.826 1.664\"></path><path d=\"M10.096 5.764l7.608 2.472\"></path></g></svg>\n bar: false\n```\n\n## 网站图标 favicon\n\n- 支持 `svg`\n- 支持 `图片url`,如:`/img/favicon.png`\n\n```yml\nfavicon: ''\n```\n\n## ICP备案号\n\n😁 如不需要备案号,可直接删除\n\n```yml\nicp: 苏ICP备xxxxxxx号-x\n```\n\n## 首页底部文字\n\n😁 如不需要,可直接删除,或者改为 `false` \n\n```yml\nmotto: false\n```\n\n## 文章版权申明\n\n默认开启当 `enable: false`,默认关闭\n\n```yml\npostCopyright:\n enable: true\n license: CC BY-NC-SA 4.0\n license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/\n```\n\n## katex 数学公式\n\n可自行配置 `cdn`,全局默认关闭该插件\n\n```yml\nkatex:\n jsCdn: //cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.js\n cssCdn: //cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.css\n```\n\n为了加载速度如果文章需要用到插件请在文章头部增加如\n\n```markdown\n---\nuse: katex\n---\n```\n\n## mermaid 流程图\n\n在撰写时请使用 `{% mermaid %}` 和 `{% endmermaid %}` 包裹,全局默认关闭该插件\n\n```markdown\n{% mermaid %}\ngraph TD;\n A --> B;\n A --> C;\n B --> D;\n C --> D;\n{% endmermaid %}\n```\n\n相应配置如下\n\n```yml\nmermaid:\n # 默认使用 neutral可选配置default | dark | forest | neutral\n theme: neutral\n cdn: //cdn.jsdelivr.net/npm/mermaid@10.4.0/dist/mermaid.min.js\n```\n\n为了加载速度如果文章需要用到插件请在文章头部增加如\n\n```markdown\n---\nuse: mermaid,katex...\n---\n```\n\n## valine 文章评论\n\n首先需要注册 `LeanCloud` 国际区用户,创建数据库\n\n请根据相关地区法规酌情全局默认关闭该插件\n\n```yml\nvaline:\n # 替换\n appId: appId\n # 替换\n appKey: appKey\n avatar: monsterid\n cdn: //unpkg.com/valine@latest/dist/Valine.min.js\n # 替换\n serverURLs: //xxxxxxxx.api.lncldglobal.com\n```\n\n为了加载速度如果文章需要用到插件请在文章头部增加如\n\n```markdown\n---\nuse: valine,mermaid...\n---\n```\n\n# algolia搜索\n\n博客自带的本地搜索基于前端开发存在或多或少的问题建议换成 `algolia`,免费账户 总共有 `10,000` 条记录,每月有 `100,000` 的操作数\n\n## 关闭搜索\n\n主页左侧导航栏不再显示搜索通知相关资源不会加载在主题 `_config.yml` 中:\n\n```yml\nsearch: false\n```\n\n## 注册 & 获取 Key\n\n1. 创建一个新的 `Index`,例如 `hex-blog`\n\n2. 复制并保存:\n - Application ID\n - Search-Only API Key\n - Admin API Key\n - Usage API Key\n\n![API Keys](/img/algolia-api-keys.png)\n\n3. 替换配置\n\n在 `Hexo` 的 `_config.yml` 中加入\n\n```yml\nalgolia:\n # 替换\n appId: Application ID\n # 替换\n apiKey: Usage API Key\n # 请勿泄露,用于上报,替换\n adminApiKey: Admin API Key\n # 替换\n SearchOnlyAPIKey: Search-Only API Key\n chunkSize: 5000\n # 替换\n indexName: hex-blog\n fields:\n - content\n - excerpt:strip\n - categories\n - title\n - permalink\n - slug\n - tags\n - title\n```\n\n## 安装 hexo-algoliasearch-next\n\n这是 Hexo 博客帖子索引插件,自动化提交索引到 Algolia\n\n> 如出遇到问题,可阅读 [hexo-algoliasearch-next 仓库](https://github.com/Becavalier/hexo-algoliasearch-next) 最新说明\n\n安装命令\n\n```bash\nnpm install hexo-algoliasearch-next --save\n```\n\n## 使用 algolia\n\n在每次博客发布之前进行索引上传的操作命令通常如下\n\n```bash\nhexo clean\nhexo generate\nhexo algolia\n``` \n\n\n# 🇨🇳 和风天气 Widget\n\nCosy 主要针对国内用户,在首页集成了和风天气的卡片,通过 [和风天气开发服务](https://dev.qweather.com/docs/start/) 注册\n\n注册完成后在配置中填入你的 `appKey` 和 `cityCode(城市代码)`\n\n```yml\nweather:\n enable: true\n # 替换\n cityCode: cityCode\n appKey: appKey\n```\n\n其中 `cityCode` 可以在 [官方的地区列表仓库](https://github.com/qwd/LocationList) 中的 `China-City-List-latest.csv` 找到你所在城市的 `cityCode`\n\n# 前置元数据\n\n在 Hexo 的 Markdown 文件中,一个典型的 YAML 格式的 `Front Matter` 可能会是这样的:\n\n```markdown\n---\ntitle: 我的文章标题\ncategories:\n- javascript\ntags: \n- 编程\n- JavaScript\n---\n```\n\n## top\n\n实现文章置顶的功能给定一个数值可以进行排序设定了 `top` 元数据的文章,会在分类列表中,使用 📌 标记\n\n例如有三篇文章\n\n- 文章1\n\n```markdown\n---\ntitle: 文章1\ntop: 0\ncategories:\n- javascript\ntags: \n- 编程\n- JavaScript\n---\n```\n\n- 文章2\n\n```markdown\n---\ntitle: 文章2\ntop: 1\ncategories:\n- javascript\ntags: \n- 编程\n- JavaScript\n---\n```\n\n- 文章3\n\n```markdown\n---\ntitle: 文章3\ncategories:\n- javascript\ntags: \n- 编程\n- JavaScript\n---\n```\n\n那么在 `javascript` 分类下,排序的顺序依次为:`文章1 > 文章2 > 文章3`\n\n## status\n\n用于区分文章的状态同时利用文章分类列表的`筛选`进行快速筛选Cosy 主题内置了 4 种状态\n\n- done完成\n- doing进行中\n- todo待办\n- other废弃\n\n例如\n\n```markdown\n---\ntitle: 文章1\ncategories:\n- javascript\nstatus: done\n---\n```\n\n# 自定义页面\n\nHexo 使用 Markdown或其他渲染引擎解析你的文章并生成静态文件以快速加载。除了默认生成的文章和归档页面之外Hexo 还允许你创建自定义页面。\n\n## 基本配置\n\n可以通过配置 `nav_meta` 属性关闭页面、更改图标\n\n```yml\nnav_meta:\n # 不显示 timeline页面\n timeline: false\n # 自定义图标\n roadmap:\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\">\n <g fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.5 20.4l-6.9-6.9c-.781-.781-.781-2.219 0-3l6.9-6.9c.781-.781 2.219-.781 3 0l6.9 6.9c.781.781.781 2.219 0 3l-6.9 6.9c-.781.781-2.219.781-3 0z\"></path>\n <path d=\"M9 14v-2c0-.59.414-1 1-1h5\"></path>\n <path d=\"M13 9l2 2l-2 2\"></path>\n </g>\n </svg>\n resume:\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\">\n <g fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M14 3v4a1 1 0 0 0 1 1h4\"></path>\n <path d=\"M5 8V5a2 2 0 0 1 2-2h7l5 5v11a2 2 0 0 1-2 2h-5\"></path>\n <circle cx=\"6\" cy=\"14\" r=\"3\"></circle>\n <path d=\"M4.5 17L3 22l3-1.5L9 22l-1.5-5\"></path>\n </g>\n </svg>\n```\n\n## Roadmap路线图\n\n创建页面你可以使用命令\n\n```bash\nhexo new page roadmap\n```\n\n成功后在 `source/` 文件夹下会生成一个新的文件夹 `/roadmap/index.md`\n\n你可以参照此模板进行配置参数说明\n\n- title: roadmap页面 html 的标题\n- initYear: 默认显示的年份\n\n```markdown\n---\ntitle: 陈不渡 - roadmap\nlayout: roadmap\ninitYear: 2023\nyears:\n 2022:\n - title: 读书\n start: 01-01\n end: 1-5\n - title: 还是读书\n start: 02-01\n end: 05-30\n 2023:\n - title: 越陌度阡\n start: 01-01\n end: 1-2\n - title: 枉用相存\n start: 02-01\n end: 06-30\n - title: 短歌行\n start: 10-26\n end: 10-31\n content: 对酒当歌,人生几何!譬如朝露,去日苦多。慨当以慷,忧思难忘。何以解忧?唯有杜康。青青子衿,悠悠我心。但为君故,沉吟至今。呦呦鹿鸣,食野之苹。\n - title: 声律启蒙\n start: 11-01\n end: 11-31\n content: 花开红锦绣,水漾碧琉璃。去妇因探邻舍枣,出妻为种后园葵\n---\n```\n\n## Resume简历页面\n\n创建页面你可以使用命令\n\n```bash\nhexo new page resume\n```\n\n成功后在 `source/` 文件夹下会生成一个新的文件夹 `/resume/index.md`\n\n你可以参照此模板进行配置参数说明\n\n- title: resume 页面 html 的标题\n- avatar: 头像图片的地址\n\n```yml\ntitle: 页面标题document.title\nlayout: resume\navatar: /img/avatar.png\nname: Hi! Mozzie\nrole: Full Stack\nemail: himozzie@gmail.com\nphone: +86 180-xxxx-xxx\nbirth: Jan 21, 1994\nlocation: Nanjing, China\nsocial:\n - name: github\n link: https://github.com/17px\n icon: svg\n\nabout:\n - 我的工作是建立你的网站,使其功能强大,用户友好,但同时具有吸引力。\n - 此外,我为您的产品添加了个人风格,并确保其引人注目且易于使用。我的目标是以最有创意的方式传达你的信息和身份。我为许多知名品牌公司设计网页。\n\nskill:\n - 熟悉Node具备后端开发能力有SpringBoot、Egg、Koa2、Midway等单个应用项目经验有Nestjs微服务应用项目经验\n - 具有Monoreo工程经验能够分离单个单元的前端和后端并应用DevOps\n\neducation:\n - school: 大学艺术学院\n time: 2012-2016\n\nworkExp:\n - inc: 创意研发\n time: 2021.09 ~ 至今\n - inc: Web设计\n time: 2021.01 ~ 2021.09\n\nprojectExp:\n - name: PC/React• 标注 ,算法数据中心\n desc: 这是一个xxx系统。它主要包括一个bc函数。我主要负责x、y和z模块的开发和维护。\n list: \n - 使用pnpm工作区管理Monorepo中的多个代码库支持多个框架共存共享通用组件库和功能\n\n - name: PC/React•Tavigator主动脉根部/外周\n desc: 这是一个xxx系统。它主要包括一个bc函数。我主要负责x、y和z模块的开发和维护。\n\n\nportfolio:\n - name: 项目A\n desc: 项目A描述\n iconSVG: 复制svg的path到这里\n link: 网址http(s)://...\n # 更多 ...\n\n```","source":"_posts/Cosy-Starter-Guide.md","raw":"---\ntitle: Cosy 入门\ntop: 2\ncategories:\n - Hexo\nstatus: doing\n---\n\n# 安装\n\n## 使用 npm 安装\n\n在主题的根目录\n\n```yml\nnpm i hexo-theme-cosy\n```\n\n此外需要新建一个 `_config.cosy.yml`,同时修改 `_config.yml`\n\n```yml\ntheme: cosy\n\nalgolia:\n appId: 你的\n apiKey: 你的\n adminApiKey: 你的\n SearchOnlyAPIKey: 你的\n chunkSize: 5000\n indexName: 你的algolia的index\n fields:\n - content\n - excerpt:strip\n - categories\n - title\n - permalink\n - slug\n - tags\n - title\n```\n\n## 传统安装 Hexo 安装主题\n\n将主题 `Hexo-theme-cosy` 文件夹复制目录的 `themes` 目录下,然后在 `Hexo` 的 `_config.yml` 中修改下主题配置即可\n\n```yml\n# 找到 theme 配置项\ntheme: Hexo-theme-cosy\n```\n\n## 获取 Cosy\n\n- 进入 [Cosy 代码仓库](https://github.com/17px/hexo-theme-cosy/tree/main),了解最新的主题开发进度\n- 在 [发布页面](https://github.com/17px/hexo-theme-cosy/releases) 下载 `hexo-theme-cosy.zip`\n- 解压至站点的 `themes` 目录下\n- 在 Hexo 的 `_config.yml` 中启用\n\n# hexo配置\n\n在 `Hexo` 的 `_config.yml` 中调整\n\n## 基础配置\n\n```yml\n# 网页标题\ntitle: 17px blog\n# 侧边栏顶部显示\nsubtitle: \"Mozzie\"\n# 用于SEO的html元描述\ndescription: \"\"\n# 用于SEO的html关键字\nkeywords:\n# 文章版权声明显示作者名称\nauthor: Mozzie\n\n# 在此处设置您的网站url\nurl: https://mozzie.cn\n```\n\n## 语言\n\n你可以在 `hexo-theme-cosy/languages` 中找到不同的语言文件,如果想切换语言,在配置文件中,填入 `yml` 的文件名\n\n```yml\nlanguage: en\n```\n\n## 文章语法高亮\n\n关闭hexo默认的highlight.js语法高亮\n\n```yml\nhighlight:\n enable: false\n line_number: true\n auto_detect: false\n tab_replace: \"\"\n wrap: true\n hljs: false\n\nprismjs:\n enable: true\n preprocess: true\n line_number: true\n line_threshold: 0\n tab_replace: \"\"\n```\n\n# Cosy 主题配置\n\n下面的配置基于 `Hexo-theme-cosy` 下的 `_config.yml` \n\n## 文章分类图标\n\n> 可以在 [xicon](https://www.xicons.org/) 获取丰富的图标\n\n在`主题_config.yml`文件中,添加`分类名称`和`图标svg`的映射,如值设置为 `false`,代表不显示该分类\n\n```yml\ncategory_meta:\n foo: <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"><g fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1\"></path><path d=\"M8 16h8\"></path><path d=\"M8.322 12.582l7.956.836\"></path><path d=\"M8.787 9.168l7.826 1.664\"></path><path d=\"M10.096 5.764l7.608 2.472\"></path></g></svg>\n bar: false\n```\n\n## 网站图标 favicon\n\n- 支持 `svg`\n- 支持 `图片url`,如:`/img/favicon.png`\n\n```yml\nfavicon: ''\n```\n\n## ICP备案号\n\n😁 如不需要备案号,可直接删除\n\n```yml\nicp: 苏ICP备xxxxxxx号-x\n```\n\n## 首页底部文字\n\n😁 如不需要,可直接删除,或者改为 `false` \n\n```yml\nmotto: false\n```\n\n## 文章版权申明\n\n默认开启当 `enable: false`,默认关闭\n\n```yml\npostCopyright:\n enable: true\n license: CC BY-NC-SA 4.0\n license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/\n```\n\n## katex 数学公式\n\n可自行配置 `cdn`,全局默认关闭该插件\n\n```yml\nkatex:\n jsCdn: //cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.js\n cssCdn: //cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.css\n```\n\n为了加载速度如果文章需要用到插件请在文章头部增加如\n\n```markdown\n---\nuse: katex\n---\n```\n\n## mermaid 流程图\n\n在撰写时请使用 `{% mermaid %}` 和 `{% endmermaid %}` 包裹,全局默认关闭该插件\n\n```markdown\n{% mermaid %}\ngraph TD;\n A --> B;\n A --> C;\n B --> D;\n C --> D;\n{% endmermaid %}\n```\n\n相应配置如下\n\n```yml\nmermaid:\n # 默认使用 neutral可选配置default | dark | forest | neutral\n theme: neutral\n cdn: //cdn.jsdelivr.net/npm/mermaid@10.4.0/dist/mermaid.min.js\n```\n\n为了加载速度如果文章需要用到插件请在文章头部增加如\n\n```markdown\n---\nuse: mermaid,katex...\n---\n```\n\n## valine 文章评论\n\n首先需要注册 `LeanCloud` 国际区用户,创建数据库\n\n请根据相关地区法规酌情全局默认关闭该插件\n\n```yml\nvaline:\n # 替换\n appId: appId\n # 替换\n appKey: appKey\n avatar: monsterid\n cdn: //unpkg.com/valine@latest/dist/Valine.min.js\n # 替换\n serverURLs: //xxxxxxxx.api.lncldglobal.com\n```\n\n为了加载速度如果文章需要用到插件请在文章头部增加如\n\n```markdown\n---\nuse: valine,mermaid...\n---\n```\n\n# algolia搜索\n\n博客自带的本地搜索基于前端开发存在或多或少的问题建议换成 `algolia`,免费账户 总共有 `10,000` 条记录,每月有 `100,000` 的操作数\n\n## 关闭搜索\n\n主页左侧导航栏不再显示搜索通知相关资源不会加载在主题 `_config.yml` 中:\n\n```yml\nsearch: false\n```\n\n## 注册 & 获取 Key\n\n1. 创建一个新的 `Index`,例如 `hex-blog`\n\n2. 复制并保存:\n - Application ID\n - Search-Only API Key\n - Admin API Key\n - Usage API Key\n\n![API Keys](/img/algolia-api-keys.png)\n\n3. 替换配置\n\n在 `Hexo` 的 `_config.yml` 中加入\n\n```yml\nalgolia:\n # 替换\n appId: Application ID\n # 替换\n apiKey: Usage API Key\n # 请勿泄露,用于上报,替换\n adminApiKey: Admin API Key\n # 替换\n SearchOnlyAPIKey: Search-Only API Key\n chunkSize: 5000\n # 替换\n indexName: hex-blog\n fields:\n - content\n - excerpt:strip\n - categories\n - title\n - permalink\n - slug\n - tags\n - title\n```\n\n## 安装 hexo-algoliasearch-next\n\n这是 Hexo 博客帖子索引插件,自动化提交索引到 Algolia\n\n> 如出遇到问题,可阅读 [hexo-algoliasearch-next 仓库](https://github.com/Becavalier/hexo-algoliasearch-next) 最新说明\n\n安装命令\n\n```bash\nnpm install hexo-algoliasearch-next --save\n```\n\n## 使用 algolia\n\n在每次博客发布之前进行索引上传的操作命令通常如下\n\n```bash\nhexo clean\nhexo generate\nhexo algolia\n``` \n\n\n# 🇨🇳 和风天气 Widget\n\nCosy 主要针对国内用户,在首页集成了和风天气的卡片,通过 [和风天气开发服务](https://dev.qweather.com/docs/start/) 注册\n\n注册完成后在配置中填入你的 `appKey` 和 `cityCode(城市代码)`\n\n```yml\nweather:\n enable: true\n # 替换\n cityCode: cityCode\n appKey: appKey\n```\n\n其中 `cityCode` 可以在 [官方的地区列表仓库](https://github.com/qwd/LocationList) 中的 `China-City-List-latest.csv` 找到你所在城市的 `cityCode`\n\n# 前置元数据\n\n在 Hexo 的 Markdown 文件中,一个典型的 YAML 格式的 `Front Matter` 可能会是这样的:\n\n```markdown\n---\ntitle: 我的文章标题\ncategories:\n- javascript\ntags: \n- 编程\n- JavaScript\n---\n```\n\n## top\n\n实现文章置顶的功能给定一个数值可以进行排序设定了 `top` 元数据的文章,会在分类列表中,使用 📌 标记\n\n例如有三篇文章\n\n- 文章1\n\n```markdown\n---\ntitle: 文章1\ntop: 0\ncategories:\n- javascript\ntags: \n- 编程\n- JavaScript\n---\n```\n\n- 文章2\n\n```markdown\n---\ntitle: 文章2\ntop: 1\ncategories:\n- javascript\ntags: \n- 编程\n- JavaScript\n---\n```\n\n- 文章3\n\n```markdown\n---\ntitle: 文章3\ncategories:\n- javascript\ntags: \n- 编程\n- JavaScript\n---\n```\n\n那么在 `javascript` 分类下,排序的顺序依次为:`文章1 > 文章2 > 文章3`\n\n## status\n\n用于区分文章的状态同时利用文章分类列表的`筛选`进行快速筛选Cosy 主题内置了 4 种状态\n\n- done完成\n- doing进行中\n- todo待办\n- other废弃\n\n例如\n\n```markdown\n---\ntitle: 文章1\ncategories:\n- javascript\nstatus: done\n---\n```\n\n# 自定义页面\n\nHexo 使用 Markdown或其他渲染引擎解析你的文章并生成静态文件以快速加载。除了默认生成的文章和归档页面之外Hexo 还允许你创建自定义页面。\n\n## 基本配置\n\n可以通过配置 `nav_meta` 属性关闭页面、更改图标\n\n```yml\nnav_meta:\n # 不显示 timeline页面\n timeline: false\n # 自定义图标\n roadmap:\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\">\n <g fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.5 20.4l-6.9-6.9c-.781-.781-.781-2.219 0-3l6.9-6.9c.781-.781 2.219-.781 3 0l6.9 6.9c.781.781.781 2.219 0 3l-6.9 6.9c-.781.781-2.219.781-3 0z\"></path>\n <path d=\"M9 14v-2c0-.59.414-1 1-1h5\"></path>\n <path d=\"M13 9l2 2l-2 2\"></path>\n </g>\n </svg>\n resume:\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\">\n <g fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M14 3v4a1 1 0 0 0 1 1h4\"></path>\n <path d=\"M5 8V5a2 2 0 0 1 2-2h7l5 5v11a2 2 0 0 1-2 2h-5\"></path>\n <circle cx=\"6\" cy=\"14\" r=\"3\"></circle>\n <path d=\"M4.5 17L3 22l3-1.5L9 22l-1.5-5\"></path>\n </g>\n </svg>\n```\n\n## Roadmap路线图\n\n创建页面你可以使用命令\n\n```bash\nhexo new page roadmap\n```\n\n成功后在 `source/` 文件夹下会生成一个新的文件夹 `/roadmap/index.md`\n\n你可以参照此模板进行配置参数说明\n\n- title: roadmap页面 html 的标题\n- initYear: 默认显示的年份\n\n```markdown\n---\ntitle: 陈不渡 - roadmap\nlayout: roadmap\ninitYear: 2023\nyears:\n 2022:\n - title: 读书\n start: 01-01\n end: 1-5\n - title: 还是读书\n start: 02-01\n end: 05-30\n 2023:\n - title: 越陌度阡\n start: 01-01\n end: 1-2\n - title: 枉用相存\n start: 02-01\n end: 06-30\n - title: 短歌行\n start: 10-26\n end: 10-31\n content: 对酒当歌,人生几何!譬如朝露,去日苦多。慨当以慷,忧思难忘。何以解忧?唯有杜康。青青子衿,悠悠我心。但为君故,沉吟至今。呦呦鹿鸣,食野之苹。\n - title: 声律启蒙\n start: 11-01\n end: 11-31\n content: 花开红锦绣,水漾碧琉璃。去妇因探邻舍枣,出妻为种后园葵\n---\n```\n\n## Resume简历页面\n\n创建页面你可以使用命令\n\n```bash\nhexo new page resume\n```\n\n成功后在 `source/` 文件夹下会生成一个新的文件夹 `/resume/index.md`\n\n你可以参照此模板进行配置参数说明\n\n- title: resume 页面 html 的标题\n- avatar: 头像图片的地址\n\n```yml\ntitle: 页面标题document.title\nlayout: resume\navatar: /img/avatar.png\nname: Hi! Mozzie\nrole: Full Stack\nemail: himozzie@gmail.com\nphone: +86 180-xxxx-xxx\nbirth: Jan 21, 1994\nlocation: Nanjing, China\nsocial:\n - name: github\n link: https://github.com/17px\n icon: svg\n\nabout:\n - 我的工作是建立你的网站,使其功能强大,用户友好,但同时具有吸引力。\n - 此外,我为您的产品添加了个人风格,并确保其引人注目且易于使用。我的目标是以最有创意的方式传达你的信息和身份。我为许多知名品牌公司设计网页。\n\nskill:\n - 熟悉Node具备后端开发能力有SpringBoot、Egg、Koa2、Midway等单个应用项目经验有Nestjs微服务应用项目经验\n - 具有Monoreo工程经验能够分离单个单元的前端和后端并应用DevOps\n\neducation:\n - school: 大学艺术学院\n time: 2012-2016\n\nworkExp:\n - inc: 创意研发\n time: 2021.09 ~ 至今\n - inc: Web设计\n time: 2021.01 ~ 2021.09\n\nprojectExp:\n - name: PC/React• 标注 ,算法数据中心\n desc: 这是一个xxx系统。它主要包括一个bc函数。我主要负责x、y和z模块的开发和维护。\n list: \n - 使用pnpm工作区管理Monorepo中的多个代码库支持多个框架共存共享通用组件库和功能\n\n - name: PC/React•Tavigator主动脉根部/外周\n desc: 这是一个xxx系统。它主要包括一个bc函数。我主要负责x、y和z模块的开发和维护。\n\n\nportfolio:\n - name: 项目A\n desc: 项目A描述\n iconSVG: 复制svg的path到这里\n link: 网址http(s)://...\n # 更多 ...\n\n```","slug":"Cosy-Starter-Guide","published":1,"date":"2023-10-23T04:01:13.108Z","updated":"2023-11-17T02:57:03.295Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58k00034cz3f1qn2ems","content":"<h1 id=\"安装\"><a href=\"#安装\" class=\"headerlink\" title=\"安装\"></a>安装</h1><h2 id=\"使用-npm-安装\"><a href=\"#使用-npm-安装\" class=\"headerlink\" title=\"使用 npm 安装\"></a>使用 npm 安装</h2><p>在主题的根目录</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\">npm i hexo<span class=\"token punctuation\">-</span>theme<span class=\"token punctuation\">-</span>cosy<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>此外,需要新建一个 <code>_config.cosy.yml</code>,同时修改 <code>_config.yml</code></p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">theme</span><span class=\"token punctuation\">:</span> cosy\n\n<span class=\"token key atrule\">algolia</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">appId</span><span class=\"token punctuation\">:</span> 你的\n <span class=\"token key atrule\">apiKey</span><span class=\"token punctuation\">:</span> 你的\n <span class=\"token key atrule\">adminApiKey</span><span class=\"token punctuation\">:</span> 你的\n <span class=\"token key atrule\">SearchOnlyAPIKey</span><span class=\"token punctuation\">:</span> 你的\n <span class=\"token key atrule\">chunkSize</span><span class=\"token punctuation\">:</span> <span class=\"token number\">5000</span>\n <span class=\"token key atrule\">indexName</span><span class=\"token punctuation\">:</span> 你的algolia的index\n <span class=\"token key atrule\">fields</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> content\n <span class=\"token punctuation\">-</span> excerpt<span class=\"token punctuation\">:</span>strip\n <span class=\"token punctuation\">-</span> categories\n <span class=\"token punctuation\">-</span> title\n <span class=\"token punctuation\">-</span> permalink\n <span class=\"token punctuation\">-</span> slug\n <span class=\"token punctuation\">-</span> tags\n <span class=\"token punctuation\">-</span> title<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"传统安装-Hexo-安装主题\"><a href=\"#传统安装-Hexo-安装主题\" class=\"headerlink\" title=\"传统安装 Hexo 安装主题\"></a>传统安装 Hexo 安装主题</h2><p>将主题 <code>Hexo-theme-cosy</code> 文件夹复制目录的 <code>themes</code> 目录下,然后在 <code>Hexo</code> 的 <code>_config.yml</code> 中修改下主题配置即可</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token comment\"># 找到 theme 配置项</span>\n<span class=\"token key atrule\">theme</span><span class=\"token punctuation\">:</span> Hexo<span class=\"token punctuation\">-</span>theme<span class=\"token punctuation\">-</span>cosy<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"获取-Cosy\"><a href=\"#获取-Cosy\" class=\"headerlink\" title=\"获取 Cosy\"></a>获取 Cosy</h2><ul>\n<li>进入 <a href=\"https://github.com/17px/hexo-theme-cosy/tree/main\">Cosy 代码仓库</a>,了解最新的主题开发进度</li>\n<li>在 <a href=\"https://github.com/17px/hexo-theme-cosy/releases\">发布页面</a> 下载 <code>hexo-theme-cosy.zip</code></li>\n<li>解压至站点的 <code>themes</code> 目录下</li>\n<li>在 Hexo 的 <code>_config.yml</code> 中启用</li>\n</ul>\n<h1 id=\"hexo配置\"><a href=\"#hexo配置\" class=\"headerlink\" title=\"hexo配置\"></a>hexo配置</h1><p>在 <code>Hexo</code> 的 <code>_config.yml</code> 中调整</p>\n<h2 id=\"基础配置\"><a href=\"#基础配置\" class=\"headerlink\" title=\"基础配置\"></a>基础配置</h2><pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token comment\"># 网页标题</span>\n<span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 17px blog\n<span class=\"token comment\"># 侧边栏顶部显示</span>\n<span class=\"token key atrule\">subtitle</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Mozzie\"</span>\n<span class=\"token comment\"># 用于SEO的html元描述</span>\n<span class=\"token key atrule\">description</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"\"</span>\n<span class=\"token comment\"># 用于SEO的html关键字</span>\n<span class=\"token key atrule\">keywords</span><span class=\"token punctuation\">:</span>\n<span class=\"token comment\"># 文章版权声明显示作者名称</span>\n<span class=\"token key atrule\">author</span><span class=\"token punctuation\">:</span> Mozzie\n\n<span class=\"token comment\"># 在此处设置您的网站url</span>\n<span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//mozzie.cn<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"语言\"><a href=\"#语言\" class=\"headerlink\" title=\"语言\"></a>语言</h2><p>你可以在 <code>hexo-theme-cosy/languages</code> 中找到不同的语言文件,如果想切换语言,在配置文件中,填入 <code>yml</code> 的文件名</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">language</span><span class=\"token punctuation\">:</span> en<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"文章语法高亮\"><a href=\"#文章语法高亮\" class=\"headerlink\" title=\"文章语法高亮\"></a>文章语法高亮</h2><p>关闭hexo默认的highlight.js语法高亮</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">highlight</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span>\n <span class=\"token key atrule\">line_number</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">auto_detect</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span>\n <span class=\"token key atrule\">tab_replace</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"\"</span>\n <span class=\"token key atrule\">wrap</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">hljs</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span>\n\n<span class=\"token key atrule\">prismjs</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">preprocess</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">line_number</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">line_threshold</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span>\n <span class=\"token key atrule\">tab_replace</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"Cosy-主题配置\"><a href=\"#Cosy-主题配置\" class=\"headerlink\" title=\"Cosy 主题配置\"></a>Cosy 主题配置</h1><p>下面的配置基于 <code>Hexo-theme-cosy</code> 下的 <code>_config.yml</code> </p>\n<h2 id=\"文章分类图标\"><a href=\"#文章分类图标\" class=\"headerlink\" title=\"文章分类图标\"></a>文章分类图标</h2><blockquote>\n<p>可以在 <a href=\"https://www.xicons.org/\">xicon</a> 获取丰富的图标</p>\n</blockquote>\n<p>在<code>主题_config.yml</code>文件中,添加<code>分类名称</code>和<code>图标svg</code>的映射,如值设置为 <code>false</code>,代表不显示该分类</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">category_meta</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">foo</span><span class=\"token punctuation\">:</span> &lt;svg xmlns=\"http<span class=\"token punctuation\">:</span>//www.w3.org/2000/svg\" xmlns<span class=\"token punctuation\">:</span>xlink=\"http<span class=\"token punctuation\">:</span>//www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"<span class=\"token punctuation\">></span>&lt;g fill=\"none\" stroke=\"currentColor\" stroke<span class=\"token punctuation\">-</span>width=\"2\" stroke<span class=\"token punctuation\">-</span>linecap=\"round\" stroke<span class=\"token punctuation\">-</span>linejoin=\"round\"<span class=\"token punctuation\">></span>&lt;path d=\"M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2<span class=\"token punctuation\">-</span>2v<span class=\"token punctuation\">-</span>1\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>&lt;path d=\"M8 16h8\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>&lt;path d=\"M8.322 12.582l7.956.836\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>&lt;path d=\"M8.787 9.168l7.826 1.664\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>&lt;path d=\"M10.096 5.764l7.608 2.472\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>&lt;/g<span class=\"token punctuation\">></span>&lt;/svg<span class=\"token punctuation\">></span>\n <span class=\"token key atrule\">bar</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"网站图标-favicon\"><a href=\"#网站图标-favicon\" class=\"headerlink\" title=\"网站图标 favicon\"></a>网站图标 favicon</h2><ul>\n<li>支持 <code>svg</code></li>\n<li>支持 <code>图片url</code>,如:<code>/img/favicon.png</code></li>\n</ul>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">favicon</span><span class=\"token punctuation\">:</span> <span class=\"token string\">''</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"ICP备案号\"><a href=\"#ICP备案号\" class=\"headerlink\" title=\"ICP备案号\"></a>ICP备案号</h2><p>😁 如不需要备案号,可直接删除</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">icp</span><span class=\"token punctuation\">:</span> 苏ICP备xxxxxxx号<span class=\"token punctuation\">-</span>x<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"首页底部文字\"><a href=\"#首页底部文字\" class=\"headerlink\" title=\"首页底部文字\"></a>首页底部文字</h2><p>😁 如不需要,可直接删除,或者改为 <code>false</code> </p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">motto</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"文章版权申明\"><a href=\"#文章版权申明\" class=\"headerlink\" title=\"文章版权申明\"></a>文章版权申明</h2><p>默认开启,当 <code>enable: false</code>,默认关闭</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">postCopyright</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">license</span><span class=\"token punctuation\">:</span> CC BY<span class=\"token punctuation\">-</span>NC<span class=\"token punctuation\">-</span>SA 4.0\n <span class=\"token key atrule\">license_url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//creativecommons.org/licenses/by<span class=\"token punctuation\">-</span>nc<span class=\"token punctuation\">-</span>sa/4.0/<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"katex-数学公式\"><a href=\"#katex-数学公式\" class=\"headerlink\" title=\"katex 数学公式\"></a>katex 数学公式</h2><p>可自行配置 <code>cdn</code>,全局默认关闭该插件</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">katex</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">jsCdn</span><span class=\"token punctuation\">:</span> //cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.js\n <span class=\"token key atrule\">cssCdn</span><span class=\"token punctuation\">:</span> //cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.css<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>为了加载速度,如果文章需要用到插件,请在文章头部增加,如</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">use</span><span class=\"token punctuation\">:</span> katex</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"mermaid-流程图\"><a href=\"#mermaid-流程图\" class=\"headerlink\" title=\"mermaid 流程图\"></a>mermaid 流程图</h2><p>在撰写时,请使用 <code>&#123;% mermaid %&#125;` 和 `&#123;% endmermaid %&#125;</code> 包裹,全局默认关闭该插件</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\">&#123;% mermaid %&#125;\ngraph TD;\n A --> B;\n A --> C;\n B --> D;\n C --> D;\n&#123;% endmermaid %&#125;<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>相应配置如下</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">mermaid</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 默认使用 neutral可选配置default | dark | forest | neutral</span>\n <span class=\"token key atrule\">theme</span><span class=\"token punctuation\">:</span> neutral\n <span class=\"token key atrule\">cdn</span><span class=\"token punctuation\">:</span> //cdn.jsdelivr.net/npm/mermaid@10.4.0/dist/mermaid.min.js<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>为了加载速度,如果文章需要用到插件,请在文章头部增加,如</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">use</span><span class=\"token punctuation\">:</span> mermaid<span class=\"token punctuation\">,</span>katex<span class=\"token punctuation\">...</span></span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"valine-文章评论\"><a href=\"#valine-文章评论\" class=\"headerlink\" title=\"valine 文章评论\"></a>valine 文章评论</h2><p>首先需要注册 <code>LeanCloud</code> 国际区用户,创建数据库</p>\n<p>请根据相关地区法规,酌情,全局默认关闭该插件</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">valine</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">appId</span><span class=\"token punctuation\">:</span> appId\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">appKey</span><span class=\"token punctuation\">:</span> appKey\n <span class=\"token key atrule\">avatar</span><span class=\"token punctuation\">:</span> monsterid\n <span class=\"token key atrule\">cdn</span><span class=\"token punctuation\">:</span> //unpkg.com/valine@latest/dist/Valine.min.js\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">serverURLs</span><span class=\"token punctuation\">:</span> //xxxxxxxx.api.lncldglobal.com<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>为了加载速度,如果文章需要用到插件,请在文章头部增加,如</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">use</span><span class=\"token punctuation\">:</span> valine<span class=\"token punctuation\">,</span>mermaid<span class=\"token punctuation\">...</span></span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"algolia搜索\"><a href=\"#algolia搜索\" class=\"headerlink\" title=\"algolia搜索\"></a>algolia搜索</h1><p>博客自带的本地搜索,基于前端开发,存在或多或少的问题,建议换成 <code>algolia</code>,免费账户 总共有 <code>10,000</code> 条记录,每月有 <code>100,000</code> 的操作数</p>\n<h2 id=\"关闭搜索\"><a href=\"#关闭搜索\" class=\"headerlink\" title=\"关闭搜索\"></a>关闭搜索</h2><p>主页左侧导航栏不再显示搜索,通知相关资源不会加载,在主题 <code>_config.yml</code> 中:</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">search</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"注册-amp-获取-Key\"><a href=\"#注册-amp-获取-Key\" class=\"headerlink\" title=\"注册 &amp; 获取 Key\"></a>注册 &amp; 获取 Key</h2><ol>\n<li><p>创建一个新的 <code>Index</code>,例如 <code>hex-blog</code></p>\n</li>\n<li><p>复制并保存:</p>\n</li>\n</ol>\n<ul>\n<li>Application ID</li>\n<li>Search-Only API Key</li>\n<li>Admin API Key</li>\n<li>Usage API Key</li>\n</ul>\n<p><img src=\"/img/algolia-api-keys.png\" alt=\"API Keys\"></p>\n<ol start=\"3\">\n<li>替换配置</li>\n</ol>\n<p>在 <code>Hexo</code> 的 <code>_config.yml</code> 中加入</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">algolia</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">appId</span><span class=\"token punctuation\">:</span> Application ID\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">apiKey</span><span class=\"token punctuation\">:</span> Usage API Key\n <span class=\"token comment\"># 请勿泄露,用于上报,替换</span>\n <span class=\"token key atrule\">adminApiKey</span><span class=\"token punctuation\">:</span> Admin API Key\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">SearchOnlyAPIKey</span><span class=\"token punctuation\">:</span> Search<span class=\"token punctuation\">-</span>Only API Key\n <span class=\"token key atrule\">chunkSize</span><span class=\"token punctuation\">:</span> <span class=\"token number\">5000</span>\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">indexName</span><span class=\"token punctuation\">:</span> hex<span class=\"token punctuation\">-</span>blog\n <span class=\"token key atrule\">fields</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> content\n <span class=\"token punctuation\">-</span> excerpt<span class=\"token punctuation\">:</span>strip\n <span class=\"token punctuation\">-</span> categories\n <span class=\"token punctuation\">-</span> title\n <span class=\"token punctuation\">-</span> permalink\n <span class=\"token punctuation\">-</span> slug\n <span class=\"token punctuation\">-</span> tags\n <span class=\"token punctuation\">-</span> title<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"安装-hexo-algoliasearch-next\"><a href=\"#安装-hexo-algoliasearch-next\" class=\"headerlink\" title=\"安装 hexo-algoliasearch-next\"></a>安装 hexo-algoliasearch-next</h2><p>这是 Hexo 博客帖子索引插件,自动化提交索引到 Algolia</p>\n<blockquote>\n<p>如出遇到问题,可阅读 <a href=\"https://github.com/Becavalier/hexo-algoliasearch-next\">hexo-algoliasearch-next 仓库</a> 最新说明</p>\n</blockquote>\n<p>安装命令:</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> hexo-algoliasearch-next <span class=\"token parameter variable\">--save</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"使用-algolia\"><a href=\"#使用-algolia\" class=\"headerlink\" title=\"使用 algolia\"></a>使用 algolia</h2><p>在每次博客发布之前,进行索引上传的操作,命令通常如下</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">hexo clean\nhexo generate\nhexo algolia<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n\n<h1 id=\"🇨🇳-和风天气-Widget\"><a href=\"#🇨🇳-和风天气-Widget\" class=\"headerlink\" title=\"🇨🇳 和风天气 Widget\"></a>🇨🇳 和风天气 Widget</h1><p>Cosy 主要针对国内用户,在首页集成了和风天气的卡片,通过 <a href=\"https://dev.qweather.com/docs/start/\">和风天气开发服务</a> 注册</p>\n<p>注册完成后,在配置中填入你的 <code>appKey</code> 和 <code>cityCode(城市代码)</code></p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">weather</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">cityCode</span><span class=\"token punctuation\">:</span> cityCode\n <span class=\"token key atrule\">appKey</span><span class=\"token punctuation\">:</span> appKey<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>其中 <code>cityCode</code> 可以在 <a href=\"https://github.com/qwd/LocationList\">官方的地区列表仓库</a> 中的 <code>China-City-List-latest.csv</code> 找到你所在城市的 <code>cityCode</code></p>\n<h1 id=\"前置元数据\"><a href=\"#前置元数据\" class=\"headerlink\" title=\"前置元数据\"></a>前置元数据</h1><p>在 Hexo 的 Markdown 文件中,一个典型的 YAML 格式的 <code>Front Matter</code> 可能会是这样的:</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 我的文章标题\n<span class=\"token key atrule\">categories</span><span class=\"token punctuation\">:</span>\n<span class=\"token punctuation\">-</span> javascript\n<span class=\"token key atrule\">tags</span><span class=\"token punctuation\">:</span> \n<span class=\"token punctuation\">-</span> 编程\n<span class=\"token punctuation\">-</span> JavaScript</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"top\"><a href=\"#top\" class=\"headerlink\" title=\"top\"></a>top</h2><p>实现文章置顶的功能,给定一个数值,可以进行排序,设定了 <code>top</code> 元数据的文章,会在分类列表中,使用 📌 标记</p>\n<p>例如有三篇文章:</p>\n<ul>\n<li>文章1</li>\n</ul>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 文章1\n<span class=\"token key atrule\">top</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span>\n<span class=\"token key atrule\">categories</span><span class=\"token punctuation\">:</span>\n<span class=\"token punctuation\">-</span> javascript\n<span class=\"token key atrule\">tags</span><span class=\"token punctuation\">:</span> \n<span class=\"token punctuation\">-</span> 编程\n<span class=\"token punctuation\">-</span> JavaScript</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<ul>\n<li>文章2</li>\n</ul>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 文章2\n<span class=\"token key atrule\">top</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1</span>\n<span class=\"token key atrule\">categories</span><span class=\"token punctuation\">:</span>\n<span class=\"token punctuation\">-</span> javascript\n<span class=\"token key atrule\">tags</span><span class=\"token punctuation\">:</span> \n<span class=\"token punctuation\">-</span> 编程\n<span class=\"token punctuation\">-</span> JavaScript</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<ul>\n<li>文章3</li>\n</ul>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 文章3\n<span class=\"token key atrule\">categories</span><span class=\"token punctuation\">:</span>\n<span class=\"token punctuation\">-</span> javascript\n<span class=\"token key atrule\">tags</span><span class=\"token punctuation\">:</span> \n<span class=\"token punctuation\">-</span> 编程\n<span class=\"token punctuation\">-</span> JavaScript</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>那么在 <code>javascript</code> 分类下,排序的顺序依次为:<code>文章1 &gt; 文章2 &gt; 文章3</code></p>\n<h2 id=\"status\"><a href=\"#status\" class=\"headerlink\" title=\"status\"></a>status</h2><p>用于区分文章的状态,同时利用文章分类列表的<code>筛选</code>进行快速筛选Cosy 主题内置了 4 种状态</p>\n<ul>\n<li>done完成</li>\n<li>doing进行中</li>\n<li>todo待办</li>\n<li>other废弃</li>\n</ul>\n<p>例如:</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 文章1\n<span class=\"token key atrule\">categories</span><span class=\"token punctuation\">:</span>\n<span class=\"token punctuation\">-</span> javascript\n<span class=\"token key atrule\">status</span><span class=\"token punctuation\">:</span> done</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"自定义页面\"><a href=\"#自定义页面\" class=\"headerlink\" title=\"自定义页面\"></a>自定义页面</h1><p>Hexo 使用 Markdown或其他渲染引擎解析你的文章并生成静态文件以快速加载。除了默认生成的文章和归档页面之外Hexo 还允许你创建自定义页面。</p>\n<h2 id=\"基本配置\"><a href=\"#基本配置\" class=\"headerlink\" title=\"基本配置\"></a>基本配置</h2><p>可以通过配置 <code>nav_meta</code> 属性关闭页面、更改图标</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">nav_meta</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 不显示 timeline页面</span>\n <span class=\"token key atrule\">timeline</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span>\n <span class=\"token comment\"># 自定义图标</span>\n <span class=\"token key atrule\">roadmap</span><span class=\"token punctuation\">:</span>\n &lt;svg xmlns=\"http<span class=\"token punctuation\">:</span>//www.w3.org/2000/svg\" xmlns<span class=\"token punctuation\">:</span>xlink=\"http<span class=\"token punctuation\">:</span>//www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"<span class=\"token punctuation\">></span>\n &lt;g fill=\"none\" stroke=\"currentColor\" stroke<span class=\"token punctuation\">-</span>width=\"2\" stroke<span class=\"token punctuation\">-</span>linecap=\"round\" stroke<span class=\"token punctuation\">-</span>linejoin=\"round\"<span class=\"token punctuation\">></span>\n &lt;path d=\"M10.5 20.4l<span class=\"token punctuation\">-</span>6.9<span class=\"token punctuation\">-</span>6.9c<span class=\"token punctuation\">-</span>.781<span class=\"token punctuation\">-</span>.781<span class=\"token punctuation\">-</span>.781<span class=\"token punctuation\">-</span>2.219 0<span class=\"token punctuation\">-</span>3l6.9<span class=\"token punctuation\">-</span>6.9c.781<span class=\"token punctuation\">-</span>.781 2.219<span class=\"token punctuation\">-</span>.781 3 0l6.9 6.9c.781.781.781 2.219 0 3l<span class=\"token punctuation\">-</span>6.9 6.9c<span class=\"token punctuation\">-</span>.781.781<span class=\"token punctuation\">-</span>2.219.781<span class=\"token punctuation\">-</span>3 0z\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;path d=\"M9 14v<span class=\"token punctuation\">-</span>2c0<span class=\"token punctuation\">-</span>.59.414<span class=\"token punctuation\">-</span>1 1<span class=\"token punctuation\">-</span>1h5\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;path d=\"M13 9l2 2l<span class=\"token punctuation\">-</span>2 2\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;/g<span class=\"token punctuation\">></span>\n &lt;/svg<span class=\"token punctuation\">></span>\n <span class=\"token key atrule\">resume</span><span class=\"token punctuation\">:</span>\n &lt;svg xmlns=\"http<span class=\"token punctuation\">:</span>//www.w3.org/2000/svg\" xmlns<span class=\"token punctuation\">:</span>xlink=\"http<span class=\"token punctuation\">:</span>//www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"<span class=\"token punctuation\">></span>\n &lt;g fill=\"none\" stroke=\"currentColor\" stroke<span class=\"token punctuation\">-</span>width=\"2\" stroke<span class=\"token punctuation\">-</span>linecap=\"round\" stroke<span class=\"token punctuation\">-</span>linejoin=\"round\"<span class=\"token punctuation\">></span>\n &lt;path d=\"M14 3v4a1 1 0 0 0 1 1h4\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;path d=\"M5 8V5a2 2 0 0 1 2<span class=\"token punctuation\">-</span>2h7l5 5v11a2 2 0 0 1<span class=\"token punctuation\">-</span>2 2h<span class=\"token punctuation\">-</span>5\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;circle cx=\"6\" cy=\"14\" r=\"3\"<span class=\"token punctuation\">></span>&lt;/circle<span class=\"token punctuation\">></span>\n &lt;path d=\"M4.5 17L3 22l3<span class=\"token punctuation\">-</span>1.5L9 22l<span class=\"token punctuation\">-</span>1.5<span class=\"token punctuation\">-</span>5\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;/g<span class=\"token punctuation\">></span>\n &lt;/svg<span class=\"token punctuation\">></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"Roadmap路线图\"><a href=\"#Roadmap路线图\" class=\"headerlink\" title=\"Roadmap路线图\"></a>Roadmap路线图</h2><p>创建页面,你可以使用命令</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">hexo new page roadmap<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>成功后在 <code>source/</code> 文件夹下会生成一个新的文件夹 <code>/roadmap/index.md</code></p>\n<p>你可以参照此模板,进行配置,参数说明:</p>\n<ul>\n<li>title: roadmap页面 html 的标题</li>\n<li>initYear: 默认显示的年份</li>\n</ul>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 陈不渡 <span class=\"token punctuation\">-</span> roadmap\n<span class=\"token key atrule\">layout</span><span class=\"token punctuation\">:</span> roadmap\n<span class=\"token key atrule\">initYear</span><span class=\"token punctuation\">:</span> <span class=\"token number\">2023</span>\n<span class=\"token key atrule\">years</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">2022</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 读书\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 01<span class=\"token punctuation\">-</span><span class=\"token number\">01</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 1<span class=\"token punctuation\">-</span><span class=\"token number\">5</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 还是读书\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 02<span class=\"token punctuation\">-</span><span class=\"token number\">01</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 05<span class=\"token punctuation\">-</span><span class=\"token number\">30</span>\n <span class=\"token key atrule\">2023</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 越陌度阡\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 01<span class=\"token punctuation\">-</span><span class=\"token number\">01</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 1<span class=\"token punctuation\">-</span><span class=\"token number\">2</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 枉用相存\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 02<span class=\"token punctuation\">-</span><span class=\"token number\">01</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 06<span class=\"token punctuation\">-</span><span class=\"token number\">30</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 短歌行\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 10<span class=\"token punctuation\">-</span><span class=\"token number\">26</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 10<span class=\"token punctuation\">-</span><span class=\"token number\">31</span>\n <span class=\"token key atrule\">content</span><span class=\"token punctuation\">:</span> 对酒当歌,人生几何!譬如朝露,去日苦多。慨当以慷,忧思难忘。何以解忧?唯有杜康。青青子衿,悠悠我心。但为君故,沉吟至今。呦呦鹿鸣,食野之苹。\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 声律启蒙\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 11<span class=\"token punctuation\">-</span><span class=\"token number\">01</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 11<span class=\"token punctuation\">-</span><span class=\"token number\">31</span>\n <span class=\"token key atrule\">content</span><span class=\"token punctuation\">:</span> 花开红锦绣,水漾碧琉璃。去妇因探邻舍枣,出妻为种后园葵</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"Resume简历页面\"><a href=\"#Resume简历页面\" class=\"headerlink\" title=\"Resume简历页面\"></a>Resume简历页面</h2><p>创建页面,你可以使用命令</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">hexo new page resume<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>成功后在 <code>source/</code> 文件夹下会生成一个新的文件夹 <code>/resume/index.md</code></p>\n<p>你可以参照此模板,进行配置,参数说明:</p>\n<ul>\n<li>title: resume 页面 html 的标题</li>\n<li>avatar: 头像图片的地址</li>\n</ul>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 页面标题document.title\n<span class=\"token key atrule\">layout</span><span class=\"token punctuation\">:</span> resume\n<span class=\"token key atrule\">avatar</span><span class=\"token punctuation\">:</span> /img/avatar.png\n<span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Hi<span class=\"token tag\">!</span> Mozzie\n<span class=\"token key atrule\">role</span><span class=\"token punctuation\">:</span> Full Stack\n<span class=\"token key atrule\">email</span><span class=\"token punctuation\">:</span> himozzie@gmail.com\n<span class=\"token key atrule\">phone</span><span class=\"token punctuation\">:</span> +86 180<span class=\"token punctuation\">-</span>xxxx<span class=\"token punctuation\">-</span>xxx\n<span class=\"token key atrule\">birth</span><span class=\"token punctuation\">:</span> Jan 21<span class=\"token punctuation\">,</span> <span class=\"token number\">1994</span>\n<span class=\"token key atrule\">location</span><span class=\"token punctuation\">:</span> Nanjing<span class=\"token punctuation\">,</span> China\n<span class=\"token key atrule\">social</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> github\n <span class=\"token key atrule\">link</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//github.com/17px\n <span class=\"token key atrule\">icon</span><span class=\"token punctuation\">:</span> svg\n\n<span class=\"token key atrule\">about</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> 我的工作是建立你的网站,使其功能强大,用户友好,但同时具有吸引力。\n <span class=\"token punctuation\">-</span> 此外,我为您的产品添加了个人风格,并确保其引人注目且易于使用。我的目标是以最有创意的方式传达你的信息和身份。我为许多知名品牌公司设计网页。\n\n<span class=\"token key atrule\">skill</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> 熟悉Node具备后端开发能力有SpringBoot、Egg、Koa2、Midway等单个应用项目经验有Nestjs微服务应用项目经验\n <span class=\"token punctuation\">-</span> 具有Monoreo工程经验能够分离单个单元的前端和后端并应用DevOps\n\n<span class=\"token key atrule\">education</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">school</span><span class=\"token punctuation\">:</span> 大学艺术学院\n <span class=\"token key atrule\">time</span><span class=\"token punctuation\">:</span> 2012<span class=\"token punctuation\">-</span><span class=\"token number\">2016</span>\n\n<span class=\"token key atrule\">workExp</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">inc</span><span class=\"token punctuation\">:</span> 创意研发\n <span class=\"token key atrule\">time</span><span class=\"token punctuation\">:</span> 2021.09 ~ 至今\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">inc</span><span class=\"token punctuation\">:</span> Web设计\n <span class=\"token key atrule\">time</span><span class=\"token punctuation\">:</span> 2021.01 ~ 2021.09\n\n<span class=\"token key atrule\">projectExp</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> PC/React• 标注 ,算法数据中心\n <span class=\"token key atrule\">desc</span><span class=\"token punctuation\">:</span> 这是一个xxx系统。它主要包括一个bc函数。我主要负责x、y和z模块的开发和维护。\n <span class=\"token key atrule\">list</span><span class=\"token punctuation\">:</span> \n <span class=\"token punctuation\">-</span> 使用pnpm工作区管理Monorepo中的多个代码库支持多个框架共存共享通用组件库和功能\n\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> PC/React•Tavigator主动脉根部/外周\n <span class=\"token key atrule\">desc</span><span class=\"token punctuation\">:</span> 这是一个xxx系统。它主要包括一个bc函数。我主要负责x、y和z模块的开发和维护。\n\n\n<span class=\"token key atrule\">portfolio</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> 项目A\n <span class=\"token key atrule\">desc</span><span class=\"token punctuation\">:</span> 项目A描述\n <span class=\"token key atrule\">iconSVG</span><span class=\"token punctuation\">:</span> 复制svg的path到这里\n <span class=\"token key atrule\">link</span><span class=\"token punctuation\">:</span> 网址http(s)<span class=\"token punctuation\">:</span>//<span class=\"token punctuation\">...</span>\n <span class=\"token comment\"># 更多 ...</span>\n<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>","site":{"data":{}},"excerpt":"","more":"<h1 id=\"安装\"><a href=\"#安装\" class=\"headerlink\" title=\"安装\"></a>安装</h1><h2 id=\"使用-npm-安装\"><a href=\"#使用-npm-安装\" class=\"headerlink\" title=\"使用 npm 安装\"></a>使用 npm 安装</h2><p>在主题的根目录</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\">npm i hexo<span class=\"token punctuation\">-</span>theme<span class=\"token punctuation\">-</span>cosy<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>此外,需要新建一个 <code>_config.cosy.yml</code>,同时修改 <code>_config.yml</code></p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">theme</span><span class=\"token punctuation\">:</span> cosy\n\n<span class=\"token key atrule\">algolia</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">appId</span><span class=\"token punctuation\">:</span> 你的\n <span class=\"token key atrule\">apiKey</span><span class=\"token punctuation\">:</span> 你的\n <span class=\"token key atrule\">adminApiKey</span><span class=\"token punctuation\">:</span> 你的\n <span class=\"token key atrule\">SearchOnlyAPIKey</span><span class=\"token punctuation\">:</span> 你的\n <span class=\"token key atrule\">chunkSize</span><span class=\"token punctuation\">:</span> <span class=\"token number\">5000</span>\n <span class=\"token key atrule\">indexName</span><span class=\"token punctuation\">:</span> 你的algolia的index\n <span class=\"token key atrule\">fields</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> content\n <span class=\"token punctuation\">-</span> excerpt<span class=\"token punctuation\">:</span>strip\n <span class=\"token punctuation\">-</span> categories\n <span class=\"token punctuation\">-</span> title\n <span class=\"token punctuation\">-</span> permalink\n <span class=\"token punctuation\">-</span> slug\n <span class=\"token punctuation\">-</span> tags\n <span class=\"token punctuation\">-</span> title<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"传统安装-Hexo-安装主题\"><a href=\"#传统安装-Hexo-安装主题\" class=\"headerlink\" title=\"传统安装 Hexo 安装主题\"></a>传统安装 Hexo 安装主题</h2><p>将主题 <code>Hexo-theme-cosy</code> 文件夹复制目录的 <code>themes</code> 目录下,然后在 <code>Hexo</code> 的 <code>_config.yml</code> 中修改下主题配置即可</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token comment\"># 找到 theme 配置项</span>\n<span class=\"token key atrule\">theme</span><span class=\"token punctuation\">:</span> Hexo<span class=\"token punctuation\">-</span>theme<span class=\"token punctuation\">-</span>cosy<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"获取-Cosy\"><a href=\"#获取-Cosy\" class=\"headerlink\" title=\"获取 Cosy\"></a>获取 Cosy</h2><ul>\n<li>进入 <a href=\"https://github.com/17px/hexo-theme-cosy/tree/main\">Cosy 代码仓库</a>,了解最新的主题开发进度</li>\n<li>在 <a href=\"https://github.com/17px/hexo-theme-cosy/releases\">发布页面</a> 下载 <code>hexo-theme-cosy.zip</code></li>\n<li>解压至站点的 <code>themes</code> 目录下</li>\n<li>在 Hexo 的 <code>_config.yml</code> 中启用</li>\n</ul>\n<h1 id=\"hexo配置\"><a href=\"#hexo配置\" class=\"headerlink\" title=\"hexo配置\"></a>hexo配置</h1><p>在 <code>Hexo</code> 的 <code>_config.yml</code> 中调整</p>\n<h2 id=\"基础配置\"><a href=\"#基础配置\" class=\"headerlink\" title=\"基础配置\"></a>基础配置</h2><pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token comment\"># 网页标题</span>\n<span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 17px blog\n<span class=\"token comment\"># 侧边栏顶部显示</span>\n<span class=\"token key atrule\">subtitle</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Mozzie\"</span>\n<span class=\"token comment\"># 用于SEO的html元描述</span>\n<span class=\"token key atrule\">description</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"\"</span>\n<span class=\"token comment\"># 用于SEO的html关键字</span>\n<span class=\"token key atrule\">keywords</span><span class=\"token punctuation\">:</span>\n<span class=\"token comment\"># 文章版权声明显示作者名称</span>\n<span class=\"token key atrule\">author</span><span class=\"token punctuation\">:</span> Mozzie\n\n<span class=\"token comment\"># 在此处设置您的网站url</span>\n<span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//mozzie.cn<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"语言\"><a href=\"#语言\" class=\"headerlink\" title=\"语言\"></a>语言</h2><p>你可以在 <code>hexo-theme-cosy/languages</code> 中找到不同的语言文件,如果想切换语言,在配置文件中,填入 <code>yml</code> 的文件名</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">language</span><span class=\"token punctuation\">:</span> en<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"文章语法高亮\"><a href=\"#文章语法高亮\" class=\"headerlink\" title=\"文章语法高亮\"></a>文章语法高亮</h2><p>关闭hexo默认的highlight.js语法高亮</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">highlight</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span>\n <span class=\"token key atrule\">line_number</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">auto_detect</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span>\n <span class=\"token key atrule\">tab_replace</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"\"</span>\n <span class=\"token key atrule\">wrap</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">hljs</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span>\n\n<span class=\"token key atrule\">prismjs</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">preprocess</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">line_number</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">line_threshold</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span>\n <span class=\"token key atrule\">tab_replace</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"Cosy-主题配置\"><a href=\"#Cosy-主题配置\" class=\"headerlink\" title=\"Cosy 主题配置\"></a>Cosy 主题配置</h1><p>下面的配置基于 <code>Hexo-theme-cosy</code> 下的 <code>_config.yml</code> </p>\n<h2 id=\"文章分类图标\"><a href=\"#文章分类图标\" class=\"headerlink\" title=\"文章分类图标\"></a>文章分类图标</h2><blockquote>\n<p>可以在 <a href=\"https://www.xicons.org/\">xicon</a> 获取丰富的图标</p>\n</blockquote>\n<p>在<code>主题_config.yml</code>文件中,添加<code>分类名称</code>和<code>图标svg</code>的映射,如值设置为 <code>false</code>,代表不显示该分类</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">category_meta</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">foo</span><span class=\"token punctuation\">:</span> &lt;svg xmlns=\"http<span class=\"token punctuation\">:</span>//www.w3.org/2000/svg\" xmlns<span class=\"token punctuation\">:</span>xlink=\"http<span class=\"token punctuation\">:</span>//www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"<span class=\"token punctuation\">></span>&lt;g fill=\"none\" stroke=\"currentColor\" stroke<span class=\"token punctuation\">-</span>width=\"2\" stroke<span class=\"token punctuation\">-</span>linecap=\"round\" stroke<span class=\"token punctuation\">-</span>linejoin=\"round\"<span class=\"token punctuation\">></span>&lt;path d=\"M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2<span class=\"token punctuation\">-</span>2v<span class=\"token punctuation\">-</span>1\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>&lt;path d=\"M8 16h8\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>&lt;path d=\"M8.322 12.582l7.956.836\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>&lt;path d=\"M8.787 9.168l7.826 1.664\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>&lt;path d=\"M10.096 5.764l7.608 2.472\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>&lt;/g<span class=\"token punctuation\">></span>&lt;/svg<span class=\"token punctuation\">></span>\n <span class=\"token key atrule\">bar</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"网站图标-favicon\"><a href=\"#网站图标-favicon\" class=\"headerlink\" title=\"网站图标 favicon\"></a>网站图标 favicon</h2><ul>\n<li>支持 <code>svg</code></li>\n<li>支持 <code>图片url</code>,如:<code>/img/favicon.png</code></li>\n</ul>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">favicon</span><span class=\"token punctuation\">:</span> <span class=\"token string\">''</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"ICP备案号\"><a href=\"#ICP备案号\" class=\"headerlink\" title=\"ICP备案号\"></a>ICP备案号</h2><p>😁 如不需要备案号,可直接删除</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">icp</span><span class=\"token punctuation\">:</span> 苏ICP备xxxxxxx号<span class=\"token punctuation\">-</span>x<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"首页底部文字\"><a href=\"#首页底部文字\" class=\"headerlink\" title=\"首页底部文字\"></a>首页底部文字</h2><p>😁 如不需要,可直接删除,或者改为 <code>false</code> </p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">motto</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"文章版权申明\"><a href=\"#文章版权申明\" class=\"headerlink\" title=\"文章版权申明\"></a>文章版权申明</h2><p>默认开启,当 <code>enable: false</code>,默认关闭</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">postCopyright</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">license</span><span class=\"token punctuation\">:</span> CC BY<span class=\"token punctuation\">-</span>NC<span class=\"token punctuation\">-</span>SA 4.0\n <span class=\"token key atrule\">license_url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//creativecommons.org/licenses/by<span class=\"token punctuation\">-</span>nc<span class=\"token punctuation\">-</span>sa/4.0/<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"katex-数学公式\"><a href=\"#katex-数学公式\" class=\"headerlink\" title=\"katex 数学公式\"></a>katex 数学公式</h2><p>可自行配置 <code>cdn</code>,全局默认关闭该插件</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">katex</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">jsCdn</span><span class=\"token punctuation\">:</span> //cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.js\n <span class=\"token key atrule\">cssCdn</span><span class=\"token punctuation\">:</span> //cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.css<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>为了加载速度,如果文章需要用到插件,请在文章头部增加,如</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">use</span><span class=\"token punctuation\">:</span> katex</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"mermaid-流程图\"><a href=\"#mermaid-流程图\" class=\"headerlink\" title=\"mermaid 流程图\"></a>mermaid 流程图</h2><p>在撰写时,请使用 <code>&#123;% mermaid %&#125;` 和 `&#123;% endmermaid %&#125;</code> 包裹,全局默认关闭该插件</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\">&#123;% mermaid %&#125;\ngraph TD;\n A --> B;\n A --> C;\n B --> D;\n C --> D;\n&#123;% endmermaid %&#125;<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>相应配置如下</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">mermaid</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 默认使用 neutral可选配置default | dark | forest | neutral</span>\n <span class=\"token key atrule\">theme</span><span class=\"token punctuation\">:</span> neutral\n <span class=\"token key atrule\">cdn</span><span class=\"token punctuation\">:</span> //cdn.jsdelivr.net/npm/mermaid@10.4.0/dist/mermaid.min.js<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>为了加载速度,如果文章需要用到插件,请在文章头部增加,如</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">use</span><span class=\"token punctuation\">:</span> mermaid<span class=\"token punctuation\">,</span>katex<span class=\"token punctuation\">...</span></span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"valine-文章评论\"><a href=\"#valine-文章评论\" class=\"headerlink\" title=\"valine 文章评论\"></a>valine 文章评论</h2><p>首先需要注册 <code>LeanCloud</code> 国际区用户,创建数据库</p>\n<p>请根据相关地区法规,酌情,全局默认关闭该插件</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">valine</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">appId</span><span class=\"token punctuation\">:</span> appId\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">appKey</span><span class=\"token punctuation\">:</span> appKey\n <span class=\"token key atrule\">avatar</span><span class=\"token punctuation\">:</span> monsterid\n <span class=\"token key atrule\">cdn</span><span class=\"token punctuation\">:</span> //unpkg.com/valine@latest/dist/Valine.min.js\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">serverURLs</span><span class=\"token punctuation\">:</span> //xxxxxxxx.api.lncldglobal.com<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>为了加载速度,如果文章需要用到插件,请在文章头部增加,如</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">use</span><span class=\"token punctuation\">:</span> valine<span class=\"token punctuation\">,</span>mermaid<span class=\"token punctuation\">...</span></span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"algolia搜索\"><a href=\"#algolia搜索\" class=\"headerlink\" title=\"algolia搜索\"></a>algolia搜索</h1><p>博客自带的本地搜索,基于前端开发,存在或多或少的问题,建议换成 <code>algolia</code>,免费账户 总共有 <code>10,000</code> 条记录,每月有 <code>100,000</code> 的操作数</p>\n<h2 id=\"关闭搜索\"><a href=\"#关闭搜索\" class=\"headerlink\" title=\"关闭搜索\"></a>关闭搜索</h2><p>主页左侧导航栏不再显示搜索,通知相关资源不会加载,在主题 <code>_config.yml</code> 中:</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">search</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"注册-amp-获取-Key\"><a href=\"#注册-amp-获取-Key\" class=\"headerlink\" title=\"注册 &amp; 获取 Key\"></a>注册 &amp; 获取 Key</h2><ol>\n<li><p>创建一个新的 <code>Index</code>,例如 <code>hex-blog</code></p>\n</li>\n<li><p>复制并保存:</p>\n</li>\n</ol>\n<ul>\n<li>Application ID</li>\n<li>Search-Only API Key</li>\n<li>Admin API Key</li>\n<li>Usage API Key</li>\n</ul>\n<p><img src=\"/img/algolia-api-keys.png\" alt=\"API Keys\"></p>\n<ol start=\"3\">\n<li>替换配置</li>\n</ol>\n<p>在 <code>Hexo</code> 的 <code>_config.yml</code> 中加入</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">algolia</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">appId</span><span class=\"token punctuation\">:</span> Application ID\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">apiKey</span><span class=\"token punctuation\">:</span> Usage API Key\n <span class=\"token comment\"># 请勿泄露,用于上报,替换</span>\n <span class=\"token key atrule\">adminApiKey</span><span class=\"token punctuation\">:</span> Admin API Key\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">SearchOnlyAPIKey</span><span class=\"token punctuation\">:</span> Search<span class=\"token punctuation\">-</span>Only API Key\n <span class=\"token key atrule\">chunkSize</span><span class=\"token punctuation\">:</span> <span class=\"token number\">5000</span>\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">indexName</span><span class=\"token punctuation\">:</span> hex<span class=\"token punctuation\">-</span>blog\n <span class=\"token key atrule\">fields</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> content\n <span class=\"token punctuation\">-</span> excerpt<span class=\"token punctuation\">:</span>strip\n <span class=\"token punctuation\">-</span> categories\n <span class=\"token punctuation\">-</span> title\n <span class=\"token punctuation\">-</span> permalink\n <span class=\"token punctuation\">-</span> slug\n <span class=\"token punctuation\">-</span> tags\n <span class=\"token punctuation\">-</span> title<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"安装-hexo-algoliasearch-next\"><a href=\"#安装-hexo-algoliasearch-next\" class=\"headerlink\" title=\"安装 hexo-algoliasearch-next\"></a>安装 hexo-algoliasearch-next</h2><p>这是 Hexo 博客帖子索引插件,自动化提交索引到 Algolia</p>\n<blockquote>\n<p>如出遇到问题,可阅读 <a href=\"https://github.com/Becavalier/hexo-algoliasearch-next\">hexo-algoliasearch-next 仓库</a> 最新说明</p>\n</blockquote>\n<p>安装命令:</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> hexo-algoliasearch-next <span class=\"token parameter variable\">--save</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"使用-algolia\"><a href=\"#使用-algolia\" class=\"headerlink\" title=\"使用 algolia\"></a>使用 algolia</h2><p>在每次博客发布之前,进行索引上传的操作,命令通常如下</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">hexo clean\nhexo generate\nhexo algolia<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n\n<h1 id=\"🇨🇳-和风天气-Widget\"><a href=\"#🇨🇳-和风天气-Widget\" class=\"headerlink\" title=\"🇨🇳 和风天气 Widget\"></a>🇨🇳 和风天气 Widget</h1><p>Cosy 主要针对国内用户,在首页集成了和风天气的卡片,通过 <a href=\"https://dev.qweather.com/docs/start/\">和风天气开发服务</a> 注册</p>\n<p>注册完成后,在配置中填入你的 <code>appKey</code> 和 <code>cityCode(城市代码)</code></p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">weather</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token comment\"># 替换</span>\n <span class=\"token key atrule\">cityCode</span><span class=\"token punctuation\">:</span> cityCode\n <span class=\"token key atrule\">appKey</span><span class=\"token punctuation\">:</span> appKey<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>其中 <code>cityCode</code> 可以在 <a href=\"https://github.com/qwd/LocationList\">官方的地区列表仓库</a> 中的 <code>China-City-List-latest.csv</code> 找到你所在城市的 <code>cityCode</code></p>\n<h1 id=\"前置元数据\"><a href=\"#前置元数据\" class=\"headerlink\" title=\"前置元数据\"></a>前置元数据</h1><p>在 Hexo 的 Markdown 文件中,一个典型的 YAML 格式的 <code>Front Matter</code> 可能会是这样的:</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 我的文章标题\n<span class=\"token key atrule\">categories</span><span class=\"token punctuation\">:</span>\n<span class=\"token punctuation\">-</span> javascript\n<span class=\"token key atrule\">tags</span><span class=\"token punctuation\">:</span> \n<span class=\"token punctuation\">-</span> 编程\n<span class=\"token punctuation\">-</span> JavaScript</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"top\"><a href=\"#top\" class=\"headerlink\" title=\"top\"></a>top</h2><p>实现文章置顶的功能,给定一个数值,可以进行排序,设定了 <code>top</code> 元数据的文章,会在分类列表中,使用 📌 标记</p>\n<p>例如有三篇文章:</p>\n<ul>\n<li>文章1</li>\n</ul>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 文章1\n<span class=\"token key atrule\">top</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span>\n<span class=\"token key atrule\">categories</span><span class=\"token punctuation\">:</span>\n<span class=\"token punctuation\">-</span> javascript\n<span class=\"token key atrule\">tags</span><span class=\"token punctuation\">:</span> \n<span class=\"token punctuation\">-</span> 编程\n<span class=\"token punctuation\">-</span> JavaScript</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<ul>\n<li>文章2</li>\n</ul>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 文章2\n<span class=\"token key atrule\">top</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1</span>\n<span class=\"token key atrule\">categories</span><span class=\"token punctuation\">:</span>\n<span class=\"token punctuation\">-</span> javascript\n<span class=\"token key atrule\">tags</span><span class=\"token punctuation\">:</span> \n<span class=\"token punctuation\">-</span> 编程\n<span class=\"token punctuation\">-</span> JavaScript</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<ul>\n<li>文章3</li>\n</ul>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 文章3\n<span class=\"token key atrule\">categories</span><span class=\"token punctuation\">:</span>\n<span class=\"token punctuation\">-</span> javascript\n<span class=\"token key atrule\">tags</span><span class=\"token punctuation\">:</span> \n<span class=\"token punctuation\">-</span> 编程\n<span class=\"token punctuation\">-</span> JavaScript</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>那么在 <code>javascript</code> 分类下,排序的顺序依次为:<code>文章1 &gt; 文章2 &gt; 文章3</code></p>\n<h2 id=\"status\"><a href=\"#status\" class=\"headerlink\" title=\"status\"></a>status</h2><p>用于区分文章的状态,同时利用文章分类列表的<code>筛选</code>进行快速筛选Cosy 主题内置了 4 种状态</p>\n<ul>\n<li>done完成</li>\n<li>doing进行中</li>\n<li>todo待办</li>\n<li>other废弃</li>\n</ul>\n<p>例如:</p>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 文章1\n<span class=\"token key atrule\">categories</span><span class=\"token punctuation\">:</span>\n<span class=\"token punctuation\">-</span> javascript\n<span class=\"token key atrule\">status</span><span class=\"token punctuation\">:</span> done</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"自定义页面\"><a href=\"#自定义页面\" class=\"headerlink\" title=\"自定义页面\"></a>自定义页面</h1><p>Hexo 使用 Markdown或其他渲染引擎解析你的文章并生成静态文件以快速加载。除了默认生成的文章和归档页面之外Hexo 还允许你创建自定义页面。</p>\n<h2 id=\"基本配置\"><a href=\"#基本配置\" class=\"headerlink\" title=\"基本配置\"></a>基本配置</h2><p>可以通过配置 <code>nav_meta</code> 属性关闭页面、更改图标</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">nav_meta</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 不显示 timeline页面</span>\n <span class=\"token key atrule\">timeline</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span>\n <span class=\"token comment\"># 自定义图标</span>\n <span class=\"token key atrule\">roadmap</span><span class=\"token punctuation\">:</span>\n &lt;svg xmlns=\"http<span class=\"token punctuation\">:</span>//www.w3.org/2000/svg\" xmlns<span class=\"token punctuation\">:</span>xlink=\"http<span class=\"token punctuation\">:</span>//www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"<span class=\"token punctuation\">></span>\n &lt;g fill=\"none\" stroke=\"currentColor\" stroke<span class=\"token punctuation\">-</span>width=\"2\" stroke<span class=\"token punctuation\">-</span>linecap=\"round\" stroke<span class=\"token punctuation\">-</span>linejoin=\"round\"<span class=\"token punctuation\">></span>\n &lt;path d=\"M10.5 20.4l<span class=\"token punctuation\">-</span>6.9<span class=\"token punctuation\">-</span>6.9c<span class=\"token punctuation\">-</span>.781<span class=\"token punctuation\">-</span>.781<span class=\"token punctuation\">-</span>.781<span class=\"token punctuation\">-</span>2.219 0<span class=\"token punctuation\">-</span>3l6.9<span class=\"token punctuation\">-</span>6.9c.781<span class=\"token punctuation\">-</span>.781 2.219<span class=\"token punctuation\">-</span>.781 3 0l6.9 6.9c.781.781.781 2.219 0 3l<span class=\"token punctuation\">-</span>6.9 6.9c<span class=\"token punctuation\">-</span>.781.781<span class=\"token punctuation\">-</span>2.219.781<span class=\"token punctuation\">-</span>3 0z\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;path d=\"M9 14v<span class=\"token punctuation\">-</span>2c0<span class=\"token punctuation\">-</span>.59.414<span class=\"token punctuation\">-</span>1 1<span class=\"token punctuation\">-</span>1h5\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;path d=\"M13 9l2 2l<span class=\"token punctuation\">-</span>2 2\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;/g<span class=\"token punctuation\">></span>\n &lt;/svg<span class=\"token punctuation\">></span>\n <span class=\"token key atrule\">resume</span><span class=\"token punctuation\">:</span>\n &lt;svg xmlns=\"http<span class=\"token punctuation\">:</span>//www.w3.org/2000/svg\" xmlns<span class=\"token punctuation\">:</span>xlink=\"http<span class=\"token punctuation\">:</span>//www.w3.org/1999/xlink\" viewBox=\"0 0 24 24\"<span class=\"token punctuation\">></span>\n &lt;g fill=\"none\" stroke=\"currentColor\" stroke<span class=\"token punctuation\">-</span>width=\"2\" stroke<span class=\"token punctuation\">-</span>linecap=\"round\" stroke<span class=\"token punctuation\">-</span>linejoin=\"round\"<span class=\"token punctuation\">></span>\n &lt;path d=\"M14 3v4a1 1 0 0 0 1 1h4\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;path d=\"M5 8V5a2 2 0 0 1 2<span class=\"token punctuation\">-</span>2h7l5 5v11a2 2 0 0 1<span class=\"token punctuation\">-</span>2 2h<span class=\"token punctuation\">-</span>5\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;circle cx=\"6\" cy=\"14\" r=\"3\"<span class=\"token punctuation\">></span>&lt;/circle<span class=\"token punctuation\">></span>\n &lt;path d=\"M4.5 17L3 22l3<span class=\"token punctuation\">-</span>1.5L9 22l<span class=\"token punctuation\">-</span>1.5<span class=\"token punctuation\">-</span>5\"<span class=\"token punctuation\">></span>&lt;/path<span class=\"token punctuation\">></span>\n &lt;/g<span class=\"token punctuation\">></span>\n &lt;/svg<span class=\"token punctuation\">></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"Roadmap路线图\"><a href=\"#Roadmap路线图\" class=\"headerlink\" title=\"Roadmap路线图\"></a>Roadmap路线图</h2><p>创建页面,你可以使用命令</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">hexo new page roadmap<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>成功后在 <code>source/</code> 文件夹下会生成一个新的文件夹 <code>/roadmap/index.md</code></p>\n<p>你可以参照此模板,进行配置,参数说明:</p>\n<ul>\n<li>title: roadmap页面 html 的标题</li>\n<li>initYear: 默认显示的年份</li>\n</ul>\n<pre class=\"line-numbers language-markdown\" data-language=\"markdown\"><code class=\"language-markdown\"><span class=\"token front-matter-block\"><span class=\"token punctuation\">---</span>\n<span class=\"token front-matter yaml language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 陈不渡 <span class=\"token punctuation\">-</span> roadmap\n<span class=\"token key atrule\">layout</span><span class=\"token punctuation\">:</span> roadmap\n<span class=\"token key atrule\">initYear</span><span class=\"token punctuation\">:</span> <span class=\"token number\">2023</span>\n<span class=\"token key atrule\">years</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">2022</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 读书\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 01<span class=\"token punctuation\">-</span><span class=\"token number\">01</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 1<span class=\"token punctuation\">-</span><span class=\"token number\">5</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 还是读书\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 02<span class=\"token punctuation\">-</span><span class=\"token number\">01</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 05<span class=\"token punctuation\">-</span><span class=\"token number\">30</span>\n <span class=\"token key atrule\">2023</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 越陌度阡\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 01<span class=\"token punctuation\">-</span><span class=\"token number\">01</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 1<span class=\"token punctuation\">-</span><span class=\"token number\">2</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 枉用相存\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 02<span class=\"token punctuation\">-</span><span class=\"token number\">01</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 06<span class=\"token punctuation\">-</span><span class=\"token number\">30</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 短歌行\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 10<span class=\"token punctuation\">-</span><span class=\"token number\">26</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 10<span class=\"token punctuation\">-</span><span class=\"token number\">31</span>\n <span class=\"token key atrule\">content</span><span class=\"token punctuation\">:</span> 对酒当歌,人生几何!譬如朝露,去日苦多。慨当以慷,忧思难忘。何以解忧?唯有杜康。青青子衿,悠悠我心。但为君故,沉吟至今。呦呦鹿鸣,食野之苹。\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 声律启蒙\n <span class=\"token key atrule\">start</span><span class=\"token punctuation\">:</span> 11<span class=\"token punctuation\">-</span><span class=\"token number\">01</span>\n <span class=\"token key atrule\">end</span><span class=\"token punctuation\">:</span> 11<span class=\"token punctuation\">-</span><span class=\"token number\">31</span>\n <span class=\"token key atrule\">content</span><span class=\"token punctuation\">:</span> 花开红锦绣,水漾碧琉璃。去妇因探邻舍枣,出妻为种后园葵</span>\n<span class=\"token punctuation\">---</span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"Resume简历页面\"><a href=\"#Resume简历页面\" class=\"headerlink\" title=\"Resume简历页面\"></a>Resume简历页面</h2><p>创建页面,你可以使用命令</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">hexo new page resume<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>成功后在 <code>source/</code> 文件夹下会生成一个新的文件夹 <code>/resume/index.md</code></p>\n<p>你可以参照此模板,进行配置,参数说明:</p>\n<ul>\n<li>title: resume 页面 html 的标题</li>\n<li>avatar: 头像图片的地址</li>\n</ul>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> 页面标题document.title\n<span class=\"token key atrule\">layout</span><span class=\"token punctuation\">:</span> resume\n<span class=\"token key atrule\">avatar</span><span class=\"token punctuation\">:</span> /img/avatar.png\n<span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Hi<span class=\"token tag\">!</span> Mozzie\n<span class=\"token key atrule\">role</span><span class=\"token punctuation\">:</span> Full Stack\n<span class=\"token key atrule\">email</span><span class=\"token punctuation\">:</span> himozzie@gmail.com\n<span class=\"token key atrule\">phone</span><span class=\"token punctuation\">:</span> +86 180<span class=\"token punctuation\">-</span>xxxx<span class=\"token punctuation\">-</span>xxx\n<span class=\"token key atrule\">birth</span><span class=\"token punctuation\">:</span> Jan 21<span class=\"token punctuation\">,</span> <span class=\"token number\">1994</span>\n<span class=\"token key atrule\">location</span><span class=\"token punctuation\">:</span> Nanjing<span class=\"token punctuation\">,</span> China\n<span class=\"token key atrule\">social</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> github\n <span class=\"token key atrule\">link</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//github.com/17px\n <span class=\"token key atrule\">icon</span><span class=\"token punctuation\">:</span> svg\n\n<span class=\"token key atrule\">about</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> 我的工作是建立你的网站,使其功能强大,用户友好,但同时具有吸引力。\n <span class=\"token punctuation\">-</span> 此外,我为您的产品添加了个人风格,并确保其引人注目且易于使用。我的目标是以最有创意的方式传达你的信息和身份。我为许多知名品牌公司设计网页。\n\n<span class=\"token key atrule\">skill</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> 熟悉Node具备后端开发能力有SpringBoot、Egg、Koa2、Midway等单个应用项目经验有Nestjs微服务应用项目经验\n <span class=\"token punctuation\">-</span> 具有Monoreo工程经验能够分离单个单元的前端和后端并应用DevOps\n\n<span class=\"token key atrule\">education</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">school</span><span class=\"token punctuation\">:</span> 大学艺术学院\n <span class=\"token key atrule\">time</span><span class=\"token punctuation\">:</span> 2012<span class=\"token punctuation\">-</span><span class=\"token number\">2016</span>\n\n<span class=\"token key atrule\">workExp</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">inc</span><span class=\"token punctuation\">:</span> 创意研发\n <span class=\"token key atrule\">time</span><span class=\"token punctuation\">:</span> 2021.09 ~ 至今\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">inc</span><span class=\"token punctuation\">:</span> Web设计\n <span class=\"token key atrule\">time</span><span class=\"token punctuation\">:</span> 2021.01 ~ 2021.09\n\n<span class=\"token key atrule\">projectExp</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> PC/React• 标注 ,算法数据中心\n <span class=\"token key atrule\">desc</span><span class=\"token punctuation\">:</span> 这是一个xxx系统。它主要包括一个bc函数。我主要负责x、y和z模块的开发和维护。\n <span class=\"token key atrule\">list</span><span class=\"token punctuation\">:</span> \n <span class=\"token punctuation\">-</span> 使用pnpm工作区管理Monorepo中的多个代码库支持多个框架共存共享通用组件库和功能\n\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> PC/React•Tavigator主动脉根部/外周\n <span class=\"token key atrule\">desc</span><span class=\"token punctuation\">:</span> 这是一个xxx系统。它主要包括一个bc函数。我主要负责x、y和z模块的开发和维护。\n\n\n<span class=\"token key atrule\">portfolio</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> 项目A\n <span class=\"token key atrule\">desc</span><span class=\"token punctuation\">:</span> 项目A描述\n <span class=\"token key atrule\">iconSVG</span><span class=\"token punctuation\">:</span> 复制svg的path到这里\n <span class=\"token key atrule\">link</span><span class=\"token punctuation\">:</span> 网址http(s)<span class=\"token punctuation\">:</span>//<span class=\"token punctuation\">...</span>\n <span class=\"token comment\"># 更多 ...</span>\n<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>"},{"title":"Markdown Sample","description":"A very simple way to add structured data to a page.","status":"done","top":0,"keywords":"Markdown, 代码高亮 (Codes), 引用 (Blockquotes), 列表 (Lists), 图片 (Images), 表格 (Tables), Emoji, TeX(KaTeX), 流程图 (mermaid)","use":"mermaid,katex,valine","_content":"\n# Linear Markdown Sample\n\n![markdown](https://pandao.github.io/editor.md/images/logos/editormd-logo-180x180.png)\n\n\n# Heading 1 link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n## Heading 2 link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n### Heading 3 link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n#### Heading 4 link [Heading link](https://github.com/pandao/editor.md \"Heading link\") Heading link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n##### Heading 5 link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n###### Heading 6 link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n\n\n\n# 字符效果和横线等\n \n----\n\n~~删除线~~ <s>删除线开启识别HTML标签时</s>\n*斜体字* _斜体字_\n**粗体** __粗体__\n***粗斜体*** ___粗斜体___\n\n上标X<sub>2</sub>下标O<sup>2</sup>\n\n**缩写(同HTML的abbr标签)**\n\n> 即更长的单词或短语的缩写形式前提是开启识别HTML标签时已默认开启\n\nThe <abbr title=\"Hyper Text Markup Language\">HTML</abbr> specification is maintained by the <abbr title=\"World Wide Web Consortium\">W3C</abbr>.\n\n# 引用 Blockquotes\n\n> 引用文本 Blockquotes\n\n引用的行内混合 Blockquotes\n \n> 引用:如果想要插入空白换行`即<br />标签`,在插入处先键入两个以上的空格然后回车即可,[普通链接](http://localhost/)。\n\n# 锚点与链接 Links\n\n[普通链接](http://localhost/)\n\n[普通链接带标题](http://localhost/ \"普通链接带标题\")\n\n直接链接<https://github.com>\n\nhttps://baidu.com\n\n[锚点链接][anchor-id] \n\n[anchor-id]: http://www.this-anchor-link.com/\n\n[mailto:test.test@gmail.com](mailto:test.test@gmail.com)\n\nGFM a-tail link [@pandao](https://my.oschina.net/u/3691274) 邮箱地址自动链接 test.test@gmail.com www@vip.qq.com\n\n> @pandao\n\n# 多语言代码高亮 Codes\n\n## 行内代码 Inline code\n\n执行命令`npm install marked`\n\n## JS代码 \n\n```javascript\nfunction test() {\n\tconsole.log(\"Hello world!\");\n}\n \n(function(){\n var box = function() {\n return box.fn.init();\n };\n\n box.prototype = box.fn = {\n init : function(){\n console.log('box.init()');\n\n\t\t\treturn this;\n },\n\n\t\tadd : function(str) {\n\t\t\talert(\"add\", str);\n\n\t\t\treturn this;\n\t\t},\n\n\t\tremove : function(str) {\n\t\t\talert(\"remove\", str);\n\n\t\t\treturn this;\n\t\t}\n };\n \n box.fn.init.prototype = box.fn;\n \n window.box =box;\n})();\n\nvar testBox = box();\ntestBox.add(\"jQuery\").remove(\"jQuery\");\n```\n\n## HTML 代码 HTML codes\n\n```html\n<!DOCTYPE html>\n<html>\n <head>\n <mate charest=\"utf-8\" />\n <meta name=\"keywords\" content=\"Editor.md, Markdown, Editor\" />\n <title>Hello world!</title>\n <style type=\"text/css\">\n body{font-size:14px;color:#444;font-family: \"Microsoft Yahei\", Tahoma, \"Hiragino Sans GB\", Arial;background:#fff;}\n ul{list-style: none;}\n img{border:none;vertical-align: middle;}\n </style>\n </head>\n <body>\n <h1 class=\"text-xxl\">Hello world!</h1>\n <p class=\"text-green\">Plain text</p>\n </body>\n</html>\n```\n\n# 图片 Images\n\nImage:\n\n![](https://pandao.github.io/editor.md/examples/images/4.jpg)\n\n> Follow your heart.\n\n![](https://pandao.github.io/editor.md/examples/images/8.jpg)\n\n> 图为:厦门白城沙滩\n\n图片加链接 (Image + Link)\n\n[![](https://pandao.github.io/editor.md/examples/images/7.jpg)](https://pandao.github.io/editor.md/images/7.jpg \"李健首张专辑《似水流年》封面\")\n\n> 图为:李健首张专辑《似水流年》封面\n \n----\n\n# 列表 Lists\n\n## 无序列表减号Unordered Lists (-)\n \n- 列表一\n- 列表二\n- 列表三\n \n## 无序列表星号Unordered Lists (*)\n\n* 列表一\n* 列表二\n* 列表三\n\n## 无序列表加号和嵌套Unordered Lists (+)\n \n+ 列表一\n+ 列表二\n + 列表二-1\n + 列表二-2\n + 列表二-3\n+ 列表三\n * 列表一\n * 列表二\n * 列表三\n\n## 有序列表 Ordered Lists (-)\n \n1. 第一行\n2. 第二行\n3. 第三行\n\n## GFM task list\n\n- [x] GFM task list 1\n- [x] GFM task list 2\n- [ ] GFM task list 3\n - [ ] GFM task list 3-1\n - [ ] GFM task list 3-2\n - [ ] GFM task list 3-3\n- [ ] GFM task list 4\n - [ ] GFM task list 4-1\n - [ ] GFM task list 4-2\n \n----\n \n# 绘制表格 Tables\n\n| 项目 | 价格 | 数量 |\n| ------ | ----: | :---: |\n| 计算机 | $1600 | 5 |\n| 手机 | $12 | 12 |\n| 管线 | $1 | 234 |\n \n| First Header | Second Header |\n| ------------ | ------------- |\n| Content Cell | Content Cell |\n| Content Cell | Content Cell |\n\n| First Header | Second Header |\n| ------------ | ------------- |\n| Content Cell | Content Cell |\n| Content Cell | Content Cell |\n\n| Function name | Description |\n| ------------- | -------------------------- |\n| `help()` | Display the help window. |\n| `destroy()` | **Destroy your computer!** |\n\n| Left-Aligned | Center Aligned | Right Aligned |\n| :------------ | :-------------: | ------------: |\n| col 3 is | some wordy text | $1600 |\n| col 2 is | centered | $12 |\n| zebra stripes | are neat | $1 |\n\n| Item | Value |\n| -------- | ----: |\n| Computer | $1600 |\n| Phone | $12 |\n| Pipe | $1 |\n \n# 科学公式 TeX(KaTeX)\n\n$$E=mc^2$$\n\n$$x > y$$\n\n$$\\(\\sqrt{3x-1}+(1+x)^2\\)$$\n \n$$\\sin(\\alpha)^{\\theta}=\\sum_{i=0}^{n}(x^i + \\cos(f))$$\n\n\n# 绘制流程图 mermaid\n\n{% mermaid %}\ngraph TD;\n A --> B;\n A --> C;\n B --> D;\n C --> D;\n{% endmermaid %}\n\n \n \nEnd","source":"_posts/Markdown Sample.md","raw":"---\ntitle: Markdown Sample\ndescription: A very simple way to add structured data to a page.\nstatus: done\ntop: 0\ncategories: \n- Hexo\nkeywords: \"Markdown, 代码高亮 (Codes), 引用 (Blockquotes), 列表 (Lists), 图片 (Images), 表格 (Tables), Emoji, TeX(KaTeX), 流程图 (mermaid)\"\nuse: mermaid,katex,valine\n---\n\n# Linear Markdown Sample\n\n![markdown](https://pandao.github.io/editor.md/images/logos/editormd-logo-180x180.png)\n\n\n# Heading 1 link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n## Heading 2 link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n### Heading 3 link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n#### Heading 4 link [Heading link](https://github.com/pandao/editor.md \"Heading link\") Heading link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n##### Heading 5 link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n###### Heading 6 link [Heading link](https://github.com/pandao/editor.md \"Heading link\")\n\n\n\n# 字符效果和横线等\n \n----\n\n~~删除线~~ <s>删除线开启识别HTML标签时</s>\n*斜体字* _斜体字_\n**粗体** __粗体__\n***粗斜体*** ___粗斜体___\n\n上标X<sub>2</sub>下标O<sup>2</sup>\n\n**缩写(同HTML的abbr标签)**\n\n> 即更长的单词或短语的缩写形式前提是开启识别HTML标签时已默认开启\n\nThe <abbr title=\"Hyper Text Markup Language\">HTML</abbr> specification is maintained by the <abbr title=\"World Wide Web Consortium\">W3C</abbr>.\n\n# 引用 Blockquotes\n\n> 引用文本 Blockquotes\n\n引用的行内混合 Blockquotes\n \n> 引用:如果想要插入空白换行`即<br />标签`,在插入处先键入两个以上的空格然后回车即可,[普通链接](http://localhost/)。\n\n# 锚点与链接 Links\n\n[普通链接](http://localhost/)\n\n[普通链接带标题](http://localhost/ \"普通链接带标题\")\n\n直接链接<https://github.com>\n\nhttps://baidu.com\n\n[锚点链接][anchor-id] \n\n[anchor-id]: http://www.this-anchor-link.com/\n\n[mailto:test.test@gmail.com](mailto:test.test@gmail.com)\n\nGFM a-tail link [@pandao](https://my.oschina.net/u/3691274) 邮箱地址自动链接 test.test@gmail.com www@vip.qq.com\n\n> @pandao\n\n# 多语言代码高亮 Codes\n\n## 行内代码 Inline code\n\n执行命令`npm install marked`\n\n## JS代码 \n\n```javascript\nfunction test() {\n\tconsole.log(\"Hello world!\");\n}\n \n(function(){\n var box = function() {\n return box.fn.init();\n };\n\n box.prototype = box.fn = {\n init : function(){\n console.log('box.init()');\n\n\t\t\treturn this;\n },\n\n\t\tadd : function(str) {\n\t\t\talert(\"add\", str);\n\n\t\t\treturn this;\n\t\t},\n\n\t\tremove : function(str) {\n\t\t\talert(\"remove\", str);\n\n\t\t\treturn this;\n\t\t}\n };\n \n box.fn.init.prototype = box.fn;\n \n window.box =box;\n})();\n\nvar testBox = box();\ntestBox.add(\"jQuery\").remove(\"jQuery\");\n```\n\n## HTML 代码 HTML codes\n\n```html\n<!DOCTYPE html>\n<html>\n <head>\n <mate charest=\"utf-8\" />\n <meta name=\"keywords\" content=\"Editor.md, Markdown, Editor\" />\n <title>Hello world!</title>\n <style type=\"text/css\">\n body{font-size:14px;color:#444;font-family: \"Microsoft Yahei\", Tahoma, \"Hiragino Sans GB\", Arial;background:#fff;}\n ul{list-style: none;}\n img{border:none;vertical-align: middle;}\n </style>\n </head>\n <body>\n <h1 class=\"text-xxl\">Hello world!</h1>\n <p class=\"text-green\">Plain text</p>\n </body>\n</html>\n```\n\n# 图片 Images\n\nImage:\n\n![](https://pandao.github.io/editor.md/examples/images/4.jpg)\n\n> Follow your heart.\n\n![](https://pandao.github.io/editor.md/examples/images/8.jpg)\n\n> 图为:厦门白城沙滩\n\n图片加链接 (Image + Link)\n\n[![](https://pandao.github.io/editor.md/examples/images/7.jpg)](https://pandao.github.io/editor.md/images/7.jpg \"李健首张专辑《似水流年》封面\")\n\n> 图为:李健首张专辑《似水流年》封面\n \n----\n\n# 列表 Lists\n\n## 无序列表减号Unordered Lists (-)\n \n- 列表一\n- 列表二\n- 列表三\n \n## 无序列表星号Unordered Lists (*)\n\n* 列表一\n* 列表二\n* 列表三\n\n## 无序列表加号和嵌套Unordered Lists (+)\n \n+ 列表一\n+ 列表二\n + 列表二-1\n + 列表二-2\n + 列表二-3\n+ 列表三\n * 列表一\n * 列表二\n * 列表三\n\n## 有序列表 Ordered Lists (-)\n \n1. 第一行\n2. 第二行\n3. 第三行\n\n## GFM task list\n\n- [x] GFM task list 1\n- [x] GFM task list 2\n- [ ] GFM task list 3\n - [ ] GFM task list 3-1\n - [ ] GFM task list 3-2\n - [ ] GFM task list 3-3\n- [ ] GFM task list 4\n - [ ] GFM task list 4-1\n - [ ] GFM task list 4-2\n \n----\n \n# 绘制表格 Tables\n\n| 项目 | 价格 | 数量 |\n| ------ | ----: | :---: |\n| 计算机 | $1600 | 5 |\n| 手机 | $12 | 12 |\n| 管线 | $1 | 234 |\n \n| First Header | Second Header |\n| ------------ | ------------- |\n| Content Cell | Content Cell |\n| Content Cell | Content Cell |\n\n| First Header | Second Header |\n| ------------ | ------------- |\n| Content Cell | Content Cell |\n| Content Cell | Content Cell |\n\n| Function name | Description |\n| ------------- | -------------------------- |\n| `help()` | Display the help window. |\n| `destroy()` | **Destroy your computer!** |\n\n| Left-Aligned | Center Aligned | Right Aligned |\n| :------------ | :-------------: | ------------: |\n| col 3 is | some wordy text | $1600 |\n| col 2 is | centered | $12 |\n| zebra stripes | are neat | $1 |\n\n| Item | Value |\n| -------- | ----: |\n| Computer | $1600 |\n| Phone | $12 |\n| Pipe | $1 |\n \n# 科学公式 TeX(KaTeX)\n\n$$E=mc^2$$\n\n$$x > y$$\n\n$$\\(\\sqrt{3x-1}+(1+x)^2\\)$$\n \n$$\\sin(\\alpha)^{\\theta}=\\sum_{i=0}^{n}(x^i + \\cos(f))$$\n\n\n# 绘制流程图 mermaid\n\n{% mermaid %}\ngraph TD;\n A --> B;\n A --> C;\n B --> D;\n C --> D;\n{% endmermaid %}\n\n \n \nEnd","slug":"Markdown Sample","published":1,"date":"2023-10-23T04:01:13.108Z","updated":"2023-11-08T02:08:01.242Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58l00054cz36gn8061p","content":"<h1 id=\"Linear-Markdown-Sample\"><a href=\"#Linear-Markdown-Sample\" class=\"headerlink\" title=\"Linear Markdown Sample\"></a>Linear Markdown Sample</h1><p><img src=\"https://pandao.github.io/editor.md/images/logos/editormd-logo-180x180.png\" alt=\"markdown\"></p>\n<h1 id=\"Heading-1-link-Heading-link\"><a href=\"#Heading-1-link-Heading-link\" class=\"headerlink\" title=\"Heading 1 link Heading link\"></a>Heading 1 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h1><h2 id=\"Heading-2-link-Heading-link\"><a href=\"#Heading-2-link-Heading-link\" class=\"headerlink\" title=\"Heading 2 link Heading link\"></a>Heading 2 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h2><h3 id=\"Heading-3-link-Heading-link\"><a href=\"#Heading-3-link-Heading-link\" class=\"headerlink\" title=\"Heading 3 link Heading link\"></a>Heading 3 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h3><h4 id=\"Heading-4-link-Heading-link-Heading-link-Heading-link\"><a href=\"#Heading-4-link-Heading-link-Heading-link-Heading-link\" class=\"headerlink\" title=\"Heading 4 link Heading link Heading link Heading link\"></a>Heading 4 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a> Heading link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h4><h5 id=\"Heading-5-link-Heading-link\"><a href=\"#Heading-5-link-Heading-link\" class=\"headerlink\" title=\"Heading 5 link Heading link\"></a>Heading 5 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h5><h6 id=\"Heading-6-link-Heading-link\"><a href=\"#Heading-6-link-Heading-link\" class=\"headerlink\" title=\"Heading 6 link Heading link\"></a>Heading 6 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h6><h1 id=\"字符效果和横线等\"><a href=\"#字符效果和横线等\" class=\"headerlink\" title=\"字符效果和横线等\"></a>字符效果和横线等</h1><hr>\n<p><del>删除线</del> <s>删除线开启识别HTML标签时</s><br><em>斜体字</em> <em>斜体字</em><br><strong>粗体</strong> <strong>粗体</strong><br><em><strong>粗斜体</strong></em> <em><strong>粗斜体</strong></em></p>\n<p>上标X<sub>2</sub>下标O<sup>2</sup></p>\n<p><strong>缩写(同HTML的abbr标签)</strong></p>\n<blockquote>\n<p>即更长的单词或短语的缩写形式前提是开启识别HTML标签时已默认开启</p>\n</blockquote>\n<p>The <abbr title=\"Hyper Text Markup Language\">HTML</abbr> specification is maintained by the <abbr title=\"World Wide Web Consortium\">W3C</abbr>.</p>\n<h1 id=\"引用-Blockquotes\"><a href=\"#引用-Blockquotes\" class=\"headerlink\" title=\"引用 Blockquotes\"></a>引用 Blockquotes</h1><blockquote>\n<p>引用文本 Blockquotes</p>\n</blockquote>\n<p>引用的行内混合 Blockquotes</p>\n<blockquote>\n<p>引用:如果想要插入空白换行<code>即&lt;br /&gt;标签</code>,在插入处先键入两个以上的空格然后回车即可,<a href=\"http://localhost/\">普通链接</a>。</p>\n</blockquote>\n<h1 id=\"锚点与链接-Links\"><a href=\"#锚点与链接-Links\" class=\"headerlink\" title=\"锚点与链接 Links\"></a>锚点与链接 Links</h1><p><a href=\"http://localhost/\">普通链接</a></p>\n<p><a href=\"http://localhost/\" title=\"普通链接带标题\">普通链接带标题</a></p>\n<p>直接链接:<a href=\"https://github.com/\">https://github.com</a></p>\n<p><a href=\"https://baidu.com/\">https://baidu.com</a></p>\n<p><a href=\"http://www.this-anchor-link.com/\">锚点链接</a> </p>\n<p><a href=\"mailto:test.test@gmail.com\">mailto:test.test@gmail.com</a></p>\n<p>GFM a-tail link <a href=\"https://my.oschina.net/u/3691274\">@pandao</a> 邮箱地址自动链接 <a href=\"mailto:&#x74;&#x65;&#x73;&#116;&#x2e;&#x74;&#101;&#x73;&#x74;&#64;&#103;&#109;&#x61;&#105;&#x6c;&#46;&#x63;&#111;&#x6d;\">&#x74;&#x65;&#x73;&#116;&#x2e;&#x74;&#101;&#x73;&#x74;&#64;&#103;&#109;&#x61;&#105;&#x6c;&#46;&#x63;&#111;&#x6d;</a> <a href=\"mailto:&#119;&#119;&#119;&#x40;&#118;&#105;&#112;&#x2e;&#113;&#113;&#x2e;&#99;&#x6f;&#109;\">&#119;&#119;&#119;&#x40;&#118;&#105;&#112;&#x2e;&#113;&#113;&#x2e;&#99;&#x6f;&#109;</a></p>\n<blockquote>\n<p>@pandao</p>\n</blockquote>\n<h1 id=\"多语言代码高亮-Codes\"><a href=\"#多语言代码高亮-Codes\" class=\"headerlink\" title=\"多语言代码高亮 Codes\"></a>多语言代码高亮 Codes</h1><h2 id=\"行内代码-Inline-code\"><a href=\"#行内代码-Inline-code\" class=\"headerlink\" title=\"行内代码 Inline code\"></a>行内代码 Inline code</h2><p>执行命令:<code>npm install marked</code></p>\n<h2 id=\"JS代码\"><a href=\"#JS代码\" class=\"headerlink\" title=\"JS代码\"></a>JS代码</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n\tconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello world!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n \n<span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> <span class=\"token function-variable function\">box</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> box<span class=\"token punctuation\">.</span>fn<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\n box<span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> box<span class=\"token punctuation\">.</span>fn <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">init</span> <span class=\"token operator\">:</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'box.init()'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\t\t\t<span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n\n\t\t<span class=\"token function-variable function\">add</span> <span class=\"token operator\">:</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">str</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n\t\t\t<span class=\"token function\">alert</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"add\"</span><span class=\"token punctuation\">,</span> str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\t\t\t<span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n\n\t\t<span class=\"token function-variable function\">remove</span> <span class=\"token operator\">:</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">str</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n\t\t\t<span class=\"token function\">alert</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"remove\"</span><span class=\"token punctuation\">,</span> str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\t\t\t<span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n \n box<span class=\"token punctuation\">.</span>fn<span class=\"token punctuation\">.</span>init<span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> box<span class=\"token punctuation\">.</span>fn<span class=\"token punctuation\">;</span>\n \n window<span class=\"token punctuation\">.</span>box <span class=\"token operator\">=</span>box<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">var</span> testBox <span class=\"token operator\">=</span> <span class=\"token function\">box</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ntestBox<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"jQuery\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">remove</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"jQuery\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"HTML-代码-HTML-codes\"><a href=\"#HTML-代码-HTML-codes\" class=\"headerlink\" title=\"HTML 代码 HTML codes\"></a>HTML 代码 HTML codes</h2><pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token doctype\"><span class=\"token punctuation\">&lt;!</span><span class=\"token doctype-tag\">DOCTYPE</span> <span class=\"token name\">html</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>head</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>mate</span> <span class=\"token attr-name\">charest</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>utf-8<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>keywords<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Editor.md, Markdown, Editor<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>title</span><span class=\"token punctuation\">></span></span>Hello world!<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>title</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>style</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>text/css<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token style\"><span class=\"token language-css\">\n <span class=\"token selector\">body</span><span class=\"token punctuation\">&#123;</span><span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span>14px<span class=\"token punctuation\">;</span><span class=\"token property\">color</span><span class=\"token punctuation\">:</span>#444<span class=\"token punctuation\">;</span><span class=\"token property\">font-family</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Microsoft Yahei\"</span><span class=\"token punctuation\">,</span> Tahoma<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Hiragino Sans GB\"</span><span class=\"token punctuation\">,</span> Arial<span class=\"token punctuation\">;</span><span class=\"token property\">background</span><span class=\"token punctuation\">:</span>#fff<span class=\"token punctuation\">;</span><span class=\"token punctuation\">&#125;</span>\n <span class=\"token selector\">ul</span><span class=\"token punctuation\">&#123;</span><span class=\"token property\">list-style</span><span class=\"token punctuation\">:</span> none<span class=\"token punctuation\">;</span><span class=\"token punctuation\">&#125;</span>\n <span class=\"token selector\">img</span><span class=\"token punctuation\">&#123;</span><span class=\"token property\">border</span><span class=\"token punctuation\">:</span>none<span class=\"token punctuation\">;</span><span class=\"token property\">vertical-align</span><span class=\"token punctuation\">:</span> middle<span class=\"token punctuation\">;</span><span class=\"token punctuation\">&#125;</span>\n </span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>style</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>head</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>body</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>text-xxl<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>Hello world!<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>text-green<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>Plain text<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>body</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>html</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"图片-Images\"><a href=\"#图片-Images\" class=\"headerlink\" title=\"图片 Images\"></a>图片 Images</h1><p>Image:</p>\n<p><img src=\"https://pandao.github.io/editor.md/examples/images/4.jpg\"></p>\n<blockquote>\n<p>Follow your heart.</p>\n</blockquote>\n<p><img src=\"https://pandao.github.io/editor.md/examples/images/8.jpg\"></p>\n<blockquote>\n<p>图为:厦门白城沙滩</p>\n</blockquote>\n<p>图片加链接 (Image + Link)</p>\n<p><a href=\"https://pandao.github.io/editor.md/images/7.jpg\" title=\"李健首张专辑《似水流年》封面\"><img src=\"https://pandao.github.io/editor.md/examples/images/7.jpg\"></a></p>\n<blockquote>\n<p>图为:李健首张专辑《似水流年》封面</p>\n</blockquote>\n<hr>\n<h1 id=\"列表-Lists\"><a href=\"#列表-Lists\" class=\"headerlink\" title=\"列表 Lists\"></a>列表 Lists</h1><h2 id=\"无序列表减号Unordered-Lists\"><a href=\"#无序列表减号Unordered-Lists\" class=\"headerlink\" title=\"无序列表减号Unordered Lists (-)\"></a>无序列表减号Unordered Lists (-)</h2><ul>\n<li>列表一</li>\n<li>列表二</li>\n<li>列表三</li>\n</ul>\n<h2 id=\"无序列表星号Unordered-Lists\"><a href=\"#无序列表星号Unordered-Lists\" class=\"headerlink\" title=\"无序列表星号Unordered Lists (*)\"></a>无序列表星号Unordered Lists (*)</h2><ul>\n<li>列表一</li>\n<li>列表二</li>\n<li>列表三</li>\n</ul>\n<h2 id=\"无序列表加号和嵌套Unordered-Lists\"><a href=\"#无序列表加号和嵌套Unordered-Lists\" class=\"headerlink\" title=\"无序列表加号和嵌套Unordered Lists (+)\"></a>无序列表加号和嵌套Unordered Lists (+)</h2><ul>\n<li>列表一</li>\n<li>列表二<ul>\n<li>列表二-1</li>\n<li>列表二-2</li>\n<li>列表二-3</li>\n</ul>\n</li>\n<li>列表三<ul>\n<li>列表一</li>\n<li>列表二</li>\n<li>列表三</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"有序列表-Ordered-Lists\"><a href=\"#有序列表-Ordered-Lists\" class=\"headerlink\" title=\"有序列表 Ordered Lists (-)\"></a>有序列表 Ordered Lists (-)</h2><ol>\n<li>第一行</li>\n<li>第二行</li>\n<li>第三行</li>\n</ol>\n<h2 id=\"GFM-task-list\"><a href=\"#GFM-task-list\" class=\"headerlink\" title=\"GFM task list\"></a>GFM task list</h2><ul>\n<li><input checked=\"\" disabled=\"\" type=\"checkbox\"> GFM task list 1</li>\n<li><input checked=\"\" disabled=\"\" type=\"checkbox\"> GFM task list 2</li>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 3<ul>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 3-1</li>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 3-2</li>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 3-3</li>\n</ul>\n</li>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 4<ul>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 4-1</li>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 4-2</li>\n</ul>\n</li>\n</ul>\n<hr>\n<h1 id=\"绘制表格-Tables\"><a href=\"#绘制表格-Tables\" class=\"headerlink\" title=\"绘制表格 Tables\"></a>绘制表格 Tables</h1><table>\n<thead>\n<tr>\n<th>项目</th>\n<th align=\"right\">价格</th>\n<th align=\"center\">数量</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>计算机</td>\n<td align=\"right\">$1600</td>\n<td align=\"center\">5</td>\n</tr>\n<tr>\n<td>手机</td>\n<td align=\"right\">$12</td>\n<td align=\"center\">12</td>\n</tr>\n<tr>\n<td>管线</td>\n<td align=\"right\">$1</td>\n<td align=\"center\">234</td>\n</tr>\n</tbody></table>\n<table>\n<thead>\n<tr>\n<th>First Header</th>\n<th>Second Header</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Content Cell</td>\n<td>Content Cell</td>\n</tr>\n<tr>\n<td>Content Cell</td>\n<td>Content Cell</td>\n</tr>\n</tbody></table>\n<table>\n<thead>\n<tr>\n<th>First Header</th>\n<th>Second Header</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Content Cell</td>\n<td>Content Cell</td>\n</tr>\n<tr>\n<td>Content Cell</td>\n<td>Content Cell</td>\n</tr>\n</tbody></table>\n<table>\n<thead>\n<tr>\n<th>Function name</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>help()</code></td>\n<td>Display the help window.</td>\n</tr>\n<tr>\n<td><code>destroy()</code></td>\n<td><strong>Destroy your computer!</strong></td>\n</tr>\n</tbody></table>\n<table>\n<thead>\n<tr>\n<th align=\"left\">Left-Aligned</th>\n<th align=\"center\">Center Aligned</th>\n<th align=\"right\">Right Aligned</th>\n</tr>\n</thead>\n<tbody><tr>\n<td align=\"left\">col 3 is</td>\n<td align=\"center\">some wordy text</td>\n<td align=\"right\">$1600</td>\n</tr>\n<tr>\n<td align=\"left\">col 2 is</td>\n<td align=\"center\">centered</td>\n<td align=\"right\">$12</td>\n</tr>\n<tr>\n<td align=\"left\">zebra stripes</td>\n<td align=\"center\">are neat</td>\n<td align=\"right\">$1</td>\n</tr>\n</tbody></table>\n<table>\n<thead>\n<tr>\n<th>Item</th>\n<th align=\"right\">Value</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Computer</td>\n<td align=\"right\">$1600</td>\n</tr>\n<tr>\n<td>Phone</td>\n<td align=\"right\">$12</td>\n</tr>\n<tr>\n<td>Pipe</td>\n<td align=\"right\">$1</td>\n</tr>\n</tbody></table>\n<h1 id=\"科学公式-TeX-KaTeX\"><a href=\"#科学公式-TeX-KaTeX\" class=\"headerlink\" title=\"科学公式 TeX(KaTeX)\"></a>科学公式 TeX(KaTeX)</h1><p>$$E&#x3D;mc^2$$</p>\n<p>$$x &gt; y$$</p>\n<p>$$(\\sqrt{3x-1}+(1+x)^2)$$</p>\n<p>$$\\sin(\\alpha)^{\\theta}&#x3D;\\sum_{i&#x3D;0}^{n}(x^i + \\cos(f))$$</p>\n<h1 id=\"绘制流程图-mermaid\"><a href=\"#绘制流程图-mermaid\" class=\"headerlink\" title=\"绘制流程图 mermaid\"></a>绘制流程图 mermaid</h1><div class=\"mermaid\">\n graph TD;\n A --> B;\n A --> C;\n B --> D;\n C --> D;\n </div>\n\n<p>End</p>\n","site":{"data":{}},"excerpt":"","more":"<h1 id=\"Linear-Markdown-Sample\"><a href=\"#Linear-Markdown-Sample\" class=\"headerlink\" title=\"Linear Markdown Sample\"></a>Linear Markdown Sample</h1><p><img src=\"https://pandao.github.io/editor.md/images/logos/editormd-logo-180x180.png\" alt=\"markdown\"></p>\n<h1 id=\"Heading-1-link-Heading-link\"><a href=\"#Heading-1-link-Heading-link\" class=\"headerlink\" title=\"Heading 1 link Heading link\"></a>Heading 1 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h1><h2 id=\"Heading-2-link-Heading-link\"><a href=\"#Heading-2-link-Heading-link\" class=\"headerlink\" title=\"Heading 2 link Heading link\"></a>Heading 2 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h2><h3 id=\"Heading-3-link-Heading-link\"><a href=\"#Heading-3-link-Heading-link\" class=\"headerlink\" title=\"Heading 3 link Heading link\"></a>Heading 3 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h3><h4 id=\"Heading-4-link-Heading-link-Heading-link-Heading-link\"><a href=\"#Heading-4-link-Heading-link-Heading-link-Heading-link\" class=\"headerlink\" title=\"Heading 4 link Heading link Heading link Heading link\"></a>Heading 4 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a> Heading link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h4><h5 id=\"Heading-5-link-Heading-link\"><a href=\"#Heading-5-link-Heading-link\" class=\"headerlink\" title=\"Heading 5 link Heading link\"></a>Heading 5 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h5><h6 id=\"Heading-6-link-Heading-link\"><a href=\"#Heading-6-link-Heading-link\" class=\"headerlink\" title=\"Heading 6 link Heading link\"></a>Heading 6 link <a href=\"https://github.com/pandao/editor.md\" title=\"Heading link\">Heading link</a></h6><h1 id=\"字符效果和横线等\"><a href=\"#字符效果和横线等\" class=\"headerlink\" title=\"字符效果和横线等\"></a>字符效果和横线等</h1><hr>\n<p><del>删除线</del> <s>删除线开启识别HTML标签时</s><br><em>斜体字</em> <em>斜体字</em><br><strong>粗体</strong> <strong>粗体</strong><br><em><strong>粗斜体</strong></em> <em><strong>粗斜体</strong></em></p>\n<p>上标X<sub>2</sub>下标O<sup>2</sup></p>\n<p><strong>缩写(同HTML的abbr标签)</strong></p>\n<blockquote>\n<p>即更长的单词或短语的缩写形式前提是开启识别HTML标签时已默认开启</p>\n</blockquote>\n<p>The <abbr title=\"Hyper Text Markup Language\">HTML</abbr> specification is maintained by the <abbr title=\"World Wide Web Consortium\">W3C</abbr>.</p>\n<h1 id=\"引用-Blockquotes\"><a href=\"#引用-Blockquotes\" class=\"headerlink\" title=\"引用 Blockquotes\"></a>引用 Blockquotes</h1><blockquote>\n<p>引用文本 Blockquotes</p>\n</blockquote>\n<p>引用的行内混合 Blockquotes</p>\n<blockquote>\n<p>引用:如果想要插入空白换行<code>即&lt;br /&gt;标签</code>,在插入处先键入两个以上的空格然后回车即可,<a href=\"http://localhost/\">普通链接</a>。</p>\n</blockquote>\n<h1 id=\"锚点与链接-Links\"><a href=\"#锚点与链接-Links\" class=\"headerlink\" title=\"锚点与链接 Links\"></a>锚点与链接 Links</h1><p><a href=\"http://localhost/\">普通链接</a></p>\n<p><a href=\"http://localhost/\" title=\"普通链接带标题\">普通链接带标题</a></p>\n<p>直接链接:<a href=\"https://github.com/\">https://github.com</a></p>\n<p><a href=\"https://baidu.com/\">https://baidu.com</a></p>\n<p><a href=\"http://www.this-anchor-link.com/\">锚点链接</a> </p>\n<p><a href=\"mailto:test.test@gmail.com\">mailto:test.test@gmail.com</a></p>\n<p>GFM a-tail link <a href=\"https://my.oschina.net/u/3691274\">@pandao</a> 邮箱地址自动链接 <a href=\"mailto:&#x74;&#x65;&#x73;&#116;&#x2e;&#x74;&#101;&#x73;&#x74;&#64;&#103;&#109;&#x61;&#105;&#x6c;&#46;&#x63;&#111;&#x6d;\">&#x74;&#x65;&#x73;&#116;&#x2e;&#x74;&#101;&#x73;&#x74;&#64;&#103;&#109;&#x61;&#105;&#x6c;&#46;&#x63;&#111;&#x6d;</a> <a href=\"mailto:&#119;&#119;&#119;&#x40;&#118;&#105;&#112;&#x2e;&#113;&#113;&#x2e;&#99;&#x6f;&#109;\">&#119;&#119;&#119;&#x40;&#118;&#105;&#112;&#x2e;&#113;&#113;&#x2e;&#99;&#x6f;&#109;</a></p>\n<blockquote>\n<p>@pandao</p>\n</blockquote>\n<h1 id=\"多语言代码高亮-Codes\"><a href=\"#多语言代码高亮-Codes\" class=\"headerlink\" title=\"多语言代码高亮 Codes\"></a>多语言代码高亮 Codes</h1><h2 id=\"行内代码-Inline-code\"><a href=\"#行内代码-Inline-code\" class=\"headerlink\" title=\"行内代码 Inline code\"></a>行内代码 Inline code</h2><p>执行命令:<code>npm install marked</code></p>\n<h2 id=\"JS代码\"><a href=\"#JS代码\" class=\"headerlink\" title=\"JS代码\"></a>JS代码</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n\tconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello world!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n \n<span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> <span class=\"token function-variable function\">box</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> box<span class=\"token punctuation\">.</span>fn<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\n box<span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> box<span class=\"token punctuation\">.</span>fn <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">init</span> <span class=\"token operator\">:</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'box.init()'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\t\t\t<span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n\n\t\t<span class=\"token function-variable function\">add</span> <span class=\"token operator\">:</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">str</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n\t\t\t<span class=\"token function\">alert</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"add\"</span><span class=\"token punctuation\">,</span> str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\t\t\t<span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n\n\t\t<span class=\"token function-variable function\">remove</span> <span class=\"token operator\">:</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">str</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n\t\t\t<span class=\"token function\">alert</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"remove\"</span><span class=\"token punctuation\">,</span> str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\t\t\t<span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n\t\t<span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n \n box<span class=\"token punctuation\">.</span>fn<span class=\"token punctuation\">.</span>init<span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> box<span class=\"token punctuation\">.</span>fn<span class=\"token punctuation\">;</span>\n \n window<span class=\"token punctuation\">.</span>box <span class=\"token operator\">=</span>box<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">var</span> testBox <span class=\"token operator\">=</span> <span class=\"token function\">box</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ntestBox<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"jQuery\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">remove</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"jQuery\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"HTML-代码-HTML-codes\"><a href=\"#HTML-代码-HTML-codes\" class=\"headerlink\" title=\"HTML 代码 HTML codes\"></a>HTML 代码 HTML codes</h2><pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token doctype\"><span class=\"token punctuation\">&lt;!</span><span class=\"token doctype-tag\">DOCTYPE</span> <span class=\"token name\">html</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>head</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>mate</span> <span class=\"token attr-name\">charest</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>utf-8<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>keywords<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Editor.md, Markdown, Editor<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>title</span><span class=\"token punctuation\">></span></span>Hello world!<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>title</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>style</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>text/css<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token style\"><span class=\"token language-css\">\n <span class=\"token selector\">body</span><span class=\"token punctuation\">&#123;</span><span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span>14px<span class=\"token punctuation\">;</span><span class=\"token property\">color</span><span class=\"token punctuation\">:</span>#444<span class=\"token punctuation\">;</span><span class=\"token property\">font-family</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Microsoft Yahei\"</span><span class=\"token punctuation\">,</span> Tahoma<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Hiragino Sans GB\"</span><span class=\"token punctuation\">,</span> Arial<span class=\"token punctuation\">;</span><span class=\"token property\">background</span><span class=\"token punctuation\">:</span>#fff<span class=\"token punctuation\">;</span><span class=\"token punctuation\">&#125;</span>\n <span class=\"token selector\">ul</span><span class=\"token punctuation\">&#123;</span><span class=\"token property\">list-style</span><span class=\"token punctuation\">:</span> none<span class=\"token punctuation\">;</span><span class=\"token punctuation\">&#125;</span>\n <span class=\"token selector\">img</span><span class=\"token punctuation\">&#123;</span><span class=\"token property\">border</span><span class=\"token punctuation\">:</span>none<span class=\"token punctuation\">;</span><span class=\"token property\">vertical-align</span><span class=\"token punctuation\">:</span> middle<span class=\"token punctuation\">;</span><span class=\"token punctuation\">&#125;</span>\n </span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>style</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>head</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>body</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>text-xxl<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>Hello world!<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>text-green<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>Plain text<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>body</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>html</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"图片-Images\"><a href=\"#图片-Images\" class=\"headerlink\" title=\"图片 Images\"></a>图片 Images</h1><p>Image:</p>\n<p><img src=\"https://pandao.github.io/editor.md/examples/images/4.jpg\"></p>\n<blockquote>\n<p>Follow your heart.</p>\n</blockquote>\n<p><img src=\"https://pandao.github.io/editor.md/examples/images/8.jpg\"></p>\n<blockquote>\n<p>图为:厦门白城沙滩</p>\n</blockquote>\n<p>图片加链接 (Image + Link)</p>\n<p><a href=\"https://pandao.github.io/editor.md/images/7.jpg\" title=\"李健首张专辑《似水流年》封面\"><img src=\"https://pandao.github.io/editor.md/examples/images/7.jpg\"></a></p>\n<blockquote>\n<p>图为:李健首张专辑《似水流年》封面</p>\n</blockquote>\n<hr>\n<h1 id=\"列表-Lists\"><a href=\"#列表-Lists\" class=\"headerlink\" title=\"列表 Lists\"></a>列表 Lists</h1><h2 id=\"无序列表减号Unordered-Lists\"><a href=\"#无序列表减号Unordered-Lists\" class=\"headerlink\" title=\"无序列表减号Unordered Lists (-)\"></a>无序列表减号Unordered Lists (-)</h2><ul>\n<li>列表一</li>\n<li>列表二</li>\n<li>列表三</li>\n</ul>\n<h2 id=\"无序列表星号Unordered-Lists\"><a href=\"#无序列表星号Unordered-Lists\" class=\"headerlink\" title=\"无序列表星号Unordered Lists (*)\"></a>无序列表星号Unordered Lists (*)</h2><ul>\n<li>列表一</li>\n<li>列表二</li>\n<li>列表三</li>\n</ul>\n<h2 id=\"无序列表加号和嵌套Unordered-Lists\"><a href=\"#无序列表加号和嵌套Unordered-Lists\" class=\"headerlink\" title=\"无序列表加号和嵌套Unordered Lists (+)\"></a>无序列表加号和嵌套Unordered Lists (+)</h2><ul>\n<li>列表一</li>\n<li>列表二<ul>\n<li>列表二-1</li>\n<li>列表二-2</li>\n<li>列表二-3</li>\n</ul>\n</li>\n<li>列表三<ul>\n<li>列表一</li>\n<li>列表二</li>\n<li>列表三</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"有序列表-Ordered-Lists\"><a href=\"#有序列表-Ordered-Lists\" class=\"headerlink\" title=\"有序列表 Ordered Lists (-)\"></a>有序列表 Ordered Lists (-)</h2><ol>\n<li>第一行</li>\n<li>第二行</li>\n<li>第三行</li>\n</ol>\n<h2 id=\"GFM-task-list\"><a href=\"#GFM-task-list\" class=\"headerlink\" title=\"GFM task list\"></a>GFM task list</h2><ul>\n<li><input checked=\"\" disabled=\"\" type=\"checkbox\"> GFM task list 1</li>\n<li><input checked=\"\" disabled=\"\" type=\"checkbox\"> GFM task list 2</li>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 3<ul>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 3-1</li>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 3-2</li>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 3-3</li>\n</ul>\n</li>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 4<ul>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 4-1</li>\n<li><input disabled=\"\" type=\"checkbox\"> GFM task list 4-2</li>\n</ul>\n</li>\n</ul>\n<hr>\n<h1 id=\"绘制表格-Tables\"><a href=\"#绘制表格-Tables\" class=\"headerlink\" title=\"绘制表格 Tables\"></a>绘制表格 Tables</h1><table>\n<thead>\n<tr>\n<th>项目</th>\n<th align=\"right\">价格</th>\n<th align=\"center\">数量</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>计算机</td>\n<td align=\"right\">$1600</td>\n<td align=\"center\">5</td>\n</tr>\n<tr>\n<td>手机</td>\n<td align=\"right\">$12</td>\n<td align=\"center\">12</td>\n</tr>\n<tr>\n<td>管线</td>\n<td align=\"right\">$1</td>\n<td align=\"center\">234</td>\n</tr>\n</tbody></table>\n<table>\n<thead>\n<tr>\n<th>First Header</th>\n<th>Second Header</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Content Cell</td>\n<td>Content Cell</td>\n</tr>\n<tr>\n<td>Content Cell</td>\n<td>Content Cell</td>\n</tr>\n</tbody></table>\n<table>\n<thead>\n<tr>\n<th>First Header</th>\n<th>Second Header</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Content Cell</td>\n<td>Content Cell</td>\n</tr>\n<tr>\n<td>Content Cell</td>\n<td>Content Cell</td>\n</tr>\n</tbody></table>\n<table>\n<thead>\n<tr>\n<th>Function name</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>help()</code></td>\n<td>Display the help window.</td>\n</tr>\n<tr>\n<td><code>destroy()</code></td>\n<td><strong>Destroy your computer!</strong></td>\n</tr>\n</tbody></table>\n<table>\n<thead>\n<tr>\n<th align=\"left\">Left-Aligned</th>\n<th align=\"center\">Center Aligned</th>\n<th align=\"right\">Right Aligned</th>\n</tr>\n</thead>\n<tbody><tr>\n<td align=\"left\">col 3 is</td>\n<td align=\"center\">some wordy text</td>\n<td align=\"right\">$1600</td>\n</tr>\n<tr>\n<td align=\"left\">col 2 is</td>\n<td align=\"center\">centered</td>\n<td align=\"right\">$12</td>\n</tr>\n<tr>\n<td align=\"left\">zebra stripes</td>\n<td align=\"center\">are neat</td>\n<td align=\"right\">$1</td>\n</tr>\n</tbody></table>\n<table>\n<thead>\n<tr>\n<th>Item</th>\n<th align=\"right\">Value</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Computer</td>\n<td align=\"right\">$1600</td>\n</tr>\n<tr>\n<td>Phone</td>\n<td align=\"right\">$12</td>\n</tr>\n<tr>\n<td>Pipe</td>\n<td align=\"right\">$1</td>\n</tr>\n</tbody></table>\n<h1 id=\"科学公式-TeX-KaTeX\"><a href=\"#科学公式-TeX-KaTeX\" class=\"headerlink\" title=\"科学公式 TeX(KaTeX)\"></a>科学公式 TeX(KaTeX)</h1><p>$$E&#x3D;mc^2$$</p>\n<p>$$x &gt; y$$</p>\n<p>$$(\\sqrt{3x-1}+(1+x)^2)$$</p>\n<p>$$\\sin(\\alpha)^{\\theta}&#x3D;\\sum_{i&#x3D;0}^{n}(x^i + \\cos(f))$$</p>\n<h1 id=\"绘制流程图-mermaid\"><a href=\"#绘制流程图-mermaid\" class=\"headerlink\" title=\"绘制流程图 mermaid\"></a>绘制流程图 mermaid</h1><div class=\"mermaid\">\n graph TD;\n A --> B;\n A --> C;\n B --> D;\n C --> D;\n </div>\n\n<p>End</p>\n"},{"title":"付鹏:逆全球化下的全球资产配置","status":"done","_content":"\n为什么会有中美贸易战为什么会有特朗普他们手上有个重要的东西选票。法国人民手上有个重要的东西什么东西公会。财富分配到最后是需要权力去平衡的也就简单讲富者恒富穷者不富的时候他手上会用一个最简单东西投出民粹主义的路线就是选票。哪个领导人愿意带著我们把工资从十块钱降到二十我就选他。有两种做法第一种让企业吐回来。第二种让中国吐回来。中国拿走的劳动收入增速现在要吐回来这就是逆全球化。企业部门拿走的高杠杆高负债获得的财富积累要吐回来。然后你就会发现他的收入增速上来他会长期的怎么样通胀。利率水平增高导致企业部门(美国制造业)变差,其实就是代表著美国的左右两边。\n\n在这种背景下既然不能从市场层面上获得收入增速就得从你自身提高收入增速答案是什么技术进步。现在工人工资我是压不下去了怎么办三个工人变两工人+机器人。所以你猜美国现在在干嘛右侧是这帮企业左侧是美国的这帮中底层的这些老百姓小日子过得太Happy了。左侧这帮企业收入增速7.5通胀5个点。开心吧挣的钱存到银行现在5个点开心吧然后08年美国次贷危机破裂了以后美国锁定在了0-0.25的这个低息区域老百姓买了低息贷款的房子储蓄多了开心吧中国出口的赚买了美国国债相当于还要回储给你们最后发现美国挣得多、存的多、债务还低。从08年到23年这15年就相当于去了15年的杠杆。企业部门要借贷5.25的利率高于目前3点几的增速被迫进入到利润下降未来要提高增长只有一个方案就是技术进步。\n\n硅谷大裁员是不影响就业的这帮生产率高的人转化再就业的能力是极强的。生产率低的人出现大规模失业才是最麻烦的。简单讲美国这帮黑人们如果全都失业了那美国就完了。08年后企业银行居民这三者的分配关系就有问题了一直拖到现在已经无解了。全世界从过去的十年只有一个大的变量\"技术进步\"。我个人有一种感觉当前的这个时间点在炒的人工智能跟过去的十年浮现出来的不太一样。美国股市现在就那几个科技公司拉着每股涨是好事。几家公司是在5.25的利率环境下拉动每股涨的。它不是那个0到0.25的利率拉动的能够扛得住资金成本5到5.25还能带来增长意味著AI可能是真的。\n\n08年到2028年整20年的周期足够一个新技术带动全社会变动了这几家公司可能在未来3到5年拉着美股创新高 继续创新高。后面的涨是正儿八经的生产率提高的涨,前两年是啥?是低利率推著泡沫在涨。如果美国完成了这条线,既保证了企业在技术进步下维持高利润增长,又保证底层居民获得了高收入增速,你猜美国的利率会是什么情况?他的利率会一直很高,进入到高增长、高通胀、高利率,三高。\n\n那么中国会事什么情况美国不给技术转化生产也不是中国制造了逆全球化嘛国内会低增长、低通胀、低利率。从全球分工来看美国底层是技术研发中间生产下面是市场。如果生产环节不给中国高端制造给谁大概率是日本。\n\n日本的全球分工的角色会跟过去的二三十年不一样英国的老牌家族的基金家族办公开始跑到日本租办公室招人了二三十年前的时候跑到香港租办公室招人跑到北京设立办事处为什么答案只有一个看好该国未来20年30年的增长。\n\n在过去的20年发展过程中我们的生产环节是针对全世界的如果出不去。只能转化成内需。我们的一个大问题出来了过去的10年中国经济最大的不同就是现在的年轻人债务过高内需是背著重重的负债前行的有一些人不准备生人再去背了。直到疫情过恢复以后到现在为止不缺生产缺谁买单。内需要么是政府部门要么是居民部门一个是投资不动一个消费不动有钱的有钱死没钱的负债死。昨天我看又新能源车下乡了然后你去看看那个评论区90后崛起了不像十年前那么好骗了他们咋回答呢啥好事都想著我们农村人。十年前什么家电下乡卖不掉的冰箱……就是电器卖给我们农村人这韭菜不能照着一个地儿割啊。\n\n笃定了老美不会给我们这条科技树所以经济当前压根就不是我们最大的问题只要能守住底线也就是你的居民仍然是可爱的人底线思维即可。当下最大的目标是重建这个秩序美国不带我玩我就去拉着ABC去重构这种国际分工、全球化市场结构重构我们的科技树。中国现在的投资跟老美一样都在反映科技树但是\"市场决定的科技树(市场经济)\"和\"政府主导的科技树(计划经济)\"结局是不一样的。所以低增长、低利率的国内必须要点科技树,但体现在股票上,国内是什么光景,美股是什么光景?\n\n很多人说A股弱美股强因为人家现在高增长、高通胀、高利率、和消费市场。08年之后。老美去了15年杠杆。居民部门老老实实还了15年的债日本人老老实实还了30年。美国的利率水平绝对不再是以前的路径不再会靠降息加杠杆的方式去推动增长而是要靠生产校长的扩张技术在两三年后我们有可能会迎来一个\"iPhone时刻\"。\n\n我们现在所有人依旧想的是如果企业不行最终还得是降息。美国会出现一种情况就是企业的技术进步把它带上去整个美元的长短端利率都在5-5.25那我就请问你光现金和资产回报都5-5.25了你觉得黄金会奔三千四千五千吗黄金的之所以在高价因为长期利率在地位加上杠杆但是如果长短端的投资回报率在5-5.25,你还会持有黄金吗?\n\n08年金融危机以后老美痛定思痛开始在极低的利率下去除杠杆也就是讲现在你看见的美国是08年的美国导致的一个结果。而08年的中国在干什么呢所有人熟知的叫四万亿(可不止),总结一句话,就是给居民部门加杠杆。中国拖起了全球经济,代价是这一代居民部门的储蓄和杠杆,就是老百姓讲的掏空了几个钱包。\n\n真正的大交易者用什么东西做负债用什么东西当资产。如果现在世界格局是这样请问我们个人该怎么办举个例子我09年回国2010年开始到2016年股灾人民币单边每年升值3%美元官方利率0到0.2%加上手续费美元借款资金成本大约2%。就造成了实际借美元利率是-1%,那时候北上广的房价是多少?房子的背后就是人口、收入、杠杆,而其中最重要的吗,在当时,不是人口、也不是收入,而是杠杆。我的借贷成本如果-1%的话,这不就是热钱吗?借-1%的钱来中国就好了,干什么东西,买房呗!\n\n所以放到现在的今天个人该怎么办呢美国进入到三高的状态中国进入到这种三低的状态。当下经营贷3.2%人民币贬值实际人民币借贷成就是负的所以答案就是人民币长期利率水平会非常的低借贷低息的人民币人民币贬值官方的借贷成本会从3个点掉到2个点并且维持在2个点三到五年让你借贷人民币的真实利率一定在0以下。所以从大交易者的角度负债解决了资产端该买啥能够给你二字头融资成本一定说明国内的资产端没有高息回报我们不出境去哪儿找高息的资产我偷偷摸摸告诉大家过一段时间你们会发现某个类型的ETF手续费还会增加什么东西用人民币结算但是持有的是境外高息资产(QDII)美国光银行存款利率在5%你该干嘛你们会发现巴菲特买的西方石油公司、买的日本的五大商社股息率在10以上你们知道该干嘛如果这个东西一直是这样倒着咱们哪来的信心觉得外资会流入\n\n所以这就是一个重要的分水岭这个最核心的原理理解超级的重要绝对对你后面三五年巨大的受益。","source":"_posts/finance/付鹏:逆全球化下的全球资产配置.md","raw":"---\ntitle: 付鹏:逆全球化下的全球资产配置\ncategories:\n - Finance\nstatus: done\n---\n\n为什么会有中美贸易战为什么会有特朗普他们手上有个重要的东西选票。法国人民手上有个重要的东西什么东西公会。财富分配到最后是需要权力去平衡的也就简单讲富者恒富穷者不富的时候他手上会用一个最简单东西投出民粹主义的路线就是选票。哪个领导人愿意带著我们把工资从十块钱降到二十我就选他。有两种做法第一种让企业吐回来。第二种让中国吐回来。中国拿走的劳动收入增速现在要吐回来这就是逆全球化。企业部门拿走的高杠杆高负债获得的财富积累要吐回来。然后你就会发现他的收入增速上来他会长期的怎么样通胀。利率水平增高导致企业部门(美国制造业)变差,其实就是代表著美国的左右两边。\n\n在这种背景下既然不能从市场层面上获得收入增速就得从你自身提高收入增速答案是什么技术进步。现在工人工资我是压不下去了怎么办三个工人变两工人+机器人。所以你猜美国现在在干嘛右侧是这帮企业左侧是美国的这帮中底层的这些老百姓小日子过得太Happy了。左侧这帮企业收入增速7.5通胀5个点。开心吧挣的钱存到银行现在5个点开心吧然后08年美国次贷危机破裂了以后美国锁定在了0-0.25的这个低息区域老百姓买了低息贷款的房子储蓄多了开心吧中国出口的赚买了美国国债相当于还要回储给你们最后发现美国挣得多、存的多、债务还低。从08年到23年这15年就相当于去了15年的杠杆。企业部门要借贷5.25的利率高于目前3点几的增速被迫进入到利润下降未来要提高增长只有一个方案就是技术进步。\n\n硅谷大裁员是不影响就业的这帮生产率高的人转化再就业的能力是极强的。生产率低的人出现大规模失业才是最麻烦的。简单讲美国这帮黑人们如果全都失业了那美国就完了。08年后企业银行居民这三者的分配关系就有问题了一直拖到现在已经无解了。全世界从过去的十年只有一个大的变量\"技术进步\"。我个人有一种感觉当前的这个时间点在炒的人工智能跟过去的十年浮现出来的不太一样。美国股市现在就那几个科技公司拉着每股涨是好事。几家公司是在5.25的利率环境下拉动每股涨的。它不是那个0到0.25的利率拉动的能够扛得住资金成本5到5.25还能带来增长意味著AI可能是真的。\n\n08年到2028年整20年的周期足够一个新技术带动全社会变动了这几家公司可能在未来3到5年拉着美股创新高 继续创新高。后面的涨是正儿八经的生产率提高的涨,前两年是啥?是低利率推著泡沫在涨。如果美国完成了这条线,既保证了企业在技术进步下维持高利润增长,又保证底层居民获得了高收入增速,你猜美国的利率会是什么情况?他的利率会一直很高,进入到高增长、高通胀、高利率,三高。\n\n那么中国会事什么情况美国不给技术转化生产也不是中国制造了逆全球化嘛国内会低增长、低通胀、低利率。从全球分工来看美国底层是技术研发中间生产下面是市场。如果生产环节不给中国高端制造给谁大概率是日本。\n\n日本的全球分工的角色会跟过去的二三十年不一样英国的老牌家族的基金家族办公开始跑到日本租办公室招人了二三十年前的时候跑到香港租办公室招人跑到北京设立办事处为什么答案只有一个看好该国未来20年30年的增长。\n\n在过去的20年发展过程中我们的生产环节是针对全世界的如果出不去。只能转化成内需。我们的一个大问题出来了过去的10年中国经济最大的不同就是现在的年轻人债务过高内需是背著重重的负债前行的有一些人不准备生人再去背了。直到疫情过恢复以后到现在为止不缺生产缺谁买单。内需要么是政府部门要么是居民部门一个是投资不动一个消费不动有钱的有钱死没钱的负债死。昨天我看又新能源车下乡了然后你去看看那个评论区90后崛起了不像十年前那么好骗了他们咋回答呢啥好事都想著我们农村人。十年前什么家电下乡卖不掉的冰箱……就是电器卖给我们农村人这韭菜不能照着一个地儿割啊。\n\n笃定了老美不会给我们这条科技树所以经济当前压根就不是我们最大的问题只要能守住底线也就是你的居民仍然是可爱的人底线思维即可。当下最大的目标是重建这个秩序美国不带我玩我就去拉着ABC去重构这种国际分工、全球化市场结构重构我们的科技树。中国现在的投资跟老美一样都在反映科技树但是\"市场决定的科技树(市场经济)\"和\"政府主导的科技树(计划经济)\"结局是不一样的。所以低增长、低利率的国内必须要点科技树,但体现在股票上,国内是什么光景,美股是什么光景?\n\n很多人说A股弱美股强因为人家现在高增长、高通胀、高利率、和消费市场。08年之后。老美去了15年杠杆。居民部门老老实实还了15年的债日本人老老实实还了30年。美国的利率水平绝对不再是以前的路径不再会靠降息加杠杆的方式去推动增长而是要靠生产校长的扩张技术在两三年后我们有可能会迎来一个\"iPhone时刻\"。\n\n我们现在所有人依旧想的是如果企业不行最终还得是降息。美国会出现一种情况就是企业的技术进步把它带上去整个美元的长短端利率都在5-5.25那我就请问你光现金和资产回报都5-5.25了你觉得黄金会奔三千四千五千吗黄金的之所以在高价因为长期利率在地位加上杠杆但是如果长短端的投资回报率在5-5.25,你还会持有黄金吗?\n\n08年金融危机以后老美痛定思痛开始在极低的利率下去除杠杆也就是讲现在你看见的美国是08年的美国导致的一个结果。而08年的中国在干什么呢所有人熟知的叫四万亿(可不止),总结一句话,就是给居民部门加杠杆。中国拖起了全球经济,代价是这一代居民部门的储蓄和杠杆,就是老百姓讲的掏空了几个钱包。\n\n真正的大交易者用什么东西做负债用什么东西当资产。如果现在世界格局是这样请问我们个人该怎么办举个例子我09年回国2010年开始到2016年股灾人民币单边每年升值3%美元官方利率0到0.2%加上手续费美元借款资金成本大约2%。就造成了实际借美元利率是-1%,那时候北上广的房价是多少?房子的背后就是人口、收入、杠杆,而其中最重要的吗,在当时,不是人口、也不是收入,而是杠杆。我的借贷成本如果-1%的话,这不就是热钱吗?借-1%的钱来中国就好了,干什么东西,买房呗!\n\n所以放到现在的今天个人该怎么办呢美国进入到三高的状态中国进入到这种三低的状态。当下经营贷3.2%人民币贬值实际人民币借贷成就是负的所以答案就是人民币长期利率水平会非常的低借贷低息的人民币人民币贬值官方的借贷成本会从3个点掉到2个点并且维持在2个点三到五年让你借贷人民币的真实利率一定在0以下。所以从大交易者的角度负债解决了资产端该买啥能够给你二字头融资成本一定说明国内的资产端没有高息回报我们不出境去哪儿找高息的资产我偷偷摸摸告诉大家过一段时间你们会发现某个类型的ETF手续费还会增加什么东西用人民币结算但是持有的是境外高息资产(QDII)美国光银行存款利率在5%你该干嘛你们会发现巴菲特买的西方石油公司、买的日本的五大商社股息率在10以上你们知道该干嘛如果这个东西一直是这样倒着咱们哪来的信心觉得外资会流入\n\n所以这就是一个重要的分水岭这个最核心的原理理解超级的重要绝对对你后面三五年巨大的受益。","slug":"finance/付鹏:逆全球化下的全球资产配置","published":1,"date":"2023-11-06T05:17:08.678Z","updated":"2023-11-06T05:17:47.196Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58m00064cz35salcgt5","content":"<p>为什么会有中美贸易战?为什么会有特朗普?他们手上有个重要的东西,选票。法国人民手上有个重要的东西,什么东西?公会。财富分配,到最后是需要权力去平衡的,也就简单讲,富者恒富,穷者不富的时候,他手上会用一个最简单东西投出民粹主义的路线,就是选票。哪个领导人愿意带著我们把工资从十块钱降到二十,我就选他。有两种做法:第一种,让企业吐回来。第二种,让中国吐回来。中国拿走的劳动收入增速,现在要吐回来,这就是逆全球化。企业部门拿走的高杠杆,高负债,获得的财富积累要吐回来。然后你就会发现,他的收入增速上来,他会长期的怎么样?通胀。利率水平增高,导致企业部门(美国制造业)变差,其实就是代表著美国的左右两边。</p>\n<p>在这种背景下,既然不能从市场层面上获得收入增速,就得从你自身提高收入增速,答案是什么?技术进步。现在工人工资我是压不下去了,怎么办?三个工人变两工人+机器人。所以你猜美国现在在干嘛右侧是这帮企业左侧是美国的这帮中底层的这些老百姓小日子过得太Happy了。左侧这帮企业收入增速7.5通胀5个点。开心吧挣的钱存到银行现在5个点开心吧然后08年美国次贷危机破裂了以后美国锁定在了0-0.25的这个低息区域老百姓买了低息贷款的房子储蓄多了开心吧中国出口的赚买了美国国债相当于还要回储给你们最后发现美国挣得多、存的多、债务还低。从08年到23年这15年就相当于去了15年的杠杆。企业部门要借贷5.25的利率高于目前3点几的增速被迫进入到利润下降未来要提高增长只有一个方案就是技术进步。</p>\n<p>硅谷大裁员是不影响就业的这帮生产率高的人转化再就业的能力是极强的。生产率低的人出现大规模失业才是最麻烦的。简单讲美国这帮黑人们如果全都失业了那美国就完了。08年后企业银行居民这三者的分配关系就有问题了一直拖到现在已经无解了。全世界从过去的十年只有一个大的变量”技术进步”。我个人有一种感觉当前的这个时间点在炒的人工智能跟过去的十年浮现出来的不太一样。美国股市现在就那几个科技公司拉着每股涨是好事。几家公司是在5.25的利率环境下拉动每股涨的。它不是那个0到0.25的利率拉动的能够扛得住资金成本5到5.25还能带来增长意味著AI可能是真的。</p>\n<p>08年到2028年整20年的周期足够一个新技术带动全社会变动了这几家公司可能在未来3到5年拉着美股创新高 继续创新高。后面的涨是正儿八经的生产率提高的涨,前两年是啥?是低利率推著泡沫在涨。如果美国完成了这条线,既保证了企业在技术进步下维持高利润增长,又保证底层居民获得了高收入增速,你猜美国的利率会是什么情况?他的利率会一直很高,进入到高增长、高通胀、高利率,三高。</p>\n<p>那么中国会事什么情况?美国不给技术,转化生产也不是中国制造了,逆全球化嘛!国内会低增长、低通胀、低利率。从全球分工来看,美国底层是技术研发,中间生产,下面是市场。如果生产环节不给中国,高端制造给谁?大概率是日本。</p>\n<p>日本的全球分工的角色会跟过去的二三十年不一样英国的老牌家族的基金家族办公开始跑到日本租办公室招人了二三十年前的时候跑到香港租办公室招人跑到北京设立办事处为什么答案只有一个看好该国未来20年30年的增长。</p>\n<p>在过去的20年发展过程中我们的生产环节是针对全世界的如果出不去。只能转化成内需。我们的一个大问题出来了过去的10年中国经济最大的不同就是现在的年轻人债务过高内需是背著重重的负债前行的有一些人不准备生人再去背了。直到疫情过恢复以后到现在为止不缺生产缺谁买单。内需要么是政府部门要么是居民部门一个是投资不动一个消费不动有钱的有钱死没钱的负债死。昨天我看又新能源车下乡了然后你去看看那个评论区90后崛起了不像十年前那么好骗了他们咋回答呢啥好事都想著我们农村人。十年前什么家电下乡卖不掉的冰箱……就是电器卖给我们农村人这韭菜不能照着一个地儿割啊。</p>\n<p>笃定了老美不会给我们这条科技树所以经济当前压根就不是我们最大的问题只要能守住底线也就是你的居民仍然是可爱的人底线思维即可。当下最大的目标是重建这个秩序美国不带我玩我就去拉着ABC去重构这种国际分工、全球化市场结构重构我们的科技树。中国现在的投资跟老美一样都在反映科技树但是”市场决定的科技树(市场经济)”和”政府主导的科技树(计划经济)”结局是不一样的。所以低增长、低利率的国内必须要点科技树,但体现在股票上,国内是什么光景,美股是什么光景?</p>\n<p>很多人说A股弱美股强因为人家现在高增长、高通胀、高利率、和消费市场。08年之后。老美去了15年杠杆。居民部门老老实实还了15年的债日本人老老实实还了30年。美国的利率水平绝对不再是以前的路径不再会靠降息加杠杆的方式去推动增长而是要靠生产校长的扩张技术在两三年后我们有可能会迎来一个”iPhone时刻”。</p>\n<p>我们现在所有人依旧想的是如果企业不行最终还得是降息。美国会出现一种情况就是企业的技术进步把它带上去整个美元的长短端利率都在5-5.25那我就请问你光现金和资产回报都5-5.25了你觉得黄金会奔三千四千五千吗黄金的之所以在高价因为长期利率在地位加上杠杆但是如果长短端的投资回报率在5-5.25,你还会持有黄金吗?</p>\n<p>08年金融危机以后老美痛定思痛开始在极低的利率下去除杠杆也就是讲现在你看见的美国是08年的美国导致的一个结果。而08年的中国在干什么呢所有人熟知的叫四万亿(可不止),总结一句话,就是给居民部门加杠杆。中国拖起了全球经济,代价是这一代居民部门的储蓄和杠杆,就是老百姓讲的掏空了几个钱包。</p>\n<p>真正的大交易者用什么东西做负债用什么东西当资产。如果现在世界格局是这样请问我们个人该怎么办举个例子我09年回国2010年开始到2016年股灾人民币单边每年升值3%美元官方利率0到0.2%加上手续费美元借款资金成本大约2%。就造成了实际借美元利率是-1%,那时候北上广的房价是多少?房子的背后就是人口、收入、杠杆,而其中最重要的吗,在当时,不是人口、也不是收入,而是杠杆。我的借贷成本如果-1%的话,这不就是热钱吗?借-1%的钱来中国就好了,干什么东西,买房呗!</p>\n<p>所以放到现在的今天个人该怎么办呢美国进入到三高的状态中国进入到这种三低的状态。当下经营贷3.2%人民币贬值实际人民币借贷成就是负的所以答案就是人民币长期利率水平会非常的低借贷低息的人民币人民币贬值官方的借贷成本会从3个点掉到2个点并且维持在2个点三到五年让你借贷人民币的真实利率一定在0以下。所以从大交易者的角度负债解决了资产端该买啥能够给你二字头融资成本一定说明国内的资产端没有高息回报我们不出境去哪儿找高息的资产我偷偷摸摸告诉大家过一段时间你们会发现某个类型的ETF手续费还会增加什么东西用人民币结算但是持有的是境外高息资产(QDII)美国光银行存款利率在5%你该干嘛你们会发现巴菲特买的西方石油公司、买的日本的五大商社股息率在10以上你们知道该干嘛如果这个东西一直是这样倒着咱们哪来的信心觉得外资会流入</p>\n<p>所以这就是一个重要的分水岭,这个最核心的原理理解,超级的重要!绝对对你后面三五年巨大的受益。</p>\n","site":{"data":{}},"excerpt":"","more":"<p>为什么会有中美贸易战?为什么会有特朗普?他们手上有个重要的东西,选票。法国人民手上有个重要的东西,什么东西?公会。财富分配,到最后是需要权力去平衡的,也就简单讲,富者恒富,穷者不富的时候,他手上会用一个最简单东西投出民粹主义的路线,就是选票。哪个领导人愿意带著我们把工资从十块钱降到二十,我就选他。有两种做法:第一种,让企业吐回来。第二种,让中国吐回来。中国拿走的劳动收入增速,现在要吐回来,这就是逆全球化。企业部门拿走的高杠杆,高负债,获得的财富积累要吐回来。然后你就会发现,他的收入增速上来,他会长期的怎么样?通胀。利率水平增高,导致企业部门(美国制造业)变差,其实就是代表著美国的左右两边。</p>\n<p>在这种背景下,既然不能从市场层面上获得收入增速,就得从你自身提高收入增速,答案是什么?技术进步。现在工人工资我是压不下去了,怎么办?三个工人变两工人+机器人。所以你猜美国现在在干嘛右侧是这帮企业左侧是美国的这帮中底层的这些老百姓小日子过得太Happy了。左侧这帮企业收入增速7.5通胀5个点。开心吧挣的钱存到银行现在5个点开心吧然后08年美国次贷危机破裂了以后美国锁定在了0-0.25的这个低息区域老百姓买了低息贷款的房子储蓄多了开心吧中国出口的赚买了美国国债相当于还要回储给你们最后发现美国挣得多、存的多、债务还低。从08年到23年这15年就相当于去了15年的杠杆。企业部门要借贷5.25的利率高于目前3点几的增速被迫进入到利润下降未来要提高增长只有一个方案就是技术进步。</p>\n<p>硅谷大裁员是不影响就业的这帮生产率高的人转化再就业的能力是极强的。生产率低的人出现大规模失业才是最麻烦的。简单讲美国这帮黑人们如果全都失业了那美国就完了。08年后企业银行居民这三者的分配关系就有问题了一直拖到现在已经无解了。全世界从过去的十年只有一个大的变量”技术进步”。我个人有一种感觉当前的这个时间点在炒的人工智能跟过去的十年浮现出来的不太一样。美国股市现在就那几个科技公司拉着每股涨是好事。几家公司是在5.25的利率环境下拉动每股涨的。它不是那个0到0.25的利率拉动的能够扛得住资金成本5到5.25还能带来增长意味著AI可能是真的。</p>\n<p>08年到2028年整20年的周期足够一个新技术带动全社会变动了这几家公司可能在未来3到5年拉着美股创新高 继续创新高。后面的涨是正儿八经的生产率提高的涨,前两年是啥?是低利率推著泡沫在涨。如果美国完成了这条线,既保证了企业在技术进步下维持高利润增长,又保证底层居民获得了高收入增速,你猜美国的利率会是什么情况?他的利率会一直很高,进入到高增长、高通胀、高利率,三高。</p>\n<p>那么中国会事什么情况?美国不给技术,转化生产也不是中国制造了,逆全球化嘛!国内会低增长、低通胀、低利率。从全球分工来看,美国底层是技术研发,中间生产,下面是市场。如果生产环节不给中国,高端制造给谁?大概率是日本。</p>\n<p>日本的全球分工的角色会跟过去的二三十年不一样英国的老牌家族的基金家族办公开始跑到日本租办公室招人了二三十年前的时候跑到香港租办公室招人跑到北京设立办事处为什么答案只有一个看好该国未来20年30年的增长。</p>\n<p>在过去的20年发展过程中我们的生产环节是针对全世界的如果出不去。只能转化成内需。我们的一个大问题出来了过去的10年中国经济最大的不同就是现在的年轻人债务过高内需是背著重重的负债前行的有一些人不准备生人再去背了。直到疫情过恢复以后到现在为止不缺生产缺谁买单。内需要么是政府部门要么是居民部门一个是投资不动一个消费不动有钱的有钱死没钱的负债死。昨天我看又新能源车下乡了然后你去看看那个评论区90后崛起了不像十年前那么好骗了他们咋回答呢啥好事都想著我们农村人。十年前什么家电下乡卖不掉的冰箱……就是电器卖给我们农村人这韭菜不能照着一个地儿割啊。</p>\n<p>笃定了老美不会给我们这条科技树所以经济当前压根就不是我们最大的问题只要能守住底线也就是你的居民仍然是可爱的人底线思维即可。当下最大的目标是重建这个秩序美国不带我玩我就去拉着ABC去重构这种国际分工、全球化市场结构重构我们的科技树。中国现在的投资跟老美一样都在反映科技树但是”市场决定的科技树(市场经济)”和”政府主导的科技树(计划经济)”结局是不一样的。所以低增长、低利率的国内必须要点科技树,但体现在股票上,国内是什么光景,美股是什么光景?</p>\n<p>很多人说A股弱美股强因为人家现在高增长、高通胀、高利率、和消费市场。08年之后。老美去了15年杠杆。居民部门老老实实还了15年的债日本人老老实实还了30年。美国的利率水平绝对不再是以前的路径不再会靠降息加杠杆的方式去推动增长而是要靠生产校长的扩张技术在两三年后我们有可能会迎来一个”iPhone时刻”。</p>\n<p>我们现在所有人依旧想的是如果企业不行最终还得是降息。美国会出现一种情况就是企业的技术进步把它带上去整个美元的长短端利率都在5-5.25那我就请问你光现金和资产回报都5-5.25了你觉得黄金会奔三千四千五千吗黄金的之所以在高价因为长期利率在地位加上杠杆但是如果长短端的投资回报率在5-5.25,你还会持有黄金吗?</p>\n<p>08年金融危机以后老美痛定思痛开始在极低的利率下去除杠杆也就是讲现在你看见的美国是08年的美国导致的一个结果。而08年的中国在干什么呢所有人熟知的叫四万亿(可不止),总结一句话,就是给居民部门加杠杆。中国拖起了全球经济,代价是这一代居民部门的储蓄和杠杆,就是老百姓讲的掏空了几个钱包。</p>\n<p>真正的大交易者用什么东西做负债用什么东西当资产。如果现在世界格局是这样请问我们个人该怎么办举个例子我09年回国2010年开始到2016年股灾人民币单边每年升值3%美元官方利率0到0.2%加上手续费美元借款资金成本大约2%。就造成了实际借美元利率是-1%,那时候北上广的房价是多少?房子的背后就是人口、收入、杠杆,而其中最重要的吗,在当时,不是人口、也不是收入,而是杠杆。我的借贷成本如果-1%的话,这不就是热钱吗?借-1%的钱来中国就好了,干什么东西,买房呗!</p>\n<p>所以放到现在的今天个人该怎么办呢美国进入到三高的状态中国进入到这种三低的状态。当下经营贷3.2%人民币贬值实际人民币借贷成就是负的所以答案就是人民币长期利率水平会非常的低借贷低息的人民币人民币贬值官方的借贷成本会从3个点掉到2个点并且维持在2个点三到五年让你借贷人民币的真实利率一定在0以下。所以从大交易者的角度负债解决了资产端该买啥能够给你二字头融资成本一定说明国内的资产端没有高息回报我们不出境去哪儿找高息的资产我偷偷摸摸告诉大家过一段时间你们会发现某个类型的ETF手续费还会增加什么东西用人民币结算但是持有的是境外高息资产(QDII)美国光银行存款利率在5%你该干嘛你们会发现巴菲特买的西方石油公司、买的日本的五大商社股息率在10以上你们知道该干嘛如果这个东西一直是这样倒着咱们哪来的信心觉得外资会流入</p>\n<p>所以这就是一个重要的分水岭,这个最核心的原理理解,超级的重要!绝对对你后面三五年巨大的受益。</p>\n"},{"title":"Unity Shader入门精要","status":"done","_content":"\n代码基于`c#`,书籍 `Unity Shader`入门精要\n\n# 什么是 OpenGL、DirectX\n\n用于渲染二维或三维图形。可以说这些接口架起了上层应用程序和底层 GPU 的沟通桥梁。一个应用程序向这些接口发送渲染命令而这些接口会依次向显卡驱动Graphics Driver发送渲染命令这些显卡驱动是真正知道如何和 GPU 通信的角色,正是它们把 OpenGL 或者 DirectX 的函数调用翻译成了 GPU 能够听懂的语言,同时它们也负责把纹理等数据转换成 GPU 所支持的格式。一个比喻是,显卡驱动就是显卡的操作系统。\n\n![shader_7](/img/shader_7.png)\n\n# 什么是 HLSL、GLSL、CG\n\n如顶点着色器、片元着色器等。这些着色器的可编程性在于我们可以使用一种特定的语言来编写程序就好比我们可以用 C#来写游戏逻辑一样。\n\n着色语言是专门用于编写着色器的常见的着色语言有\n\n- DirectX 的 HLSLHigh Level Shading Language\n\n- OpenGL 的 GLSLOpenGL Shading Language\n\n- NVIDIA 的 CGC for Graphic。\n\nHLSL、GLSL、CG 都是“高级High-Level”语言但这种高级是相对于汇编语言来说的而不是像 C#相对于 C 的高级那样。这些语言会被编译成与机器无关的汇编语言也被称为中间语言Intermediate Language, IL。这些中间语言再交给显卡驱动来翻译成真正的机器语言即 GPU 可以理解的语言。\n\n# GPU 流水线\n\n当 GPU 从 CPU 那里得到渲染命令后,就会进行一系列流水线操作,最终把图元渲染到屏幕上。\n\n![shader_1](/img/shader_1.png)\n\n- 顶点着色器Vertex Shader是完全可编程的它通常用于实现顶点的空间变换、顶点着色等功能\n\n- 曲面细分着色器Tessellation Shader是一个可选的着色器它用于细分图元\n\n- 几何着色器Geometry Shader同样是一个可选的着色器它可以被用于执行逐图元Per-Primitive的着色操作或者被用于产生更多的图元\n\n- 裁剪Clipping这一阶段的目的是将那些不在摄像机视野内的顶点裁剪掉并剔除某些三角图元的面片。例如我们可以使用自定义的裁剪平面来配置裁剪区域也可以通过指令控制裁剪三角图元的正面还是背面。\n\n- 片元着色器Fragment Shader则是完全可编程的它用于实现逐片元Per-Fragment的着色操作\n\n## 顶点着色器 Vertex Shader\n\nCPU 输入进来的每个顶点都会调用一次顶点着色器。顶点着色器本身不可以创建或者销毁任何顶点而且无法得到顶点与顶点之间的关系。例如我们无法得知两个顶点是否属于同一个三角网格。但正是因为这样的相互独立性GPU 可以利用本身的特性并行化处理每一个顶点,这意味着这一阶段的处理速度会很快。\n\n顶点着色器需要完成的工作主要有\n\n- 坐标变换:把顶点坐标转换到齐次裁剪坐标系下,接着通常再由硬件做透视除法后,最终得到归一化的设备坐标(NDC)\n\n![shader_2](/img/shader_2.png)\n\n> 在 DirectX 中NDC 的 z 方向取值范围是[0,1],在 OpenGL 环境下是-1.0DirectX 中是 0.0\n\n- 逐顶点光照\n\n## 裁剪\n\n只有在单位立方体的图元才需要被继续处\n\n![shader_3](/img/shader_3.png)\n\n## 屏幕映射\n\nOpenGL 和 DirectX 之间的差异问题。OpenGL 把屏幕的左下角当成最小的窗口坐标值,而 DirectX 则定义了屏幕的左上角为最小的窗口坐标值\n\n![shader_4](/img/shader_4.png)\n\n## 光栅阶段\n\n从上一个阶段输出的信息屏幕坐标系下的顶点位置以及和它们相关的额外信息如深度值z 坐标)、法线方向、视角方向等。光栅化阶段有两个最重要的目标:计算每个图元覆盖了哪些像素,以及为这些像素计算它们的颜色。\n\n### 三角形设置\n\n如果要得到整个三角网格对像素的覆盖情况我们就必须计算每条边上的像素坐标。为了能够计算边界像素的坐标信息我们就需要得到三角形边界的表示方式。\n\n### 三角形遍历()\n\n1. 扫描变换三角形遍历Triangle Traversal阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖的话就会生成一个片元fragment、\n\n2. 使用三角网格 3 个顶点的顶点信息对整个覆盖区域的像素进行插值\n\n![shader_5](/img/shader_5.png)\n\n这一步的输出就是得到一个片元序列。需要注意的是一个片元并不是真正意义上的像素而是包含了很多状态的集合这些状态用于计算每个像素的最终颜色。这些状态包括了但不限于它的屏幕坐标、深度信息以及其他从几何阶段输出的顶点信息例如法线、纹理坐标等。\n\n## 片元着色器 Fragment Shader\n\n前面的光栅化阶段实际上并不会影响屏幕上每个像素的颜色值而是会产生一系列的数据信息用来表述一个三角网格是怎样覆盖每个像素的。而每个片元就负责存储这样一系列数据。真正会对像素产生影响的阶段是下一个流水线阶段——逐片元操作\n\n> 在 DirectX 中片元着色器被称为像素着色器Pixel Shader但片元着色器是一个更合适的名字因为此时的片元并不是一个真正意义上的像素。\n\n![shader_6](/img/shader_6.png)\n\n## 逐片元操作\n\n这一阶段有几个主要任务:\n\n- 决定每个片元的可见性。这涉及了很多测试工作,例如深度测试、模板测试等。\n\n- 如果一个片元通过了所有的测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行合并,或者说是混合。\n\n> !! 对于不透明物体开发者可以关闭混合Blend操作。这样片元着色器计算得到的颜色值就会直接覆盖掉颜色缓冲区中的像素值。但对于半透明物体我们就需要使用混合操作来让这个物体看起来是透明的。\n\n## Draw Call\n\nCPU 调用图像编程接口,如 OpenGL 中的 `glDrawElements` 命令或者 DirectX 中的 `DrawIndexedPrimitive`命令,以命令 GPU 进行渲染的操作。\n\n### CPU 和 GPU 是如何实现并行工作的?\n\n如果没有流水线化那么 CPU 需要等到 GPU 完成上一个渲染任务才能再次发送渲染命令。但这种方法显然会造成效率低下。解决方法就是使用一个命令缓冲区Command Buffer。\n\n由 CPU 向其中添加命令,而由 GPU 从中读取命令,添加和读取的过程是互相独立的。\n\n### 为什么 Draw Call 多了会影响帧率?\n\n每一个复制动作需要很多额外的操作例如分配内存、创建各种元数据等。如你所见这些操作将造成很多额外的性能开销如果我们复制了很多小文件那么这个开销将会很大\n\n### 如何减少 Draw Call\n\n尽管减少 Draw Call 的方法有很多但我们这里仅讨论使用批处理Batching的方法。我们讲过提交大量很小的 Draw Call 会造成 CPU 的性能瓶颈,即 CPU 把时间都花费在准备 Draw Call 的工作上了。那么,一个很显然的优化想法就是把很多小的 DrawCall 合并成一个大的 Draw Call这就是批处理的思想。\n\n在游戏开发过程中为了减少 Draw Call 的开销,有两点需要注意。\n\n- 避免使用大量很小的网格。当不可避免地需要使用很小的网格结构时,考虑是否可以合并它们。\n\n- 避免使用过多的材质。尽量在不同的网格之间共用同一个材质。\n\n# 你明白什么是 Shader\n\n- GPU 流水线上一些可高度编程的阶段,而由着色器编译出来的最终代码是会在 GPU 上运行的(对于固定管线的渲染来说,着色器有时等同于一些特定的渲染设置)\n\n- 有一些特定类型的着色器,如顶点着色器、片元着色器等\n\n- 依靠着色器我们可以控制流水线中的渲染细节,例如用顶点着色器来进行顶点变换以及传递数据,用片元着色器来进行逐像素的渲染。\n\n# Unity Shader\n\n> !! Unity Shader ! = 真正的 Shader\n\nUnity Shader 实际上指的就是一个 ShaderLab 文件——硬盘上以shader 作为文件后缀的一种文件,提供了一种让开发者同时控制渲染流水线中多个阶段的一种方式,不仅仅是提供 Shader 代码。\n\n作为开发者而言我们绝大部分时候只需要和 Unity Shader 打交道,而不需要关心渲染引擎底层的实现细节\n\nUnity 编辑器会把这些 CG 片段编译成低级语言如汇编语言等。通常Unity 会自动把这些 CG 片段编译到所有相关平台(这里的平台是指不同的渲染平台,例如 Direct3D 9、OpenGL、Direct3D 11、OpenGL ES 等)上\n\n## 基础\n\n在没有 Unity 这类编辑器的情况下,如果我们想要对某个模型设置渲染状态,可能需要类似下面的代码:\n\n上述伪代码仅仅是简化后的版本, 当渲染的模型数目、需要调整的着色器属性不断增多时,上述过程将变得更加复杂和冗长。\n\n而且当涉及透明物体等多物体的渲染时如果没有编辑器的帮助我们要非常小心如渲染顺序等问题。\n\n```js\n// 初始化渲染设置\nvoid Initialization() {\n // 从硬盘上加载顶点着色器的代码\n string vertexShaderCode = LoadShaderFromFile(VertexShader.shader);\n // 从硬盘上加载片元着色器的代码\n string fragmentShaderCode = LoadShaderFromFile(FragmentShader.shader);\n // 把顶点着色器加载到GPU中\n LoadVertexShaderFromString(vertexShaderCode);\n // 把片元着色器加载到GPU中\n LoadFragmentShaderFromString(fragmentShaderCode);\n // 设置名为\"vertexPosition\"的属性的输入,即模型顶点坐标\n SetVertexShaderProperty(\"vertexPosition\", vertices);\n // 设置名为\"MainTex\"的属性的输入someTexture是某张已加载的纹理\n SetVertexShaderProperty(\"MainTex\", someTexture);\n // 设置名为\"MVP\"的属性的输入MVP是之前由开发者计算好的变换矩阵\n SetVertexShaderProperty(\"MVP\", MVP);\n // 关闭混合\n Disable(Blend);\n // 设置深度测试\n Enable(ZText);\n SetZTestFunction(LessOrEqual);\n // 其他设置\n …\n}\n// 每一帧迚行渲染\nvoid OnRendering() {\n // 调用渲染命令\n DrawCall();\n // 当涉及多种渲染设置时,我们可能还需要在这里改变各种渲染设置\n ...\n}\n```\n\nVertexShader.shader\n\n```js\n// 输入顶点位置、纹理、MVP变换矩阵\nin float3 vertexPosition;\nin sampler2D MainTex;\nin Matrix4x4 MVP;\n// 输出顶点经过MVP变换后的位置\nout float4 position;\nvoid main() {\n // 使用MVP对模型顶点坐标迚行变换\n position = MVP vertexPosition;\n}\n```\n\nFragmentShader.shader\n\n```js\n// 输入VertexShader输出的position、经过光栅化程序插值后的该片元对应的position\nin float4 position;\n// 输出:该片元的颜色值\nout float4 fragColor;\nvoid main() {\n // 将片元颜色设为白色\n fragColor = float4(1.0, 1.0, 1.0, 1.0);\n}\n```\n\n## 材质和 Unity Shader\n\n总体来说在 Unity 中我们需要配合使用材质Material和 Unity Shader 才能达到需要的效果。一个最常见的流程是:\n\n- 创建一个材质\n\n- 创建一个 Unity Shader并把它赋给上一步中创建的材质\n\n- 把材质赋给要渲染的对象\n\n- 在材质面板中调整 Unity Shader 的属性,如使用的纹理、漫反射系数\n\n## Unity 表面着色器\n\n表面着色器Surface Shader是 Unity 自己创造的一种着色器代码类型。它需要的代码量很少Unity 在背后做了很多工作,但渲染的代价比较大。它在本质上和下面要讲到的顶点/片元着色器是一样的。也就是说,当给 Unity 提供一个表面着色器的时候,它在背后仍旧把它转换成对应的顶点/片元着色器。我们可以理解成,表面着色器是 Unity 对顶点/片元着色器的更高一层的抽象。它存在的价值在于Unity 为我们处理了很多光照细节,使得我们不需要再操心这些“烦人的事情”。\n\n```js\nShader \"Custom/Simple Surface Shader\" {\n SubShader {\n Tags { \"RenderType\" = \"Opaque\" }\n CGPROGRAM\n #pragma surface surf Lambert\n struct Input {\n float4 color : COLOR;\n };\n void surf (Input IN, inout SurfaceOutput o) {\n o.Albedo = 1;\n }\n ENDCG\n }\n Fallback \"Diffuse\"\n}\n```\n\n## 顶点/片元着色器\n\n```js\nShader \"Custom/Simple VertexFragment Shader\" {\n SubShader {\n Pass {\n CGPROGRAM\n #pragma vertex vert\n #pragma fragment frag\n float4 vert(float4 v : POSITION) : SV_POSITION {\n return mul (UNITY_MATRIX_MVP, v);\n }\n fixed4 frag() : SV_Target {\n return fixed4(1.0,0.0,0.0,1.0);\n }\n ENDCG\n }\n }\n}\n```\n\n# 坐标系\n\nUnity 使用的是左手坐标系\n\n## 左右手\n\n![shader_8](/img/shader_8.png)\n\n![shader_9](/img/shader_9.png)\n\n## 向量(矢量)\n\n### 模\n\n矢量的模是一个标量可以理解为是矢量在空间中的长度。它的表示符号通常是在矢量两旁分别加上一条垂直线\n\n![shader_10](/img/shader_10.png)\n\n### 单位矢量\n\n在很多情况下我们只关心矢量的方向而不是模。例如在计算光照模型时我们往往需要得到顶点的法线方向和光源方向此时我们不关心这些矢量有多长。在这些情况下我们就需要计算单位矢量unit vector\n\n单位矢量指的是那些模为 1 的矢量。单位矢量也被称为被归一化的矢量normalized vector。对任何给定的非零矢量把它转换成单位矢量的过程就被称为归一化\n\n![shader_11](/img/shader_11.png)\n\n### 点积\n\n一个向量在另一个向量方向上投影的长度是一个标量\n\n公式`a·b = |a||b|cosθ`\n\n### 向量积 ∧ ×\n\n> 向量积,数学中又称外积、叉积,物理中称矢积、叉乘\n\n几何意义一个和已有两个向量都垂直的向量法向量\n\n![shader_16](/img/shader_16.png)\n\n向量 a 和向量 b\n\n![shader_12](/img/shader_12.png)\n\n叉乘公式为\n\n![shader_13](/img/shader_13.png)\n\n其中\n\n![shader_14](/img/shader_14.png)\n\n根据 i、j、k 间关系,有:\n\n![shader_15](/img/shader_15.png)\n\n例如\n\n(1,2,3)×(-2,-1,4) = (2 × 4 - 3 × -1, 3 × -2 - 1 × 4, 1 × -1 - 2 × -2) = (11,10,3)\n\n# 矩阵变换 Vec4\n\n由于 3×3 矩阵不能表示平移操作,我们就把其扩展到了 4×4 的矩阵\n\n## 平移矩阵\n\n点的 x、y、z 分量分别增加了一个位置偏移。在 3D 中的可视化效果是,把点(x, y, z)在空间中平移了(tx, ty, tz)个单位\n\n![shader_17](/img/shader_17.png)\n\n## 缩放矩阵\n\n## 旋转矩阵\n\n旋转操作需要指定一个旋转轴这个旋转轴不一定是空间中的坐标轴但本节所讲的旋转就是指绕着空间中的 x 轴、y 轴或 z 轴进行旋转\n\n如果我们需要把点绕着 x 轴旋转 θ 度\n\n![shader_18](/img/shader_18.png)\n\n绕 y 轴的旋转\n\n![shader_19](/img/shader_19.png)\n\n绕 z 轴的旋转\n\n![shader_20](/img/shader_20.png)\n\n## 复合变换\n\n先进行大小为(2, 2, 2)的缩放,再绕 y 轴旋转 30°最后向 z 轴平移 4 个单位。\n\n> 矩阵乘法注意顺序\n\n![shader_21](/img/shader_21.png)\n\n> ?? 如果我们需要同时绕着 3 个轴进行旋转,是先绕 x 轴、再绕 y 轴最后绕 z 轴旋转还是按其他的旋转顺序呢?\n\n根据坐标系需要调整轴的顺序\n\n![shader_22](/img/shader_22.png)\n\n## 法线变换\n\n在游戏中模型的一个顶点往往会携带额外的信息而顶点法线就是其中一种信息。当我们变换一个模型的时候不仅需要变换它的顶点还需要变换顶点法线以便在后续处理如片元着色器中计算光照等。\n\n# 坐标空间\n\n事实上在我们的生活中我们也总是使用不同的坐标空间来交流。现在正在读这本书的你很可能正坐在办公室或书房中。如果问你“办公室的饮水机在哪里”你大概会回答“在办公室门的左方 3 米处。”这里,你很自然地使用了以门为原点的坐标空间。\n\n要想定义一个坐标空间必须指明其原点位置和 3 个坐标轴的方向。而这些数值实际上是相对于另一个坐标空间的读者需要记住所有的都是相对的。也就是说坐标空间会形成一个层次结构——每个坐标空间都是另一个坐标空间的子空间反过来说每个空间都有一个父parent坐标空间。对坐标空间的变换实际上就是在父空间和子空间之间对点和矢量进行变换。\n\n## 模型空间\n\n每个模型都有自己独立的坐标空间当它移动或旋转的时候模型空间也会跟着它移动和旋转。\n\n> Unity 在模型空间中使用的是左手坐标系,因此在模型空间中,+x 轴、+y 轴、+z 轴分别对应的是模型的右、上和前向。\n\n![shader_24](/img/shader_24.png)\n\n## 世界空间\n\n世界空间world space是一个特殊的坐标系因为它建立了我们所关心的最大的空间。一些读者可能会指出空间可以是无限大的怎么会有“最大”这一说呢这里说的最大指的是一个宏观的概念也就是说它是我们所关心的`最外层`的坐标空间。\n\n## 摄像机空间\n\n摄像机决定了我们渲染游戏所使用的视角。在观察空间中摄像机位于原点\n\n> Unity 中观察空间的坐标轴选择是:+x 轴指向右方,+y 轴指向上方,而+z 轴指向的是摄像机的后方\n\nQ模型空间和世界空间中+z 轴指的都是物体的前方,为什么这里不一样了呢?\n\nAUnity 在模型空间和世界空间中选用的都是左手坐标系,而在观察空间中使用的是右手坐标系。这是符合 OpenGL 传统的,在这样的观察空间中,摄像机的正前方指向的是-z 轴方向。\n\n## 裁剪空间\n\n用于变换的矩阵叫做裁剪矩阵clip matrix也被称为投影矩阵projection matrix。位于这块空间内部的图元将会被保留否则他剔除。由视锥体view frustum来决定。\n\n![shader_26](/img/shader_26.png)\n\n视锥体指的是空间中的一块区域这块区域决定了摄像机可以看到的空间。视锥体由六个平面包围而成这些平面也被称为裁剪平面clip planes。视锥体有两种类型这涉及两种投影类型\n\n- 正交投影orthographic projection所有的网格大小都一样而且平行线会一直保持平行\n- 透视投影perspective projection地板上的平行线并不会保持平行离摄像机越近网格越大离摄像机越远网格越小。\n\n![shader_25](/img/shader_25.png)\n\n> 追求真实感的 3D 游戏中我们往往会使用透视投影,而在一些 2D 游戏或渲染小地图等其他 HUD 元素时,我们会使用正交投影\n\n### 透视摄像机视锥体模型\n\n在 Unity 中,一个摄像机的横纵比由 Game 视图的横纵比和 Viewport Rect 中的 `W` 和 `H` 属性共同决定实际上Unity 允许我们在脚本里通过 `Camera.aspect` 进行更改,但这里不做讨论)\n\n![shader_27](/img/shader_27.png)\n\n### 正交摄像机视锥体模型\n\n通过 Camera 组件的 `Size` 属性来改变视锥体竖直方向上高度的一半,而 Clipping Planes 中的 Near 和 Far 参数可以控制视锥体的近裁剪平面和远裁剪平面距离摄像机的远近。\n\n![shader_28](/img/shader_28.png)\n\n## 屏幕空间\n\n> 在 Unity 中,从裁剪空间到屏幕空间的转换是由 Unity 帮我们完成的。\n\n屏幕空间是一个二维空间因此我们必须把顶点从裁剪空间投影到屏幕空间中来生成对应的 2D 坐标。这个过程可以理解成有两个步骤:\n\n1. 标准齐次除法(透视除法):用齐次坐标系的 w 分量去除以 x、y、z 分量,在 OpenGL 中得到的坐标叫做归一化的设备坐标Normalized Device Coordinates, NDC\n\n经过透视投影变换后的裁剪空间经过齐次除法后会变换到一个立方体内。按照 OpenGL 的传统,这个立方体的 x、y、z 分量的范围都是[-1, 1]。但在 DirectX 这样的 API 中z 分量的范围会是[0, 1]。而 Unity 选择了 OpenGL 这样的齐次裁剪空间,如图所示\n\n![shader_29](/img/shader_29.png)\n\n而对于正交投影来说它的裁剪空间实际已经是一个立方体了而且由于经过正交投影矩阵变换后的顶点的 w 分量是 1因此齐次除法并不会对顶点的 x、y、z 坐标产生影响,如图所示\n\n![shader_30](/img/shader_30.png)\n\n2. 映射输出窗口的对应像素坐标\n\n## Unity 内置变换矩阵\n\n| 变量名 | 描述 |\n| ------------------ | ---------------------------------------------------------------------------------------------------- |\n| UNITY MATRIX MVP | 当前的模型·观察·投影矩阵,用于将顶点/方向矢量从模型空间变换到裁剪空间 |\n| UNITY MATRIX MV | 当前的模型·观察矩阵,用于将顶点/方向矢量从模型空间变换到观察空间 |\n| UNITY MATRIX V | 当前的观察矩阵,用于将顶点/方向矢量从世界空间变换到观察空间 |\n| UNITY MATRIX P | 当前的投影矩阵,用于将顶点/方向矢量从观察空间变换到裁剪空间 |\n| UNITY MATRIX VP | 当前的观察投影矩阵,用于将顶点/方向矢量从世界空间变换到裁剪空间 |\n| UNITY MATRIX T MV | UNITYMATRIX MV 的转置矩阵 |\n| UNITY MATRIX IT MV | UNITYMATRIX MV 的逆转置矩阵,用于将法线从模型空间变换到观察空间,也可用于得到 UNITYMATRIXMV 的逆矩阵 |\n| Object2World | 当前的模型矩阵,用于将顶点/方向矢量从模型空间变换到世界空间 |\n| World2Object | Object2World 的逆矩阵,用于将顶点/方向矢量从世界空间变换到模型空间 |\n\n\n","source":"_posts/front-end/Unity Shader入门精要.md","raw":"---\ntitle: Unity Shader入门精要\ncategories:\n - Front-End\nstatus: done\n---\n\n代码基于`c#`,书籍 `Unity Shader`入门精要\n\n# 什么是 OpenGL、DirectX\n\n用于渲染二维或三维图形。可以说这些接口架起了上层应用程序和底层 GPU 的沟通桥梁。一个应用程序向这些接口发送渲染命令而这些接口会依次向显卡驱动Graphics Driver发送渲染命令这些显卡驱动是真正知道如何和 GPU 通信的角色,正是它们把 OpenGL 或者 DirectX 的函数调用翻译成了 GPU 能够听懂的语言,同时它们也负责把纹理等数据转换成 GPU 所支持的格式。一个比喻是,显卡驱动就是显卡的操作系统。\n\n![shader_7](/img/shader_7.png)\n\n# 什么是 HLSL、GLSL、CG\n\n如顶点着色器、片元着色器等。这些着色器的可编程性在于我们可以使用一种特定的语言来编写程序就好比我们可以用 C#来写游戏逻辑一样。\n\n着色语言是专门用于编写着色器的常见的着色语言有\n\n- DirectX 的 HLSLHigh Level Shading Language\n\n- OpenGL 的 GLSLOpenGL Shading Language\n\n- NVIDIA 的 CGC for Graphic。\n\nHLSL、GLSL、CG 都是“高级High-Level”语言但这种高级是相对于汇编语言来说的而不是像 C#相对于 C 的高级那样。这些语言会被编译成与机器无关的汇编语言也被称为中间语言Intermediate Language, IL。这些中间语言再交给显卡驱动来翻译成真正的机器语言即 GPU 可以理解的语言。\n\n# GPU 流水线\n\n当 GPU 从 CPU 那里得到渲染命令后,就会进行一系列流水线操作,最终把图元渲染到屏幕上。\n\n![shader_1](/img/shader_1.png)\n\n- 顶点着色器Vertex Shader是完全可编程的它通常用于实现顶点的空间变换、顶点着色等功能\n\n- 曲面细分着色器Tessellation Shader是一个可选的着色器它用于细分图元\n\n- 几何着色器Geometry Shader同样是一个可选的着色器它可以被用于执行逐图元Per-Primitive的着色操作或者被用于产生更多的图元\n\n- 裁剪Clipping这一阶段的目的是将那些不在摄像机视野内的顶点裁剪掉并剔除某些三角图元的面片。例如我们可以使用自定义的裁剪平面来配置裁剪区域也可以通过指令控制裁剪三角图元的正面还是背面。\n\n- 片元着色器Fragment Shader则是完全可编程的它用于实现逐片元Per-Fragment的着色操作\n\n## 顶点着色器 Vertex Shader\n\nCPU 输入进来的每个顶点都会调用一次顶点着色器。顶点着色器本身不可以创建或者销毁任何顶点而且无法得到顶点与顶点之间的关系。例如我们无法得知两个顶点是否属于同一个三角网格。但正是因为这样的相互独立性GPU 可以利用本身的特性并行化处理每一个顶点,这意味着这一阶段的处理速度会很快。\n\n顶点着色器需要完成的工作主要有\n\n- 坐标变换:把顶点坐标转换到齐次裁剪坐标系下,接着通常再由硬件做透视除法后,最终得到归一化的设备坐标(NDC)\n\n![shader_2](/img/shader_2.png)\n\n> 在 DirectX 中NDC 的 z 方向取值范围是[0,1],在 OpenGL 环境下是-1.0DirectX 中是 0.0\n\n- 逐顶点光照\n\n## 裁剪\n\n只有在单位立方体的图元才需要被继续处\n\n![shader_3](/img/shader_3.png)\n\n## 屏幕映射\n\nOpenGL 和 DirectX 之间的差异问题。OpenGL 把屏幕的左下角当成最小的窗口坐标值,而 DirectX 则定义了屏幕的左上角为最小的窗口坐标值\n\n![shader_4](/img/shader_4.png)\n\n## 光栅阶段\n\n从上一个阶段输出的信息屏幕坐标系下的顶点位置以及和它们相关的额外信息如深度值z 坐标)、法线方向、视角方向等。光栅化阶段有两个最重要的目标:计算每个图元覆盖了哪些像素,以及为这些像素计算它们的颜色。\n\n### 三角形设置\n\n如果要得到整个三角网格对像素的覆盖情况我们就必须计算每条边上的像素坐标。为了能够计算边界像素的坐标信息我们就需要得到三角形边界的表示方式。\n\n### 三角形遍历()\n\n1. 扫描变换三角形遍历Triangle Traversal阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖的话就会生成一个片元fragment、\n\n2. 使用三角网格 3 个顶点的顶点信息对整个覆盖区域的像素进行插值\n\n![shader_5](/img/shader_5.png)\n\n这一步的输出就是得到一个片元序列。需要注意的是一个片元并不是真正意义上的像素而是包含了很多状态的集合这些状态用于计算每个像素的最终颜色。这些状态包括了但不限于它的屏幕坐标、深度信息以及其他从几何阶段输出的顶点信息例如法线、纹理坐标等。\n\n## 片元着色器 Fragment Shader\n\n前面的光栅化阶段实际上并不会影响屏幕上每个像素的颜色值而是会产生一系列的数据信息用来表述一个三角网格是怎样覆盖每个像素的。而每个片元就负责存储这样一系列数据。真正会对像素产生影响的阶段是下一个流水线阶段——逐片元操作\n\n> 在 DirectX 中片元着色器被称为像素着色器Pixel Shader但片元着色器是一个更合适的名字因为此时的片元并不是一个真正意义上的像素。\n\n![shader_6](/img/shader_6.png)\n\n## 逐片元操作\n\n这一阶段有几个主要任务:\n\n- 决定每个片元的可见性。这涉及了很多测试工作,例如深度测试、模板测试等。\n\n- 如果一个片元通过了所有的测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行合并,或者说是混合。\n\n> !! 对于不透明物体开发者可以关闭混合Blend操作。这样片元着色器计算得到的颜色值就会直接覆盖掉颜色缓冲区中的像素值。但对于半透明物体我们就需要使用混合操作来让这个物体看起来是透明的。\n\n## Draw Call\n\nCPU 调用图像编程接口,如 OpenGL 中的 `glDrawElements` 命令或者 DirectX 中的 `DrawIndexedPrimitive`命令,以命令 GPU 进行渲染的操作。\n\n### CPU 和 GPU 是如何实现并行工作的?\n\n如果没有流水线化那么 CPU 需要等到 GPU 完成上一个渲染任务才能再次发送渲染命令。但这种方法显然会造成效率低下。解决方法就是使用一个命令缓冲区Command Buffer。\n\n由 CPU 向其中添加命令,而由 GPU 从中读取命令,添加和读取的过程是互相独立的。\n\n### 为什么 Draw Call 多了会影响帧率?\n\n每一个复制动作需要很多额外的操作例如分配内存、创建各种元数据等。如你所见这些操作将造成很多额外的性能开销如果我们复制了很多小文件那么这个开销将会很大\n\n### 如何减少 Draw Call\n\n尽管减少 Draw Call 的方法有很多但我们这里仅讨论使用批处理Batching的方法。我们讲过提交大量很小的 Draw Call 会造成 CPU 的性能瓶颈,即 CPU 把时间都花费在准备 Draw Call 的工作上了。那么,一个很显然的优化想法就是把很多小的 DrawCall 合并成一个大的 Draw Call这就是批处理的思想。\n\n在游戏开发过程中为了减少 Draw Call 的开销,有两点需要注意。\n\n- 避免使用大量很小的网格。当不可避免地需要使用很小的网格结构时,考虑是否可以合并它们。\n\n- 避免使用过多的材质。尽量在不同的网格之间共用同一个材质。\n\n# 你明白什么是 Shader\n\n- GPU 流水线上一些可高度编程的阶段,而由着色器编译出来的最终代码是会在 GPU 上运行的(对于固定管线的渲染来说,着色器有时等同于一些特定的渲染设置)\n\n- 有一些特定类型的着色器,如顶点着色器、片元着色器等\n\n- 依靠着色器我们可以控制流水线中的渲染细节,例如用顶点着色器来进行顶点变换以及传递数据,用片元着色器来进行逐像素的渲染。\n\n# Unity Shader\n\n> !! Unity Shader ! = 真正的 Shader\n\nUnity Shader 实际上指的就是一个 ShaderLab 文件——硬盘上以shader 作为文件后缀的一种文件,提供了一种让开发者同时控制渲染流水线中多个阶段的一种方式,不仅仅是提供 Shader 代码。\n\n作为开发者而言我们绝大部分时候只需要和 Unity Shader 打交道,而不需要关心渲染引擎底层的实现细节\n\nUnity 编辑器会把这些 CG 片段编译成低级语言如汇编语言等。通常Unity 会自动把这些 CG 片段编译到所有相关平台(这里的平台是指不同的渲染平台,例如 Direct3D 9、OpenGL、Direct3D 11、OpenGL ES 等)上\n\n## 基础\n\n在没有 Unity 这类编辑器的情况下,如果我们想要对某个模型设置渲染状态,可能需要类似下面的代码:\n\n上述伪代码仅仅是简化后的版本, 当渲染的模型数目、需要调整的着色器属性不断增多时,上述过程将变得更加复杂和冗长。\n\n而且当涉及透明物体等多物体的渲染时如果没有编辑器的帮助我们要非常小心如渲染顺序等问题。\n\n```js\n// 初始化渲染设置\nvoid Initialization() {\n // 从硬盘上加载顶点着色器的代码\n string vertexShaderCode = LoadShaderFromFile(VertexShader.shader);\n // 从硬盘上加载片元着色器的代码\n string fragmentShaderCode = LoadShaderFromFile(FragmentShader.shader);\n // 把顶点着色器加载到GPU中\n LoadVertexShaderFromString(vertexShaderCode);\n // 把片元着色器加载到GPU中\n LoadFragmentShaderFromString(fragmentShaderCode);\n // 设置名为\"vertexPosition\"的属性的输入,即模型顶点坐标\n SetVertexShaderProperty(\"vertexPosition\", vertices);\n // 设置名为\"MainTex\"的属性的输入someTexture是某张已加载的纹理\n SetVertexShaderProperty(\"MainTex\", someTexture);\n // 设置名为\"MVP\"的属性的输入MVP是之前由开发者计算好的变换矩阵\n SetVertexShaderProperty(\"MVP\", MVP);\n // 关闭混合\n Disable(Blend);\n // 设置深度测试\n Enable(ZText);\n SetZTestFunction(LessOrEqual);\n // 其他设置\n …\n}\n// 每一帧迚行渲染\nvoid OnRendering() {\n // 调用渲染命令\n DrawCall();\n // 当涉及多种渲染设置时,我们可能还需要在这里改变各种渲染设置\n ...\n}\n```\n\nVertexShader.shader\n\n```js\n// 输入顶点位置、纹理、MVP变换矩阵\nin float3 vertexPosition;\nin sampler2D MainTex;\nin Matrix4x4 MVP;\n// 输出顶点经过MVP变换后的位置\nout float4 position;\nvoid main() {\n // 使用MVP对模型顶点坐标迚行变换\n position = MVP vertexPosition;\n}\n```\n\nFragmentShader.shader\n\n```js\n// 输入VertexShader输出的position、经过光栅化程序插值后的该片元对应的position\nin float4 position;\n// 输出:该片元的颜色值\nout float4 fragColor;\nvoid main() {\n // 将片元颜色设为白色\n fragColor = float4(1.0, 1.0, 1.0, 1.0);\n}\n```\n\n## 材质和 Unity Shader\n\n总体来说在 Unity 中我们需要配合使用材质Material和 Unity Shader 才能达到需要的效果。一个最常见的流程是:\n\n- 创建一个材质\n\n- 创建一个 Unity Shader并把它赋给上一步中创建的材质\n\n- 把材质赋给要渲染的对象\n\n- 在材质面板中调整 Unity Shader 的属性,如使用的纹理、漫反射系数\n\n## Unity 表面着色器\n\n表面着色器Surface Shader是 Unity 自己创造的一种着色器代码类型。它需要的代码量很少Unity 在背后做了很多工作,但渲染的代价比较大。它在本质上和下面要讲到的顶点/片元着色器是一样的。也就是说,当给 Unity 提供一个表面着色器的时候,它在背后仍旧把它转换成对应的顶点/片元着色器。我们可以理解成,表面着色器是 Unity 对顶点/片元着色器的更高一层的抽象。它存在的价值在于Unity 为我们处理了很多光照细节,使得我们不需要再操心这些“烦人的事情”。\n\n```js\nShader \"Custom/Simple Surface Shader\" {\n SubShader {\n Tags { \"RenderType\" = \"Opaque\" }\n CGPROGRAM\n #pragma surface surf Lambert\n struct Input {\n float4 color : COLOR;\n };\n void surf (Input IN, inout SurfaceOutput o) {\n o.Albedo = 1;\n }\n ENDCG\n }\n Fallback \"Diffuse\"\n}\n```\n\n## 顶点/片元着色器\n\n```js\nShader \"Custom/Simple VertexFragment Shader\" {\n SubShader {\n Pass {\n CGPROGRAM\n #pragma vertex vert\n #pragma fragment frag\n float4 vert(float4 v : POSITION) : SV_POSITION {\n return mul (UNITY_MATRIX_MVP, v);\n }\n fixed4 frag() : SV_Target {\n return fixed4(1.0,0.0,0.0,1.0);\n }\n ENDCG\n }\n }\n}\n```\n\n# 坐标系\n\nUnity 使用的是左手坐标系\n\n## 左右手\n\n![shader_8](/img/shader_8.png)\n\n![shader_9](/img/shader_9.png)\n\n## 向量(矢量)\n\n### 模\n\n矢量的模是一个标量可以理解为是矢量在空间中的长度。它的表示符号通常是在矢量两旁分别加上一条垂直线\n\n![shader_10](/img/shader_10.png)\n\n### 单位矢量\n\n在很多情况下我们只关心矢量的方向而不是模。例如在计算光照模型时我们往往需要得到顶点的法线方向和光源方向此时我们不关心这些矢量有多长。在这些情况下我们就需要计算单位矢量unit vector\n\n单位矢量指的是那些模为 1 的矢量。单位矢量也被称为被归一化的矢量normalized vector。对任何给定的非零矢量把它转换成单位矢量的过程就被称为归一化\n\n![shader_11](/img/shader_11.png)\n\n### 点积\n\n一个向量在另一个向量方向上投影的长度是一个标量\n\n公式`a·b = |a||b|cosθ`\n\n### 向量积 ∧ ×\n\n> 向量积,数学中又称外积、叉积,物理中称矢积、叉乘\n\n几何意义一个和已有两个向量都垂直的向量法向量\n\n![shader_16](/img/shader_16.png)\n\n向量 a 和向量 b\n\n![shader_12](/img/shader_12.png)\n\n叉乘公式为\n\n![shader_13](/img/shader_13.png)\n\n其中\n\n![shader_14](/img/shader_14.png)\n\n根据 i、j、k 间关系,有:\n\n![shader_15](/img/shader_15.png)\n\n例如\n\n(1,2,3)×(-2,-1,4) = (2 × 4 - 3 × -1, 3 × -2 - 1 × 4, 1 × -1 - 2 × -2) = (11,10,3)\n\n# 矩阵变换 Vec4\n\n由于 3×3 矩阵不能表示平移操作,我们就把其扩展到了 4×4 的矩阵\n\n## 平移矩阵\n\n点的 x、y、z 分量分别增加了一个位置偏移。在 3D 中的可视化效果是,把点(x, y, z)在空间中平移了(tx, ty, tz)个单位\n\n![shader_17](/img/shader_17.png)\n\n## 缩放矩阵\n\n## 旋转矩阵\n\n旋转操作需要指定一个旋转轴这个旋转轴不一定是空间中的坐标轴但本节所讲的旋转就是指绕着空间中的 x 轴、y 轴或 z 轴进行旋转\n\n如果我们需要把点绕着 x 轴旋转 θ 度\n\n![shader_18](/img/shader_18.png)\n\n绕 y 轴的旋转\n\n![shader_19](/img/shader_19.png)\n\n绕 z 轴的旋转\n\n![shader_20](/img/shader_20.png)\n\n## 复合变换\n\n先进行大小为(2, 2, 2)的缩放,再绕 y 轴旋转 30°最后向 z 轴平移 4 个单位。\n\n> 矩阵乘法注意顺序\n\n![shader_21](/img/shader_21.png)\n\n> ?? 如果我们需要同时绕着 3 个轴进行旋转,是先绕 x 轴、再绕 y 轴最后绕 z 轴旋转还是按其他的旋转顺序呢?\n\n根据坐标系需要调整轴的顺序\n\n![shader_22](/img/shader_22.png)\n\n## 法线变换\n\n在游戏中模型的一个顶点往往会携带额外的信息而顶点法线就是其中一种信息。当我们变换一个模型的时候不仅需要变换它的顶点还需要变换顶点法线以便在后续处理如片元着色器中计算光照等。\n\n# 坐标空间\n\n事实上在我们的生活中我们也总是使用不同的坐标空间来交流。现在正在读这本书的你很可能正坐在办公室或书房中。如果问你“办公室的饮水机在哪里”你大概会回答“在办公室门的左方 3 米处。”这里,你很自然地使用了以门为原点的坐标空间。\n\n要想定义一个坐标空间必须指明其原点位置和 3 个坐标轴的方向。而这些数值实际上是相对于另一个坐标空间的读者需要记住所有的都是相对的。也就是说坐标空间会形成一个层次结构——每个坐标空间都是另一个坐标空间的子空间反过来说每个空间都有一个父parent坐标空间。对坐标空间的变换实际上就是在父空间和子空间之间对点和矢量进行变换。\n\n## 模型空间\n\n每个模型都有自己独立的坐标空间当它移动或旋转的时候模型空间也会跟着它移动和旋转。\n\n> Unity 在模型空间中使用的是左手坐标系,因此在模型空间中,+x 轴、+y 轴、+z 轴分别对应的是模型的右、上和前向。\n\n![shader_24](/img/shader_24.png)\n\n## 世界空间\n\n世界空间world space是一个特殊的坐标系因为它建立了我们所关心的最大的空间。一些读者可能会指出空间可以是无限大的怎么会有“最大”这一说呢这里说的最大指的是一个宏观的概念也就是说它是我们所关心的`最外层`的坐标空间。\n\n## 摄像机空间\n\n摄像机决定了我们渲染游戏所使用的视角。在观察空间中摄像机位于原点\n\n> Unity 中观察空间的坐标轴选择是:+x 轴指向右方,+y 轴指向上方,而+z 轴指向的是摄像机的后方\n\nQ模型空间和世界空间中+z 轴指的都是物体的前方,为什么这里不一样了呢?\n\nAUnity 在模型空间和世界空间中选用的都是左手坐标系,而在观察空间中使用的是右手坐标系。这是符合 OpenGL 传统的,在这样的观察空间中,摄像机的正前方指向的是-z 轴方向。\n\n## 裁剪空间\n\n用于变换的矩阵叫做裁剪矩阵clip matrix也被称为投影矩阵projection matrix。位于这块空间内部的图元将会被保留否则他剔除。由视锥体view frustum来决定。\n\n![shader_26](/img/shader_26.png)\n\n视锥体指的是空间中的一块区域这块区域决定了摄像机可以看到的空间。视锥体由六个平面包围而成这些平面也被称为裁剪平面clip planes。视锥体有两种类型这涉及两种投影类型\n\n- 正交投影orthographic projection所有的网格大小都一样而且平行线会一直保持平行\n- 透视投影perspective projection地板上的平行线并不会保持平行离摄像机越近网格越大离摄像机越远网格越小。\n\n![shader_25](/img/shader_25.png)\n\n> 追求真实感的 3D 游戏中我们往往会使用透视投影,而在一些 2D 游戏或渲染小地图等其他 HUD 元素时,我们会使用正交投影\n\n### 透视摄像机视锥体模型\n\n在 Unity 中,一个摄像机的横纵比由 Game 视图的横纵比和 Viewport Rect 中的 `W` 和 `H` 属性共同决定实际上Unity 允许我们在脚本里通过 `Camera.aspect` 进行更改,但这里不做讨论)\n\n![shader_27](/img/shader_27.png)\n\n### 正交摄像机视锥体模型\n\n通过 Camera 组件的 `Size` 属性来改变视锥体竖直方向上高度的一半,而 Clipping Planes 中的 Near 和 Far 参数可以控制视锥体的近裁剪平面和远裁剪平面距离摄像机的远近。\n\n![shader_28](/img/shader_28.png)\n\n## 屏幕空间\n\n> 在 Unity 中,从裁剪空间到屏幕空间的转换是由 Unity 帮我们完成的。\n\n屏幕空间是一个二维空间因此我们必须把顶点从裁剪空间投影到屏幕空间中来生成对应的 2D 坐标。这个过程可以理解成有两个步骤:\n\n1. 标准齐次除法(透视除法):用齐次坐标系的 w 分量去除以 x、y、z 分量,在 OpenGL 中得到的坐标叫做归一化的设备坐标Normalized Device Coordinates, NDC\n\n经过透视投影变换后的裁剪空间经过齐次除法后会变换到一个立方体内。按照 OpenGL 的传统,这个立方体的 x、y、z 分量的范围都是[-1, 1]。但在 DirectX 这样的 API 中z 分量的范围会是[0, 1]。而 Unity 选择了 OpenGL 这样的齐次裁剪空间,如图所示\n\n![shader_29](/img/shader_29.png)\n\n而对于正交投影来说它的裁剪空间实际已经是一个立方体了而且由于经过正交投影矩阵变换后的顶点的 w 分量是 1因此齐次除法并不会对顶点的 x、y、z 坐标产生影响,如图所示\n\n![shader_30](/img/shader_30.png)\n\n2. 映射输出窗口的对应像素坐标\n\n## Unity 内置变换矩阵\n\n| 变量名 | 描述 |\n| ------------------ | ---------------------------------------------------------------------------------------------------- |\n| UNITY MATRIX MVP | 当前的模型·观察·投影矩阵,用于将顶点/方向矢量从模型空间变换到裁剪空间 |\n| UNITY MATRIX MV | 当前的模型·观察矩阵,用于将顶点/方向矢量从模型空间变换到观察空间 |\n| UNITY MATRIX V | 当前的观察矩阵,用于将顶点/方向矢量从世界空间变换到观察空间 |\n| UNITY MATRIX P | 当前的投影矩阵,用于将顶点/方向矢量从观察空间变换到裁剪空间 |\n| UNITY MATRIX VP | 当前的观察投影矩阵,用于将顶点/方向矢量从世界空间变换到裁剪空间 |\n| UNITY MATRIX T MV | UNITYMATRIX MV 的转置矩阵 |\n| UNITY MATRIX IT MV | UNITYMATRIX MV 的逆转置矩阵,用于将法线从模型空间变换到观察空间,也可用于得到 UNITYMATRIXMV 的逆矩阵 |\n| Object2World | 当前的模型矩阵,用于将顶点/方向矢量从模型空间变换到世界空间 |\n| World2Object | Object2World 的逆矩阵,用于将顶点/方向矢量从世界空间变换到模型空间 |\n\n\n","slug":"front-end/Unity Shader入门精要","published":1,"date":"2023-11-06T08:00:24.546Z","updated":"2023-11-06T08:08:10.905Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58m00074cz31y3lcvvy","content":"<p>代码基于<code>c#</code>,书籍 <code>Unity Shader</code>入门精要</p>\n<h1 id=\"什么是-OpenGL、DirectX\"><a href=\"#什么是-OpenGL、DirectX\" class=\"headerlink\" title=\"什么是 OpenGL、DirectX\"></a>什么是 OpenGL、DirectX</h1><p>用于渲染二维或三维图形。可以说,这些接口架起了上层应用程序和底层 GPU 的沟通桥梁。一个应用程序向这些接口发送渲染命令而这些接口会依次向显卡驱动Graphics Driver发送渲染命令这些显卡驱动是真正知道如何和 GPU 通信的角色,正是它们把 OpenGL 或者 DirectX 的函数调用翻译成了 GPU 能够听懂的语言,同时它们也负责把纹理等数据转换成 GPU 所支持的格式。一个比喻是,显卡驱动就是显卡的操作系统。</p>\n<p><img src=\"/img/shader_7.png\" alt=\"shader_7\"></p>\n<h1 id=\"什么是-HLSL、GLSL、CG\"><a href=\"#什么是-HLSL、GLSL、CG\" class=\"headerlink\" title=\"什么是 HLSL、GLSL、CG\"></a>什么是 HLSL、GLSL、CG</h1><p>如顶点着色器、片元着色器等。这些着色器的可编程性在于,我们可以使用一种特定的语言来编写程序,就好比我们可以用 C#来写游戏逻辑一样。</p>\n<p>着色语言是专门用于编写着色器的,常见的着色语言有</p>\n<ul>\n<li><p>DirectX 的 HLSLHigh Level Shading Language</p>\n</li>\n<li><p>OpenGL 的 GLSLOpenGL Shading Language</p>\n</li>\n<li><p>NVIDIA 的 CGC for Graphic。</p>\n</li>\n</ul>\n<p>HLSL、GLSL、CG 都是“高级High-Level”语言但这种高级是相对于汇编语言来说的而不是像 C#相对于 C 的高级那样。这些语言会被编译成与机器无关的汇编语言也被称为中间语言Intermediate Language, IL。这些中间语言再交给显卡驱动来翻译成真正的机器语言即 GPU 可以理解的语言。</p>\n<h1 id=\"GPU-流水线\"><a href=\"#GPU-流水线\" class=\"headerlink\" title=\"GPU 流水线\"></a>GPU 流水线</h1><p>当 GPU 从 CPU 那里得到渲染命令后,就会进行一系列流水线操作,最终把图元渲染到屏幕上。</p>\n<p><img src=\"/img/shader_1.png\" alt=\"shader_1\"></p>\n<ul>\n<li><p>顶点着色器Vertex Shader是完全可编程的它通常用于实现顶点的空间变换、顶点着色等功能</p>\n</li>\n<li><p>曲面细分着色器Tessellation Shader是一个可选的着色器它用于细分图元</p>\n</li>\n<li><p>几何着色器Geometry Shader同样是一个可选的着色器它可以被用于执行逐图元Per-Primitive的着色操作或者被用于产生更多的图元</p>\n</li>\n<li><p>裁剪Clipping这一阶段的目的是将那些不在摄像机视野内的顶点裁剪掉并剔除某些三角图元的面片。例如我们可以使用自定义的裁剪平面来配置裁剪区域也可以通过指令控制裁剪三角图元的正面还是背面。</p>\n</li>\n<li><p>片元着色器Fragment Shader则是完全可编程的它用于实现逐片元Per-Fragment的着色操作</p>\n</li>\n</ul>\n<h2 id=\"顶点着色器-Vertex-Shader\"><a href=\"#顶点着色器-Vertex-Shader\" class=\"headerlink\" title=\"顶点着色器 Vertex Shader\"></a>顶点着色器 Vertex Shader</h2><p>CPU 输入进来的每个顶点都会调用一次顶点着色器。顶点着色器本身不可以创建或者销毁任何顶点而且无法得到顶点与顶点之间的关系。例如我们无法得知两个顶点是否属于同一个三角网格。但正是因为这样的相互独立性GPU 可以利用本身的特性并行化处理每一个顶点,这意味着这一阶段的处理速度会很快。</p>\n<p>顶点着色器需要完成的工作主要有:</p>\n<ul>\n<li>坐标变换:把顶点坐标转换到齐次裁剪坐标系下,接着通常再由硬件做透视除法后,最终得到归一化的设备坐标(NDC)</li>\n</ul>\n<p><img src=\"/img/shader_2.png\" alt=\"shader_2\"></p>\n<blockquote>\n<p>在 DirectX 中NDC 的 z 方向取值范围是[0,1],在 OpenGL 环境下是-1.0DirectX 中是 0.0</p>\n</blockquote>\n<ul>\n<li>逐顶点光照</li>\n</ul>\n<h2 id=\"裁剪\"><a href=\"#裁剪\" class=\"headerlink\" title=\"裁剪\"></a>裁剪</h2><p>只有在单位立方体的图元才需要被继续处</p>\n<p><img src=\"/img/shader_3.png\" alt=\"shader_3\"></p>\n<h2 id=\"屏幕映射\"><a href=\"#屏幕映射\" class=\"headerlink\" title=\"屏幕映射\"></a>屏幕映射</h2><p>OpenGL 和 DirectX 之间的差异问题。OpenGL 把屏幕的左下角当成最小的窗口坐标值,而 DirectX 则定义了屏幕的左上角为最小的窗口坐标值</p>\n<p><img src=\"/img/shader_4.png\" alt=\"shader_4\"></p>\n<h2 id=\"光栅阶段\"><a href=\"#光栅阶段\" class=\"headerlink\" title=\"光栅阶段\"></a>光栅阶段</h2><p>从上一个阶段输出的信息屏幕坐标系下的顶点位置以及和它们相关的额外信息如深度值z 坐标)、法线方向、视角方向等。光栅化阶段有两个最重要的目标:计算每个图元覆盖了哪些像素,以及为这些像素计算它们的颜色。</p>\n<h3 id=\"三角形设置\"><a href=\"#三角形设置\" class=\"headerlink\" title=\"三角形设置\"></a>三角形设置</h3><p>如果要得到整个三角网格对像素的覆盖情况,我们就必须计算每条边上的像素坐标。为了能够计算边界像素的坐标信息,我们就需要得到三角形边界的表示方式。</p>\n<h3 id=\"三角形遍历\"><a href=\"#三角形遍历\" class=\"headerlink\" title=\"三角形遍历()\"></a>三角形遍历()</h3><ol>\n<li><p>扫描变换三角形遍历Triangle Traversal阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖的话就会生成一个片元fragment、</p>\n</li>\n<li><p>使用三角网格 3 个顶点的顶点信息对整个覆盖区域的像素进行插值</p>\n</li>\n</ol>\n<p><img src=\"/img/shader_5.png\" alt=\"shader_5\"></p>\n<p>这一步的输出就是得到一个片元序列。需要注意的是,一个片元并不是真正意义上的像素,而是包含了很多状态的集合,这些状态用于计算每个像素的最终颜色。这些状态包括了(但不限于)它的屏幕坐标、深度信息,以及其他从几何阶段输出的顶点信息,例如法线、纹理坐标等。</p>\n<h2 id=\"片元着色器-Fragment-Shader\"><a href=\"#片元着色器-Fragment-Shader\" class=\"headerlink\" title=\"片元着色器 Fragment Shader\"></a>片元着色器 Fragment Shader</h2><p>前面的光栅化阶段实际上并不会影响屏幕上每个像素的颜色值,而是会产生一系列的数据信息,用来表述一个三角网格是怎样覆盖每个像素的。而每个片元就负责存储这样一系列数据。真正会对像素产生影响的阶段是下一个流水线阶段——逐片元操作</p>\n<blockquote>\n<p>在 DirectX 中片元着色器被称为像素着色器Pixel Shader但片元着色器是一个更合适的名字因为此时的片元并不是一个真正意义上的像素。</p>\n</blockquote>\n<p><img src=\"/img/shader_6.png\" alt=\"shader_6\"></p>\n<h2 id=\"逐片元操作\"><a href=\"#逐片元操作\" class=\"headerlink\" title=\"逐片元操作\"></a>逐片元操作</h2><p>这一阶段有几个主要任务:</p>\n<ul>\n<li><p>决定每个片元的可见性。这涉及了很多测试工作,例如深度测试、模板测试等。</p>\n</li>\n<li><p>如果一个片元通过了所有的测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行合并,或者说是混合。</p>\n</li>\n</ul>\n<blockquote>\n<p>!! 对于不透明物体开发者可以关闭混合Blend操作。这样片元着色器计算得到的颜色值就会直接覆盖掉颜色缓冲区中的像素值。但对于半透明物体我们就需要使用混合操作来让这个物体看起来是透明的。</p>\n</blockquote>\n<h2 id=\"Draw-Call\"><a href=\"#Draw-Call\" class=\"headerlink\" title=\"Draw Call\"></a>Draw Call</h2><p>CPU 调用图像编程接口,如 OpenGL 中的 <code>glDrawElements</code> 命令或者 DirectX 中的 <code>DrawIndexedPrimitive</code>命令,以命令 GPU 进行渲染的操作。</p>\n<h3 id=\"CPU-和-GPU-是如何实现并行工作的?\"><a href=\"#CPU-和-GPU-是如何实现并行工作的?\" class=\"headerlink\" title=\"CPU 和 GPU 是如何实现并行工作的?\"></a>CPU 和 GPU 是如何实现并行工作的?</h3><p>如果没有流水线化,那么 CPU 需要等到 GPU 完成上一个渲染任务才能再次发送渲染命令。但这种方法显然会造成效率低下。解决方法就是使用一个命令缓冲区Command Buffer。</p>\n<p>由 CPU 向其中添加命令,而由 GPU 从中读取命令,添加和读取的过程是互相独立的。</p>\n<h3 id=\"为什么-Draw-Call-多了会影响帧率?\"><a href=\"#为什么-Draw-Call-多了会影响帧率?\" class=\"headerlink\" title=\"为什么 Draw Call 多了会影响帧率?\"></a>为什么 Draw Call 多了会影响帧率?</h3><p>每一个复制动作需要很多额外的操作,例如分配内存、创建各种元数据等。如你所见,这些操作将造成很多额外的性能开销,如果我们复制了很多小文件,那么这个开销将会很大</p>\n<h3 id=\"如何减少-Draw-Call\"><a href=\"#如何减少-Draw-Call\" class=\"headerlink\" title=\"如何减少 Draw Call\"></a>如何减少 Draw Call</h3><p>尽管减少 Draw Call 的方法有很多但我们这里仅讨论使用批处理Batching的方法。我们讲过提交大量很小的 Draw Call 会造成 CPU 的性能瓶颈,即 CPU 把时间都花费在准备 Draw Call 的工作上了。那么,一个很显然的优化想法就是把很多小的 DrawCall 合并成一个大的 Draw Call这就是批处理的思想。</p>\n<p>在游戏开发过程中,为了减少 Draw Call 的开销,有两点需要注意。</p>\n<ul>\n<li><p>避免使用大量很小的网格。当不可避免地需要使用很小的网格结构时,考虑是否可以合并它们。</p>\n</li>\n<li><p>避免使用过多的材质。尽量在不同的网格之间共用同一个材质。</p>\n</li>\n</ul>\n<h1 id=\"你明白什么是-Shader\"><a href=\"#你明白什么是-Shader\" class=\"headerlink\" title=\"你明白什么是 Shader\"></a>你明白什么是 Shader</h1><ul>\n<li><p>GPU 流水线上一些可高度编程的阶段,而由着色器编译出来的最终代码是会在 GPU 上运行的(对于固定管线的渲染来说,着色器有时等同于一些特定的渲染设置)</p>\n</li>\n<li><p>有一些特定类型的着色器,如顶点着色器、片元着色器等</p>\n</li>\n<li><p>依靠着色器我们可以控制流水线中的渲染细节,例如用顶点着色器来进行顶点变换以及传递数据,用片元着色器来进行逐像素的渲染。</p>\n</li>\n</ul>\n<h1 id=\"Unity-Shader\"><a href=\"#Unity-Shader\" class=\"headerlink\" title=\"Unity Shader\"></a>Unity Shader</h1><blockquote>\n<p>!! Unity Shader ! &#x3D; 真正的 Shader</p>\n</blockquote>\n<p>Unity Shader 实际上指的就是一个 ShaderLab 文件——硬盘上以shader 作为文件后缀的一种文件,提供了一种让开发者同时控制渲染流水线中多个阶段的一种方式,不仅仅是提供 Shader 代码。</p>\n<p>作为开发者而言,我们绝大部分时候只需要和 Unity Shader 打交道,而不需要关心渲染引擎底层的实现细节</p>\n<p>Unity 编辑器会把这些 CG 片段编译成低级语言如汇编语言等。通常Unity 会自动把这些 CG 片段编译到所有相关平台(这里的平台是指不同的渲染平台,例如 Direct3D 9、OpenGL、Direct3D 11、OpenGL ES 等)上</p>\n<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><p>在没有 Unity 这类编辑器的情况下,如果我们想要对某个模型设置渲染状态,可能需要类似下面的代码:</p>\n<p>上述伪代码仅仅是简化后的版本, 当渲染的模型数目、需要调整的着色器属性不断增多时,上述过程将变得更加复杂和冗长。</p>\n<p>而且,当涉及透明物体等多物体的渲染时,如果没有编辑器的帮助,我们要非常小心如渲染顺序等问题。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 初始化渲染设置</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">Initialization</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 从硬盘上加载顶点着色器的代码</span>\n string vertexShaderCode <span class=\"token operator\">=</span> <span class=\"token function\">LoadShaderFromFile</span><span class=\"token punctuation\">(</span>VertexShader<span class=\"token punctuation\">.</span>shader<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 从硬盘上加载片元着色器的代码</span>\n string fragmentShaderCode <span class=\"token operator\">=</span> <span class=\"token function\">LoadShaderFromFile</span><span class=\"token punctuation\">(</span>FragmentShader<span class=\"token punctuation\">.</span>shader<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 把顶点着色器加载到GPU中</span>\n <span class=\"token function\">LoadVertexShaderFromString</span><span class=\"token punctuation\">(</span>vertexShaderCode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 把片元着色器加载到GPU中</span>\n <span class=\"token function\">LoadFragmentShaderFromString</span><span class=\"token punctuation\">(</span>fragmentShaderCode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 设置名为\"vertexPosition\"的属性的输入,即模型顶点坐标</span>\n <span class=\"token function\">SetVertexShaderProperty</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"vertexPosition\"</span><span class=\"token punctuation\">,</span> vertices<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 设置名为\"MainTex\"的属性的输入someTexture是某张已加载的纹理</span>\n <span class=\"token function\">SetVertexShaderProperty</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"MainTex\"</span><span class=\"token punctuation\">,</span> someTexture<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 设置名为\"MVP\"的属性的输入MVP是之前由开发者计算好的变换矩阵</span>\n <span class=\"token function\">SetVertexShaderProperty</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"MVP\"</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">MVP</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 关闭混合</span>\n <span class=\"token function\">Disable</span><span class=\"token punctuation\">(</span>Blend<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 设置深度测试</span>\n <span class=\"token function\">Enable</span><span class=\"token punctuation\">(</span>ZText<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token function\">SetZTestFunction</span><span class=\"token punctuation\">(</span>LessOrEqual<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 其他设置</span>\n …\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 每一帧迚行渲染</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">OnRendering</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 调用渲染命令</span>\n <span class=\"token function\">DrawCall</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 当涉及多种渲染设置时,我们可能还需要在这里改变各种渲染设置</span>\n <span class=\"token operator\">...</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>VertexShader.shader</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 输入顶点位置、纹理、MVP变换矩阵</span>\n<span class=\"token keyword\">in</span> float3 vertexPosition<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">in</span> sampler2D MainTex<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">in</span> Matrix4x4 <span class=\"token constant\">MVP</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 输出顶点经过MVP变换后的位置</span>\nout float4 position<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 使用MVP对模型顶点坐标迚行变换</span>\n position <span class=\"token operator\">=</span> <span class=\"token constant\">MVP</span> vertexPosition<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>FragmentShader.shader</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 输入VertexShader输出的position、经过光栅化程序插值后的该片元对应的position</span>\n<span class=\"token keyword\">in</span> float4 position<span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 输出:该片元的颜色值</span>\nout float4 fragColor<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 将片元颜色设为白色</span>\n fragColor <span class=\"token operator\">=</span> <span class=\"token function\">float4</span><span class=\"token punctuation\">(</span><span class=\"token number\">1.0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1.0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1.0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1.0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"材质和-Unity-Shader\"><a href=\"#材质和-Unity-Shader\" class=\"headerlink\" title=\"材质和 Unity Shader\"></a>材质和 Unity Shader</h2><p>总体来说,在 Unity 中我们需要配合使用材质Material和 Unity Shader 才能达到需要的效果。一个最常见的流程是:</p>\n<ul>\n<li><p>创建一个材质</p>\n</li>\n<li><p>创建一个 Unity Shader并把它赋给上一步中创建的材质</p>\n</li>\n<li><p>把材质赋给要渲染的对象</p>\n</li>\n<li><p>在材质面板中调整 Unity Shader 的属性,如使用的纹理、漫反射系数</p>\n</li>\n</ul>\n<h2 id=\"Unity-表面着色器\"><a href=\"#Unity-表面着色器\" class=\"headerlink\" title=\"Unity 表面着色器\"></a>Unity 表面着色器</h2><p>表面着色器Surface Shader是 Unity 自己创造的一种着色器代码类型。它需要的代码量很少Unity 在背后做了很多工作,但渲染的代价比较大。它在本质上和下面要讲到的顶点&#x2F;片元着色器是一样的。也就是说,当给 Unity 提供一个表面着色器的时候,它在背后仍旧把它转换成对应的顶点&#x2F;片元着色器。我们可以理解成,表面着色器是 Unity 对顶点&#x2F;片元着色器的更高一层的抽象。它存在的价值在于Unity 为我们处理了很多光照细节,使得我们不需要再操心这些“烦人的事情”。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">Shader <span class=\"token string\">\"Custom/Simple Surface Shader\"</span> <span class=\"token punctuation\">&#123;</span>\n SubShader <span class=\"token punctuation\">&#123;</span>\n Tags <span class=\"token punctuation\">&#123;</span> <span class=\"token string\">\"RenderType\"</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"Opaque\"</span> <span class=\"token punctuation\">&#125;</span>\n <span class=\"token constant\">CGPROGRAM</span>\n #pragma surface surf Lambert\n struct Input <span class=\"token punctuation\">&#123;</span>\n float4 color <span class=\"token operator\">:</span> <span class=\"token constant\">COLOR</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">void</span> <span class=\"token function\">surf</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">Input <span class=\"token constant\">IN</span><span class=\"token punctuation\">,</span> inout SurfaceOutput o</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n o<span class=\"token punctuation\">.</span>Albedo <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token constant\">ENDCG</span>\n <span class=\"token punctuation\">&#125;</span>\n Fallback <span class=\"token string\">\"Diffuse\"</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"顶点-x2F-片元着色器\"><a href=\"#顶点-x2F-片元着色器\" class=\"headerlink\" title=\"顶点&#x2F;片元着色器\"></a>顶点&#x2F;片元着色器</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">Shader <span class=\"token string\">\"Custom/Simple VertexFragment Shader\"</span> <span class=\"token punctuation\">&#123;</span>\n SubShader <span class=\"token punctuation\">&#123;</span>\n Pass <span class=\"token punctuation\">&#123;</span>\n <span class=\"token constant\">CGPROGRAM</span>\n #pragma vertex vert\n #pragma fragment frag\n float4 <span class=\"token function\">vert</span><span class=\"token punctuation\">(</span>float4 v <span class=\"token operator\">:</span> <span class=\"token constant\">POSITION</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> <span class=\"token constant\">SV_POSITION</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token function\">mul</span> <span class=\"token punctuation\">(</span><span class=\"token constant\">UNITY_MATRIX_MVP</span><span class=\"token punctuation\">,</span> v<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n fixed4 <span class=\"token function\">frag</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> SV_Target <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token function\">fixed4</span><span class=\"token punctuation\">(</span><span class=\"token number\">1.0</span><span class=\"token punctuation\">,</span><span class=\"token number\">0.0</span><span class=\"token punctuation\">,</span><span class=\"token number\">0.0</span><span class=\"token punctuation\">,</span><span class=\"token number\">1.0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token constant\">ENDCG</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"坐标系\"><a href=\"#坐标系\" class=\"headerlink\" title=\"坐标系\"></a>坐标系</h1><p>Unity 使用的是左手坐标系</p>\n<h2 id=\"左右手\"><a href=\"#左右手\" class=\"headerlink\" title=\"左右手\"></a>左右手</h2><p><img src=\"/img/shader_8.png\" alt=\"shader_8\"></p>\n<p><img src=\"/img/shader_9.png\" alt=\"shader_9\"></p>\n<h2 id=\"向量-矢量\"><a href=\"#向量-矢量\" class=\"headerlink\" title=\"向量(矢量)\"></a>向量(矢量)</h2><h3 id=\"模\"><a href=\"#模\" class=\"headerlink\" title=\"模\"></a>模</h3><p>矢量的模是一个标量,可以理解为是矢量在空间中的长度。它的表示符号通常是在矢量两旁分别加上一条垂直线</p>\n<p><img src=\"/img/shader_10.png\" alt=\"shader_10\"></p>\n<h3 id=\"单位矢量\"><a href=\"#单位矢量\" class=\"headerlink\" title=\"单位矢量\"></a>单位矢量</h3><p>在很多情况下我们只关心矢量的方向而不是模。例如在计算光照模型时我们往往需要得到顶点的法线方向和光源方向此时我们不关心这些矢量有多长。在这些情况下我们就需要计算单位矢量unit vector</p>\n<p>单位矢量指的是那些模为 1 的矢量。单位矢量也被称为被归一化的矢量normalized vector。对任何给定的非零矢量把它转换成单位矢量的过程就被称为归一化</p>\n<p><img src=\"/img/shader_11.png\" alt=\"shader_11\"></p>\n<h3 id=\"点积\"><a href=\"#点积\" class=\"headerlink\" title=\"点积\"></a>点积</h3><p>一个向量在另一个向量方向上投影的长度,是一个标量</p>\n<p>公式:<code>a·b = |a||b|cosθ</code></p>\n<h3 id=\"向量积-∧-×\"><a href=\"#向量积-∧-×\" class=\"headerlink\" title=\"向量积 ∧ ×\"></a>向量积 ∧ ×</h3><blockquote>\n<p>向量积,数学中又称外积、叉积,物理中称矢积、叉乘</p>\n</blockquote>\n<p>几何意义,一个和已有两个向量都垂直的向量,法向量</p>\n<p><img src=\"/img/shader_16.png\" alt=\"shader_16\"></p>\n<p>向量 a 和向量 b</p>\n<p><img src=\"/img/shader_12.png\" alt=\"shader_12\"></p>\n<p>叉乘公式为:</p>\n<p><img src=\"/img/shader_13.png\" alt=\"shader_13\"></p>\n<p>其中:</p>\n<p><img src=\"/img/shader_14.png\" alt=\"shader_14\"></p>\n<p>根据 i、j、k 间关系,有:</p>\n<p><img src=\"/img/shader_15.png\" alt=\"shader_15\"></p>\n<p>例如</p>\n<p>(1,2,3)×(-2,-1,4) &#x3D; (2 × 4 - 3 × -1, 3 × -2 - 1 × 4, 1 × -1 - 2 × -2) &#x3D; (11,10,3)</p>\n<h1 id=\"矩阵变换-Vec4\"><a href=\"#矩阵变换-Vec4\" class=\"headerlink\" title=\"矩阵变换 Vec4\"></a>矩阵变换 Vec4</h1><p>由于 3×3 矩阵不能表示平移操作,我们就把其扩展到了 4×4 的矩阵</p>\n<h2 id=\"平移矩阵\"><a href=\"#平移矩阵\" class=\"headerlink\" title=\"平移矩阵\"></a>平移矩阵</h2><p>点的 x、y、z 分量分别增加了一个位置偏移。在 3D 中的可视化效果是,把点(x, y, z)在空间中平移了(tx, ty, tz)个单位</p>\n<p><img src=\"/img/shader_17.png\" alt=\"shader_17\"></p>\n<h2 id=\"缩放矩阵\"><a href=\"#缩放矩阵\" class=\"headerlink\" title=\"缩放矩阵\"></a>缩放矩阵</h2><h2 id=\"旋转矩阵\"><a href=\"#旋转矩阵\" class=\"headerlink\" title=\"旋转矩阵\"></a>旋转矩阵</h2><p>旋转操作需要指定一个旋转轴,这个旋转轴不一定是空间中的坐标轴,但本节所讲的旋转就是指绕着空间中的 x 轴、y 轴或 z 轴进行旋转</p>\n<p>如果我们需要把点绕着 x 轴旋转 θ 度</p>\n<p><img src=\"/img/shader_18.png\" alt=\"shader_18\"></p>\n<p>绕 y 轴的旋转</p>\n<p><img src=\"/img/shader_19.png\" alt=\"shader_19\"></p>\n<p>绕 z 轴的旋转</p>\n<p><img src=\"/img/shader_20.png\" alt=\"shader_20\"></p>\n<h2 id=\"复合变换\"><a href=\"#复合变换\" class=\"headerlink\" title=\"复合变换\"></a>复合变换</h2><p>先进行大小为(2, 2, 2)的缩放,再绕 y 轴旋转 30°最后向 z 轴平移 4 个单位。</p>\n<blockquote>\n<p>矩阵乘法注意顺序</p>\n</blockquote>\n<p><img src=\"/img/shader_21.png\" alt=\"shader_21\"></p>\n<blockquote>\n<p>?? 如果我们需要同时绕着 3 个轴进行旋转,是先绕 x 轴、再绕 y 轴最后绕 z 轴旋转还是按其他的旋转顺序呢?</p>\n</blockquote>\n<p>根据坐标系,需要调整轴的顺序</p>\n<p><img src=\"/img/shader_22.png\" alt=\"shader_22\"></p>\n<h2 id=\"法线变换\"><a href=\"#法线变换\" class=\"headerlink\" title=\"法线变换\"></a>法线变换</h2><p>在游戏中,模型的一个顶点往往会携带额外的信息,而顶点法线就是其中一种信息。当我们变换一个模型的时候,不仅需要变换它的顶点,还需要变换顶点法线,以便在后续处理(如片元着色器)中计算光照等。</p>\n<h1 id=\"坐标空间\"><a href=\"#坐标空间\" class=\"headerlink\" title=\"坐标空间\"></a>坐标空间</h1><p>事实上,在我们的生活中,我们也总是使用不同的坐标空间来交流。现在正在读这本书的你,很可能正坐在办公室或书房中。如果问你:“办公室的饮水机在哪里?”你大概会回答:“在办公室门的左方 3 米处。”这里,你很自然地使用了以门为原点的坐标空间。</p>\n<p>要想定义一个坐标空间,必须指明其原点位置和 3 个坐标轴的方向。而这些数值实际上是相对于另一个坐标空间的读者需要记住所有的都是相对的。也就是说坐标空间会形成一个层次结构——每个坐标空间都是另一个坐标空间的子空间反过来说每个空间都有一个父parent坐标空间。对坐标空间的变换实际上就是在父空间和子空间之间对点和矢量进行变换。</p>\n<h2 id=\"模型空间\"><a href=\"#模型空间\" class=\"headerlink\" title=\"模型空间\"></a>模型空间</h2><p>每个模型都有自己独立的坐标空间,当它移动或旋转的时候,模型空间也会跟着它移动和旋转。</p>\n<blockquote>\n<p>Unity 在模型空间中使用的是左手坐标系,因此在模型空间中,+x 轴、+y 轴、+z 轴分别对应的是模型的右、上和前向。</p>\n</blockquote>\n<p><img src=\"/img/shader_24.png\" alt=\"shader_24\"></p>\n<h2 id=\"世界空间\"><a href=\"#世界空间\" class=\"headerlink\" title=\"世界空间\"></a>世界空间</h2><p>世界空间world space是一个特殊的坐标系因为它建立了我们所关心的最大的空间。一些读者可能会指出空间可以是无限大的怎么会有“最大”这一说呢这里说的最大指的是一个宏观的概念也就是说它是我们所关心的<code>最外层</code>的坐标空间。</p>\n<h2 id=\"摄像机空间\"><a href=\"#摄像机空间\" class=\"headerlink\" title=\"摄像机空间\"></a>摄像机空间</h2><p>摄像机决定了我们渲染游戏所使用的视角。在观察空间中,摄像机位于原点</p>\n<blockquote>\n<p>Unity 中观察空间的坐标轴选择是:+x 轴指向右方,+y 轴指向上方,而+z 轴指向的是摄像机的后方</p>\n</blockquote>\n<p>Q模型空间和世界空间中+z 轴指的都是物体的前方,为什么这里不一样了呢?</p>\n<p>AUnity 在模型空间和世界空间中选用的都是左手坐标系,而在观察空间中使用的是右手坐标系。这是符合 OpenGL 传统的,在这样的观察空间中,摄像机的正前方指向的是-z 轴方向。</p>\n<h2 id=\"裁剪空间\"><a href=\"#裁剪空间\" class=\"headerlink\" title=\"裁剪空间\"></a>裁剪空间</h2><p>用于变换的矩阵叫做裁剪矩阵clip matrix也被称为投影矩阵projection matrix。位于这块空间内部的图元将会被保留否则他剔除。由视锥体view frustum来决定。</p>\n<p><img src=\"/img/shader_26.png\" alt=\"shader_26\"></p>\n<p>视锥体指的是空间中的一块区域这块区域决定了摄像机可以看到的空间。视锥体由六个平面包围而成这些平面也被称为裁剪平面clip planes。视锥体有两种类型这涉及两种投影类型</p>\n<ul>\n<li>正交投影orthographic projection所有的网格大小都一样而且平行线会一直保持平行</li>\n<li>透视投影perspective projection地板上的平行线并不会保持平行离摄像机越近网格越大离摄像机越远网格越小。</li>\n</ul>\n<p><img src=\"/img/shader_25.png\" alt=\"shader_25\"></p>\n<blockquote>\n<p>追求真实感的 3D 游戏中我们往往会使用透视投影,而在一些 2D 游戏或渲染小地图等其他 HUD 元素时,我们会使用正交投影</p>\n</blockquote>\n<h3 id=\"透视摄像机视锥体模型\"><a href=\"#透视摄像机视锥体模型\" class=\"headerlink\" title=\"透视摄像机视锥体模型\"></a>透视摄像机视锥体模型</h3><p>在 Unity 中,一个摄像机的横纵比由 Game 视图的横纵比和 Viewport Rect 中的 <code>W</code> 和 <code>H</code> 属性共同决定实际上Unity 允许我们在脚本里通过 <code>Camera.aspect</code> 进行更改,但这里不做讨论)</p>\n<p><img src=\"/img/shader_27.png\" alt=\"shader_27\"></p>\n<h3 id=\"正交摄像机视锥体模型\"><a href=\"#正交摄像机视锥体模型\" class=\"headerlink\" title=\"正交摄像机视锥体模型\"></a>正交摄像机视锥体模型</h3><p>通过 Camera 组件的 <code>Size</code> 属性来改变视锥体竖直方向上高度的一半,而 Clipping Planes 中的 Near 和 Far 参数可以控制视锥体的近裁剪平面和远裁剪平面距离摄像机的远近。</p>\n<p><img src=\"/img/shader_28.png\" alt=\"shader_28\"></p>\n<h2 id=\"屏幕空间\"><a href=\"#屏幕空间\" class=\"headerlink\" title=\"屏幕空间\"></a>屏幕空间</h2><blockquote>\n<p>在 Unity 中,从裁剪空间到屏幕空间的转换是由 Unity 帮我们完成的。</p>\n</blockquote>\n<p>屏幕空间是一个二维空间,因此,我们必须把顶点从裁剪空间投影到屏幕空间中,来生成对应的 2D 坐标。这个过程可以理解成有两个步骤:</p>\n<ol>\n<li>标准齐次除法(透视除法):用齐次坐标系的 w 分量去除以 x、y、z 分量,在 OpenGL 中得到的坐标叫做归一化的设备坐标Normalized Device Coordinates, NDC</li>\n</ol>\n<p>经过透视投影变换后的裁剪空间,经过齐次除法后会变换到一个立方体内。按照 OpenGL 的传统,这个立方体的 x、y、z 分量的范围都是[-1, 1]。但在 DirectX 这样的 API 中z 分量的范围会是[0, 1]。而 Unity 选择了 OpenGL 这样的齐次裁剪空间,如图所示</p>\n<p><img src=\"/img/shader_29.png\" alt=\"shader_29\"></p>\n<p>而对于正交投影来说,它的裁剪空间实际已经是一个立方体了,而且由于经过正交投影矩阵变换后的顶点的 w 分量是 1因此齐次除法并不会对顶点的 x、y、z 坐标产生影响,如图所示</p>\n<p><img src=\"/img/shader_30.png\" alt=\"shader_30\"></p>\n<ol start=\"2\">\n<li>映射输出窗口的对应像素坐标</li>\n</ol>\n<h2 id=\"Unity-内置变换矩阵\"><a href=\"#Unity-内置变换矩阵\" class=\"headerlink\" title=\"Unity 内置变换矩阵\"></a>Unity 内置变换矩阵</h2><table>\n<thead>\n<tr>\n<th>变量名</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>UNITY MATRIX MVP</td>\n<td>当前的模型·观察·投影矩阵,用于将顶点&#x2F;方向矢量从模型空间变换到裁剪空间</td>\n</tr>\n<tr>\n<td>UNITY MATRIX MV</td>\n<td>当前的模型·观察矩阵,用于将顶点&#x2F;方向矢量从模型空间变换到观察空间</td>\n</tr>\n<tr>\n<td>UNITY MATRIX V</td>\n<td>当前的观察矩阵,用于将顶点&#x2F;方向矢量从世界空间变换到观察空间</td>\n</tr>\n<tr>\n<td>UNITY MATRIX P</td>\n<td>当前的投影矩阵,用于将顶点&#x2F;方向矢量从观察空间变换到裁剪空间</td>\n</tr>\n<tr>\n<td>UNITY MATRIX VP</td>\n<td>当前的观察投影矩阵,用于将顶点&#x2F;方向矢量从世界空间变换到裁剪空间</td>\n</tr>\n<tr>\n<td>UNITY MATRIX T MV</td>\n<td>UNITYMATRIX MV 的转置矩阵</td>\n</tr>\n<tr>\n<td>UNITY MATRIX IT MV</td>\n<td>UNITYMATRIX MV 的逆转置矩阵,用于将法线从模型空间变换到观察空间,也可用于得到 UNITYMATRIXMV 的逆矩阵</td>\n</tr>\n<tr>\n<td>Object2World</td>\n<td>当前的模型矩阵,用于将顶点&#x2F;方向矢量从模型空间变换到世界空间</td>\n</tr>\n<tr>\n<td>World2Object</td>\n<td>Object2World 的逆矩阵,用于将顶点&#x2F;方向矢量从世界空间变换到模型空间</td>\n</tr>\n</tbody></table>\n","site":{"data":{}},"excerpt":"","more":"<p>代码基于<code>c#</code>,书籍 <code>Unity Shader</code>入门精要</p>\n<h1 id=\"什么是-OpenGL、DirectX\"><a href=\"#什么是-OpenGL、DirectX\" class=\"headerlink\" title=\"什么是 OpenGL、DirectX\"></a>什么是 OpenGL、DirectX</h1><p>用于渲染二维或三维图形。可以说,这些接口架起了上层应用程序和底层 GPU 的沟通桥梁。一个应用程序向这些接口发送渲染命令而这些接口会依次向显卡驱动Graphics Driver发送渲染命令这些显卡驱动是真正知道如何和 GPU 通信的角色,正是它们把 OpenGL 或者 DirectX 的函数调用翻译成了 GPU 能够听懂的语言,同时它们也负责把纹理等数据转换成 GPU 所支持的格式。一个比喻是,显卡驱动就是显卡的操作系统。</p>\n<p><img src=\"/img/shader_7.png\" alt=\"shader_7\"></p>\n<h1 id=\"什么是-HLSL、GLSL、CG\"><a href=\"#什么是-HLSL、GLSL、CG\" class=\"headerlink\" title=\"什么是 HLSL、GLSL、CG\"></a>什么是 HLSL、GLSL、CG</h1><p>如顶点着色器、片元着色器等。这些着色器的可编程性在于,我们可以使用一种特定的语言来编写程序,就好比我们可以用 C#来写游戏逻辑一样。</p>\n<p>着色语言是专门用于编写着色器的,常见的着色语言有</p>\n<ul>\n<li><p>DirectX 的 HLSLHigh Level Shading Language</p>\n</li>\n<li><p>OpenGL 的 GLSLOpenGL Shading Language</p>\n</li>\n<li><p>NVIDIA 的 CGC for Graphic。</p>\n</li>\n</ul>\n<p>HLSL、GLSL、CG 都是“高级High-Level”语言但这种高级是相对于汇编语言来说的而不是像 C#相对于 C 的高级那样。这些语言会被编译成与机器无关的汇编语言也被称为中间语言Intermediate Language, IL。这些中间语言再交给显卡驱动来翻译成真正的机器语言即 GPU 可以理解的语言。</p>\n<h1 id=\"GPU-流水线\"><a href=\"#GPU-流水线\" class=\"headerlink\" title=\"GPU 流水线\"></a>GPU 流水线</h1><p>当 GPU 从 CPU 那里得到渲染命令后,就会进行一系列流水线操作,最终把图元渲染到屏幕上。</p>\n<p><img src=\"/img/shader_1.png\" alt=\"shader_1\"></p>\n<ul>\n<li><p>顶点着色器Vertex Shader是完全可编程的它通常用于实现顶点的空间变换、顶点着色等功能</p>\n</li>\n<li><p>曲面细分着色器Tessellation Shader是一个可选的着色器它用于细分图元</p>\n</li>\n<li><p>几何着色器Geometry Shader同样是一个可选的着色器它可以被用于执行逐图元Per-Primitive的着色操作或者被用于产生更多的图元</p>\n</li>\n<li><p>裁剪Clipping这一阶段的目的是将那些不在摄像机视野内的顶点裁剪掉并剔除某些三角图元的面片。例如我们可以使用自定义的裁剪平面来配置裁剪区域也可以通过指令控制裁剪三角图元的正面还是背面。</p>\n</li>\n<li><p>片元着色器Fragment Shader则是完全可编程的它用于实现逐片元Per-Fragment的着色操作</p>\n</li>\n</ul>\n<h2 id=\"顶点着色器-Vertex-Shader\"><a href=\"#顶点着色器-Vertex-Shader\" class=\"headerlink\" title=\"顶点着色器 Vertex Shader\"></a>顶点着色器 Vertex Shader</h2><p>CPU 输入进来的每个顶点都会调用一次顶点着色器。顶点着色器本身不可以创建或者销毁任何顶点而且无法得到顶点与顶点之间的关系。例如我们无法得知两个顶点是否属于同一个三角网格。但正是因为这样的相互独立性GPU 可以利用本身的特性并行化处理每一个顶点,这意味着这一阶段的处理速度会很快。</p>\n<p>顶点着色器需要完成的工作主要有:</p>\n<ul>\n<li>坐标变换:把顶点坐标转换到齐次裁剪坐标系下,接着通常再由硬件做透视除法后,最终得到归一化的设备坐标(NDC)</li>\n</ul>\n<p><img src=\"/img/shader_2.png\" alt=\"shader_2\"></p>\n<blockquote>\n<p>在 DirectX 中NDC 的 z 方向取值范围是[0,1],在 OpenGL 环境下是-1.0DirectX 中是 0.0</p>\n</blockquote>\n<ul>\n<li>逐顶点光照</li>\n</ul>\n<h2 id=\"裁剪\"><a href=\"#裁剪\" class=\"headerlink\" title=\"裁剪\"></a>裁剪</h2><p>只有在单位立方体的图元才需要被继续处</p>\n<p><img src=\"/img/shader_3.png\" alt=\"shader_3\"></p>\n<h2 id=\"屏幕映射\"><a href=\"#屏幕映射\" class=\"headerlink\" title=\"屏幕映射\"></a>屏幕映射</h2><p>OpenGL 和 DirectX 之间的差异问题。OpenGL 把屏幕的左下角当成最小的窗口坐标值,而 DirectX 则定义了屏幕的左上角为最小的窗口坐标值</p>\n<p><img src=\"/img/shader_4.png\" alt=\"shader_4\"></p>\n<h2 id=\"光栅阶段\"><a href=\"#光栅阶段\" class=\"headerlink\" title=\"光栅阶段\"></a>光栅阶段</h2><p>从上一个阶段输出的信息屏幕坐标系下的顶点位置以及和它们相关的额外信息如深度值z 坐标)、法线方向、视角方向等。光栅化阶段有两个最重要的目标:计算每个图元覆盖了哪些像素,以及为这些像素计算它们的颜色。</p>\n<h3 id=\"三角形设置\"><a href=\"#三角形设置\" class=\"headerlink\" title=\"三角形设置\"></a>三角形设置</h3><p>如果要得到整个三角网格对像素的覆盖情况,我们就必须计算每条边上的像素坐标。为了能够计算边界像素的坐标信息,我们就需要得到三角形边界的表示方式。</p>\n<h3 id=\"三角形遍历\"><a href=\"#三角形遍历\" class=\"headerlink\" title=\"三角形遍历()\"></a>三角形遍历()</h3><ol>\n<li><p>扫描变换三角形遍历Triangle Traversal阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖的话就会生成一个片元fragment、</p>\n</li>\n<li><p>使用三角网格 3 个顶点的顶点信息对整个覆盖区域的像素进行插值</p>\n</li>\n</ol>\n<p><img src=\"/img/shader_5.png\" alt=\"shader_5\"></p>\n<p>这一步的输出就是得到一个片元序列。需要注意的是,一个片元并不是真正意义上的像素,而是包含了很多状态的集合,这些状态用于计算每个像素的最终颜色。这些状态包括了(但不限于)它的屏幕坐标、深度信息,以及其他从几何阶段输出的顶点信息,例如法线、纹理坐标等。</p>\n<h2 id=\"片元着色器-Fragment-Shader\"><a href=\"#片元着色器-Fragment-Shader\" class=\"headerlink\" title=\"片元着色器 Fragment Shader\"></a>片元着色器 Fragment Shader</h2><p>前面的光栅化阶段实际上并不会影响屏幕上每个像素的颜色值,而是会产生一系列的数据信息,用来表述一个三角网格是怎样覆盖每个像素的。而每个片元就负责存储这样一系列数据。真正会对像素产生影响的阶段是下一个流水线阶段——逐片元操作</p>\n<blockquote>\n<p>在 DirectX 中片元着色器被称为像素着色器Pixel Shader但片元着色器是一个更合适的名字因为此时的片元并不是一个真正意义上的像素。</p>\n</blockquote>\n<p><img src=\"/img/shader_6.png\" alt=\"shader_6\"></p>\n<h2 id=\"逐片元操作\"><a href=\"#逐片元操作\" class=\"headerlink\" title=\"逐片元操作\"></a>逐片元操作</h2><p>这一阶段有几个主要任务:</p>\n<ul>\n<li><p>决定每个片元的可见性。这涉及了很多测试工作,例如深度测试、模板测试等。</p>\n</li>\n<li><p>如果一个片元通过了所有的测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行合并,或者说是混合。</p>\n</li>\n</ul>\n<blockquote>\n<p>!! 对于不透明物体开发者可以关闭混合Blend操作。这样片元着色器计算得到的颜色值就会直接覆盖掉颜色缓冲区中的像素值。但对于半透明物体我们就需要使用混合操作来让这个物体看起来是透明的。</p>\n</blockquote>\n<h2 id=\"Draw-Call\"><a href=\"#Draw-Call\" class=\"headerlink\" title=\"Draw Call\"></a>Draw Call</h2><p>CPU 调用图像编程接口,如 OpenGL 中的 <code>glDrawElements</code> 命令或者 DirectX 中的 <code>DrawIndexedPrimitive</code>命令,以命令 GPU 进行渲染的操作。</p>\n<h3 id=\"CPU-和-GPU-是如何实现并行工作的?\"><a href=\"#CPU-和-GPU-是如何实现并行工作的?\" class=\"headerlink\" title=\"CPU 和 GPU 是如何实现并行工作的?\"></a>CPU 和 GPU 是如何实现并行工作的?</h3><p>如果没有流水线化,那么 CPU 需要等到 GPU 完成上一个渲染任务才能再次发送渲染命令。但这种方法显然会造成效率低下。解决方法就是使用一个命令缓冲区Command Buffer。</p>\n<p>由 CPU 向其中添加命令,而由 GPU 从中读取命令,添加和读取的过程是互相独立的。</p>\n<h3 id=\"为什么-Draw-Call-多了会影响帧率?\"><a href=\"#为什么-Draw-Call-多了会影响帧率?\" class=\"headerlink\" title=\"为什么 Draw Call 多了会影响帧率?\"></a>为什么 Draw Call 多了会影响帧率?</h3><p>每一个复制动作需要很多额外的操作,例如分配内存、创建各种元数据等。如你所见,这些操作将造成很多额外的性能开销,如果我们复制了很多小文件,那么这个开销将会很大</p>\n<h3 id=\"如何减少-Draw-Call\"><a href=\"#如何减少-Draw-Call\" class=\"headerlink\" title=\"如何减少 Draw Call\"></a>如何减少 Draw Call</h3><p>尽管减少 Draw Call 的方法有很多但我们这里仅讨论使用批处理Batching的方法。我们讲过提交大量很小的 Draw Call 会造成 CPU 的性能瓶颈,即 CPU 把时间都花费在准备 Draw Call 的工作上了。那么,一个很显然的优化想法就是把很多小的 DrawCall 合并成一个大的 Draw Call这就是批处理的思想。</p>\n<p>在游戏开发过程中,为了减少 Draw Call 的开销,有两点需要注意。</p>\n<ul>\n<li><p>避免使用大量很小的网格。当不可避免地需要使用很小的网格结构时,考虑是否可以合并它们。</p>\n</li>\n<li><p>避免使用过多的材质。尽量在不同的网格之间共用同一个材质。</p>\n</li>\n</ul>\n<h1 id=\"你明白什么是-Shader\"><a href=\"#你明白什么是-Shader\" class=\"headerlink\" title=\"你明白什么是 Shader\"></a>你明白什么是 Shader</h1><ul>\n<li><p>GPU 流水线上一些可高度编程的阶段,而由着色器编译出来的最终代码是会在 GPU 上运行的(对于固定管线的渲染来说,着色器有时等同于一些特定的渲染设置)</p>\n</li>\n<li><p>有一些特定类型的着色器,如顶点着色器、片元着色器等</p>\n</li>\n<li><p>依靠着色器我们可以控制流水线中的渲染细节,例如用顶点着色器来进行顶点变换以及传递数据,用片元着色器来进行逐像素的渲染。</p>\n</li>\n</ul>\n<h1 id=\"Unity-Shader\"><a href=\"#Unity-Shader\" class=\"headerlink\" title=\"Unity Shader\"></a>Unity Shader</h1><blockquote>\n<p>!! Unity Shader ! &#x3D; 真正的 Shader</p>\n</blockquote>\n<p>Unity Shader 实际上指的就是一个 ShaderLab 文件——硬盘上以shader 作为文件后缀的一种文件,提供了一种让开发者同时控制渲染流水线中多个阶段的一种方式,不仅仅是提供 Shader 代码。</p>\n<p>作为开发者而言,我们绝大部分时候只需要和 Unity Shader 打交道,而不需要关心渲染引擎底层的实现细节</p>\n<p>Unity 编辑器会把这些 CG 片段编译成低级语言如汇编语言等。通常Unity 会自动把这些 CG 片段编译到所有相关平台(这里的平台是指不同的渲染平台,例如 Direct3D 9、OpenGL、Direct3D 11、OpenGL ES 等)上</p>\n<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><p>在没有 Unity 这类编辑器的情况下,如果我们想要对某个模型设置渲染状态,可能需要类似下面的代码:</p>\n<p>上述伪代码仅仅是简化后的版本, 当渲染的模型数目、需要调整的着色器属性不断增多时,上述过程将变得更加复杂和冗长。</p>\n<p>而且,当涉及透明物体等多物体的渲染时,如果没有编辑器的帮助,我们要非常小心如渲染顺序等问题。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 初始化渲染设置</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">Initialization</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 从硬盘上加载顶点着色器的代码</span>\n string vertexShaderCode <span class=\"token operator\">=</span> <span class=\"token function\">LoadShaderFromFile</span><span class=\"token punctuation\">(</span>VertexShader<span class=\"token punctuation\">.</span>shader<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 从硬盘上加载片元着色器的代码</span>\n string fragmentShaderCode <span class=\"token operator\">=</span> <span class=\"token function\">LoadShaderFromFile</span><span class=\"token punctuation\">(</span>FragmentShader<span class=\"token punctuation\">.</span>shader<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 把顶点着色器加载到GPU中</span>\n <span class=\"token function\">LoadVertexShaderFromString</span><span class=\"token punctuation\">(</span>vertexShaderCode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 把片元着色器加载到GPU中</span>\n <span class=\"token function\">LoadFragmentShaderFromString</span><span class=\"token punctuation\">(</span>fragmentShaderCode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 设置名为\"vertexPosition\"的属性的输入,即模型顶点坐标</span>\n <span class=\"token function\">SetVertexShaderProperty</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"vertexPosition\"</span><span class=\"token punctuation\">,</span> vertices<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 设置名为\"MainTex\"的属性的输入someTexture是某张已加载的纹理</span>\n <span class=\"token function\">SetVertexShaderProperty</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"MainTex\"</span><span class=\"token punctuation\">,</span> someTexture<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 设置名为\"MVP\"的属性的输入MVP是之前由开发者计算好的变换矩阵</span>\n <span class=\"token function\">SetVertexShaderProperty</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"MVP\"</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">MVP</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 关闭混合</span>\n <span class=\"token function\">Disable</span><span class=\"token punctuation\">(</span>Blend<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 设置深度测试</span>\n <span class=\"token function\">Enable</span><span class=\"token punctuation\">(</span>ZText<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token function\">SetZTestFunction</span><span class=\"token punctuation\">(</span>LessOrEqual<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 其他设置</span>\n …\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 每一帧迚行渲染</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">OnRendering</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 调用渲染命令</span>\n <span class=\"token function\">DrawCall</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 当涉及多种渲染设置时,我们可能还需要在这里改变各种渲染设置</span>\n <span class=\"token operator\">...</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>VertexShader.shader</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 输入顶点位置、纹理、MVP变换矩阵</span>\n<span class=\"token keyword\">in</span> float3 vertexPosition<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">in</span> sampler2D MainTex<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">in</span> Matrix4x4 <span class=\"token constant\">MVP</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 输出顶点经过MVP变换后的位置</span>\nout float4 position<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 使用MVP对模型顶点坐标迚行变换</span>\n position <span class=\"token operator\">=</span> <span class=\"token constant\">MVP</span> vertexPosition<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>FragmentShader.shader</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 输入VertexShader输出的position、经过光栅化程序插值后的该片元对应的position</span>\n<span class=\"token keyword\">in</span> float4 position<span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 输出:该片元的颜色值</span>\nout float4 fragColor<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 将片元颜色设为白色</span>\n fragColor <span class=\"token operator\">=</span> <span class=\"token function\">float4</span><span class=\"token punctuation\">(</span><span class=\"token number\">1.0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1.0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1.0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1.0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"材质和-Unity-Shader\"><a href=\"#材质和-Unity-Shader\" class=\"headerlink\" title=\"材质和 Unity Shader\"></a>材质和 Unity Shader</h2><p>总体来说,在 Unity 中我们需要配合使用材质Material和 Unity Shader 才能达到需要的效果。一个最常见的流程是:</p>\n<ul>\n<li><p>创建一个材质</p>\n</li>\n<li><p>创建一个 Unity Shader并把它赋给上一步中创建的材质</p>\n</li>\n<li><p>把材质赋给要渲染的对象</p>\n</li>\n<li><p>在材质面板中调整 Unity Shader 的属性,如使用的纹理、漫反射系数</p>\n</li>\n</ul>\n<h2 id=\"Unity-表面着色器\"><a href=\"#Unity-表面着色器\" class=\"headerlink\" title=\"Unity 表面着色器\"></a>Unity 表面着色器</h2><p>表面着色器Surface Shader是 Unity 自己创造的一种着色器代码类型。它需要的代码量很少Unity 在背后做了很多工作,但渲染的代价比较大。它在本质上和下面要讲到的顶点&#x2F;片元着色器是一样的。也就是说,当给 Unity 提供一个表面着色器的时候,它在背后仍旧把它转换成对应的顶点&#x2F;片元着色器。我们可以理解成,表面着色器是 Unity 对顶点&#x2F;片元着色器的更高一层的抽象。它存在的价值在于Unity 为我们处理了很多光照细节,使得我们不需要再操心这些“烦人的事情”。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">Shader <span class=\"token string\">\"Custom/Simple Surface Shader\"</span> <span class=\"token punctuation\">&#123;</span>\n SubShader <span class=\"token punctuation\">&#123;</span>\n Tags <span class=\"token punctuation\">&#123;</span> <span class=\"token string\">\"RenderType\"</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"Opaque\"</span> <span class=\"token punctuation\">&#125;</span>\n <span class=\"token constant\">CGPROGRAM</span>\n #pragma surface surf Lambert\n struct Input <span class=\"token punctuation\">&#123;</span>\n float4 color <span class=\"token operator\">:</span> <span class=\"token constant\">COLOR</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">void</span> <span class=\"token function\">surf</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">Input <span class=\"token constant\">IN</span><span class=\"token punctuation\">,</span> inout SurfaceOutput o</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n o<span class=\"token punctuation\">.</span>Albedo <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token constant\">ENDCG</span>\n <span class=\"token punctuation\">&#125;</span>\n Fallback <span class=\"token string\">\"Diffuse\"</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"顶点-x2F-片元着色器\"><a href=\"#顶点-x2F-片元着色器\" class=\"headerlink\" title=\"顶点&#x2F;片元着色器\"></a>顶点&#x2F;片元着色器</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">Shader <span class=\"token string\">\"Custom/Simple VertexFragment Shader\"</span> <span class=\"token punctuation\">&#123;</span>\n SubShader <span class=\"token punctuation\">&#123;</span>\n Pass <span class=\"token punctuation\">&#123;</span>\n <span class=\"token constant\">CGPROGRAM</span>\n #pragma vertex vert\n #pragma fragment frag\n float4 <span class=\"token function\">vert</span><span class=\"token punctuation\">(</span>float4 v <span class=\"token operator\">:</span> <span class=\"token constant\">POSITION</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> <span class=\"token constant\">SV_POSITION</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token function\">mul</span> <span class=\"token punctuation\">(</span><span class=\"token constant\">UNITY_MATRIX_MVP</span><span class=\"token punctuation\">,</span> v<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n fixed4 <span class=\"token function\">frag</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> SV_Target <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token function\">fixed4</span><span class=\"token punctuation\">(</span><span class=\"token number\">1.0</span><span class=\"token punctuation\">,</span><span class=\"token number\">0.0</span><span class=\"token punctuation\">,</span><span class=\"token number\">0.0</span><span class=\"token punctuation\">,</span><span class=\"token number\">1.0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token constant\">ENDCG</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"坐标系\"><a href=\"#坐标系\" class=\"headerlink\" title=\"坐标系\"></a>坐标系</h1><p>Unity 使用的是左手坐标系</p>\n<h2 id=\"左右手\"><a href=\"#左右手\" class=\"headerlink\" title=\"左右手\"></a>左右手</h2><p><img src=\"/img/shader_8.png\" alt=\"shader_8\"></p>\n<p><img src=\"/img/shader_9.png\" alt=\"shader_9\"></p>\n<h2 id=\"向量-矢量\"><a href=\"#向量-矢量\" class=\"headerlink\" title=\"向量(矢量)\"></a>向量(矢量)</h2><h3 id=\"模\"><a href=\"#模\" class=\"headerlink\" title=\"模\"></a>模</h3><p>矢量的模是一个标量,可以理解为是矢量在空间中的长度。它的表示符号通常是在矢量两旁分别加上一条垂直线</p>\n<p><img src=\"/img/shader_10.png\" alt=\"shader_10\"></p>\n<h3 id=\"单位矢量\"><a href=\"#单位矢量\" class=\"headerlink\" title=\"单位矢量\"></a>单位矢量</h3><p>在很多情况下我们只关心矢量的方向而不是模。例如在计算光照模型时我们往往需要得到顶点的法线方向和光源方向此时我们不关心这些矢量有多长。在这些情况下我们就需要计算单位矢量unit vector</p>\n<p>单位矢量指的是那些模为 1 的矢量。单位矢量也被称为被归一化的矢量normalized vector。对任何给定的非零矢量把它转换成单位矢量的过程就被称为归一化</p>\n<p><img src=\"/img/shader_11.png\" alt=\"shader_11\"></p>\n<h3 id=\"点积\"><a href=\"#点积\" class=\"headerlink\" title=\"点积\"></a>点积</h3><p>一个向量在另一个向量方向上投影的长度,是一个标量</p>\n<p>公式:<code>a·b = |a||b|cosθ</code></p>\n<h3 id=\"向量积-∧-×\"><a href=\"#向量积-∧-×\" class=\"headerlink\" title=\"向量积 ∧ ×\"></a>向量积 ∧ ×</h3><blockquote>\n<p>向量积,数学中又称外积、叉积,物理中称矢积、叉乘</p>\n</blockquote>\n<p>几何意义,一个和已有两个向量都垂直的向量,法向量</p>\n<p><img src=\"/img/shader_16.png\" alt=\"shader_16\"></p>\n<p>向量 a 和向量 b</p>\n<p><img src=\"/img/shader_12.png\" alt=\"shader_12\"></p>\n<p>叉乘公式为:</p>\n<p><img src=\"/img/shader_13.png\" alt=\"shader_13\"></p>\n<p>其中:</p>\n<p><img src=\"/img/shader_14.png\" alt=\"shader_14\"></p>\n<p>根据 i、j、k 间关系,有:</p>\n<p><img src=\"/img/shader_15.png\" alt=\"shader_15\"></p>\n<p>例如</p>\n<p>(1,2,3)×(-2,-1,4) &#x3D; (2 × 4 - 3 × -1, 3 × -2 - 1 × 4, 1 × -1 - 2 × -2) &#x3D; (11,10,3)</p>\n<h1 id=\"矩阵变换-Vec4\"><a href=\"#矩阵变换-Vec4\" class=\"headerlink\" title=\"矩阵变换 Vec4\"></a>矩阵变换 Vec4</h1><p>由于 3×3 矩阵不能表示平移操作,我们就把其扩展到了 4×4 的矩阵</p>\n<h2 id=\"平移矩阵\"><a href=\"#平移矩阵\" class=\"headerlink\" title=\"平移矩阵\"></a>平移矩阵</h2><p>点的 x、y、z 分量分别增加了一个位置偏移。在 3D 中的可视化效果是,把点(x, y, z)在空间中平移了(tx, ty, tz)个单位</p>\n<p><img src=\"/img/shader_17.png\" alt=\"shader_17\"></p>\n<h2 id=\"缩放矩阵\"><a href=\"#缩放矩阵\" class=\"headerlink\" title=\"缩放矩阵\"></a>缩放矩阵</h2><h2 id=\"旋转矩阵\"><a href=\"#旋转矩阵\" class=\"headerlink\" title=\"旋转矩阵\"></a>旋转矩阵</h2><p>旋转操作需要指定一个旋转轴,这个旋转轴不一定是空间中的坐标轴,但本节所讲的旋转就是指绕着空间中的 x 轴、y 轴或 z 轴进行旋转</p>\n<p>如果我们需要把点绕着 x 轴旋转 θ 度</p>\n<p><img src=\"/img/shader_18.png\" alt=\"shader_18\"></p>\n<p>绕 y 轴的旋转</p>\n<p><img src=\"/img/shader_19.png\" alt=\"shader_19\"></p>\n<p>绕 z 轴的旋转</p>\n<p><img src=\"/img/shader_20.png\" alt=\"shader_20\"></p>\n<h2 id=\"复合变换\"><a href=\"#复合变换\" class=\"headerlink\" title=\"复合变换\"></a>复合变换</h2><p>先进行大小为(2, 2, 2)的缩放,再绕 y 轴旋转 30°最后向 z 轴平移 4 个单位。</p>\n<blockquote>\n<p>矩阵乘法注意顺序</p>\n</blockquote>\n<p><img src=\"/img/shader_21.png\" alt=\"shader_21\"></p>\n<blockquote>\n<p>?? 如果我们需要同时绕着 3 个轴进行旋转,是先绕 x 轴、再绕 y 轴最后绕 z 轴旋转还是按其他的旋转顺序呢?</p>\n</blockquote>\n<p>根据坐标系,需要调整轴的顺序</p>\n<p><img src=\"/img/shader_22.png\" alt=\"shader_22\"></p>\n<h2 id=\"法线变换\"><a href=\"#法线变换\" class=\"headerlink\" title=\"法线变换\"></a>法线变换</h2><p>在游戏中,模型的一个顶点往往会携带额外的信息,而顶点法线就是其中一种信息。当我们变换一个模型的时候,不仅需要变换它的顶点,还需要变换顶点法线,以便在后续处理(如片元着色器)中计算光照等。</p>\n<h1 id=\"坐标空间\"><a href=\"#坐标空间\" class=\"headerlink\" title=\"坐标空间\"></a>坐标空间</h1><p>事实上,在我们的生活中,我们也总是使用不同的坐标空间来交流。现在正在读这本书的你,很可能正坐在办公室或书房中。如果问你:“办公室的饮水机在哪里?”你大概会回答:“在办公室门的左方 3 米处。”这里,你很自然地使用了以门为原点的坐标空间。</p>\n<p>要想定义一个坐标空间,必须指明其原点位置和 3 个坐标轴的方向。而这些数值实际上是相对于另一个坐标空间的读者需要记住所有的都是相对的。也就是说坐标空间会形成一个层次结构——每个坐标空间都是另一个坐标空间的子空间反过来说每个空间都有一个父parent坐标空间。对坐标空间的变换实际上就是在父空间和子空间之间对点和矢量进行变换。</p>\n<h2 id=\"模型空间\"><a href=\"#模型空间\" class=\"headerlink\" title=\"模型空间\"></a>模型空间</h2><p>每个模型都有自己独立的坐标空间,当它移动或旋转的时候,模型空间也会跟着它移动和旋转。</p>\n<blockquote>\n<p>Unity 在模型空间中使用的是左手坐标系,因此在模型空间中,+x 轴、+y 轴、+z 轴分别对应的是模型的右、上和前向。</p>\n</blockquote>\n<p><img src=\"/img/shader_24.png\" alt=\"shader_24\"></p>\n<h2 id=\"世界空间\"><a href=\"#世界空间\" class=\"headerlink\" title=\"世界空间\"></a>世界空间</h2><p>世界空间world space是一个特殊的坐标系因为它建立了我们所关心的最大的空间。一些读者可能会指出空间可以是无限大的怎么会有“最大”这一说呢这里说的最大指的是一个宏观的概念也就是说它是我们所关心的<code>最外层</code>的坐标空间。</p>\n<h2 id=\"摄像机空间\"><a href=\"#摄像机空间\" class=\"headerlink\" title=\"摄像机空间\"></a>摄像机空间</h2><p>摄像机决定了我们渲染游戏所使用的视角。在观察空间中,摄像机位于原点</p>\n<blockquote>\n<p>Unity 中观察空间的坐标轴选择是:+x 轴指向右方,+y 轴指向上方,而+z 轴指向的是摄像机的后方</p>\n</blockquote>\n<p>Q模型空间和世界空间中+z 轴指的都是物体的前方,为什么这里不一样了呢?</p>\n<p>AUnity 在模型空间和世界空间中选用的都是左手坐标系,而在观察空间中使用的是右手坐标系。这是符合 OpenGL 传统的,在这样的观察空间中,摄像机的正前方指向的是-z 轴方向。</p>\n<h2 id=\"裁剪空间\"><a href=\"#裁剪空间\" class=\"headerlink\" title=\"裁剪空间\"></a>裁剪空间</h2><p>用于变换的矩阵叫做裁剪矩阵clip matrix也被称为投影矩阵projection matrix。位于这块空间内部的图元将会被保留否则他剔除。由视锥体view frustum来决定。</p>\n<p><img src=\"/img/shader_26.png\" alt=\"shader_26\"></p>\n<p>视锥体指的是空间中的一块区域这块区域决定了摄像机可以看到的空间。视锥体由六个平面包围而成这些平面也被称为裁剪平面clip planes。视锥体有两种类型这涉及两种投影类型</p>\n<ul>\n<li>正交投影orthographic projection所有的网格大小都一样而且平行线会一直保持平行</li>\n<li>透视投影perspective projection地板上的平行线并不会保持平行离摄像机越近网格越大离摄像机越远网格越小。</li>\n</ul>\n<p><img src=\"/img/shader_25.png\" alt=\"shader_25\"></p>\n<blockquote>\n<p>追求真实感的 3D 游戏中我们往往会使用透视投影,而在一些 2D 游戏或渲染小地图等其他 HUD 元素时,我们会使用正交投影</p>\n</blockquote>\n<h3 id=\"透视摄像机视锥体模型\"><a href=\"#透视摄像机视锥体模型\" class=\"headerlink\" title=\"透视摄像机视锥体模型\"></a>透视摄像机视锥体模型</h3><p>在 Unity 中,一个摄像机的横纵比由 Game 视图的横纵比和 Viewport Rect 中的 <code>W</code> 和 <code>H</code> 属性共同决定实际上Unity 允许我们在脚本里通过 <code>Camera.aspect</code> 进行更改,但这里不做讨论)</p>\n<p><img src=\"/img/shader_27.png\" alt=\"shader_27\"></p>\n<h3 id=\"正交摄像机视锥体模型\"><a href=\"#正交摄像机视锥体模型\" class=\"headerlink\" title=\"正交摄像机视锥体模型\"></a>正交摄像机视锥体模型</h3><p>通过 Camera 组件的 <code>Size</code> 属性来改变视锥体竖直方向上高度的一半,而 Clipping Planes 中的 Near 和 Far 参数可以控制视锥体的近裁剪平面和远裁剪平面距离摄像机的远近。</p>\n<p><img src=\"/img/shader_28.png\" alt=\"shader_28\"></p>\n<h2 id=\"屏幕空间\"><a href=\"#屏幕空间\" class=\"headerlink\" title=\"屏幕空间\"></a>屏幕空间</h2><blockquote>\n<p>在 Unity 中,从裁剪空间到屏幕空间的转换是由 Unity 帮我们完成的。</p>\n</blockquote>\n<p>屏幕空间是一个二维空间,因此,我们必须把顶点从裁剪空间投影到屏幕空间中,来生成对应的 2D 坐标。这个过程可以理解成有两个步骤:</p>\n<ol>\n<li>标准齐次除法(透视除法):用齐次坐标系的 w 分量去除以 x、y、z 分量,在 OpenGL 中得到的坐标叫做归一化的设备坐标Normalized Device Coordinates, NDC</li>\n</ol>\n<p>经过透视投影变换后的裁剪空间,经过齐次除法后会变换到一个立方体内。按照 OpenGL 的传统,这个立方体的 x、y、z 分量的范围都是[-1, 1]。但在 DirectX 这样的 API 中z 分量的范围会是[0, 1]。而 Unity 选择了 OpenGL 这样的齐次裁剪空间,如图所示</p>\n<p><img src=\"/img/shader_29.png\" alt=\"shader_29\"></p>\n<p>而对于正交投影来说,它的裁剪空间实际已经是一个立方体了,而且由于经过正交投影矩阵变换后的顶点的 w 分量是 1因此齐次除法并不会对顶点的 x、y、z 坐标产生影响,如图所示</p>\n<p><img src=\"/img/shader_30.png\" alt=\"shader_30\"></p>\n<ol start=\"2\">\n<li>映射输出窗口的对应像素坐标</li>\n</ol>\n<h2 id=\"Unity-内置变换矩阵\"><a href=\"#Unity-内置变换矩阵\" class=\"headerlink\" title=\"Unity 内置变换矩阵\"></a>Unity 内置变换矩阵</h2><table>\n<thead>\n<tr>\n<th>变量名</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>UNITY MATRIX MVP</td>\n<td>当前的模型·观察·投影矩阵,用于将顶点&#x2F;方向矢量从模型空间变换到裁剪空间</td>\n</tr>\n<tr>\n<td>UNITY MATRIX MV</td>\n<td>当前的模型·观察矩阵,用于将顶点&#x2F;方向矢量从模型空间变换到观察空间</td>\n</tr>\n<tr>\n<td>UNITY MATRIX V</td>\n<td>当前的观察矩阵,用于将顶点&#x2F;方向矢量从世界空间变换到观察空间</td>\n</tr>\n<tr>\n<td>UNITY MATRIX P</td>\n<td>当前的投影矩阵,用于将顶点&#x2F;方向矢量从观察空间变换到裁剪空间</td>\n</tr>\n<tr>\n<td>UNITY MATRIX VP</td>\n<td>当前的观察投影矩阵,用于将顶点&#x2F;方向矢量从世界空间变换到裁剪空间</td>\n</tr>\n<tr>\n<td>UNITY MATRIX T MV</td>\n<td>UNITYMATRIX MV 的转置矩阵</td>\n</tr>\n<tr>\n<td>UNITY MATRIX IT MV</td>\n<td>UNITYMATRIX MV 的逆转置矩阵,用于将法线从模型空间变换到观察空间,也可用于得到 UNITYMATRIXMV 的逆矩阵</td>\n</tr>\n<tr>\n<td>Object2World</td>\n<td>当前的模型矩阵,用于将顶点&#x2F;方向矢量从模型空间变换到世界空间</td>\n</tr>\n<tr>\n<td>World2Object</td>\n<td>Object2World 的逆矩阵,用于将顶点&#x2F;方向矢量从世界空间变换到模型空间</td>\n</tr>\n</tbody></table>\n"},{"title":"css奇技淫巧","status":"doing","_content":"\n# grid 布局\n\n> flex 布局操纵的是一维、一行/一列grid 布局具备操纵二维的能力\n\n设为网格布局以后容器子元素项目的`float`、`display: inline-block`、`display: table-cell`、`vertical-align`和 `column-`等设置都将失效。\n\n- grid-template-columns: 定义每一列的列宽\n- grid-template-rows: 定义每一行的行高\n- grid-row-gap: 行间距\n- grid-column-gap: 列间距\n- grid-gap: 行列间距合并\n- grid-template-areas: 一个区域由单个或多个单元格组成\n- grid-auto-flow: 默认值是 row即\"先行后列\",即先填满第一行,再开始放入第二行\n- justify-items: `单元格内容`的水平对齐\n- align-items: `单元格内容`垂直对齐\n- place-items: align-items 属性和 justify-items 属性的合并简写形式\n- justify-content: `整个内容区域`水平对齐\n- align-content: `整个内容区域`垂直对齐\n- place-content: align-content 属性和 justify-content 属性的合并简写形式\n\n> 设置的行或者列比较多的时候,可以使用 repeat()这个函数简化重复的值\n\n## repeat()\n\n第一个参数是重复的次数第二个参数是所要重复的值、也可以是某个模式\n\n```css\n/* 重复 3个100px的列 */\ngrid-template-columns: repeat(3, 100px);\n/* 重复这种布局2次 */\ngrid-template-columns: repeat(2, 100px 20px 80px);\n/* 自动填充,直到容器放不下为止 */\ngrid-template-columns: repeat(auto-fill, 100px);\n```\n\n## fr\n\n方便表示比例关系网格布局提供了 fr 关键字\n\n```css\ngrid-template-columns: 1fr 1fr;\n```\n\n## grid-template-areas\n\n```css\ngrid-template-areas:\n \"header header header\"\n \"main main sidebar\"\n \"footer footer footer\";\n```\n\n## item 定位\n\n![grid_1](/img/grid_1.png)\n\n```css\n/* 1号项目就是从第二根垂直网格线开始第四根结束 */\n.item1 {\n grid-column-start: 2;\n grid-column-end: 4;\n background: red;\n}\n```\n\n# 硬件加速(IE9+)\n\n> 移动端开启,吃内存、增加耗电\n\n`animation`、`transform`、`transition`不会自动开启`GPU`加速,利用`transform: translateZ(0)` 就可以开启`3D变换`,出发硬件加速\n\n场景`webKit内核`偶尔页面闪烁:`transform: translate3d(0, 0, 0);`\n\n# 控制台打印 shield 徽章\n\n```js\nconsole.log(\n \"%c\" +\n eval(\"'mozzie.com'\") +\n \"%cv\" +\n eval(\"'2.0.0'\") +\n \"%c\\r\\n\" +\n eval(\"'了解更多:https://www.mozzie.com'\"),\n \"color: #fff; background: #5281FA; font-size: 12px;border-radius:2px 0 0 2px;padding:3px 6px;\",\n \"border-radius:0 2px 2px 0;padding:3px 6px;color:#333;background:#EBEBEB\",\n \"margin-top:10px;\"\n);\n```\n\n# css 判断 input 是否为空\n\n`:placeholder-shown`:占位符是否显示的伪类,配合 `:not()` (不是必须,反过来也可以)\n\n```html\n<div id=\"demo\">\n <input id=\"demo-input\" type=\"text\" placeholder=\"name\" />\n <label id=\"demo-label\">Name</label>\n</div>\n```\n\n```css\n#demo {\n width: 90%;\n max-width: 450px;\n position: relative;\n}\n#demo-input {\n width: 100%;\n height: 60px;\n line-height: 60px;\n font-size: 20px;\n border-bottom: 1px solid #ffa500;\n}\n#demo-input::placeholder {\n font-size: 0;\n}\n#demo-input:focus + label,\n#demo-input:not(:placeholder-shown) + label {\n top: 0;\n font-size: 12px;\n}\n#demo-label {\n font-size: 22px;\n color: #ffa500;\n position: absolute;\n left: 0;\n top: 50%;\n transform: translateY(-50%);\n transition: all 0.3s;\n}\n/*\n* Default\n*/\nbody {\n height: 100vh;\n display: flex;\n}\nbody div {\n margin: auto;\n}\nbody div input {\n border: 0;\n outline: 0;\n}\n```\n\n# 居中\n\n## transform 大法\n\n```css\n#wrapper {\n position: relative;\n}\n#box {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n}\n```\n\n## 0000 大法\n\n```css\n#wrapper {\n position: relative;\n}\n#box {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n}\n```\n\n## 如何让 img 垂直居中\n\n```html\n<div id=\"imgWrapper\">\n <img src=\"xxx.png\" />\n</div>\n```\n\n```css\n.imgWrapper {\n display: table-cell;\n text-align: center;\n vertical-align: middle;\n}\n```\n\n## ul 下 li 居中\n\n```html\n<!--外层包个div/section block元素 -->\n<div>\n <ul class=\"clearfix\">\n <li>1</li>\n <li>2</li>\n </ul>\n</div>\n```\n\n```css\ndiv{\n text-align: center\n}\nul{\n display: inline-block\n}\nli{\n display: inline\n float: left\n}\n```\n\n# js 随机渐变背景\n\n```javascript\nfunction getRandomRangeNum(min, max) {\n return min + Math.floor(Math.random() * (max - min));\n}\n\nfunction setRandomBg(el) {\n var left = getRandomRangeNum(0, 255);\n var bottom = getRandomRangeNum(0, 255);\n var css = [\n \"linear-gradient(to left bottom,hsl(\",\n left,\n \", 100%, 85%) 0%,hsl(\",\n bottom,\n \", 100%, 85%) 100%)\",\n ];\n el.style.background = css.join(\"\");\n}\n```\n\n# css 三角形\n\n```css\nspan {\n width: 0;\n height: 0;\n border-top: 40px solid transparent;\n border-left: 40px solid transparent;\n border-right: 40px solid transparent;\n border-bottom: 40px solid #ff0000;\n}\n```\n\n# 1px 神迹\n\n## pc 端最优解\n\n```html\n<div style=\"height:1px;overflow:hidden;background:red\"></div>\n```\n\n## 移动端 - 媒体查询 + transform\n\n```css\n@media only screen and (-webkit-min-device-pixel-ratio: 2) {\n .border-bottom::after {\n -webkit-transform: scaleY(0.5);\n transform: scaleY(0.5);\n }\n}\n```\n\n## 移动端 - 媒体查询 + 伪类\n\n```css\n.border__1px:before {\n content: '';\n position: absolute;\n top: 0;\n height: 1px;\n width: 100%\n background-color: #000;\n transform-origin: 50% 0%;\n}\n@media only screen and (-webkit-min-device-pixel-ratio:2) {\n .border__1px:before {\n transform: scaleY(0.5)\n }\n}\n@media only screen and (-webkit-min-device-pixel-ratio:3) {\n .border__1px:before {\n transform: scaleY(0.33)\n }\n}\n```\n\n# 横竖屏适配\n\njs 检测\n\n```js\nwindow.addEventListener(\"resize\", () => {\n if (window.orientation === 180 || window.orientation === 0) {\n // 正常方向或屏幕旋转180度\n console.log(\"竖屏\");\n }\n if (window.orientation === 90 || window.orientation === -90) {\n // 屏幕顺时钟旋转90度或屏幕逆时针旋转90度\n console.log(\"横屏\");\n }\n});\n```\n\ncss 检测\n\n```css\n@media screen and (orientation: portrait) {\n /*竖屏...*/\n}\n@media screen and (orientation: landscape) {\n /*横屏...*/\n}\n```\n\n# 像素\n\n- 物理像素: 物理设备真实的像素\n- 独立像素: 平时开发写的 px\n- 设备像素比(DPR): = 物理像素 / 设备独立像素\n\n```js\n// 获取 DPR\nwindow.devicePixelRatio;\n```\n\n也可以使用媒体查询\n\n```css\n@media (-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2) {\n}\n```\n\n# srcset\n\n使用 img 标签的 `srcset` 属性,浏览器会自动根据像素密度匹配最佳显示图片:\n\n```html\n<img src=\"conardLi_1x.png\" srcset=\"conardLi_2x.png 2x, conardLi_3x.png 3x\" />\n```\n\n# 字体小于 12px\n\ncss3 的 `transform` 属性,设置值为 `scale(x, y)` 定义 2D 缩放转换\n\n\n# css 清浮动\n\n```css\n.clearfix::after {\n content: \"\";\n display: block;\n clear: both;\n}\n```\n\n# ellipsis\n\n## 单行\n\n```css\n.ellipsis {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n```\n\n## 多行\n\n```css\n.ellipsis {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 3; // 最多显示几行\n overflow: hidden;\n}\n```\n\n# 页面导入样式时,使用 link 和 @import\n\n> 你可能不信ie5+就支持@import 了\n\n- link: 与`dom`异步加载\n- @import: 先加载`dom`\n\n\n# em | rem 换算\n\n相对于HTML根元素 `font-size` 来确定的,浏览器的默认字体高是 `16px`,因此:\n\n- 16px = 1em\n- 12px = .75em\n- 10px = .625em\n\n简化 rem 到 px 的换算,因为每个 rem 单位都是 10px 的倍数\n\n```css\nhtml {\n font-size: 62.5%; /* 这会将默认的 16px 缩小为 10px */\n}\n```\n\n也可以使用 js 检测设置\n\n```js\n// set 1rem = viewWidth / 10\nfunction setRemUnit() {\n var docEl = document.documentElement;\n var rem = docEl.clientWidth / 10;\n docEl.style.fontSize = rem + \"px\";\n}\n\nwindow.addEventListener(\"resize\", setRemUnit);\nwindow.addEventListener(\"pageShow\", function (e) {\n if (e.persisted) setRemUnit()\n});\n```\n\n# less 常用\n\n## 变量\n\nLESS 中的变量为完全的 `常量` ,所以只能定义一次\n\n```less\n@nice-blue: #5B83AD;\n@light-blue: @nice-blue + #111;\n\n#header {\n color: @light-blue;\n}\n```\n\n输出\n\n```less\n#header {\n color: #6c94be;\n}\n```\n\n## 混合\n\n```less\n.bordered {\n border-top: dotted 1px black;\n border-bottom: solid 2px black;\n}\n```\n\n使用\n\n```less\n#menu a {\n color: #111;\n .bordered;\n}\n.post a {\n color: red;\n .bordered;\n}\n```\n\n带参\n\n```less\n.border-radius (@radius) {\n border-radius: @radius;\n -moz-border-radius: @radius;\n -webkit-border-radius: @radius;\n}\n```\n\n#header {\n.border-radius(4px);\n}\n\n`@arguments`变量,包含了所有传递进来的参数. 如果你不想单独处理每一个参数\n\n```less\n.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #000) {\n box-shadow: @arguments;\n -moz-box-shadow: @arguments;\n -webkit-box-shadow: @arguments;\n}\n.box-shadow(2px, 5px);\n```\n\n无参\n\n```less\n.wrap () {\n text-wrap: wrap;\n white-space: pre-wrap;\n white-space: -moz-pre-wrap;\n word-wrap: break-word;\n}\n\npre {\n .wrap;\n}\n```\n\n## lighten 和 darken\n\n```less\n@color-base: #3bafda;\n@color-hover:lighten (@color-primary,10%);\n@color-focus:darken (@color-primary,10%);\n```\n\n## contrast\n\n选择两种颜色中哪一种颜色与另一种颜色形成最大对比。\n\n```less\np {\n a: contrast(#bbbbbb); //output: black\n b: contrast(#222222, #101010); //output: white\n}\n```\n\n## JavaScript 表达式\n\n```less\n@var: ` \"hello\" .toUpperCase() + \"!\" `;\n@height: `document.body.clientHeight`;\n```\n\n## & 父选择器\n\n`&` 只能代表父元素,不能代表父亲的父辈元素,施加改性类或伪类\n\n```less\na {\n color: blue;\n &:hover {\n color: green;\n }\n}\n```\n\n## 重复父类名\n\n```less\n.button {\n &-ok {\n background-image: url(\"ok.png\");\n }\n &-cancel {\n background-image: url(\"cancel.png\");\n }\n\n &-custom {\n background-image: url(\"custom.png\");\n }\n}\n```\n","source":"_posts/front-end/css奇技淫巧.md","raw":"---\ntitle: css奇技淫巧\ncategories:\n - Front-End\nstatus: doing\n---\n\n# grid 布局\n\n> flex 布局操纵的是一维、一行/一列grid 布局具备操纵二维的能力\n\n设为网格布局以后容器子元素项目的`float`、`display: inline-block`、`display: table-cell`、`vertical-align`和 `column-`等设置都将失效。\n\n- grid-template-columns: 定义每一列的列宽\n- grid-template-rows: 定义每一行的行高\n- grid-row-gap: 行间距\n- grid-column-gap: 列间距\n- grid-gap: 行列间距合并\n- grid-template-areas: 一个区域由单个或多个单元格组成\n- grid-auto-flow: 默认值是 row即\"先行后列\",即先填满第一行,再开始放入第二行\n- justify-items: `单元格内容`的水平对齐\n- align-items: `单元格内容`垂直对齐\n- place-items: align-items 属性和 justify-items 属性的合并简写形式\n- justify-content: `整个内容区域`水平对齐\n- align-content: `整个内容区域`垂直对齐\n- place-content: align-content 属性和 justify-content 属性的合并简写形式\n\n> 设置的行或者列比较多的时候,可以使用 repeat()这个函数简化重复的值\n\n## repeat()\n\n第一个参数是重复的次数第二个参数是所要重复的值、也可以是某个模式\n\n```css\n/* 重复 3个100px的列 */\ngrid-template-columns: repeat(3, 100px);\n/* 重复这种布局2次 */\ngrid-template-columns: repeat(2, 100px 20px 80px);\n/* 自动填充,直到容器放不下为止 */\ngrid-template-columns: repeat(auto-fill, 100px);\n```\n\n## fr\n\n方便表示比例关系网格布局提供了 fr 关键字\n\n```css\ngrid-template-columns: 1fr 1fr;\n```\n\n## grid-template-areas\n\n```css\ngrid-template-areas:\n \"header header header\"\n \"main main sidebar\"\n \"footer footer footer\";\n```\n\n## item 定位\n\n![grid_1](/img/grid_1.png)\n\n```css\n/* 1号项目就是从第二根垂直网格线开始第四根结束 */\n.item1 {\n grid-column-start: 2;\n grid-column-end: 4;\n background: red;\n}\n```\n\n# 硬件加速(IE9+)\n\n> 移动端开启,吃内存、增加耗电\n\n`animation`、`transform`、`transition`不会自动开启`GPU`加速,利用`transform: translateZ(0)` 就可以开启`3D变换`,出发硬件加速\n\n场景`webKit内核`偶尔页面闪烁:`transform: translate3d(0, 0, 0);`\n\n# 控制台打印 shield 徽章\n\n```js\nconsole.log(\n \"%c\" +\n eval(\"'mozzie.com'\") +\n \"%cv\" +\n eval(\"'2.0.0'\") +\n \"%c\\r\\n\" +\n eval(\"'了解更多:https://www.mozzie.com'\"),\n \"color: #fff; background: #5281FA; font-size: 12px;border-radius:2px 0 0 2px;padding:3px 6px;\",\n \"border-radius:0 2px 2px 0;padding:3px 6px;color:#333;background:#EBEBEB\",\n \"margin-top:10px;\"\n);\n```\n\n# css 判断 input 是否为空\n\n`:placeholder-shown`:占位符是否显示的伪类,配合 `:not()` (不是必须,反过来也可以)\n\n```html\n<div id=\"demo\">\n <input id=\"demo-input\" type=\"text\" placeholder=\"name\" />\n <label id=\"demo-label\">Name</label>\n</div>\n```\n\n```css\n#demo {\n width: 90%;\n max-width: 450px;\n position: relative;\n}\n#demo-input {\n width: 100%;\n height: 60px;\n line-height: 60px;\n font-size: 20px;\n border-bottom: 1px solid #ffa500;\n}\n#demo-input::placeholder {\n font-size: 0;\n}\n#demo-input:focus + label,\n#demo-input:not(:placeholder-shown) + label {\n top: 0;\n font-size: 12px;\n}\n#demo-label {\n font-size: 22px;\n color: #ffa500;\n position: absolute;\n left: 0;\n top: 50%;\n transform: translateY(-50%);\n transition: all 0.3s;\n}\n/*\n* Default\n*/\nbody {\n height: 100vh;\n display: flex;\n}\nbody div {\n margin: auto;\n}\nbody div input {\n border: 0;\n outline: 0;\n}\n```\n\n# 居中\n\n## transform 大法\n\n```css\n#wrapper {\n position: relative;\n}\n#box {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n}\n```\n\n## 0000 大法\n\n```css\n#wrapper {\n position: relative;\n}\n#box {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n}\n```\n\n## 如何让 img 垂直居中\n\n```html\n<div id=\"imgWrapper\">\n <img src=\"xxx.png\" />\n</div>\n```\n\n```css\n.imgWrapper {\n display: table-cell;\n text-align: center;\n vertical-align: middle;\n}\n```\n\n## ul 下 li 居中\n\n```html\n<!--外层包个div/section block元素 -->\n<div>\n <ul class=\"clearfix\">\n <li>1</li>\n <li>2</li>\n </ul>\n</div>\n```\n\n```css\ndiv{\n text-align: center\n}\nul{\n display: inline-block\n}\nli{\n display: inline\n float: left\n}\n```\n\n# js 随机渐变背景\n\n```javascript\nfunction getRandomRangeNum(min, max) {\n return min + Math.floor(Math.random() * (max - min));\n}\n\nfunction setRandomBg(el) {\n var left = getRandomRangeNum(0, 255);\n var bottom = getRandomRangeNum(0, 255);\n var css = [\n \"linear-gradient(to left bottom,hsl(\",\n left,\n \", 100%, 85%) 0%,hsl(\",\n bottom,\n \", 100%, 85%) 100%)\",\n ];\n el.style.background = css.join(\"\");\n}\n```\n\n# css 三角形\n\n```css\nspan {\n width: 0;\n height: 0;\n border-top: 40px solid transparent;\n border-left: 40px solid transparent;\n border-right: 40px solid transparent;\n border-bottom: 40px solid #ff0000;\n}\n```\n\n# 1px 神迹\n\n## pc 端最优解\n\n```html\n<div style=\"height:1px;overflow:hidden;background:red\"></div>\n```\n\n## 移动端 - 媒体查询 + transform\n\n```css\n@media only screen and (-webkit-min-device-pixel-ratio: 2) {\n .border-bottom::after {\n -webkit-transform: scaleY(0.5);\n transform: scaleY(0.5);\n }\n}\n```\n\n## 移动端 - 媒体查询 + 伪类\n\n```css\n.border__1px:before {\n content: '';\n position: absolute;\n top: 0;\n height: 1px;\n width: 100%\n background-color: #000;\n transform-origin: 50% 0%;\n}\n@media only screen and (-webkit-min-device-pixel-ratio:2) {\n .border__1px:before {\n transform: scaleY(0.5)\n }\n}\n@media only screen and (-webkit-min-device-pixel-ratio:3) {\n .border__1px:before {\n transform: scaleY(0.33)\n }\n}\n```\n\n# 横竖屏适配\n\njs 检测\n\n```js\nwindow.addEventListener(\"resize\", () => {\n if (window.orientation === 180 || window.orientation === 0) {\n // 正常方向或屏幕旋转180度\n console.log(\"竖屏\");\n }\n if (window.orientation === 90 || window.orientation === -90) {\n // 屏幕顺时钟旋转90度或屏幕逆时针旋转90度\n console.log(\"横屏\");\n }\n});\n```\n\ncss 检测\n\n```css\n@media screen and (orientation: portrait) {\n /*竖屏...*/\n}\n@media screen and (orientation: landscape) {\n /*横屏...*/\n}\n```\n\n# 像素\n\n- 物理像素: 物理设备真实的像素\n- 独立像素: 平时开发写的 px\n- 设备像素比(DPR): = 物理像素 / 设备独立像素\n\n```js\n// 获取 DPR\nwindow.devicePixelRatio;\n```\n\n也可以使用媒体查询\n\n```css\n@media (-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2) {\n}\n```\n\n# srcset\n\n使用 img 标签的 `srcset` 属性,浏览器会自动根据像素密度匹配最佳显示图片:\n\n```html\n<img src=\"conardLi_1x.png\" srcset=\"conardLi_2x.png 2x, conardLi_3x.png 3x\" />\n```\n\n# 字体小于 12px\n\ncss3 的 `transform` 属性,设置值为 `scale(x, y)` 定义 2D 缩放转换\n\n\n# css 清浮动\n\n```css\n.clearfix::after {\n content: \"\";\n display: block;\n clear: both;\n}\n```\n\n# ellipsis\n\n## 单行\n\n```css\n.ellipsis {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n```\n\n## 多行\n\n```css\n.ellipsis {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 3; // 最多显示几行\n overflow: hidden;\n}\n```\n\n# 页面导入样式时,使用 link 和 @import\n\n> 你可能不信ie5+就支持@import 了\n\n- link: 与`dom`异步加载\n- @import: 先加载`dom`\n\n\n# em | rem 换算\n\n相对于HTML根元素 `font-size` 来确定的,浏览器的默认字体高是 `16px`,因此:\n\n- 16px = 1em\n- 12px = .75em\n- 10px = .625em\n\n简化 rem 到 px 的换算,因为每个 rem 单位都是 10px 的倍数\n\n```css\nhtml {\n font-size: 62.5%; /* 这会将默认的 16px 缩小为 10px */\n}\n```\n\n也可以使用 js 检测设置\n\n```js\n// set 1rem = viewWidth / 10\nfunction setRemUnit() {\n var docEl = document.documentElement;\n var rem = docEl.clientWidth / 10;\n docEl.style.fontSize = rem + \"px\";\n}\n\nwindow.addEventListener(\"resize\", setRemUnit);\nwindow.addEventListener(\"pageShow\", function (e) {\n if (e.persisted) setRemUnit()\n});\n```\n\n# less 常用\n\n## 变量\n\nLESS 中的变量为完全的 `常量` ,所以只能定义一次\n\n```less\n@nice-blue: #5B83AD;\n@light-blue: @nice-blue + #111;\n\n#header {\n color: @light-blue;\n}\n```\n\n输出\n\n```less\n#header {\n color: #6c94be;\n}\n```\n\n## 混合\n\n```less\n.bordered {\n border-top: dotted 1px black;\n border-bottom: solid 2px black;\n}\n```\n\n使用\n\n```less\n#menu a {\n color: #111;\n .bordered;\n}\n.post a {\n color: red;\n .bordered;\n}\n```\n\n带参\n\n```less\n.border-radius (@radius) {\n border-radius: @radius;\n -moz-border-radius: @radius;\n -webkit-border-radius: @radius;\n}\n```\n\n#header {\n.border-radius(4px);\n}\n\n`@arguments`变量,包含了所有传递进来的参数. 如果你不想单独处理每一个参数\n\n```less\n.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #000) {\n box-shadow: @arguments;\n -moz-box-shadow: @arguments;\n -webkit-box-shadow: @arguments;\n}\n.box-shadow(2px, 5px);\n```\n\n无参\n\n```less\n.wrap () {\n text-wrap: wrap;\n white-space: pre-wrap;\n white-space: -moz-pre-wrap;\n word-wrap: break-word;\n}\n\npre {\n .wrap;\n}\n```\n\n## lighten 和 darken\n\n```less\n@color-base: #3bafda;\n@color-hover:lighten (@color-primary,10%);\n@color-focus:darken (@color-primary,10%);\n```\n\n## contrast\n\n选择两种颜色中哪一种颜色与另一种颜色形成最大对比。\n\n```less\np {\n a: contrast(#bbbbbb); //output: black\n b: contrast(#222222, #101010); //output: white\n}\n```\n\n## JavaScript 表达式\n\n```less\n@var: ` \"hello\" .toUpperCase() + \"!\" `;\n@height: `document.body.clientHeight`;\n```\n\n## & 父选择器\n\n`&` 只能代表父元素,不能代表父亲的父辈元素,施加改性类或伪类\n\n```less\na {\n color: blue;\n &:hover {\n color: green;\n }\n}\n```\n\n## 重复父类名\n\n```less\n.button {\n &-ok {\n background-image: url(\"ok.png\");\n }\n &-cancel {\n background-image: url(\"cancel.png\");\n }\n\n &-custom {\n background-image: url(\"custom.png\");\n }\n}\n```\n","slug":"front-end/css奇技淫巧","published":1,"date":"2023-11-06T08:02:18.176Z","updated":"2023-11-08T01:33:30.288Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58n00094cz3bshsgix4","content":"<h1 id=\"grid-布局\"><a href=\"#grid-布局\" class=\"headerlink\" title=\"grid 布局\"></a>grid 布局</h1><blockquote>\n<p>flex 布局操纵的是一维、一行&#x2F;一列grid 布局具备操纵二维的能力</p>\n</blockquote>\n<p>设为网格布局以后,容器子元素(项目)的<code>float</code>、<code>display: inline-block</code>、<code>display: table-cell</code>、<code>vertical-align</code>和 <code>column-</code>等设置都将失效。</p>\n<ul>\n<li>grid-template-columns: 定义每一列的列宽</li>\n<li>grid-template-rows: 定义每一行的行高</li>\n<li>grid-row-gap: 行间距</li>\n<li>grid-column-gap: 列间距</li>\n<li>grid-gap: 行列间距合并</li>\n<li>grid-template-areas: 一个区域由单个或多个单元格组成</li>\n<li>grid-auto-flow: 默认值是 row即”先行后列”,即先填满第一行,再开始放入第二行</li>\n<li>justify-items: <code>单元格内容</code>的水平对齐</li>\n<li>align-items: <code>单元格内容</code>垂直对齐</li>\n<li>place-items: align-items 属性和 justify-items 属性的合并简写形式</li>\n<li>justify-content: <code>整个内容区域</code>水平对齐</li>\n<li>align-content: <code>整个内容区域</code>垂直对齐</li>\n<li>place-content: align-content 属性和 justify-content 属性的合并简写形式</li>\n</ul>\n<blockquote>\n<p>设置的行或者列比较多的时候,可以使用 repeat()这个函数简化重复的值</p>\n</blockquote>\n<h2 id=\"repeat\"><a href=\"#repeat\" class=\"headerlink\" title=\"repeat()\"></a>repeat()</h2><p>第一个参数是重复的次数,第二个参数是所要重复的值、也可以是某个模式</p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token comment\">/* 重复 3个100px的列 */</span>\n<span class=\"token property\">grid-template-columns</span><span class=\"token punctuation\">:</span> <span class=\"token function\">repeat</span><span class=\"token punctuation\">(</span>3<span class=\"token punctuation\">,</span> 100px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">/* 重复这种布局2次 */</span>\n<span class=\"token property\">grid-template-columns</span><span class=\"token punctuation\">:</span> <span class=\"token function\">repeat</span><span class=\"token punctuation\">(</span>2<span class=\"token punctuation\">,</span> 100px 20px 80px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">/* 自动填充,直到容器放不下为止 */</span>\n<span class=\"token property\">grid-template-columns</span><span class=\"token punctuation\">:</span> <span class=\"token function\">repeat</span><span class=\"token punctuation\">(</span>auto-fill<span class=\"token punctuation\">,</span> 100px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"fr\"><a href=\"#fr\" class=\"headerlink\" title=\"fr\"></a>fr</h2><p>方便表示比例关系,网格布局提供了 fr 关键字</p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token property\">grid-template-columns</span><span class=\"token punctuation\">:</span> 1fr 1fr<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"grid-template-areas\"><a href=\"#grid-template-areas\" class=\"headerlink\" title=\"grid-template-areas\"></a>grid-template-areas</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token property\">grid-template-areas</span><span class=\"token punctuation\">:</span>\n <span class=\"token string\">\"header header header\"</span>\n <span class=\"token string\">\"main main sidebar\"</span>\n <span class=\"token string\">\"footer footer footer\"</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"item-定位\"><a href=\"#item-定位\" class=\"headerlink\" title=\"item 定位\"></a>item 定位</h2><p><img src=\"/img/grid_1.png\" alt=\"grid_1\"></p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token comment\">/* 1号项目就是从第二根垂直网格线开始第四根结束 */</span>\n<span class=\"token selector\">.item1</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">grid-column-start</span><span class=\"token punctuation\">:</span> 2<span class=\"token punctuation\">;</span>\n <span class=\"token property\">grid-column-end</span><span class=\"token punctuation\">:</span> 4<span class=\"token punctuation\">;</span>\n <span class=\"token property\">background</span><span class=\"token punctuation\">:</span> red<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"硬件加速-IE9\"><a href=\"#硬件加速-IE9\" class=\"headerlink\" title=\"硬件加速(IE9+)\"></a>硬件加速(IE9+)</h1><blockquote>\n<p>移动端开启,吃内存、增加耗电</p>\n</blockquote>\n<p><code>animation</code>、<code>transform</code>、<code>transition</code>不会自动开启<code>GPU</code>加速,利用<code>transform: translateZ(0)</code> 就可以开启<code>3D变换</code>,出发硬件加速</p>\n<p>场景:<code>webKit内核</code>偶尔页面闪烁:<code>transform: translate3d(0, 0, 0);</code></p>\n<h1 id=\"控制台打印-shield-徽章\"><a href=\"#控制台打印-shield-徽章\" class=\"headerlink\" title=\"控制台打印 shield 徽章\"></a>控制台打印 shield 徽章</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>\n <span class=\"token string\">\"%c\"</span> <span class=\"token operator\">+</span>\n <span class=\"token function\">eval</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"'mozzie.com'\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span>\n <span class=\"token string\">\"%cv\"</span> <span class=\"token operator\">+</span>\n <span class=\"token function\">eval</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"'2.0.0'\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span>\n <span class=\"token string\">\"%c\\r\\n\"</span> <span class=\"token operator\">+</span>\n <span class=\"token function\">eval</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"'了解更多:https://www.mozzie.com'\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"color: #fff; background: #5281FA; font-size: 12px;border-radius:2px 0 0 2px;padding:3px 6px;\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"border-radius:0 2px 2px 0;padding:3px 6px;color:#333;background:#EBEBEB\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"margin-top:10px;\"</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"css-判断-input-是否为空\"><a href=\"#css-判断-input-是否为空\" class=\"headerlink\" title=\"css 判断 input 是否为空\"></a>css 判断 input 是否为空</h1><p><code>:placeholder-shown</code>:占位符是否显示的伪类,配合 <code>:not()</code> (不是必须,反过来也可以)</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>demo<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>demo-input<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>text<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">placeholder</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>label</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>demo-label<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>Name<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>label</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">#demo</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 90%<span class=\"token punctuation\">;</span>\n <span class=\"token property\">max-width</span><span class=\"token punctuation\">:</span> 450px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> relative<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#demo-input</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 100%<span class=\"token punctuation\">;</span>\n <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 60px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">line-height</span><span class=\"token punctuation\">:</span> 60px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 20px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-bottom</span><span class=\"token punctuation\">:</span> 1px solid #ffa500<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#demo-input::placeholder</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#demo-input:focus + label,\n#demo-input:not(:placeholder-shown) + label</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">top</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 12px<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#demo-label</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 22px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> #ffa500<span class=\"token punctuation\">;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span>\n <span class=\"token property\">left</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">top</span><span class=\"token punctuation\">:</span> 50%<span class=\"token punctuation\">;</span>\n <span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">translateY</span><span class=\"token punctuation\">(</span>-50%<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">transition</span><span class=\"token punctuation\">:</span> all 0.3s<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">/*\n* Default\n*/</span>\n<span class=\"token selector\">body</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 100vh<span class=\"token punctuation\">;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> flex<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">body div</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">margin</span><span class=\"token punctuation\">:</span> auto<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">body div input</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">border</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">outline</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"居中\"><a href=\"#居中\" class=\"headerlink\" title=\"居中\"></a>居中</h1><h2 id=\"transform-大法\"><a href=\"#transform-大法\" class=\"headerlink\" title=\"transform 大法\"></a>transform 大法</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">#wrapper</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> relative<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#box</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span>\n <span class=\"token property\">top</span><span class=\"token punctuation\">:</span> 50%<span class=\"token punctuation\">;</span>\n <span class=\"token property\">left</span><span class=\"token punctuation\">:</span> 50%<span class=\"token punctuation\">;</span>\n <span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">translate</span><span class=\"token punctuation\">(</span>-50%<span class=\"token punctuation\">,</span> -50%<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"0000-大法\"><a href=\"#0000-大法\" class=\"headerlink\" title=\"0000 大法\"></a>0000 大法</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">#wrapper</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> relative<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#box</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span>\n <span class=\"token property\">top</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">left</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">right</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">bottom</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"如何让-img-垂直居中\"><a href=\"#如何让-img-垂直居中\" class=\"headerlink\" title=\"如何让 img 垂直居中\"></a>如何让 img 垂直居中</h2><pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>imgWrapper<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>xxx.png<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">.imgWrapper</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> table-cell<span class=\"token punctuation\">;</span>\n <span class=\"token property\">text-align</span><span class=\"token punctuation\">:</span> center<span class=\"token punctuation\">;</span>\n <span class=\"token property\">vertical-align</span><span class=\"token punctuation\">:</span> middle<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"ul-下-li-居中\"><a href=\"#ul-下-li-居中\" class=\"headerlink\" title=\"ul 下 li 居中\"></a>ul 下 li 居中</h2><pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token comment\">&lt;!--外层包个div/section block元素 --></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>clearfix<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>1<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>2<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">div</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">text-align</span><span class=\"token punctuation\">:</span> center\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">ul</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> inline-block\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">li</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> inline\n <span class=\"token property\">float</span><span class=\"token punctuation\">:</span> left\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"js-随机渐变背景\"><a href=\"#js-随机渐变背景\" class=\"headerlink\" title=\"js 随机渐变背景\"></a>js 随机渐变背景</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">getRandomRangeNum</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">min<span class=\"token punctuation\">,</span> max</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> min <span class=\"token operator\">+</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">random</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span>max <span class=\"token operator\">-</span> min<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">setRandomBg</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">el</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> left <span class=\"token operator\">=</span> <span class=\"token function\">getRandomRangeNum</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">255</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">var</span> bottom <span class=\"token operator\">=</span> <span class=\"token function\">getRandomRangeNum</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">255</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">var</span> css <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token string\">\"linear-gradient(to left bottom,hsl(\"</span><span class=\"token punctuation\">,</span>\n left<span class=\"token punctuation\">,</span>\n <span class=\"token string\">\", 100%, 85%) 0%,hsl(\"</span><span class=\"token punctuation\">,</span>\n bottom<span class=\"token punctuation\">,</span>\n <span class=\"token string\">\", 100%, 85%) 100%)\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n el<span class=\"token punctuation\">.</span>style<span class=\"token punctuation\">.</span>background <span class=\"token operator\">=</span> css<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"css-三角形\"><a href=\"#css-三角形\" class=\"headerlink\" title=\"css 三角形\"></a>css 三角形</h1><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">span</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-top</span><span class=\"token punctuation\">:</span> 40px solid transparent<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-left</span><span class=\"token punctuation\">:</span> 40px solid transparent<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-right</span><span class=\"token punctuation\">:</span> 40px solid transparent<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-bottom</span><span class=\"token punctuation\">:</span> 40px solid #ff0000<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"1px-神迹\"><a href=\"#1px-神迹\" class=\"headerlink\" title=\"1px 神迹\"></a>1px 神迹</h1><h2 id=\"pc-端最优解\"><a href=\"#pc-端最优解\" class=\"headerlink\" title=\"pc 端最优解\"></a>pc 端最优解</h2><pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token special-attr\"><span class=\"token attr-name\">style</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token value css language-css\"><span class=\"token property\">height</span><span class=\"token punctuation\">:</span>1px<span class=\"token punctuation\">;</span><span class=\"token property\">overflow</span><span class=\"token punctuation\">:</span>hidden<span class=\"token punctuation\">;</span><span class=\"token property\">background</span><span class=\"token punctuation\">:</span>red</span><span class=\"token punctuation\">\"</span></span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"移动端-媒体查询-transform\"><a href=\"#移动端-媒体查询-transform\" class=\"headerlink\" title=\"移动端 - 媒体查询 + transform\"></a>移动端 - 媒体查询 + transform</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token atrule\"><span class=\"token rule\">@media</span> <span class=\"token keyword\">only</span> screen <span class=\"token keyword\">and</span> <span class=\"token punctuation\">(</span><span class=\"token property\">-webkit-min-device-pixel-ratio</span><span class=\"token punctuation\">:</span> 2<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token selector\">.border-bottom::after</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">-webkit-transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">scaleY</span><span class=\"token punctuation\">(</span>0.5<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">scaleY</span><span class=\"token punctuation\">(</span>0.5<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"移动端-媒体查询-伪类\"><a href=\"#移动端-媒体查询-伪类\" class=\"headerlink\" title=\"移动端 - 媒体查询 + 伪类\"></a>移动端 - 媒体查询 + 伪类</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">.border__1px:before</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">content</span><span class=\"token punctuation\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span>\n <span class=\"token property\">top</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 1px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 100%\n <span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> #000<span class=\"token punctuation\">;</span>\n <span class=\"token property\">transform-origin</span><span class=\"token punctuation\">:</span> 50% 0%<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token atrule\"><span class=\"token rule\">@media</span> <span class=\"token keyword\">only</span> screen <span class=\"token keyword\">and</span> <span class=\"token punctuation\">(</span><span class=\"token property\">-webkit-min-device-pixel-ratio</span><span class=\"token punctuation\">:</span>2<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token selector\">.border__1px:before</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">scaleY</span><span class=\"token punctuation\">(</span>0.5<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token atrule\"><span class=\"token rule\">@media</span> <span class=\"token keyword\">only</span> screen <span class=\"token keyword\">and</span> <span class=\"token punctuation\">(</span><span class=\"token property\">-webkit-min-device-pixel-ratio</span><span class=\"token punctuation\">:</span>3<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token selector\">.border__1px:before</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">scaleY</span><span class=\"token punctuation\">(</span>0.33<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"横竖屏适配\"><a href=\"#横竖屏适配\" class=\"headerlink\" title=\"横竖屏适配\"></a>横竖屏适配</h1><p>js 检测</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"resize\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">.</span>orientation <span class=\"token operator\">===</span> <span class=\"token number\">180</span> <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>orientation <span class=\"token operator\">===</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 正常方向或屏幕旋转180度</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"竖屏\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">.</span>orientation <span class=\"token operator\">===</span> <span class=\"token number\">90</span> <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>orientation <span class=\"token operator\">===</span> <span class=\"token operator\">-</span><span class=\"token number\">90</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 屏幕顺时钟旋转90度或屏幕逆时针旋转90度</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"横屏\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>css 检测</p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token atrule\"><span class=\"token rule\">@media</span> screen <span class=\"token keyword\">and</span> <span class=\"token punctuation\">(</span><span class=\"token property\">orientation</span><span class=\"token punctuation\">:</span> portrait<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">/*竖屏...*/</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token atrule\"><span class=\"token rule\">@media</span> screen <span class=\"token keyword\">and</span> <span class=\"token punctuation\">(</span><span class=\"token property\">orientation</span><span class=\"token punctuation\">:</span> landscape<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">/*横屏...*/</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"像素\"><a href=\"#像素\" class=\"headerlink\" title=\"像素\"></a>像素</h1><ul>\n<li>物理像素: 物理设备真实的像素</li>\n<li>独立像素: 平时开发写的 px</li>\n<li>设备像素比(DPR): &#x3D; 物理像素 &#x2F; 设备独立像素</li>\n</ul>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 获取 DPR</span>\nwindow<span class=\"token punctuation\">.</span>devicePixelRatio<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<p>也可以使用媒体查询</p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token atrule\"><span class=\"token rule\">@media</span> <span class=\"token punctuation\">(</span><span class=\"token property\">-webkit-min-device-pixel-ratio</span><span class=\"token punctuation\">:</span> 2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token property\">min-device-pixel-ratio</span><span class=\"token punctuation\">:</span> 2<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"srcset\"><a href=\"#srcset\" class=\"headerlink\" title=\"srcset\"></a>srcset</h1><p>使用 img 标签的 <code>srcset</code> 属性,浏览器会自动根据像素密度匹配最佳显示图片:</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>conardLi_1x.png<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>conardLi_2x.png 2x, conardLi_3x.png 3x<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h1 id=\"字体小于-12px\"><a href=\"#字体小于-12px\" class=\"headerlink\" title=\"字体小于 12px\"></a>字体小于 12px</h1><p>css3 的 <code>transform</code> 属性,设置值为 <code>scale(x, y)</code> 定义 2D 缩放转换</p>\n<h1 id=\"css-清浮动\"><a href=\"#css-清浮动\" class=\"headerlink\" title=\"css 清浮动\"></a>css 清浮动</h1><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">.clearfix::after</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">content</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> block<span class=\"token punctuation\">;</span>\n <span class=\"token property\">clear</span><span class=\"token punctuation\">:</span> both<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"ellipsis\"><a href=\"#ellipsis\" class=\"headerlink\" title=\"ellipsis\"></a>ellipsis</h1><h2 id=\"单行\"><a href=\"#单行\" class=\"headerlink\" title=\"单行\"></a>单行</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">.ellipsis</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">overflow</span><span class=\"token punctuation\">:</span> hidden<span class=\"token punctuation\">;</span>\n <span class=\"token property\">text-overflow</span><span class=\"token punctuation\">:</span> ellipsis<span class=\"token punctuation\">;</span>\n <span class=\"token property\">white-space</span><span class=\"token punctuation\">:</span> nowrap<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"多行\"><a href=\"#多行\" class=\"headerlink\" title=\"多行\"></a>多行</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">.ellipsis</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> -webkit-box<span class=\"token punctuation\">;</span>\n <span class=\"token property\">-webkit-box-orient</span><span class=\"token punctuation\">:</span> vertical<span class=\"token punctuation\">;</span>\n <span class=\"token property\">-webkit-line-clamp</span><span class=\"token punctuation\">:</span> 3<span class=\"token punctuation\">;</span> // 最多显示几行\n <span class=\"token property\">overflow</span><span class=\"token punctuation\">:</span> hidden<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"页面导入样式时,使用-link-和-import\"><a href=\"#页面导入样式时,使用-link-和-import\" class=\"headerlink\" title=\"页面导入样式时,使用 link 和 @import\"></a>页面导入样式时,使用 link 和 @import</h1><blockquote>\n<p>你可能不信ie5+就支持@import 了</p>\n</blockquote>\n<ul>\n<li>link: 与<code>dom</code>异步加载</li>\n<li>@import: 先加载<code>dom</code></li>\n</ul>\n<h1 id=\"em-rem-换算\"><a href=\"#em-rem-换算\" class=\"headerlink\" title=\"em | rem 换算\"></a>em | rem 换算</h1><p>相对于HTML根元素 <code>font-size</code> 来确定的,浏览器的默认字体高是 <code>16px</code>,因此:</p>\n<ul>\n<li>16px &#x3D; 1em</li>\n<li>12px &#x3D; .75em</li>\n<li>10px &#x3D; .625em</li>\n</ul>\n<p>简化 rem 到 px 的换算,因为每个 rem 单位都是 10px 的倍数</p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">html</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 62.5%<span class=\"token punctuation\">;</span> <span class=\"token comment\">/* 这会将默认的 16px 缩小为 10px */</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>也可以使用 js 检测设置</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// set 1rem = viewWidth / 10</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">setRemUnit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> docEl <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span>documentElement<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">var</span> rem <span class=\"token operator\">=</span> docEl<span class=\"token punctuation\">.</span>clientWidth <span class=\"token operator\">/</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span>\n docEl<span class=\"token punctuation\">.</span>style<span class=\"token punctuation\">.</span>fontSize <span class=\"token operator\">=</span> rem <span class=\"token operator\">+</span> <span class=\"token string\">\"px\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\nwindow<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"resize\"</span><span class=\"token punctuation\">,</span> setRemUnit<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nwindow<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"pageShow\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>persisted<span class=\"token punctuation\">)</span> <span class=\"token function\">setRemUnit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"less-常用\"><a href=\"#less-常用\" class=\"headerlink\" title=\"less 常用\"></a>less 常用</h1><h2 id=\"变量\"><a href=\"#变量\" class=\"headerlink\" title=\"变量\"></a>变量</h2><p>LESS 中的变量为完全的 <code>常量</code> ,所以只能定义一次</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token variable\">@nice-blue<span class=\"token punctuation\">:</span></span> #5B83AD<span class=\"token punctuation\">;</span>\n<span class=\"token variable\">@light-blue<span class=\"token punctuation\">:</span></span> <span class=\"token variable\">@nice-blue</span> <span class=\"token operator\">+</span> #111<span class=\"token punctuation\">;</span>\n\n<span class=\"token selector\">#header</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@light-blue</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>输出</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">#header</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> #6c94be<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"混合\"><a href=\"#混合\" class=\"headerlink\" title=\"混合\"></a>混合</h2><pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">.bordered</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">border-top</span><span class=\"token punctuation\">:</span> dotted 1px black<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-bottom</span><span class=\"token punctuation\">:</span> solid 2px black<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>使用</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">#menu a</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> #111<span class=\"token punctuation\">;</span>\n <span class=\"token mixin-usage function\">.bordered</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">.post a</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> red<span class=\"token punctuation\">;</span>\n <span class=\"token mixin-usage function\">.bordered</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>带参</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">.border-radius (<span class=\"token variable\">@radius</span>)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">border-radius</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@radius</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">-moz-border-radius</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@radius</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">-webkit-border-radius</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@radius</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>#header {<br>.border-radius(4px);<br>}</p>\n<p><code>@arguments</code>变量,包含了所有传递进来的参数. 如果你不想单独处理每一个参数</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">.box-shadow (<span class=\"token variable\">@x</span>: 0, <span class=\"token variable\">@y</span>: 0, <span class=\"token variable\">@blur</span>: 1px, <span class=\"token variable\">@color</span>: #000)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">box-shadow</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@arguments</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">-moz-box-shadow</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@arguments</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">-webkit-box-shadow</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@arguments</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n.<span class=\"token function\">box-shadow</span><span class=\"token punctuation\">(</span>2px<span class=\"token punctuation\">,</span> 5px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>无参</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">.wrap ()</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">text-wrap</span><span class=\"token punctuation\">:</span> wrap<span class=\"token punctuation\">;</span>\n <span class=\"token property\">white-space</span><span class=\"token punctuation\">:</span> pre<span class=\"token operator\">-</span>wrap<span class=\"token punctuation\">;</span>\n <span class=\"token property\">white-space</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">-</span>moz<span class=\"token operator\">-</span>pre<span class=\"token operator\">-</span>wrap<span class=\"token punctuation\">;</span>\n <span class=\"token property\">word-wrap</span><span class=\"token punctuation\">:</span> break<span class=\"token operator\">-</span>word<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token selector\">pre</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token mixin-usage function\">.wrap</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"lighten-和-darken\"><a href=\"#lighten-和-darken\" class=\"headerlink\" title=\"lighten 和 darken\"></a>lighten 和 darken</h2><pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token variable\">@color-base<span class=\"token punctuation\">:</span></span> #3bafda<span class=\"token punctuation\">;</span>\n<span class=\"token variable\">@color-hover<span class=\"token punctuation\">:</span></span>lighten <span class=\"token punctuation\">(</span><span class=\"token variable\">@color-primary</span><span class=\"token punctuation\">,</span>10%<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token variable\">@color-focus<span class=\"token punctuation\">:</span></span>darken <span class=\"token punctuation\">(</span><span class=\"token variable\">@color-primary</span><span class=\"token punctuation\">,</span>10%<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"contrast\"><a href=\"#contrast\" class=\"headerlink\" title=\"contrast\"></a>contrast</h2><p>选择两种颜色中哪一种颜色与另一种颜色形成最大对比。</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">p</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">a</span><span class=\"token punctuation\">:</span> <span class=\"token function\">contrast</span><span class=\"token punctuation\">(</span>#bbbbbb<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//output: black</span>\n <span class=\"token property\">b</span><span class=\"token punctuation\">:</span> <span class=\"token function\">contrast</span><span class=\"token punctuation\">(</span>#222222<span class=\"token punctuation\">,</span> #101010<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//output: white</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"JavaScript-表达式\"><a href=\"#JavaScript-表达式\" class=\"headerlink\" title=\"JavaScript 表达式\"></a>JavaScript 表达式</h2><pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token variable\">@var<span class=\"token punctuation\">:</span></span> ` <span class=\"token string\">\"hello\"</span> .<span class=\"token function\">toUpperCase</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token string\">\"!\"</span> `<span class=\"token punctuation\">;</span>\n<span class=\"token variable\">@height<span class=\"token punctuation\">:</span></span> `document.body.clientHeight`<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"amp-父选择器\"><a href=\"#amp-父选择器\" class=\"headerlink\" title=\"&amp; 父选择器\"></a>&amp; 父选择器</h2><p><code>&amp;</code> 只能代表父元素,不能代表父亲的父辈元素,施加改性类或伪类</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">a</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> blue<span class=\"token punctuation\">;</span>\n <span class=\"token selector\">&amp;:hover</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> green<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"重复父类名\"><a href=\"#重复父类名\" class=\"headerlink\" title=\"重复父类名\"></a>重复父类名</h2><pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">.button</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token selector\">&amp;-ok</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">background-image</span><span class=\"token punctuation\">:</span> <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">\"ok.png\"</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token selector\">&amp;-cancel</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">background-image</span><span class=\"token punctuation\">:</span> <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">\"cancel.png\"</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token selector\">&amp;-custom</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">background-image</span><span class=\"token punctuation\">:</span> <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">\"custom.png\"</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n","site":{"data":{}},"excerpt":"","more":"<h1 id=\"grid-布局\"><a href=\"#grid-布局\" class=\"headerlink\" title=\"grid 布局\"></a>grid 布局</h1><blockquote>\n<p>flex 布局操纵的是一维、一行&#x2F;一列grid 布局具备操纵二维的能力</p>\n</blockquote>\n<p>设为网格布局以后,容器子元素(项目)的<code>float</code>、<code>display: inline-block</code>、<code>display: table-cell</code>、<code>vertical-align</code>和 <code>column-</code>等设置都将失效。</p>\n<ul>\n<li>grid-template-columns: 定义每一列的列宽</li>\n<li>grid-template-rows: 定义每一行的行高</li>\n<li>grid-row-gap: 行间距</li>\n<li>grid-column-gap: 列间距</li>\n<li>grid-gap: 行列间距合并</li>\n<li>grid-template-areas: 一个区域由单个或多个单元格组成</li>\n<li>grid-auto-flow: 默认值是 row即”先行后列”,即先填满第一行,再开始放入第二行</li>\n<li>justify-items: <code>单元格内容</code>的水平对齐</li>\n<li>align-items: <code>单元格内容</code>垂直对齐</li>\n<li>place-items: align-items 属性和 justify-items 属性的合并简写形式</li>\n<li>justify-content: <code>整个内容区域</code>水平对齐</li>\n<li>align-content: <code>整个内容区域</code>垂直对齐</li>\n<li>place-content: align-content 属性和 justify-content 属性的合并简写形式</li>\n</ul>\n<blockquote>\n<p>设置的行或者列比较多的时候,可以使用 repeat()这个函数简化重复的值</p>\n</blockquote>\n<h2 id=\"repeat\"><a href=\"#repeat\" class=\"headerlink\" title=\"repeat()\"></a>repeat()</h2><p>第一个参数是重复的次数,第二个参数是所要重复的值、也可以是某个模式</p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token comment\">/* 重复 3个100px的列 */</span>\n<span class=\"token property\">grid-template-columns</span><span class=\"token punctuation\">:</span> <span class=\"token function\">repeat</span><span class=\"token punctuation\">(</span>3<span class=\"token punctuation\">,</span> 100px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">/* 重复这种布局2次 */</span>\n<span class=\"token property\">grid-template-columns</span><span class=\"token punctuation\">:</span> <span class=\"token function\">repeat</span><span class=\"token punctuation\">(</span>2<span class=\"token punctuation\">,</span> 100px 20px 80px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">/* 自动填充,直到容器放不下为止 */</span>\n<span class=\"token property\">grid-template-columns</span><span class=\"token punctuation\">:</span> <span class=\"token function\">repeat</span><span class=\"token punctuation\">(</span>auto-fill<span class=\"token punctuation\">,</span> 100px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"fr\"><a href=\"#fr\" class=\"headerlink\" title=\"fr\"></a>fr</h2><p>方便表示比例关系,网格布局提供了 fr 关键字</p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token property\">grid-template-columns</span><span class=\"token punctuation\">:</span> 1fr 1fr<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"grid-template-areas\"><a href=\"#grid-template-areas\" class=\"headerlink\" title=\"grid-template-areas\"></a>grid-template-areas</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token property\">grid-template-areas</span><span class=\"token punctuation\">:</span>\n <span class=\"token string\">\"header header header\"</span>\n <span class=\"token string\">\"main main sidebar\"</span>\n <span class=\"token string\">\"footer footer footer\"</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"item-定位\"><a href=\"#item-定位\" class=\"headerlink\" title=\"item 定位\"></a>item 定位</h2><p><img src=\"/img/grid_1.png\" alt=\"grid_1\"></p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token comment\">/* 1号项目就是从第二根垂直网格线开始第四根结束 */</span>\n<span class=\"token selector\">.item1</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">grid-column-start</span><span class=\"token punctuation\">:</span> 2<span class=\"token punctuation\">;</span>\n <span class=\"token property\">grid-column-end</span><span class=\"token punctuation\">:</span> 4<span class=\"token punctuation\">;</span>\n <span class=\"token property\">background</span><span class=\"token punctuation\">:</span> red<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"硬件加速-IE9\"><a href=\"#硬件加速-IE9\" class=\"headerlink\" title=\"硬件加速(IE9+)\"></a>硬件加速(IE9+)</h1><blockquote>\n<p>移动端开启,吃内存、增加耗电</p>\n</blockquote>\n<p><code>animation</code>、<code>transform</code>、<code>transition</code>不会自动开启<code>GPU</code>加速,利用<code>transform: translateZ(0)</code> 就可以开启<code>3D变换</code>,出发硬件加速</p>\n<p>场景:<code>webKit内核</code>偶尔页面闪烁:<code>transform: translate3d(0, 0, 0);</code></p>\n<h1 id=\"控制台打印-shield-徽章\"><a href=\"#控制台打印-shield-徽章\" class=\"headerlink\" title=\"控制台打印 shield 徽章\"></a>控制台打印 shield 徽章</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>\n <span class=\"token string\">\"%c\"</span> <span class=\"token operator\">+</span>\n <span class=\"token function\">eval</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"'mozzie.com'\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span>\n <span class=\"token string\">\"%cv\"</span> <span class=\"token operator\">+</span>\n <span class=\"token function\">eval</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"'2.0.0'\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span>\n <span class=\"token string\">\"%c\\r\\n\"</span> <span class=\"token operator\">+</span>\n <span class=\"token function\">eval</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"'了解更多:https://www.mozzie.com'\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"color: #fff; background: #5281FA; font-size: 12px;border-radius:2px 0 0 2px;padding:3px 6px;\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"border-radius:0 2px 2px 0;padding:3px 6px;color:#333;background:#EBEBEB\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"margin-top:10px;\"</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"css-判断-input-是否为空\"><a href=\"#css-判断-input-是否为空\" class=\"headerlink\" title=\"css 判断 input 是否为空\"></a>css 判断 input 是否为空</h1><p><code>:placeholder-shown</code>:占位符是否显示的伪类,配合 <code>:not()</code> (不是必须,反过来也可以)</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>demo<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>demo-input<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>text<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">placeholder</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>label</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>demo-label<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>Name<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>label</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">#demo</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 90%<span class=\"token punctuation\">;</span>\n <span class=\"token property\">max-width</span><span class=\"token punctuation\">:</span> 450px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> relative<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#demo-input</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 100%<span class=\"token punctuation\">;</span>\n <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 60px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">line-height</span><span class=\"token punctuation\">:</span> 60px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 20px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-bottom</span><span class=\"token punctuation\">:</span> 1px solid #ffa500<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#demo-input::placeholder</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#demo-input:focus + label,\n#demo-input:not(:placeholder-shown) + label</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">top</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 12px<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#demo-label</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 22px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> #ffa500<span class=\"token punctuation\">;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span>\n <span class=\"token property\">left</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">top</span><span class=\"token punctuation\">:</span> 50%<span class=\"token punctuation\">;</span>\n <span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">translateY</span><span class=\"token punctuation\">(</span>-50%<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">transition</span><span class=\"token punctuation\">:</span> all 0.3s<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">/*\n* Default\n*/</span>\n<span class=\"token selector\">body</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 100vh<span class=\"token punctuation\">;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> flex<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">body div</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">margin</span><span class=\"token punctuation\">:</span> auto<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">body div input</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">border</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">outline</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"居中\"><a href=\"#居中\" class=\"headerlink\" title=\"居中\"></a>居中</h1><h2 id=\"transform-大法\"><a href=\"#transform-大法\" class=\"headerlink\" title=\"transform 大法\"></a>transform 大法</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">#wrapper</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> relative<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#box</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span>\n <span class=\"token property\">top</span><span class=\"token punctuation\">:</span> 50%<span class=\"token punctuation\">;</span>\n <span class=\"token property\">left</span><span class=\"token punctuation\">:</span> 50%<span class=\"token punctuation\">;</span>\n <span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">translate</span><span class=\"token punctuation\">(</span>-50%<span class=\"token punctuation\">,</span> -50%<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"0000-大法\"><a href=\"#0000-大法\" class=\"headerlink\" title=\"0000 大法\"></a>0000 大法</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">#wrapper</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> relative<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">#box</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span>\n <span class=\"token property\">top</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">left</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">right</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">bottom</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"如何让-img-垂直居中\"><a href=\"#如何让-img-垂直居中\" class=\"headerlink\" title=\"如何让 img 垂直居中\"></a>如何让 img 垂直居中</h2><pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>imgWrapper<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>xxx.png<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">.imgWrapper</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> table-cell<span class=\"token punctuation\">;</span>\n <span class=\"token property\">text-align</span><span class=\"token punctuation\">:</span> center<span class=\"token punctuation\">;</span>\n <span class=\"token property\">vertical-align</span><span class=\"token punctuation\">:</span> middle<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"ul-下-li-居中\"><a href=\"#ul-下-li-居中\" class=\"headerlink\" title=\"ul 下 li 居中\"></a>ul 下 li 居中</h2><pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token comment\">&lt;!--外层包个div/section block元素 --></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>clearfix<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>1<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>2<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">div</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">text-align</span><span class=\"token punctuation\">:</span> center\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">ul</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> inline-block\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">li</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> inline\n <span class=\"token property\">float</span><span class=\"token punctuation\">:</span> left\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"js-随机渐变背景\"><a href=\"#js-随机渐变背景\" class=\"headerlink\" title=\"js 随机渐变背景\"></a>js 随机渐变背景</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">getRandomRangeNum</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">min<span class=\"token punctuation\">,</span> max</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> min <span class=\"token operator\">+</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">random</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span>max <span class=\"token operator\">-</span> min<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">setRandomBg</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">el</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> left <span class=\"token operator\">=</span> <span class=\"token function\">getRandomRangeNum</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">255</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">var</span> bottom <span class=\"token operator\">=</span> <span class=\"token function\">getRandomRangeNum</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">255</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">var</span> css <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token string\">\"linear-gradient(to left bottom,hsl(\"</span><span class=\"token punctuation\">,</span>\n left<span class=\"token punctuation\">,</span>\n <span class=\"token string\">\", 100%, 85%) 0%,hsl(\"</span><span class=\"token punctuation\">,</span>\n bottom<span class=\"token punctuation\">,</span>\n <span class=\"token string\">\", 100%, 85%) 100%)\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n el<span class=\"token punctuation\">.</span>style<span class=\"token punctuation\">.</span>background <span class=\"token operator\">=</span> css<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"css-三角形\"><a href=\"#css-三角形\" class=\"headerlink\" title=\"css 三角形\"></a>css 三角形</h1><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">span</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-top</span><span class=\"token punctuation\">:</span> 40px solid transparent<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-left</span><span class=\"token punctuation\">:</span> 40px solid transparent<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-right</span><span class=\"token punctuation\">:</span> 40px solid transparent<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-bottom</span><span class=\"token punctuation\">:</span> 40px solid #ff0000<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"1px-神迹\"><a href=\"#1px-神迹\" class=\"headerlink\" title=\"1px 神迹\"></a>1px 神迹</h1><h2 id=\"pc-端最优解\"><a href=\"#pc-端最优解\" class=\"headerlink\" title=\"pc 端最优解\"></a>pc 端最优解</h2><pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token special-attr\"><span class=\"token attr-name\">style</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token value css language-css\"><span class=\"token property\">height</span><span class=\"token punctuation\">:</span>1px<span class=\"token punctuation\">;</span><span class=\"token property\">overflow</span><span class=\"token punctuation\">:</span>hidden<span class=\"token punctuation\">;</span><span class=\"token property\">background</span><span class=\"token punctuation\">:</span>red</span><span class=\"token punctuation\">\"</span></span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"移动端-媒体查询-transform\"><a href=\"#移动端-媒体查询-transform\" class=\"headerlink\" title=\"移动端 - 媒体查询 + transform\"></a>移动端 - 媒体查询 + transform</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token atrule\"><span class=\"token rule\">@media</span> <span class=\"token keyword\">only</span> screen <span class=\"token keyword\">and</span> <span class=\"token punctuation\">(</span><span class=\"token property\">-webkit-min-device-pixel-ratio</span><span class=\"token punctuation\">:</span> 2<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token selector\">.border-bottom::after</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">-webkit-transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">scaleY</span><span class=\"token punctuation\">(</span>0.5<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">scaleY</span><span class=\"token punctuation\">(</span>0.5<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"移动端-媒体查询-伪类\"><a href=\"#移动端-媒体查询-伪类\" class=\"headerlink\" title=\"移动端 - 媒体查询 + 伪类\"></a>移动端 - 媒体查询 + 伪类</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">.border__1px:before</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">content</span><span class=\"token punctuation\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span>\n <span class=\"token property\">top</span><span class=\"token punctuation\">:</span> 0<span class=\"token punctuation\">;</span>\n <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 1px<span class=\"token punctuation\">;</span>\n <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 100%\n <span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> #000<span class=\"token punctuation\">;</span>\n <span class=\"token property\">transform-origin</span><span class=\"token punctuation\">:</span> 50% 0%<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token atrule\"><span class=\"token rule\">@media</span> <span class=\"token keyword\">only</span> screen <span class=\"token keyword\">and</span> <span class=\"token punctuation\">(</span><span class=\"token property\">-webkit-min-device-pixel-ratio</span><span class=\"token punctuation\">:</span>2<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token selector\">.border__1px:before</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">scaleY</span><span class=\"token punctuation\">(</span>0.5<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token atrule\"><span class=\"token rule\">@media</span> <span class=\"token keyword\">only</span> screen <span class=\"token keyword\">and</span> <span class=\"token punctuation\">(</span><span class=\"token property\">-webkit-min-device-pixel-ratio</span><span class=\"token punctuation\">:</span>3<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token selector\">.border__1px:before</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token function\">scaleY</span><span class=\"token punctuation\">(</span>0.33<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"横竖屏适配\"><a href=\"#横竖屏适配\" class=\"headerlink\" title=\"横竖屏适配\"></a>横竖屏适配</h1><p>js 检测</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"resize\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">.</span>orientation <span class=\"token operator\">===</span> <span class=\"token number\">180</span> <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>orientation <span class=\"token operator\">===</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 正常方向或屏幕旋转180度</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"竖屏\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">.</span>orientation <span class=\"token operator\">===</span> <span class=\"token number\">90</span> <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>orientation <span class=\"token operator\">===</span> <span class=\"token operator\">-</span><span class=\"token number\">90</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 屏幕顺时钟旋转90度或屏幕逆时针旋转90度</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"横屏\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>css 检测</p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token atrule\"><span class=\"token rule\">@media</span> screen <span class=\"token keyword\">and</span> <span class=\"token punctuation\">(</span><span class=\"token property\">orientation</span><span class=\"token punctuation\">:</span> portrait<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">/*竖屏...*/</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token atrule\"><span class=\"token rule\">@media</span> screen <span class=\"token keyword\">and</span> <span class=\"token punctuation\">(</span><span class=\"token property\">orientation</span><span class=\"token punctuation\">:</span> landscape<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">/*横屏...*/</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"像素\"><a href=\"#像素\" class=\"headerlink\" title=\"像素\"></a>像素</h1><ul>\n<li>物理像素: 物理设备真实的像素</li>\n<li>独立像素: 平时开发写的 px</li>\n<li>设备像素比(DPR): &#x3D; 物理像素 &#x2F; 设备独立像素</li>\n</ul>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 获取 DPR</span>\nwindow<span class=\"token punctuation\">.</span>devicePixelRatio<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<p>也可以使用媒体查询</p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token atrule\"><span class=\"token rule\">@media</span> <span class=\"token punctuation\">(</span><span class=\"token property\">-webkit-min-device-pixel-ratio</span><span class=\"token punctuation\">:</span> 2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token property\">min-device-pixel-ratio</span><span class=\"token punctuation\">:</span> 2<span class=\"token punctuation\">)</span></span> <span class=\"token punctuation\">&#123;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"srcset\"><a href=\"#srcset\" class=\"headerlink\" title=\"srcset\"></a>srcset</h1><p>使用 img 标签的 <code>srcset</code> 属性,浏览器会自动根据像素密度匹配最佳显示图片:</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>conardLi_1x.png<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>conardLi_2x.png 2x, conardLi_3x.png 3x<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h1 id=\"字体小于-12px\"><a href=\"#字体小于-12px\" class=\"headerlink\" title=\"字体小于 12px\"></a>字体小于 12px</h1><p>css3 的 <code>transform</code> 属性,设置值为 <code>scale(x, y)</code> 定义 2D 缩放转换</p>\n<h1 id=\"css-清浮动\"><a href=\"#css-清浮动\" class=\"headerlink\" title=\"css 清浮动\"></a>css 清浮动</h1><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">.clearfix::after</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">content</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> block<span class=\"token punctuation\">;</span>\n <span class=\"token property\">clear</span><span class=\"token punctuation\">:</span> both<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"ellipsis\"><a href=\"#ellipsis\" class=\"headerlink\" title=\"ellipsis\"></a>ellipsis</h1><h2 id=\"单行\"><a href=\"#单行\" class=\"headerlink\" title=\"单行\"></a>单行</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">.ellipsis</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">overflow</span><span class=\"token punctuation\">:</span> hidden<span class=\"token punctuation\">;</span>\n <span class=\"token property\">text-overflow</span><span class=\"token punctuation\">:</span> ellipsis<span class=\"token punctuation\">;</span>\n <span class=\"token property\">white-space</span><span class=\"token punctuation\">:</span> nowrap<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"多行\"><a href=\"#多行\" class=\"headerlink\" title=\"多行\"></a>多行</h2><pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">.ellipsis</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> -webkit-box<span class=\"token punctuation\">;</span>\n <span class=\"token property\">-webkit-box-orient</span><span class=\"token punctuation\">:</span> vertical<span class=\"token punctuation\">;</span>\n <span class=\"token property\">-webkit-line-clamp</span><span class=\"token punctuation\">:</span> 3<span class=\"token punctuation\">;</span> // 最多显示几行\n <span class=\"token property\">overflow</span><span class=\"token punctuation\">:</span> hidden<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"页面导入样式时,使用-link-和-import\"><a href=\"#页面导入样式时,使用-link-和-import\" class=\"headerlink\" title=\"页面导入样式时,使用 link 和 @import\"></a>页面导入样式时,使用 link 和 @import</h1><blockquote>\n<p>你可能不信ie5+就支持@import 了</p>\n</blockquote>\n<ul>\n<li>link: 与<code>dom</code>异步加载</li>\n<li>@import: 先加载<code>dom</code></li>\n</ul>\n<h1 id=\"em-rem-换算\"><a href=\"#em-rem-换算\" class=\"headerlink\" title=\"em | rem 换算\"></a>em | rem 换算</h1><p>相对于HTML根元素 <code>font-size</code> 来确定的,浏览器的默认字体高是 <code>16px</code>,因此:</p>\n<ul>\n<li>16px &#x3D; 1em</li>\n<li>12px &#x3D; .75em</li>\n<li>10px &#x3D; .625em</li>\n</ul>\n<p>简化 rem 到 px 的换算,因为每个 rem 单位都是 10px 的倍数</p>\n<pre class=\"line-numbers language-css\" data-language=\"css\"><code class=\"language-css\"><span class=\"token selector\">html</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 62.5%<span class=\"token punctuation\">;</span> <span class=\"token comment\">/* 这会将默认的 16px 缩小为 10px */</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>也可以使用 js 检测设置</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// set 1rem = viewWidth / 10</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">setRemUnit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> docEl <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span>documentElement<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">var</span> rem <span class=\"token operator\">=</span> docEl<span class=\"token punctuation\">.</span>clientWidth <span class=\"token operator\">/</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span>\n docEl<span class=\"token punctuation\">.</span>style<span class=\"token punctuation\">.</span>fontSize <span class=\"token operator\">=</span> rem <span class=\"token operator\">+</span> <span class=\"token string\">\"px\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\nwindow<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"resize\"</span><span class=\"token punctuation\">,</span> setRemUnit<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nwindow<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"pageShow\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>persisted<span class=\"token punctuation\">)</span> <span class=\"token function\">setRemUnit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"less-常用\"><a href=\"#less-常用\" class=\"headerlink\" title=\"less 常用\"></a>less 常用</h1><h2 id=\"变量\"><a href=\"#变量\" class=\"headerlink\" title=\"变量\"></a>变量</h2><p>LESS 中的变量为完全的 <code>常量</code> ,所以只能定义一次</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token variable\">@nice-blue<span class=\"token punctuation\">:</span></span> #5B83AD<span class=\"token punctuation\">;</span>\n<span class=\"token variable\">@light-blue<span class=\"token punctuation\">:</span></span> <span class=\"token variable\">@nice-blue</span> <span class=\"token operator\">+</span> #111<span class=\"token punctuation\">;</span>\n\n<span class=\"token selector\">#header</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@light-blue</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>输出</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">#header</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> #6c94be<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"混合\"><a href=\"#混合\" class=\"headerlink\" title=\"混合\"></a>混合</h2><pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">.bordered</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">border-top</span><span class=\"token punctuation\">:</span> dotted 1px black<span class=\"token punctuation\">;</span>\n <span class=\"token property\">border-bottom</span><span class=\"token punctuation\">:</span> solid 2px black<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>使用</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">#menu a</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> #111<span class=\"token punctuation\">;</span>\n <span class=\"token mixin-usage function\">.bordered</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token selector\">.post a</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> red<span class=\"token punctuation\">;</span>\n <span class=\"token mixin-usage function\">.bordered</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>带参</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">.border-radius (<span class=\"token variable\">@radius</span>)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">border-radius</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@radius</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">-moz-border-radius</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@radius</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">-webkit-border-radius</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@radius</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>#header {<br>.border-radius(4px);<br>}</p>\n<p><code>@arguments</code>变量,包含了所有传递进来的参数. 如果你不想单独处理每一个参数</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">.box-shadow (<span class=\"token variable\">@x</span>: 0, <span class=\"token variable\">@y</span>: 0, <span class=\"token variable\">@blur</span>: 1px, <span class=\"token variable\">@color</span>: #000)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">box-shadow</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@arguments</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">-moz-box-shadow</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@arguments</span><span class=\"token punctuation\">;</span>\n <span class=\"token property\">-webkit-box-shadow</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">@arguments</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n.<span class=\"token function\">box-shadow</span><span class=\"token punctuation\">(</span>2px<span class=\"token punctuation\">,</span> 5px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>无参</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">.wrap ()</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">text-wrap</span><span class=\"token punctuation\">:</span> wrap<span class=\"token punctuation\">;</span>\n <span class=\"token property\">white-space</span><span class=\"token punctuation\">:</span> pre<span class=\"token operator\">-</span>wrap<span class=\"token punctuation\">;</span>\n <span class=\"token property\">white-space</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">-</span>moz<span class=\"token operator\">-</span>pre<span class=\"token operator\">-</span>wrap<span class=\"token punctuation\">;</span>\n <span class=\"token property\">word-wrap</span><span class=\"token punctuation\">:</span> break<span class=\"token operator\">-</span>word<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token selector\">pre</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token mixin-usage function\">.wrap</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"lighten-和-darken\"><a href=\"#lighten-和-darken\" class=\"headerlink\" title=\"lighten 和 darken\"></a>lighten 和 darken</h2><pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token variable\">@color-base<span class=\"token punctuation\">:</span></span> #3bafda<span class=\"token punctuation\">;</span>\n<span class=\"token variable\">@color-hover<span class=\"token punctuation\">:</span></span>lighten <span class=\"token punctuation\">(</span><span class=\"token variable\">@color-primary</span><span class=\"token punctuation\">,</span>10%<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token variable\">@color-focus<span class=\"token punctuation\">:</span></span>darken <span class=\"token punctuation\">(</span><span class=\"token variable\">@color-primary</span><span class=\"token punctuation\">,</span>10%<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"contrast\"><a href=\"#contrast\" class=\"headerlink\" title=\"contrast\"></a>contrast</h2><p>选择两种颜色中哪一种颜色与另一种颜色形成最大对比。</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">p</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">a</span><span class=\"token punctuation\">:</span> <span class=\"token function\">contrast</span><span class=\"token punctuation\">(</span>#bbbbbb<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//output: black</span>\n <span class=\"token property\">b</span><span class=\"token punctuation\">:</span> <span class=\"token function\">contrast</span><span class=\"token punctuation\">(</span>#222222<span class=\"token punctuation\">,</span> #101010<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//output: white</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"JavaScript-表达式\"><a href=\"#JavaScript-表达式\" class=\"headerlink\" title=\"JavaScript 表达式\"></a>JavaScript 表达式</h2><pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token variable\">@var<span class=\"token punctuation\">:</span></span> ` <span class=\"token string\">\"hello\"</span> .<span class=\"token function\">toUpperCase</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token string\">\"!\"</span> `<span class=\"token punctuation\">;</span>\n<span class=\"token variable\">@height<span class=\"token punctuation\">:</span></span> `document.body.clientHeight`<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"amp-父选择器\"><a href=\"#amp-父选择器\" class=\"headerlink\" title=\"&amp; 父选择器\"></a>&amp; 父选择器</h2><p><code>&amp;</code> 只能代表父元素,不能代表父亲的父辈元素,施加改性类或伪类</p>\n<pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">a</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> blue<span class=\"token punctuation\">;</span>\n <span class=\"token selector\">&amp;:hover</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> green<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"重复父类名\"><a href=\"#重复父类名\" class=\"headerlink\" title=\"重复父类名\"></a>重复父类名</h2><pre class=\"line-numbers language-less\" data-language=\"less\"><code class=\"language-less\"><span class=\"token selector\">.button</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token selector\">&amp;-ok</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">background-image</span><span class=\"token punctuation\">:</span> <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">\"ok.png\"</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token selector\">&amp;-cancel</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">background-image</span><span class=\"token punctuation\">:</span> <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">\"cancel.png\"</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token selector\">&amp;-custom</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">background-image</span><span class=\"token punctuation\">:</span> <span class=\"token url\"><span class=\"token function\">url</span><span class=\"token punctuation\">(</span><span class=\"token string url\">\"custom.png\"</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n"},{"title":"领域驱动设计","status":"doing","_content":"\n\n# 参考文献\n\n- [蚂蚁金服数据体验技术团队 - 领域驱动设计](https://juejin.cn/post/6844903618680881165)\n- [美团 - 领域驱动设计在互联网业务开发中的实践](https://tech.meituan.com/2017/12/22/ddd-in-practice.html)\n- [领域驱动实战思考](https://huhao.dev/posts/61190ae2/#%E9%97%AE%E9%A2%98%E5%AD%90%E5%9F%9F%E8%AF%86%E5%88%AB)\n- [基于 DDD 的前端项目架构设计与实战](https://www.tangshuang.net/8663.html)\n- [React 语境下前端 DDD 的思考](https://www.tangshuang.net/8212.html)\n\n# 架构对比\n\n从后端视角看对比传统的三层架构领域驱动\n\n- `充血`复用了:领域对外的接口\n- `领域服务`封装了:领域之间的联系\n\n贫血模型->充血模型,降低了`service层`的负担,同时保证了业务迭代,`entity`的独立性\n\n## MVC\n\n从数据库视角、分析实体出发进行系统的构建\n\n- DAO 层\n- Service 层\n- Controller 层\n\n## 后端 DDD\n\n> 针对基础设施层,也可以考虑加入`防腐层`、`工厂`\n\n一个领域基本四层架构\n\n1. 用户层(user interface): 对标 controller对外提供 web 服务、接口\n2. 应用层(application): 业务层,定义领域可以解决的问题 `domainService`\n3. 领域层(domain): 纯粹的描述业务实体\n4. 基础设施层(infra): 持久化层(Builder+repository)\n\n同时领域拆分带来如下两个致命问题\n\n- 领域化(微服务)后,数据库是分开的,导致实体调用链复杂,避免跨库查询\n- 避免分布式事务同步\n\n## 前端 DDD\n\n> ?? 这里存在一个问题api 网关到底要不要挪到前端领域目录下来开发\n\n1. 用户层: web、mobile、mini-program ...多端\n2. service: 暴露给 UI 组件的 `domainSerivce`,组织实体的状态流转\n3. entity: 实体、聚合实体、事件\n4. infra: api 请求、缓存、工具\n\n## 工厂 Factory / Builder\n\n- 数据库表设计层面,如果要`多对多`的关系,只能很别扭的设计一个中间表。\n- 实体 A 适合 `mongo`文档形存储,实体 B 适合`mysql`关系型存储。对于 `Builder` 而言,直接在这个领域搓出来 `A 和 B` 的 `CRUD`的实现方法\n\n## 防腐层 Facade / Adaptor\n\n也被成为适配器隔离第三方/外部服务,例如场景,用户上传文件到阿里云、腾讯云\n\n```js\nclass UserUploadServiceFacade extends UserService {\n /**\n * 上传\n */\n async upload(oss) {\n if (oss === \"ali\") return \"OK\";\n if (oss === \"tx\") return \"FAIL\";\n }\n}\n```\n\n# 领域模型\n\n实体的`贫血->充血`是一个随着业务发展过程演变的结果,初期业务场景不明确,很难充血,瞎几把充血,纯属找难受。\n\n是否需要引入`聚合根(aggregate root)`的概念,解决领域内实体独立、平铺关系带来的不方便,这个可能比较看心情\n\n## 贫血模型(POJO)的问题\n\n> 脱离了业务复杂度谈分层,好比抛开剂量谈毒性\n\n领域对象里只有`get/set`方法,所有的业务逻辑都不包含在内,从而造成`失忆症`,从实体中,无法知道发生了那些业务,需要去 `service层` 里挨个梳理,一旦业务迭代、`service 层`直接开始变成屎山\n\n## 充血模型 && 领域服务的关系\n\n> 确保领域之间独立的,随着不断的充血,保证领域(实体)是独立发展的\n\n假定两个 domain(实体)\n\n- 学生: 上课、做作业\n- 老师、全体起立、布置作业\n\n假定`老师`调用`全体起立`,对应肯定要`学生`调用`上课`,这个就是 `领域服务(domainService)` 需要去处理的,他俩不能建立直接的联系。\n\n- 增加新的业务逻辑:在 `domainService` 增加新的方法。\n- 调整旧的业务逻辑:修改`学生``老师`,内部具体的方法,`domainService` 完全不需要变化。\n","source":"_posts/front-end/ddd.md","raw":"---\ntitle: 领域驱动设计\ncategories:\n - Front-End\nstatus: doing\n---\n\n\n# 参考文献\n\n- [蚂蚁金服数据体验技术团队 - 领域驱动设计](https://juejin.cn/post/6844903618680881165)\n- [美团 - 领域驱动设计在互联网业务开发中的实践](https://tech.meituan.com/2017/12/22/ddd-in-practice.html)\n- [领域驱动实战思考](https://huhao.dev/posts/61190ae2/#%E9%97%AE%E9%A2%98%E5%AD%90%E5%9F%9F%E8%AF%86%E5%88%AB)\n- [基于 DDD 的前端项目架构设计与实战](https://www.tangshuang.net/8663.html)\n- [React 语境下前端 DDD 的思考](https://www.tangshuang.net/8212.html)\n\n# 架构对比\n\n从后端视角看对比传统的三层架构领域驱动\n\n- `充血`复用了:领域对外的接口\n- `领域服务`封装了:领域之间的联系\n\n贫血模型->充血模型,降低了`service层`的负担,同时保证了业务迭代,`entity`的独立性\n\n## MVC\n\n从数据库视角、分析实体出发进行系统的构建\n\n- DAO 层\n- Service 层\n- Controller 层\n\n## 后端 DDD\n\n> 针对基础设施层,也可以考虑加入`防腐层`、`工厂`\n\n一个领域基本四层架构\n\n1. 用户层(user interface): 对标 controller对外提供 web 服务、接口\n2. 应用层(application): 业务层,定义领域可以解决的问题 `domainService`\n3. 领域层(domain): 纯粹的描述业务实体\n4. 基础设施层(infra): 持久化层(Builder+repository)\n\n同时领域拆分带来如下两个致命问题\n\n- 领域化(微服务)后,数据库是分开的,导致实体调用链复杂,避免跨库查询\n- 避免分布式事务同步\n\n## 前端 DDD\n\n> ?? 这里存在一个问题api 网关到底要不要挪到前端领域目录下来开发\n\n1. 用户层: web、mobile、mini-program ...多端\n2. service: 暴露给 UI 组件的 `domainSerivce`,组织实体的状态流转\n3. entity: 实体、聚合实体、事件\n4. infra: api 请求、缓存、工具\n\n## 工厂 Factory / Builder\n\n- 数据库表设计层面,如果要`多对多`的关系,只能很别扭的设计一个中间表。\n- 实体 A 适合 `mongo`文档形存储,实体 B 适合`mysql`关系型存储。对于 `Builder` 而言,直接在这个领域搓出来 `A 和 B` 的 `CRUD`的实现方法\n\n## 防腐层 Facade / Adaptor\n\n也被成为适配器隔离第三方/外部服务,例如场景,用户上传文件到阿里云、腾讯云\n\n```js\nclass UserUploadServiceFacade extends UserService {\n /**\n * 上传\n */\n async upload(oss) {\n if (oss === \"ali\") return \"OK\";\n if (oss === \"tx\") return \"FAIL\";\n }\n}\n```\n\n# 领域模型\n\n实体的`贫血->充血`是一个随着业务发展过程演变的结果,初期业务场景不明确,很难充血,瞎几把充血,纯属找难受。\n\n是否需要引入`聚合根(aggregate root)`的概念,解决领域内实体独立、平铺关系带来的不方便,这个可能比较看心情\n\n## 贫血模型(POJO)的问题\n\n> 脱离了业务复杂度谈分层,好比抛开剂量谈毒性\n\n领域对象里只有`get/set`方法,所有的业务逻辑都不包含在内,从而造成`失忆症`,从实体中,无法知道发生了那些业务,需要去 `service层` 里挨个梳理,一旦业务迭代、`service 层`直接开始变成屎山\n\n## 充血模型 && 领域服务的关系\n\n> 确保领域之间独立的,随着不断的充血,保证领域(实体)是独立发展的\n\n假定两个 domain(实体)\n\n- 学生: 上课、做作业\n- 老师、全体起立、布置作业\n\n假定`老师`调用`全体起立`,对应肯定要`学生`调用`上课`,这个就是 `领域服务(domainService)` 需要去处理的,他俩不能建立直接的联系。\n\n- 增加新的业务逻辑:在 `domainService` 增加新的方法。\n- 调整旧的业务逻辑:修改`学生``老师`,内部具体的方法,`domainService` 完全不需要变化。\n","slug":"front-end/ddd","published":1,"date":"2023-11-06T07:56:40.047Z","updated":"2023-11-06T08:02:39.167Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58n000a4cz39b6r5kmh","content":"<h1 id=\"参考文献\"><a href=\"#参考文献\" class=\"headerlink\" title=\"参考文献\"></a>参考文献</h1><ul>\n<li><a href=\"https://juejin.cn/post/6844903618680881165\">蚂蚁金服数据体验技术团队 - 领域驱动设计</a></li>\n<li><a href=\"https://tech.meituan.com/2017/12/22/ddd-in-practice.html\">美团 - 领域驱动设计在互联网业务开发中的实践</a></li>\n<li><a href=\"https://huhao.dev/posts/61190ae2/#%E9%97%AE%E9%A2%98%E5%AD%90%E5%9F%9F%E8%AF%86%E5%88%AB\">领域驱动实战思考</a></li>\n<li><a href=\"https://www.tangshuang.net/8663.html\">基于 DDD 的前端项目架构设计与实战</a></li>\n<li><a href=\"https://www.tangshuang.net/8212.html\">React 语境下前端 DDD 的思考</a></li>\n</ul>\n<h1 id=\"架构对比\"><a href=\"#架构对比\" class=\"headerlink\" title=\"架构对比\"></a>架构对比</h1><p>从后端视角看,对比传统的三层架构,领域驱动</p>\n<ul>\n<li><code>充血</code>复用了:领域对外的接口</li>\n<li><code>领域服务</code>封装了:领域之间的联系</li>\n</ul>\n<p>贫血模型-&gt;充血模型,降低了<code>service层</code>的负担,同时保证了业务迭代,<code>entity</code>的独立性</p>\n<h2 id=\"MVC\"><a href=\"#MVC\" class=\"headerlink\" title=\"MVC\"></a>MVC</h2><p>从数据库视角、分析实体出发,进行系统的构建</p>\n<ul>\n<li>DAO 层</li>\n<li>Service 层</li>\n<li>Controller 层</li>\n</ul>\n<h2 id=\"后端-DDD\"><a href=\"#后端-DDD\" class=\"headerlink\" title=\"后端 DDD\"></a>后端 DDD</h2><blockquote>\n<p>针对基础设施层,也可以考虑加入<code>防腐层</code>、<code>工厂</code></p>\n</blockquote>\n<p>一个领域基本四层架构</p>\n<ol>\n<li>用户层(user interface): 对标 controller对外提供 web 服务、接口</li>\n<li>应用层(application): 业务层,定义领域可以解决的问题 <code>domainService</code></li>\n<li>领域层(domain): 纯粹的描述业务实体</li>\n<li>基础设施层(infra): 持久化层(Builder+repository)</li>\n</ol>\n<p>同时,领域拆分带来如下两个致命问题</p>\n<ul>\n<li>领域化(微服务)后,数据库是分开的,导致实体调用链复杂,避免跨库查询</li>\n<li>避免分布式事务同步</li>\n</ul>\n<h2 id=\"前端-DDD\"><a href=\"#前端-DDD\" class=\"headerlink\" title=\"前端 DDD\"></a>前端 DDD</h2><blockquote>\n<p>?? 这里存在一个问题api 网关到底要不要挪到前端领域目录下来开发</p>\n</blockquote>\n<ol>\n<li>用户层: web、mobile、mini-program …多端</li>\n<li>service: 暴露给 UI 组件的 <code>domainSerivce</code>,组织实体的状态流转</li>\n<li>entity: 实体、聚合实体、事件</li>\n<li>infra: api 请求、缓存、工具</li>\n</ol>\n<h2 id=\"工厂-Factory-x2F-Builder\"><a href=\"#工厂-Factory-x2F-Builder\" class=\"headerlink\" title=\"工厂 Factory &#x2F; Builder\"></a>工厂 Factory &#x2F; Builder</h2><ul>\n<li>数据库表设计层面,如果要<code>多对多</code>的关系,只能很别扭的设计一个中间表。</li>\n<li>实体 A 适合 <code>mongo</code>文档形存储,实体 B 适合<code>mysql</code>关系型存储。对于 <code>Builder</code> 而言,直接在这个领域搓出来 <code>A 和 B</code> 的 <code>CRUD</code>的实现方法</li>\n</ul>\n<h2 id=\"防腐层-Facade-x2F-Adaptor\"><a href=\"#防腐层-Facade-x2F-Adaptor\" class=\"headerlink\" title=\"防腐层 Facade &#x2F; Adaptor\"></a>防腐层 Facade &#x2F; Adaptor</h2><p>也被成为适配器,隔离第三方&#x2F;外部服务,例如场景,用户上传文件到阿里云、腾讯云</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">UserUploadServiceFacade</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">UserService</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">/**\n * 上传\n */</span>\n <span class=\"token keyword\">async</span> <span class=\"token function\">upload</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">oss</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>oss <span class=\"token operator\">===</span> <span class=\"token string\">\"ali\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token string\">\"OK\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>oss <span class=\"token operator\">===</span> <span class=\"token string\">\"tx\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token string\">\"FAIL\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"领域模型\"><a href=\"#领域模型\" class=\"headerlink\" title=\"领域模型\"></a>领域模型</h1><p>实体的<code>贫血-&gt;充血</code>是一个随着业务发展过程演变的结果,初期业务场景不明确,很难充血,瞎几把充血,纯属找难受。</p>\n<p>是否需要引入<code>聚合根(aggregate root)</code>的概念,解决领域内实体独立、平铺关系带来的不方便,这个可能比较看心情</p>\n<h2 id=\"贫血模型-POJO-的问题\"><a href=\"#贫血模型-POJO-的问题\" class=\"headerlink\" title=\"贫血模型(POJO)的问题\"></a>贫血模型(POJO)的问题</h2><blockquote>\n<p>脱离了业务复杂度谈分层,好比抛开剂量谈毒性</p>\n</blockquote>\n<p>领域对象里只有<code>get/set</code>方法,所有的业务逻辑都不包含在内,从而造成<code>失忆症</code>,从实体中,无法知道发生了那些业务,需要去 <code>service层</code> 里挨个梳理,一旦业务迭代、<code>service 层</code>直接开始变成屎山</p>\n<h2 id=\"充血模型-amp-amp-领域服务的关系\"><a href=\"#充血模型-amp-amp-领域服务的关系\" class=\"headerlink\" title=\"充血模型 &amp;&amp; 领域服务的关系\"></a>充血模型 &amp;&amp; 领域服务的关系</h2><blockquote>\n<p>确保领域之间独立的,随着不断的充血,保证领域(实体)是独立发展的</p>\n</blockquote>\n<p>假定两个 domain(实体)</p>\n<ul>\n<li>学生: 上课、做作业</li>\n<li>老师、全体起立、布置作业</li>\n</ul>\n<p>假定<code>老师</code>调用<code>全体起立</code>,对应肯定要<code>学生</code>调用<code>上课</code>,这个就是 <code>领域服务(domainService)</code> 需要去处理的,他俩不能建立直接的联系。</p>\n<ul>\n<li>增加新的业务逻辑:在 <code>domainService</code> 增加新的方法。</li>\n<li>调整旧的业务逻辑:修改<code>学生</code><code>老师</code>,内部具体的方法,<code>domainService</code> 完全不需要变化。</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h1 id=\"参考文献\"><a href=\"#参考文献\" class=\"headerlink\" title=\"参考文献\"></a>参考文献</h1><ul>\n<li><a href=\"https://juejin.cn/post/6844903618680881165\">蚂蚁金服数据体验技术团队 - 领域驱动设计</a></li>\n<li><a href=\"https://tech.meituan.com/2017/12/22/ddd-in-practice.html\">美团 - 领域驱动设计在互联网业务开发中的实践</a></li>\n<li><a href=\"https://huhao.dev/posts/61190ae2/#%E9%97%AE%E9%A2%98%E5%AD%90%E5%9F%9F%E8%AF%86%E5%88%AB\">领域驱动实战思考</a></li>\n<li><a href=\"https://www.tangshuang.net/8663.html\">基于 DDD 的前端项目架构设计与实战</a></li>\n<li><a href=\"https://www.tangshuang.net/8212.html\">React 语境下前端 DDD 的思考</a></li>\n</ul>\n<h1 id=\"架构对比\"><a href=\"#架构对比\" class=\"headerlink\" title=\"架构对比\"></a>架构对比</h1><p>从后端视角看,对比传统的三层架构,领域驱动</p>\n<ul>\n<li><code>充血</code>复用了:领域对外的接口</li>\n<li><code>领域服务</code>封装了:领域之间的联系</li>\n</ul>\n<p>贫血模型-&gt;充血模型,降低了<code>service层</code>的负担,同时保证了业务迭代,<code>entity</code>的独立性</p>\n<h2 id=\"MVC\"><a href=\"#MVC\" class=\"headerlink\" title=\"MVC\"></a>MVC</h2><p>从数据库视角、分析实体出发,进行系统的构建</p>\n<ul>\n<li>DAO 层</li>\n<li>Service 层</li>\n<li>Controller 层</li>\n</ul>\n<h2 id=\"后端-DDD\"><a href=\"#后端-DDD\" class=\"headerlink\" title=\"后端 DDD\"></a>后端 DDD</h2><blockquote>\n<p>针对基础设施层,也可以考虑加入<code>防腐层</code>、<code>工厂</code></p>\n</blockquote>\n<p>一个领域基本四层架构</p>\n<ol>\n<li>用户层(user interface): 对标 controller对外提供 web 服务、接口</li>\n<li>应用层(application): 业务层,定义领域可以解决的问题 <code>domainService</code></li>\n<li>领域层(domain): 纯粹的描述业务实体</li>\n<li>基础设施层(infra): 持久化层(Builder+repository)</li>\n</ol>\n<p>同时,领域拆分带来如下两个致命问题</p>\n<ul>\n<li>领域化(微服务)后,数据库是分开的,导致实体调用链复杂,避免跨库查询</li>\n<li>避免分布式事务同步</li>\n</ul>\n<h2 id=\"前端-DDD\"><a href=\"#前端-DDD\" class=\"headerlink\" title=\"前端 DDD\"></a>前端 DDD</h2><blockquote>\n<p>?? 这里存在一个问题api 网关到底要不要挪到前端领域目录下来开发</p>\n</blockquote>\n<ol>\n<li>用户层: web、mobile、mini-program …多端</li>\n<li>service: 暴露给 UI 组件的 <code>domainSerivce</code>,组织实体的状态流转</li>\n<li>entity: 实体、聚合实体、事件</li>\n<li>infra: api 请求、缓存、工具</li>\n</ol>\n<h2 id=\"工厂-Factory-x2F-Builder\"><a href=\"#工厂-Factory-x2F-Builder\" class=\"headerlink\" title=\"工厂 Factory &#x2F; Builder\"></a>工厂 Factory &#x2F; Builder</h2><ul>\n<li>数据库表设计层面,如果要<code>多对多</code>的关系,只能很别扭的设计一个中间表。</li>\n<li>实体 A 适合 <code>mongo</code>文档形存储,实体 B 适合<code>mysql</code>关系型存储。对于 <code>Builder</code> 而言,直接在这个领域搓出来 <code>A 和 B</code> 的 <code>CRUD</code>的实现方法</li>\n</ul>\n<h2 id=\"防腐层-Facade-x2F-Adaptor\"><a href=\"#防腐层-Facade-x2F-Adaptor\" class=\"headerlink\" title=\"防腐层 Facade &#x2F; Adaptor\"></a>防腐层 Facade &#x2F; Adaptor</h2><p>也被成为适配器,隔离第三方&#x2F;外部服务,例如场景,用户上传文件到阿里云、腾讯云</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">UserUploadServiceFacade</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">UserService</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">/**\n * 上传\n */</span>\n <span class=\"token keyword\">async</span> <span class=\"token function\">upload</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">oss</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>oss <span class=\"token operator\">===</span> <span class=\"token string\">\"ali\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token string\">\"OK\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>oss <span class=\"token operator\">===</span> <span class=\"token string\">\"tx\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token string\">\"FAIL\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"领域模型\"><a href=\"#领域模型\" class=\"headerlink\" title=\"领域模型\"></a>领域模型</h1><p>实体的<code>贫血-&gt;充血</code>是一个随着业务发展过程演变的结果,初期业务场景不明确,很难充血,瞎几把充血,纯属找难受。</p>\n<p>是否需要引入<code>聚合根(aggregate root)</code>的概念,解决领域内实体独立、平铺关系带来的不方便,这个可能比较看心情</p>\n<h2 id=\"贫血模型-POJO-的问题\"><a href=\"#贫血模型-POJO-的问题\" class=\"headerlink\" title=\"贫血模型(POJO)的问题\"></a>贫血模型(POJO)的问题</h2><blockquote>\n<p>脱离了业务复杂度谈分层,好比抛开剂量谈毒性</p>\n</blockquote>\n<p>领域对象里只有<code>get/set</code>方法,所有的业务逻辑都不包含在内,从而造成<code>失忆症</code>,从实体中,无法知道发生了那些业务,需要去 <code>service层</code> 里挨个梳理,一旦业务迭代、<code>service 层</code>直接开始变成屎山</p>\n<h2 id=\"充血模型-amp-amp-领域服务的关系\"><a href=\"#充血模型-amp-amp-领域服务的关系\" class=\"headerlink\" title=\"充血模型 &amp;&amp; 领域服务的关系\"></a>充血模型 &amp;&amp; 领域服务的关系</h2><blockquote>\n<p>确保领域之间独立的,随着不断的充血,保证领域(实体)是独立发展的</p>\n</blockquote>\n<p>假定两个 domain(实体)</p>\n<ul>\n<li>学生: 上课、做作业</li>\n<li>老师、全体起立、布置作业</li>\n</ul>\n<p>假定<code>老师</code>调用<code>全体起立</code>,对应肯定要<code>学生</code>调用<code>上课</code>,这个就是 <code>领域服务(domainService)</code> 需要去处理的,他俩不能建立直接的联系。</p>\n<ul>\n<li>增加新的业务逻辑:在 <code>domainService</code> 增加新的方法。</li>\n<li>调整旧的业务逻辑:修改<code>学生</code><code>老师</code>,内部具体的方法,<code>domainService</code> 完全不需要变化。</li>\n</ul>\n"},{"title":"jQuery","status":"done","_content":"\n# 基础\n\n在 `window` 对象中挂载了 `$`和`jQuery`\n\n```js\nwindow.jQuery();\nwindow.$ = window.jQuery;\n```\n\n# 模块化\n\n## 原始写法\n\n只要把不同的函数以及记录状态的变量简单地放在一起就算是一个模块。\n\n> 缺点很明显:\"污染\"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。\n\n```js\nfunction m1() {\n //...\n}\n\nfunction m2() {\n //...\n}\n```\n\n## 对象写法\n\n把模块写成一个对象\n\n> 写法会暴露所有模块成员,内部状态可以被外部改写。\n\n```js\nvar module1 = new Object({\n _count: 0,\n\n m1: function () {\n //...\n },\n\n m2: function () {\n //...\n },\n});\n\n// 使用\nmodule1.m1();\n```\n\n## IIFE 立即执行函数写法[推荐]\n\n> 外部代码无法读取内部的成员变量\n\n```js\nvar module1 = (function () {\n var _count = 0;\n\n var m1 = function () {\n //...\n };\n\n var m2 = function () {\n //...\n };\n\n return {\n m1: m1,\n m2: m2,\n };\n})();\n\nconsole.info(module1._count); //undefined\n```\n\n## (宽)放大模式\n\n如果一个模块很大必须分成几个部分或者一个模块需要继承另一个模块这时就有必要采用\"放大模式\"\n\n```js\nvar module1 = (function (mod) {\n mod.m3 = function () {\n //...\n };\n return mod;\n})(module1);\n```\n\nmod 可能存在异步,不知道内部哪个部分会先加载,如果采用上面的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用\"宽放大模式\"。\n\n```js\nvar module1 = (function (mod) {\n //...\n return mod;\n})(window.module1 || {});\n```\n\n## 输入全局变量[推荐]\n\n为了在模块内部调用全局变量必须显式地将其他变量输入模块\n\n```js\nvar module1 = (function ($, YAHOO) {\n //...\n})(jQuery, YAHOO);\n```\n\n# 链式操作\n\n```js\n$('div').find('#child').addClass('red')\n// end() 函数返回上一级\n$('div').find('#child').addClass('red').end().addClass'yellow'\n```\n\n# 选择器\n\n## 筛选器\n\n```js\n// $('li').first()\n$(\"li:first\"); //第一个元素\n// $('li').last()\n$(\"li:last\"); //最后一个元素\n$(\"tr:even\"); //索引为偶数的元素,从 0 开始\n$(\"tr:odd\"); //索引为奇数的元素,从 0 开始\n// $(\"tr\").eq(1)\n$(\"tr:eq(1)\"); //给定索引值的元素\n$(\"tr:gt(0)\"); //大于给定索引值的元素\n$(\"tr:lt(2)\"); //小于给定索引值的元素\n$(\":focus\"); //当前获取焦点的元素\n$(\":animated\"); //正在执行动画效果的元素\n```\n\n## 内容选择器\n\n```js\n$(\"div:contains('nick')\"); //包含nick文本的元素\n\n$(\"td:empty\"); //不包含子元素或者文本的空元素\n\n$(\"div:has(p)\"); //含有选择器所匹配的元素\n\n$(\"td:parent\"); //含有子元素或者文本的元素\n```\n\n## 表单选择器\n\n```js\n$(\":input\"); //匹配所有 input, textarea, select 和 button 元素\n\n$(\":text\"); //所有的单行文本框\n\n$(\":password\"); //所有密码框\n\n$(\":radio\"); //所有单选按钮\n\n$(\":checkbox\"); //所有复选框\n\n$(\":submit\"); //所有提交按钮\n\n$(\":reset\"); //所有重置按钮\n\n$(\":button\"); //所有button按钮\n\n$(\":file\"); //所有文件域\n\n$(\"input:radio[name=sex]:checked\"); //所有name 尾input选中的元素\n\n$(\"select option:selected\"); //select中所有选中的option元素\n```\n\n## 查找\n\n```js\n$(\"#xxx\"); //返回 一个 jquery 对象\n\n$(\"#xxx\").find(\".xxx\"); //查找#xxx里的.xxx元素\n\n$(\"#xxx\").parent(); //获取父类\n\n$(\"#xxx\").parents(\"xxx\"); //获取xxx祖先\n\n$(\"#xxx\").children(); //获取子类\n\n$(\"#xxx\").siblings(); //获取同一父类的其他元素\n\n$(\"#xxx\").next(); //获取下一个元素\n\n$(\"#xxx\").prev(); //获取上一个元素\n```\n\n## 属性操作\n\n```js\n$(\"img\").attr(\"src\"); //返回文档中所有图像的src属性值\n\n$(\"img\").attr(\"src\", \"test.jpg\"); //设置所有图像的src属性\n\n$(\"img\").removeAttr(\"src\"); //将文档中图像的src属性删除\n\n$(\"input[type='checkbox']\").prop(\"checked\", true); //选中复选框\n\n$(\"input[type='checkbox']\").prop(\"checked\", false);\n\n$(\"img\").removeProp(\"src\"); //删除img的src属性\n```\n\n## css 操作\n\n```js\n$(\"p\").addClass(\"selected\"); //为p元素加上 'selected' 类\n\n$(\"p\").removeClass(\"selected\"); //从p元素中删除 'selected' 类\n\n$(\"p\").toggleClass(\"selected\"); //如果存在就删除,否则就添加\n\n$(\"p\").css(\"color\"); //访问查看p元素的color属性\n\n$(\"p\").css(\"color\", \"red\"); //设置p元素的color属性为red\n\n$(\"p\").css({ color: \"red\", background: \"yellow\" }); // 设置多个属性\n```\n\n## 文档处理\n\n内部插入\n\n```js\n$(\"p\").append(\"<b>nick</b>\"); //每个p元素内后面追加内容\n\n$(\"p\").appendTo(\"div\"); //p元素追加到div内后\n\n$(\"p\").prepend(\"<b>Hello</b>\"); //每个p元素内前面追加内容\n\n$(\"p\").prependTo(\"div\"); //p元素追加到div内前\n```\n\n外部插入\n\n```js\n$(\"p\").after(\"<b>nick</b>\"); //每个p元素同级之后插入内容\n\n$(\"p\").before(\"<b>nick</b>\"); //在每个p元素同级之前插入内容\n\n$(\"p\").insertAfter(\"#test\"); //所有p元素插入到id为test元素的后面\n\n$(\"p\").insertBefore(\"#test\"); //所有p元素插入到id为test元素的前面\n```\n\n## 复制\n\n```js\n$(\"p\").clone(); //克隆元素并选中克隆的副本\n\n$(\"p\").clone(true); //布尔值指事件处理函数是否会被复制\n```\n\n# attr 和 prop 区别\n\nprop 和 attr 均可获取属性值,但 prop 获取的是 `DOM 对象内置属性`。\n\n> !! 例如 inputradioslect 元素,请使用 prop 获取\n\n```html\n<img src=\"https://www.runoob.com/images/pulpit.jpg\" />\n<p tinyval=\"12\"></p>\n```\n\n```js\n// 因为页面源代码中没有设置 width 属性\n$(\"img\").attr(\"width\"); // undefined\n$(\"img\").prop(\"width\"); // 284\n\n// 由于 tinyval 并非 HTML 标准属性\n$(\"p\").prop(\"tinyval\"); // undefined\n$(\"p\").attr(\"tinyval\"); // 12\n```\n\n# 事件\n\n## 事件委托\n\n- 可极大减少事件绑定次数,提高性能\n- 可让动态加入的子元素绑定相同的命令\n\n```js\nfunction handleClick(event) {\n // this 表示当前单击的元素\n alert($(this).html());\n}\n// 把子级li元素的单击事件委托在父级ul身上\n$(\"ul\").delegate(\"li\", \"click\", handleClick);\n```\n\n## 单事件单元素\n\n```js\nfunction handleClick() {}\n$xxx.on(\"click\", handleClick);\n```\n\n## 单事件多元素\n\n```js\nfunction handleClick() {}\n$xxx.on(\"click\", \"#aaa, .bbb\", handleClick);\n```\n\n## 多事件多元素\n\n```js\nfunction handleClick() {}\nfunction handleMounseEnter() {}\n$xxx.on(\n {\n click: handleClick,\n mounseenter: handleMounseEnter,\n },\n \"#aaa, .bbb\"\n);\n```\n\n## 一夜情事件\n\n```js\nfunction handleClick() {}\n$xxx.one(\"click\", handleClick);\n```\n\n# 对象操作\n\n```js\n$.trim(); //去除字符串两端的空格\n\n$.each(); //遍历一个数组或对象for循环\n\n$.inArray(); //返回一个值在数组中的索引位置,不存在返回-1\n\n$.grep(); //返回数组中符合某种标准的元素\n\n$.extend(true, {}, a, b); // 深浅拷贝合并 a、b 到 {} 上\n\n$.makeArray(); //将对象转化为数组\n\n$.type(); //判断对象的类别(函数对象、日期对象、数组对象、正则对象等等\n\n$.isArray(); //判断某个参数是否为数组\n\n$.isEmptyObject(); //判断某个对象是否为空(不含有任何属性)\n\n$.isFunction(); //判断某个参数是否为函数\n\n$.isPlainObject(); //判断某个参数是否为用\"{}\"或\"new Object\"建立的对象\n\n$.support(); //判断浏览器是否支持某个特性\n```\n\n# 禁止右键功能菜单\n\n```js\n$(window).on({\n contextmenu: function () {\n return false;\n },\n keydown: function (e) {\n if (e.ctrlKey || (e.metaKey && (e.keyCode === 67 || e.keyCode === 8)))\n return false;\n },\n});\n```\n\n# 自动修改破损图像\n\n```js\n$(\"img\").on(\"error\", function () {\n $(this).prop(\"src\", \"img/broken.png\");\n});\n```\n\n# 模块化 jquery 最佳实践\n\n```js\n// xx 视图模块 #xx\n(function ($, $view) {\n console.log($ + \"has been imported\");\n\n // 缓存 dom需要用到的 dom提高性能\n var $partA = $view.find(\".partA\"),\n $partB = $view.find(\".partB\");\n\n // 链式表结构,事件委托\n $view\n .on(\"focus\", \"#btnFocusPartA\", handleBtnFocusPartA)\n .on(\"click\", \".btnClickPartB\", handleBtnClickPartB);\n\n // 方法,建议函数式\n function handleBtnFocusPartA() {\n console.log($partA + \"handler\");\n }\n\n function handleBtnClickPartB(e) {\n console.log($partB + \"handler\", \"click 的 e.target\" + e.target);\n }\n})(jQuery || window.jQuery || window.$, $(\"#viewModule\"));\n```\n\n更骚的`路由表`的写法,搭配模块化开发更优雅,更方便管理\n\n```js\n// xx 视图模块 #xx\n(function ($, $view) {\n console.log($ + \"has been imported\");\n\n // 缓存 dom需要用到的 dom提高性能\n var $partA = $view.find(\".partA\"),\n $partB = $view.find(\".partB\");\n\n // $view 视图的事件委托表\n var eventTable = [\n {\n name: \"focus\",\n elem: \"#btnFocusPartA\",\n handler: handleBtnFocusPartA,\n },\n {\n name: \"click\",\n elem: \".btnClickPartB\",\n handler: handleBtnClickPartB,\n },\n ];\n\n // 注册事件\n eventTable.forEach(function (item) {\n $view.on(item.name, item.elem, item.handler);\n });\n\n // 方法,建议函数式\n function handleBtnFocusPartA() {\n console.log($partA + \"handler\");\n }\n\n function handleBtnClickPartB(e) {\n console.log($partB + \"handler\", \"click 的 e.target\" + e.target);\n }\n})(jQuery || window.jQuery || window.$, $(\"#viewModule\"));\n```\n","source":"_posts/front-end/jquery.md","raw":"---\ntitle: jQuery\ncategories:\n - Front-End\nstatus: done\n---\n\n# 基础\n\n在 `window` 对象中挂载了 `$`和`jQuery`\n\n```js\nwindow.jQuery();\nwindow.$ = window.jQuery;\n```\n\n# 模块化\n\n## 原始写法\n\n只要把不同的函数以及记录状态的变量简单地放在一起就算是一个模块。\n\n> 缺点很明显:\"污染\"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。\n\n```js\nfunction m1() {\n //...\n}\n\nfunction m2() {\n //...\n}\n```\n\n## 对象写法\n\n把模块写成一个对象\n\n> 写法会暴露所有模块成员,内部状态可以被外部改写。\n\n```js\nvar module1 = new Object({\n _count: 0,\n\n m1: function () {\n //...\n },\n\n m2: function () {\n //...\n },\n});\n\n// 使用\nmodule1.m1();\n```\n\n## IIFE 立即执行函数写法[推荐]\n\n> 外部代码无法读取内部的成员变量\n\n```js\nvar module1 = (function () {\n var _count = 0;\n\n var m1 = function () {\n //...\n };\n\n var m2 = function () {\n //...\n };\n\n return {\n m1: m1,\n m2: m2,\n };\n})();\n\nconsole.info(module1._count); //undefined\n```\n\n## (宽)放大模式\n\n如果一个模块很大必须分成几个部分或者一个模块需要继承另一个模块这时就有必要采用\"放大模式\"\n\n```js\nvar module1 = (function (mod) {\n mod.m3 = function () {\n //...\n };\n return mod;\n})(module1);\n```\n\nmod 可能存在异步,不知道内部哪个部分会先加载,如果采用上面的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用\"宽放大模式\"。\n\n```js\nvar module1 = (function (mod) {\n //...\n return mod;\n})(window.module1 || {});\n```\n\n## 输入全局变量[推荐]\n\n为了在模块内部调用全局变量必须显式地将其他变量输入模块\n\n```js\nvar module1 = (function ($, YAHOO) {\n //...\n})(jQuery, YAHOO);\n```\n\n# 链式操作\n\n```js\n$('div').find('#child').addClass('red')\n// end() 函数返回上一级\n$('div').find('#child').addClass('red').end().addClass'yellow'\n```\n\n# 选择器\n\n## 筛选器\n\n```js\n// $('li').first()\n$(\"li:first\"); //第一个元素\n// $('li').last()\n$(\"li:last\"); //最后一个元素\n$(\"tr:even\"); //索引为偶数的元素,从 0 开始\n$(\"tr:odd\"); //索引为奇数的元素,从 0 开始\n// $(\"tr\").eq(1)\n$(\"tr:eq(1)\"); //给定索引值的元素\n$(\"tr:gt(0)\"); //大于给定索引值的元素\n$(\"tr:lt(2)\"); //小于给定索引值的元素\n$(\":focus\"); //当前获取焦点的元素\n$(\":animated\"); //正在执行动画效果的元素\n```\n\n## 内容选择器\n\n```js\n$(\"div:contains('nick')\"); //包含nick文本的元素\n\n$(\"td:empty\"); //不包含子元素或者文本的空元素\n\n$(\"div:has(p)\"); //含有选择器所匹配的元素\n\n$(\"td:parent\"); //含有子元素或者文本的元素\n```\n\n## 表单选择器\n\n```js\n$(\":input\"); //匹配所有 input, textarea, select 和 button 元素\n\n$(\":text\"); //所有的单行文本框\n\n$(\":password\"); //所有密码框\n\n$(\":radio\"); //所有单选按钮\n\n$(\":checkbox\"); //所有复选框\n\n$(\":submit\"); //所有提交按钮\n\n$(\":reset\"); //所有重置按钮\n\n$(\":button\"); //所有button按钮\n\n$(\":file\"); //所有文件域\n\n$(\"input:radio[name=sex]:checked\"); //所有name 尾input选中的元素\n\n$(\"select option:selected\"); //select中所有选中的option元素\n```\n\n## 查找\n\n```js\n$(\"#xxx\"); //返回 一个 jquery 对象\n\n$(\"#xxx\").find(\".xxx\"); //查找#xxx里的.xxx元素\n\n$(\"#xxx\").parent(); //获取父类\n\n$(\"#xxx\").parents(\"xxx\"); //获取xxx祖先\n\n$(\"#xxx\").children(); //获取子类\n\n$(\"#xxx\").siblings(); //获取同一父类的其他元素\n\n$(\"#xxx\").next(); //获取下一个元素\n\n$(\"#xxx\").prev(); //获取上一个元素\n```\n\n## 属性操作\n\n```js\n$(\"img\").attr(\"src\"); //返回文档中所有图像的src属性值\n\n$(\"img\").attr(\"src\", \"test.jpg\"); //设置所有图像的src属性\n\n$(\"img\").removeAttr(\"src\"); //将文档中图像的src属性删除\n\n$(\"input[type='checkbox']\").prop(\"checked\", true); //选中复选框\n\n$(\"input[type='checkbox']\").prop(\"checked\", false);\n\n$(\"img\").removeProp(\"src\"); //删除img的src属性\n```\n\n## css 操作\n\n```js\n$(\"p\").addClass(\"selected\"); //为p元素加上 'selected' 类\n\n$(\"p\").removeClass(\"selected\"); //从p元素中删除 'selected' 类\n\n$(\"p\").toggleClass(\"selected\"); //如果存在就删除,否则就添加\n\n$(\"p\").css(\"color\"); //访问查看p元素的color属性\n\n$(\"p\").css(\"color\", \"red\"); //设置p元素的color属性为red\n\n$(\"p\").css({ color: \"red\", background: \"yellow\" }); // 设置多个属性\n```\n\n## 文档处理\n\n内部插入\n\n```js\n$(\"p\").append(\"<b>nick</b>\"); //每个p元素内后面追加内容\n\n$(\"p\").appendTo(\"div\"); //p元素追加到div内后\n\n$(\"p\").prepend(\"<b>Hello</b>\"); //每个p元素内前面追加内容\n\n$(\"p\").prependTo(\"div\"); //p元素追加到div内前\n```\n\n外部插入\n\n```js\n$(\"p\").after(\"<b>nick</b>\"); //每个p元素同级之后插入内容\n\n$(\"p\").before(\"<b>nick</b>\"); //在每个p元素同级之前插入内容\n\n$(\"p\").insertAfter(\"#test\"); //所有p元素插入到id为test元素的后面\n\n$(\"p\").insertBefore(\"#test\"); //所有p元素插入到id为test元素的前面\n```\n\n## 复制\n\n```js\n$(\"p\").clone(); //克隆元素并选中克隆的副本\n\n$(\"p\").clone(true); //布尔值指事件处理函数是否会被复制\n```\n\n# attr 和 prop 区别\n\nprop 和 attr 均可获取属性值,但 prop 获取的是 `DOM 对象内置属性`。\n\n> !! 例如 inputradioslect 元素,请使用 prop 获取\n\n```html\n<img src=\"https://www.runoob.com/images/pulpit.jpg\" />\n<p tinyval=\"12\"></p>\n```\n\n```js\n// 因为页面源代码中没有设置 width 属性\n$(\"img\").attr(\"width\"); // undefined\n$(\"img\").prop(\"width\"); // 284\n\n// 由于 tinyval 并非 HTML 标准属性\n$(\"p\").prop(\"tinyval\"); // undefined\n$(\"p\").attr(\"tinyval\"); // 12\n```\n\n# 事件\n\n## 事件委托\n\n- 可极大减少事件绑定次数,提高性能\n- 可让动态加入的子元素绑定相同的命令\n\n```js\nfunction handleClick(event) {\n // this 表示当前单击的元素\n alert($(this).html());\n}\n// 把子级li元素的单击事件委托在父级ul身上\n$(\"ul\").delegate(\"li\", \"click\", handleClick);\n```\n\n## 单事件单元素\n\n```js\nfunction handleClick() {}\n$xxx.on(\"click\", handleClick);\n```\n\n## 单事件多元素\n\n```js\nfunction handleClick() {}\n$xxx.on(\"click\", \"#aaa, .bbb\", handleClick);\n```\n\n## 多事件多元素\n\n```js\nfunction handleClick() {}\nfunction handleMounseEnter() {}\n$xxx.on(\n {\n click: handleClick,\n mounseenter: handleMounseEnter,\n },\n \"#aaa, .bbb\"\n);\n```\n\n## 一夜情事件\n\n```js\nfunction handleClick() {}\n$xxx.one(\"click\", handleClick);\n```\n\n# 对象操作\n\n```js\n$.trim(); //去除字符串两端的空格\n\n$.each(); //遍历一个数组或对象for循环\n\n$.inArray(); //返回一个值在数组中的索引位置,不存在返回-1\n\n$.grep(); //返回数组中符合某种标准的元素\n\n$.extend(true, {}, a, b); // 深浅拷贝合并 a、b 到 {} 上\n\n$.makeArray(); //将对象转化为数组\n\n$.type(); //判断对象的类别(函数对象、日期对象、数组对象、正则对象等等\n\n$.isArray(); //判断某个参数是否为数组\n\n$.isEmptyObject(); //判断某个对象是否为空(不含有任何属性)\n\n$.isFunction(); //判断某个参数是否为函数\n\n$.isPlainObject(); //判断某个参数是否为用\"{}\"或\"new Object\"建立的对象\n\n$.support(); //判断浏览器是否支持某个特性\n```\n\n# 禁止右键功能菜单\n\n```js\n$(window).on({\n contextmenu: function () {\n return false;\n },\n keydown: function (e) {\n if (e.ctrlKey || (e.metaKey && (e.keyCode === 67 || e.keyCode === 8)))\n return false;\n },\n});\n```\n\n# 自动修改破损图像\n\n```js\n$(\"img\").on(\"error\", function () {\n $(this).prop(\"src\", \"img/broken.png\");\n});\n```\n\n# 模块化 jquery 最佳实践\n\n```js\n// xx 视图模块 #xx\n(function ($, $view) {\n console.log($ + \"has been imported\");\n\n // 缓存 dom需要用到的 dom提高性能\n var $partA = $view.find(\".partA\"),\n $partB = $view.find(\".partB\");\n\n // 链式表结构,事件委托\n $view\n .on(\"focus\", \"#btnFocusPartA\", handleBtnFocusPartA)\n .on(\"click\", \".btnClickPartB\", handleBtnClickPartB);\n\n // 方法,建议函数式\n function handleBtnFocusPartA() {\n console.log($partA + \"handler\");\n }\n\n function handleBtnClickPartB(e) {\n console.log($partB + \"handler\", \"click 的 e.target\" + e.target);\n }\n})(jQuery || window.jQuery || window.$, $(\"#viewModule\"));\n```\n\n更骚的`路由表`的写法,搭配模块化开发更优雅,更方便管理\n\n```js\n// xx 视图模块 #xx\n(function ($, $view) {\n console.log($ + \"has been imported\");\n\n // 缓存 dom需要用到的 dom提高性能\n var $partA = $view.find(\".partA\"),\n $partB = $view.find(\".partB\");\n\n // $view 视图的事件委托表\n var eventTable = [\n {\n name: \"focus\",\n elem: \"#btnFocusPartA\",\n handler: handleBtnFocusPartA,\n },\n {\n name: \"click\",\n elem: \".btnClickPartB\",\n handler: handleBtnClickPartB,\n },\n ];\n\n // 注册事件\n eventTable.forEach(function (item) {\n $view.on(item.name, item.elem, item.handler);\n });\n\n // 方法,建议函数式\n function handleBtnFocusPartA() {\n console.log($partA + \"handler\");\n }\n\n function handleBtnClickPartB(e) {\n console.log($partB + \"handler\", \"click 的 e.target\" + e.target);\n }\n})(jQuery || window.jQuery || window.$, $(\"#viewModule\"));\n```\n","slug":"front-end/jquery","published":1,"date":"2023-11-06T08:01:17.912Z","updated":"2023-11-06T08:02:35.529Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58o000d4cz39b94fqx5","content":"<h1 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h1><p>在 <code>window</code> 对象中挂载了 <code>$</code>和<code>jQuery</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">window<span class=\"token punctuation\">.</span><span class=\"token function\">jQuery</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nwindow<span class=\"token punctuation\">.</span>$ <span class=\"token operator\">=</span> window<span class=\"token punctuation\">.</span>jQuery<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"模块化\"><a href=\"#模块化\" class=\"headerlink\" title=\"模块化\"></a>模块化</h1><h2 id=\"原始写法\"><a href=\"#原始写法\" class=\"headerlink\" title=\"原始写法\"></a>原始写法</h2><p>只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块。</p>\n<blockquote>\n<p>缺点很明显:”污染”了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">m1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">m2</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"对象写法\"><a href=\"#对象写法\" class=\"headerlink\" title=\"对象写法\"></a>对象写法</h2><p>把模块写成一个对象</p>\n<blockquote>\n<p>写法会暴露所有模块成员,内部状态可以被外部改写。</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module1 <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Object</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">_count</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n\n <span class=\"token function-variable function\">m1</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n\n <span class=\"token function-variable function\">m2</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 使用</span>\nmodule1<span class=\"token punctuation\">.</span><span class=\"token function\">m1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"IIFE-立即执行函数写法-推荐\"><a href=\"#IIFE-立即执行函数写法-推荐\" class=\"headerlink\" title=\"IIFE 立即执行函数写法[推荐]\"></a>IIFE 立即执行函数写法[推荐]</h2><blockquote>\n<p>外部代码无法读取内部的成员变量</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> _count <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token keyword\">var</span> <span class=\"token function-variable function\">m1</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token keyword\">var</span> <span class=\"token function-variable function\">m2</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">m1</span><span class=\"token operator\">:</span> m1<span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">m2</span><span class=\"token operator\">:</span> m2<span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">info</span><span class=\"token punctuation\">(</span>module1<span class=\"token punctuation\">.</span>_count<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//undefined</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"宽-放大模式\"><a href=\"#宽-放大模式\" class=\"headerlink\" title=\"(宽)放大模式\"></a>(宽)放大模式</h2><p>如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用”放大模式”</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">mod</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n mod<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">m3</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> mod<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>module1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>mod 可能存在异步,不知道内部哪个部分会先加载,如果采用上面的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用”宽放大模式”。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">mod</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token keyword\">return</span> mod<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">.</span>module1 <span class=\"token operator\">||</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"输入全局变量-推荐\"><a href=\"#输入全局变量-推荐\" class=\"headerlink\" title=\"输入全局变量[推荐]\"></a>输入全局变量[推荐]</h2><p>为了在模块内部调用全局变量,必须显式地将其他变量输入模块</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">$<span class=\"token punctuation\">,</span> <span class=\"token constant\">YAHOO</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>jQuery<span class=\"token punctuation\">,</span> <span class=\"token constant\">YAHOO</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"链式操作\"><a href=\"#链式操作\" class=\"headerlink\" title=\"链式操作\"></a>链式操作</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">'div'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#child'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">addClass</span><span class=\"token punctuation\">(</span><span class=\"token string\">'red'</span><span class=\"token punctuation\">)</span>\n<span class=\"token comment\">// end() 函数返回上一级</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">'div'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#child'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">addClass</span><span class=\"token punctuation\">(</span><span class=\"token string\">'red'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>addClass<span class=\"token string\">'yellow'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"选择器\"><a href=\"#选择器\" class=\"headerlink\" title=\"选择器\"></a>选择器</h1><h2 id=\"筛选器\"><a href=\"#筛选器\" class=\"headerlink\" title=\"筛选器\"></a>筛选器</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// $('li').first()</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"li:first\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//第一个元素</span>\n<span class=\"token comment\">// $('li').last()</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"li:last\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//最后一个元素</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tr:even\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//索引为偶数的元素,从 0 开始</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tr:odd\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//索引为奇数的元素,从 0 开始</span>\n<span class=\"token comment\">// $(\"tr\").eq(1)</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tr:eq(1)\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//给定索引值的元素</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tr:gt(0)\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//大于给定索引值的元素</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tr:lt(2)\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//小于给定索引值的元素</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":focus\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//当前获取焦点的元素</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":animated\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//正在执行动画效果的元素</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"内容选择器\"><a href=\"#内容选择器\" class=\"headerlink\" title=\"内容选择器\"></a>内容选择器</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"div:contains('nick')\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//包含nick文本的元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"td:empty\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//不包含子元素或者文本的空元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"div:has(p)\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//含有选择器所匹配的元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"td:parent\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//含有子元素或者文本的元素</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"表单选择器\"><a href=\"#表单选择器\" class=\"headerlink\" title=\"表单选择器\"></a>表单选择器</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":input\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//匹配所有 input, textarea, select 和 button 元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":text\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有的单行文本框</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":password\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有密码框</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":radio\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有单选按钮</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":checkbox\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有复选框</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":submit\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有提交按钮</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":reset\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有重置按钮</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":button\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有button按钮</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":file\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有文件域</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"input:radio[name=sex]:checked\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有name 尾input选中的元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"select option:selected\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//select中所有选中的option元素</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"查找\"><a href=\"#查找\" class=\"headerlink\" title=\"查找\"></a>查找</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//返回 一个 jquery 对象</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//查找#xxx里的.xxx元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">parent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取父类</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">parents</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取xxx祖先</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">children</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取子类</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">siblings</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取同一父类的其他元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取下一个元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prev</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取上一个元素</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"属性操作\"><a href=\"#属性操作\" class=\"headerlink\" title=\"属性操作\"></a>属性操作</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">attr</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"src\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//返回文档中所有图像的src属性值</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">attr</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"src\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"test.jpg\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//设置所有图像的src属性</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">removeAttr</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"src\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//将文档中图像的src属性删除</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"input[type='checkbox']\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prop</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"checked\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//选中复选框</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"input[type='checkbox']\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prop</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"checked\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">removeProp</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"src\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//删除img的src属性</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"css-操作\"><a href=\"#css-操作\" class=\"headerlink\" title=\"css 操作\"></a>css 操作</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">addClass</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"selected\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//为p元素加上 'selected' 类</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">removeClass</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"selected\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//从p元素中删除 'selected' 类</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toggleClass</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"selected\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//如果存在就删除,否则就添加</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">css</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"color\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//访问查看p元素的color属性</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">css</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"color\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"red\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//设置p元素的color属性为red</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">css</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">color</span><span class=\"token operator\">:</span> <span class=\"token string\">\"red\"</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">background</span><span class=\"token operator\">:</span> <span class=\"token string\">\"yellow\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 设置多个属性</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"文档处理\"><a href=\"#文档处理\" class=\"headerlink\" title=\"文档处理\"></a>文档处理</h2><p>内部插入</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">append</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&lt;b>nick&lt;/b>\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//每个p元素内后面追加内容</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">appendTo</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"div\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//p元素追加到div内后</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prepend</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&lt;b>Hello&lt;/b>\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//每个p元素内前面追加内容</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prependTo</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"div\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//p元素追加到div内前</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>外部插入</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">after</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&lt;b>nick&lt;/b>\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//每个p元素同级之后插入内容</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">before</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&lt;b>nick&lt;/b>\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//在每个p元素同级之前插入内容</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">insertAfter</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#test\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有p元素插入到id为test元素的后面</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">insertBefore</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#test\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有p元素插入到id为test元素的前面</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"复制\"><a href=\"#复制\" class=\"headerlink\" title=\"复制\"></a>复制</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">clone</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//克隆元素并选中克隆的副本</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">clone</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//布尔值指事件处理函数是否会被复制</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"attr-和-prop-区别\"><a href=\"#attr-和-prop-区别\" class=\"headerlink\" title=\"attr 和 prop 区别\"></a>attr 和 prop 区别</h1><p>prop 和 attr 均可获取属性值,但 prop 获取的是 <code>DOM 对象内置属性</code>。</p>\n<blockquote>\n<p>!! 例如 inputradioslect 元素,请使用 prop 获取</p>\n</blockquote>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://www.runoob.com/images/pulpit.jpg<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span> <span class=\"token attr-name\">tinyval</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>12<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 因为页面源代码中没有设置 width 属性</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">attr</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"width\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prop</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"width\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 284</span>\n\n<span class=\"token comment\">// 由于 tinyval 并非 HTML 标准属性</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prop</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tinyval\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">attr</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tinyval\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 12</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"事件\"><a href=\"#事件\" class=\"headerlink\" title=\"事件\"></a>事件</h1><h2 id=\"事件委托\"><a href=\"#事件委托\" class=\"headerlink\" title=\"事件委托\"></a>事件委托</h2><ul>\n<li>可极大减少事件绑定次数,提高性能</li>\n<li>可让动态加入的子元素绑定相同的命令</li>\n</ul>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// this 表示当前单击的元素</span>\n <span class=\"token function\">alert</span><span class=\"token punctuation\">(</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">html</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 把子级li元素的单击事件委托在父级ul身上</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"ul\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">delegate</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"li\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span> handleClick<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"单事件单元素\"><a href=\"#单事件单元素\" class=\"headerlink\" title=\"单事件单元素\"></a>单事件单元素</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n$xxx<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span> handleClick<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"单事件多元素\"><a href=\"#单事件多元素\" class=\"headerlink\" title=\"单事件多元素\"></a>单事件多元素</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n$xxx<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"#aaa, .bbb\"</span><span class=\"token punctuation\">,</span> handleClick<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"多事件多元素\"><a href=\"#多事件多元素\" class=\"headerlink\" title=\"多事件多元素\"></a>多事件多元素</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">handleMounseEnter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n$xxx<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">click</span><span class=\"token operator\">:</span> handleClick<span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">mounseenter</span><span class=\"token operator\">:</span> handleMounseEnter<span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"#aaa, .bbb\"</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"一夜情事件\"><a href=\"#一夜情事件\" class=\"headerlink\" title=\"一夜情事件\"></a>一夜情事件</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n$xxx<span class=\"token punctuation\">.</span><span class=\"token function\">one</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span> handleClick<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"对象操作\"><a href=\"#对象操作\" class=\"headerlink\" title=\"对象操作\"></a>对象操作</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">$<span class=\"token punctuation\">.</span><span class=\"token function\">trim</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//去除字符串两端的空格</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">each</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//遍历一个数组或对象for循环</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">inArray</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//返回一个值在数组中的索引位置,不存在返回-1</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">grep</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//返回数组中符合某种标准的元素</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">extend</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 深浅拷贝合并 a、b 到 &#123;&#125; 上</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">makeArray</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//将对象转化为数组</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">type</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断对象的类别(函数对象、日期对象、数组对象、正则对象等等</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断某个参数是否为数组</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">isEmptyObject</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断某个对象是否为空(不含有任何属性)</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">isFunction</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断某个参数是否为函数</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">isPlainObject</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断某个参数是否为用\"&#123;&#125;\"或\"new Object\"建立的对象</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">support</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断浏览器是否支持某个特性</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"禁止右键功能菜单\"><a href=\"#禁止右键功能菜单\" class=\"headerlink\" title=\"禁止右键功能菜单\"></a>禁止右键功能菜单</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">contextmenu</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">keydown</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>ctrlKey <span class=\"token operator\">||</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>metaKey <span class=\"token operator\">&amp;&amp;</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>keyCode <span class=\"token operator\">===</span> <span class=\"token number\">67</span> <span class=\"token operator\">||</span> e<span class=\"token punctuation\">.</span>keyCode <span class=\"token operator\">===</span> <span class=\"token number\">8</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"自动修改破损图像\"><a href=\"#自动修改破损图像\" class=\"headerlink\" title=\"自动修改破损图像\"></a>自动修改破损图像</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"error\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prop</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"src\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"img/broken.png\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"模块化-jquery-最佳实践\"><a href=\"#模块化-jquery-最佳实践\" class=\"headerlink\" title=\"模块化 jquery 最佳实践\"></a>模块化 jquery 最佳实践</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// xx 视图模块 #xx</span>\n<span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">$<span class=\"token punctuation\">,</span> $view</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$ <span class=\"token operator\">+</span> <span class=\"token string\">\"has been imported\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 缓存 dom需要用到的 dom提高性能</span>\n <span class=\"token keyword\">var</span> $partA <span class=\"token operator\">=</span> $view<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".partA\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n $partB <span class=\"token operator\">=</span> $view<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".partB\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 链式表结构,事件委托</span>\n $view\n <span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"focus\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"#btnFocusPartA\"</span><span class=\"token punctuation\">,</span> handleBtnFocusPartA<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\".btnClickPartB\"</span><span class=\"token punctuation\">,</span> handleBtnClickPartB<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 方法,建议函数式</span>\n <span class=\"token keyword\">function</span> <span class=\"token function\">handleBtnFocusPartA</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$partA <span class=\"token operator\">+</span> <span class=\"token string\">\"handler\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token keyword\">function</span> <span class=\"token function\">handleBtnClickPartB</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$partB <span class=\"token operator\">+</span> <span class=\"token string\">\"handler\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"click 的 e.target\"</span> <span class=\"token operator\">+</span> e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>jQuery <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>jQuery <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>$<span class=\"token punctuation\">,</span> <span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#viewModule\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>更骚的<code>路由表</code>的写法,搭配模块化开发更优雅,更方便管理</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// xx 视图模块 #xx</span>\n<span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">$<span class=\"token punctuation\">,</span> $view</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$ <span class=\"token operator\">+</span> <span class=\"token string\">\"has been imported\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 缓存 dom需要用到的 dom提高性能</span>\n <span class=\"token keyword\">var</span> $partA <span class=\"token operator\">=</span> $view<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".partA\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n $partB <span class=\"token operator\">=</span> $view<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".partB\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// $view 视图的事件委托表</span>\n <span class=\"token keyword\">var</span> eventTable <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"focus\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">elem</span><span class=\"token operator\">:</span> <span class=\"token string\">\"#btnFocusPartA\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">handler</span><span class=\"token operator\">:</span> handleBtnFocusPartA<span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">elem</span><span class=\"token operator\">:</span> <span class=\"token string\">\".btnClickPartB\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">handler</span><span class=\"token operator\">:</span> handleBtnClickPartB<span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 注册事件</span>\n eventTable<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">item</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n $view<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span>item<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">,</span> item<span class=\"token punctuation\">.</span>elem<span class=\"token punctuation\">,</span> item<span class=\"token punctuation\">.</span>handler<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 方法,建议函数式</span>\n <span class=\"token keyword\">function</span> <span class=\"token function\">handleBtnFocusPartA</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$partA <span class=\"token operator\">+</span> <span class=\"token string\">\"handler\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token keyword\">function</span> <span class=\"token function\">handleBtnClickPartB</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$partB <span class=\"token operator\">+</span> <span class=\"token string\">\"handler\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"click 的 e.target\"</span> <span class=\"token operator\">+</span> e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>jQuery <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>jQuery <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>$<span class=\"token punctuation\">,</span> <span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#viewModule\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n","site":{"data":{}},"excerpt":"","more":"<h1 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h1><p>在 <code>window</code> 对象中挂载了 <code>$</code>和<code>jQuery</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">window<span class=\"token punctuation\">.</span><span class=\"token function\">jQuery</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nwindow<span class=\"token punctuation\">.</span>$ <span class=\"token operator\">=</span> window<span class=\"token punctuation\">.</span>jQuery<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"模块化\"><a href=\"#模块化\" class=\"headerlink\" title=\"模块化\"></a>模块化</h1><h2 id=\"原始写法\"><a href=\"#原始写法\" class=\"headerlink\" title=\"原始写法\"></a>原始写法</h2><p>只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块。</p>\n<blockquote>\n<p>缺点很明显:”污染”了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">m1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">m2</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"对象写法\"><a href=\"#对象写法\" class=\"headerlink\" title=\"对象写法\"></a>对象写法</h2><p>把模块写成一个对象</p>\n<blockquote>\n<p>写法会暴露所有模块成员,内部状态可以被外部改写。</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module1 <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Object</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">_count</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n\n <span class=\"token function-variable function\">m1</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n\n <span class=\"token function-variable function\">m2</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 使用</span>\nmodule1<span class=\"token punctuation\">.</span><span class=\"token function\">m1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"IIFE-立即执行函数写法-推荐\"><a href=\"#IIFE-立即执行函数写法-推荐\" class=\"headerlink\" title=\"IIFE 立即执行函数写法[推荐]\"></a>IIFE 立即执行函数写法[推荐]</h2><blockquote>\n<p>外部代码无法读取内部的成员变量</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> _count <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token keyword\">var</span> <span class=\"token function-variable function\">m1</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token keyword\">var</span> <span class=\"token function-variable function\">m2</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">m1</span><span class=\"token operator\">:</span> m1<span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">m2</span><span class=\"token operator\">:</span> m2<span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">info</span><span class=\"token punctuation\">(</span>module1<span class=\"token punctuation\">.</span>_count<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//undefined</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"宽-放大模式\"><a href=\"#宽-放大模式\" class=\"headerlink\" title=\"(宽)放大模式\"></a>(宽)放大模式</h2><p>如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用”放大模式”</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">mod</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n mod<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">m3</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> mod<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>module1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>mod 可能存在异步,不知道内部哪个部分会先加载,如果采用上面的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用”宽放大模式”。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">mod</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n <span class=\"token keyword\">return</span> mod<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">.</span>module1 <span class=\"token operator\">||</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"输入全局变量-推荐\"><a href=\"#输入全局变量-推荐\" class=\"headerlink\" title=\"输入全局变量[推荐]\"></a>输入全局变量[推荐]</h2><p>为了在模块内部调用全局变量,必须显式地将其他变量输入模块</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">$<span class=\"token punctuation\">,</span> <span class=\"token constant\">YAHOO</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">//...</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>jQuery<span class=\"token punctuation\">,</span> <span class=\"token constant\">YAHOO</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"链式操作\"><a href=\"#链式操作\" class=\"headerlink\" title=\"链式操作\"></a>链式操作</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">'div'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#child'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">addClass</span><span class=\"token punctuation\">(</span><span class=\"token string\">'red'</span><span class=\"token punctuation\">)</span>\n<span class=\"token comment\">// end() 函数返回上一级</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">'div'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">'#child'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">addClass</span><span class=\"token punctuation\">(</span><span class=\"token string\">'red'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>addClass<span class=\"token string\">'yellow'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"选择器\"><a href=\"#选择器\" class=\"headerlink\" title=\"选择器\"></a>选择器</h1><h2 id=\"筛选器\"><a href=\"#筛选器\" class=\"headerlink\" title=\"筛选器\"></a>筛选器</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// $('li').first()</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"li:first\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//第一个元素</span>\n<span class=\"token comment\">// $('li').last()</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"li:last\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//最后一个元素</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tr:even\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//索引为偶数的元素,从 0 开始</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tr:odd\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//索引为奇数的元素,从 0 开始</span>\n<span class=\"token comment\">// $(\"tr\").eq(1)</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tr:eq(1)\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//给定索引值的元素</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tr:gt(0)\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//大于给定索引值的元素</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tr:lt(2)\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//小于给定索引值的元素</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":focus\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//当前获取焦点的元素</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":animated\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//正在执行动画效果的元素</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"内容选择器\"><a href=\"#内容选择器\" class=\"headerlink\" title=\"内容选择器\"></a>内容选择器</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"div:contains('nick')\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//包含nick文本的元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"td:empty\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//不包含子元素或者文本的空元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"div:has(p)\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//含有选择器所匹配的元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"td:parent\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//含有子元素或者文本的元素</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"表单选择器\"><a href=\"#表单选择器\" class=\"headerlink\" title=\"表单选择器\"></a>表单选择器</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":input\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//匹配所有 input, textarea, select 和 button 元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":text\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有的单行文本框</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":password\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有密码框</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":radio\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有单选按钮</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":checkbox\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有复选框</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":submit\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有提交按钮</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":reset\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有重置按钮</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":button\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有button按钮</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":file\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有文件域</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"input:radio[name=sex]:checked\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有name 尾input选中的元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"select option:selected\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//select中所有选中的option元素</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"查找\"><a href=\"#查找\" class=\"headerlink\" title=\"查找\"></a>查找</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//返回 一个 jquery 对象</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//查找#xxx里的.xxx元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">parent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取父类</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">parents</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取xxx祖先</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">children</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取子类</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">siblings</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取同一父类的其他元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取下一个元素</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#xxx\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prev</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//获取上一个元素</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"属性操作\"><a href=\"#属性操作\" class=\"headerlink\" title=\"属性操作\"></a>属性操作</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">attr</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"src\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//返回文档中所有图像的src属性值</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">attr</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"src\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"test.jpg\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//设置所有图像的src属性</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">removeAttr</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"src\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//将文档中图像的src属性删除</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"input[type='checkbox']\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prop</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"checked\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//选中复选框</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"input[type='checkbox']\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prop</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"checked\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">removeProp</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"src\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//删除img的src属性</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"css-操作\"><a href=\"#css-操作\" class=\"headerlink\" title=\"css 操作\"></a>css 操作</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">addClass</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"selected\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//为p元素加上 'selected' 类</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">removeClass</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"selected\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//从p元素中删除 'selected' 类</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toggleClass</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"selected\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//如果存在就删除,否则就添加</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">css</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"color\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//访问查看p元素的color属性</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">css</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"color\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"red\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//设置p元素的color属性为red</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">css</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">color</span><span class=\"token operator\">:</span> <span class=\"token string\">\"red\"</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">background</span><span class=\"token operator\">:</span> <span class=\"token string\">\"yellow\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 设置多个属性</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"文档处理\"><a href=\"#文档处理\" class=\"headerlink\" title=\"文档处理\"></a>文档处理</h2><p>内部插入</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">append</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&lt;b>nick&lt;/b>\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//每个p元素内后面追加内容</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">appendTo</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"div\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//p元素追加到div内后</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prepend</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&lt;b>Hello&lt;/b>\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//每个p元素内前面追加内容</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prependTo</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"div\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//p元素追加到div内前</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>外部插入</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">after</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&lt;b>nick&lt;/b>\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//每个p元素同级之后插入内容</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">before</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&lt;b>nick&lt;/b>\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//在每个p元素同级之前插入内容</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">insertAfter</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#test\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有p元素插入到id为test元素的后面</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">insertBefore</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#test\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//所有p元素插入到id为test元素的前面</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"复制\"><a href=\"#复制\" class=\"headerlink\" title=\"复制\"></a>复制</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">clone</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//克隆元素并选中克隆的副本</span>\n\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">clone</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//布尔值指事件处理函数是否会被复制</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"attr-和-prop-区别\"><a href=\"#attr-和-prop-区别\" class=\"headerlink\" title=\"attr 和 prop 区别\"></a>attr 和 prop 区别</h1><p>prop 和 attr 均可获取属性值,但 prop 获取的是 <code>DOM 对象内置属性</code>。</p>\n<blockquote>\n<p>!! 例如 inputradioslect 元素,请使用 prop 获取</p>\n</blockquote>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://www.runoob.com/images/pulpit.jpg<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span> <span class=\"token attr-name\">tinyval</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>12<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 因为页面源代码中没有设置 width 属性</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">attr</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"width\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prop</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"width\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 284</span>\n\n<span class=\"token comment\">// 由于 tinyval 并非 HTML 标准属性</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prop</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tinyval\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">attr</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"tinyval\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 12</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"事件\"><a href=\"#事件\" class=\"headerlink\" title=\"事件\"></a>事件</h1><h2 id=\"事件委托\"><a href=\"#事件委托\" class=\"headerlink\" title=\"事件委托\"></a>事件委托</h2><ul>\n<li>可极大减少事件绑定次数,提高性能</li>\n<li>可让动态加入的子元素绑定相同的命令</li>\n</ul>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// this 表示当前单击的元素</span>\n <span class=\"token function\">alert</span><span class=\"token punctuation\">(</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">html</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 把子级li元素的单击事件委托在父级ul身上</span>\n<span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"ul\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">delegate</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"li\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span> handleClick<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"单事件单元素\"><a href=\"#单事件单元素\" class=\"headerlink\" title=\"单事件单元素\"></a>单事件单元素</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n$xxx<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span> handleClick<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"单事件多元素\"><a href=\"#单事件多元素\" class=\"headerlink\" title=\"单事件多元素\"></a>单事件多元素</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n$xxx<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"#aaa, .bbb\"</span><span class=\"token punctuation\">,</span> handleClick<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"多事件多元素\"><a href=\"#多事件多元素\" class=\"headerlink\" title=\"多事件多元素\"></a>多事件多元素</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">handleMounseEnter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n$xxx<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">click</span><span class=\"token operator\">:</span> handleClick<span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">mounseenter</span><span class=\"token operator\">:</span> handleMounseEnter<span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"#aaa, .bbb\"</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"一夜情事件\"><a href=\"#一夜情事件\" class=\"headerlink\" title=\"一夜情事件\"></a>一夜情事件</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n$xxx<span class=\"token punctuation\">.</span><span class=\"token function\">one</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span> handleClick<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"对象操作\"><a href=\"#对象操作\" class=\"headerlink\" title=\"对象操作\"></a>对象操作</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">$<span class=\"token punctuation\">.</span><span class=\"token function\">trim</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//去除字符串两端的空格</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">each</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//遍历一个数组或对象for循环</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">inArray</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//返回一个值在数组中的索引位置,不存在返回-1</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">grep</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//返回数组中符合某种标准的元素</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">extend</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 深浅拷贝合并 a、b 到 &#123;&#125; 上</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">makeArray</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//将对象转化为数组</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">type</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断对象的类别(函数对象、日期对象、数组对象、正则对象等等</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断某个参数是否为数组</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">isEmptyObject</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断某个对象是否为空(不含有任何属性)</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">isFunction</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断某个参数是否为函数</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">isPlainObject</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断某个参数是否为用\"&#123;&#125;\"或\"new Object\"建立的对象</span>\n\n$<span class=\"token punctuation\">.</span><span class=\"token function\">support</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//判断浏览器是否支持某个特性</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"禁止右键功能菜单\"><a href=\"#禁止右键功能菜单\" class=\"headerlink\" title=\"禁止右键功能菜单\"></a>禁止右键功能菜单</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">contextmenu</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">keydown</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>ctrlKey <span class=\"token operator\">||</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>metaKey <span class=\"token operator\">&amp;&amp;</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>keyCode <span class=\"token operator\">===</span> <span class=\"token number\">67</span> <span class=\"token operator\">||</span> e<span class=\"token punctuation\">.</span>keyCode <span class=\"token operator\">===</span> <span class=\"token number\">8</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"自动修改破损图像\"><a href=\"#自动修改破损图像\" class=\"headerlink\" title=\"自动修改破损图像\"></a>自动修改破损图像</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"img\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"error\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">prop</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"src\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"img/broken.png\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"模块化-jquery-最佳实践\"><a href=\"#模块化-jquery-最佳实践\" class=\"headerlink\" title=\"模块化 jquery 最佳实践\"></a>模块化 jquery 最佳实践</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// xx 视图模块 #xx</span>\n<span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">$<span class=\"token punctuation\">,</span> $view</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$ <span class=\"token operator\">+</span> <span class=\"token string\">\"has been imported\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 缓存 dom需要用到的 dom提高性能</span>\n <span class=\"token keyword\">var</span> $partA <span class=\"token operator\">=</span> $view<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".partA\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n $partB <span class=\"token operator\">=</span> $view<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".partB\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 链式表结构,事件委托</span>\n $view\n <span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"focus\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"#btnFocusPartA\"</span><span class=\"token punctuation\">,</span> handleBtnFocusPartA<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\".btnClickPartB\"</span><span class=\"token punctuation\">,</span> handleBtnClickPartB<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 方法,建议函数式</span>\n <span class=\"token keyword\">function</span> <span class=\"token function\">handleBtnFocusPartA</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$partA <span class=\"token operator\">+</span> <span class=\"token string\">\"handler\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token keyword\">function</span> <span class=\"token function\">handleBtnClickPartB</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$partB <span class=\"token operator\">+</span> <span class=\"token string\">\"handler\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"click 的 e.target\"</span> <span class=\"token operator\">+</span> e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>jQuery <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>jQuery <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>$<span class=\"token punctuation\">,</span> <span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#viewModule\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>更骚的<code>路由表</code>的写法,搭配模块化开发更优雅,更方便管理</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// xx 视图模块 #xx</span>\n<span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">$<span class=\"token punctuation\">,</span> $view</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$ <span class=\"token operator\">+</span> <span class=\"token string\">\"has been imported\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 缓存 dom需要用到的 dom提高性能</span>\n <span class=\"token keyword\">var</span> $partA <span class=\"token operator\">=</span> $view<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".partA\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n $partB <span class=\"token operator\">=</span> $view<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".partB\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// $view 视图的事件委托表</span>\n <span class=\"token keyword\">var</span> eventTable <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"focus\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">elem</span><span class=\"token operator\">:</span> <span class=\"token string\">\"#btnFocusPartA\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">handler</span><span class=\"token operator\">:</span> handleBtnFocusPartA<span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">elem</span><span class=\"token operator\">:</span> <span class=\"token string\">\".btnClickPartB\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">handler</span><span class=\"token operator\">:</span> handleBtnClickPartB<span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 注册事件</span>\n eventTable<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">item</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n $view<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span>item<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">,</span> item<span class=\"token punctuation\">.</span>elem<span class=\"token punctuation\">,</span> item<span class=\"token punctuation\">.</span>handler<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n <span class=\"token comment\">// 方法,建议函数式</span>\n <span class=\"token keyword\">function</span> <span class=\"token function\">handleBtnFocusPartA</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$partA <span class=\"token operator\">+</span> <span class=\"token string\">\"handler\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token keyword\">function</span> <span class=\"token function\">handleBtnClickPartB</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>$partB <span class=\"token operator\">+</span> <span class=\"token string\">\"handler\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"click 的 e.target\"</span> <span class=\"token operator\">+</span> e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>jQuery <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>jQuery <span class=\"token operator\">||</span> window<span class=\"token punctuation\">.</span>$<span class=\"token punctuation\">,</span> <span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#viewModule\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n"},{"title":"Git","status":"done","_content":"\n\n# GIT 最佳实践\n\nGIT 本质是一个数据库,用来存代码的\n\n- 工作区一个沙箱环境GIT 不负责管理,你尽管在沙箱里面对文件进行操作\n- 暂存区:`工作区`文件变动先不急着提交,暂存到一定数量,在提交到版本库\n- 版本库:\n\n> !! Linus 永远的神!\n\n## 配置用户\n\n```bash\ngit config --global user.name \"mozzie\"\ngit config --global user.email himozzie@foxmail.com\n```\n\n## alias 别名\n\n解决参数太多记不住的问题\n\n> !! HEAD -> master HEAD 相当于一个指针,指向当前所在分支\n\n```bash\n# 查看项目分支图,\ngit config --global alias.lo \"log --oneline --decorate --graph --all\"\n```\n\n## .git 文件结构\n\n- hooks提交代码前检查代码格式……\n- info包含一个排除性文件\n- logs保存日志信息不太需要\n- `objects`:相当于数据库,存储所有数据内容\n- `refs`:存放提交对象指针,管理分支的\n- config配置文件\n- description仓库描述信息\n- `HEAD`:指示目前被检出的分支\n- `index`:文件保存暂存区信息\n\n## 修改远程仓库\n\n```bash\n# way 1\ngit remote set-url origin [url]\n# way 2\ngit remote rm origin\ngit remote add origin [url]\n# way3\n修改 config 文件\n```\n\n## 高层命令\n\n### 初始化仓库\n\n`git init`\n\n### 修改添加到暂存区\n\n`git add ./`,相当于如下操作:\n\n```bash\n# 有多少文件改动,就执行多少次\ngit hash-object -w 文件名\ngit update-index\n```\n\n> !! git add ./ 先把工作区生成 git 对象,放到版本库,然后再放到暂存区\n\n### 暂存区提交到版本库\n\n`git commit -m 'comment'`,相当于如下操作:\n\n```bash\ngit write-tree\ngit commit-tree\n```\n\n也可以跳过暂存区提交`git commit -a -m `\n\n### 查看哪些修改没有暂存\n\n`git diff`:没有暂存\n\n`git diff --staged`:查看哪些修改以及被暂存了,但没有提交\n\n### 查看提交历史记录\n\n`git log --oneline`,打印出`hash值`是提交对象\n\n## 分支\n\n本质是一个`提交对象`,每次`git branch name`中的`name`,指针`HEAD`,就会根据`name`指向提交对象\n\n如果要开发新功能就新建一个`分支A`,写完再合`master`分支,正常来说`master`分支不会轻易给修改权限。\n\n如果另一个新功能和`分支A`同级、并行的,那就`切到master`分支,在`master`分支基础上,开`分支B`,进行新功能开发\n\n> 一般来说master 分支没有权限,需要自己重新写开一个分支,分支名用 nickname\n\n```bash\nC1 master\n|——C2——C3——C4 mozzie\n```\n\n### 分支列表\n\n`git branch`\n\n### 创建分支\n\n`git branch 分支名`,并不会自动切换到分支\n\n### 切换分支\n\n> !! 最佳实践每次切换分之前git status 查一下,当前分支一定要是干净的\n\n`git checkout 分支名`\n\n### 合并分支\n\n> !! 做任何事情,确保做完了,再合并到 master 分支\n\n场景需要增加功能`feat:#53`\n\n```bash\n# HEAD -> master新开一个分支\ngit checkout -b 'feat53'\n```\n\n突然发现 bug需要修复`bug:#52`\n\n```bash\n# HEAD -> feat53先提交#53分支的工作\ngit commit -a -m 'feat53 完成50%'\n# 切回 master 分支\ngit checkout master\n# HEAD -> master创建 issue52 分支\ngit checkout -b 'issue52'\n# 改完了issue52\ngit commit -a -m 'fix:issue52'\n# HEAD -> master\ngit checkout master\n# 合\ngit merge issue52\n# 删除 issue52分支(hash还在)\ngit branch -d issue52\n```\n\n> 此时,由于`issue52`是在之前的 master 分支上生成的,故而`feat53`的分支仍然存在`issue52`的 bug所以有可能存在冲突需要手动解决\n\n```bash\n# HEAD -> master\ngit merge feat53\n# 此处省略解决冲突\ngit add ./\ngit commit -m 'fix:merge conflict'\n# 删除 feat53\ngit branch -d feat53\n```\n\n### 删除分支\n\n查看哪些分支合并到当前分支`git branch --merged`,这个列表中分支名字前没有\\*号的分支通常可以使用`git branch -d 分支名`删掉\n\n`git branch -D 分支名`,强制删除\n\n### 新建分支并指向指定提交对象\n\n`git branch name commitHash`,例`git log --oneline`如下:\n\n```bash\n* hasfh2asd 1.txt\n* 1shfd2zsw 2.txt\n* 67rf73has 3.txt\n* 03uhr4rug 4.txt\n```\n\n输入`git branch CCC 03uhr4rug`,那么会创建一个名为`CCC`的分支,并且`CCC`分支有`4.txt`\n\n> 通常想看原来的某个版本的代码,就可以这样操作,看完,把这个分支删了\n\n### 远程分支\n\n> `git clone`下来的分支,默认就会建立一个`远程跟踪分支`(同步关系),例如 master 分支\n\n- 本地分支\n\n场景一如果想公开一个`share`分支 ,与他人共同写作:\n\n```bash\n# 过程中会生成生成一个远程跟踪分支 origin/share\ngit push origin share\n```\n\n场景二创建一个本地分支`b1`,直接跟踪远程分支`orgin/b1`\n\n```bash\ngit checkout -b 'b1' 'origin/b1'\n```\n\n场景三已存在一个本地分支`dev`,改成远程跟踪分支\n\n```bash\n# HEAD -> dev建立 本地分支 dev 与 远程分支 origin/dev 关系\ngit branch -u origin/dev\n# 这样就可以直接\ngit push / git pull\n```\n\n- 远程分支\n\n查看远程分支`git remote -v`\n\n查看当前本地分支的远程跟踪分支`git branch -vv`\n\n## 远程分支删除, 本地更新 --prune\n\n```bash\n# 不加 --prune和 fetch 等价, 远程被删除的分支不会同步删除本地origin的分支\ngit remote update origin --prune\n```\n\n# 提交规范\n\n```bash\ntype(scope): subject\n# 例如\nfeat(miniprogram): 增加了小程序模板消息相关功能\n```\n\n通常`type`有如下:\n\n- feat - 新功能 feature\n- fix - 修复 bug\n- docs - 文档注释\n- style - 代码格式(不影响代码运行的变动)\n- refactor - 重构、优化(既不增加新功能,也不是修复 bug)\n- perf - 性能优化\n- test - 增加测试\n- chore - 构建过程或辅助工具的变动\n- revert - 回退\n- build - 打包\n\n## 自动生成 Change log\n\n原理利用 `child_process`获取 `git log`内容,处理字符串\n\n```js\nconst execSync = require(\"child_process\").execSync; //同步子进程\nconst fs = require(\"fs\");\nconst process = require(\"process\");\nconst path = require(\"path\");\nconst inquirer = require(\"inquirer\");\nconst dayjs = require(\"dayjs\");\nconst axios = require(\"axios\");\n\n// env\nconst isForCommanHuman = process.argv.includes(\"--common\");\n\n// changelog.md生成路径\nconst outputpath = path.resolve(process.cwd(), \"./changelog.md\");\n// 非空检测\nif (!fs.existsSync(outputpath)) fs.writeFile(outputpath, \"\", (err) => {});\n// 华丽的gitlog日志\nconst perfectGitLog = (startTime, endTime) =>\n isForCommanHuman\n ? `git log --since=\"${startTime}\" --until=\"${endTime}\" --no-merges --pretty=format:\"%cr %C(cyan)%s\"`\n : `git log --since=\"${startTime}\" --until=\"${endTime}\" --no-merges --pretty=format:\"%C(yellow)%h %C(green)%cn %C(redz)(%cr:%ci) %C(cyan)%s\"`;\n\nconst wxrobotHook =\n \"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=be4d4473-c290-4ddd-a089-41df3ed1d601\";\n\n// 当前时间\nconst now = Date.now();\n// 2周前\nconst weeks_2_ago = now - 14 * 24 * 60 * 60 * 1000;\n\ninquirer\n .prompt([\n {\n type: \"input\",\n name: \"startDate\",\n message: `起始时间,默认13天前 \\n`,\n default: dayjs(weeks_2_ago).format(\"YYYY.MM.DD\"),\n validate: (val) => /\\d{4}.\\d{2}.\\d{2}/.test(val),\n },\n {\n type: \"input\",\n name: \"endDate\",\n message: `结束时间,默认今天 \\n`,\n default: dayjs(now).format(\"YYYY.MM.DD\"),\n validate: (val) => /\\d{4}.\\d{2}.\\d{2}/.test(val),\n },\n {\n type: \"rawlist\",\n message: \"是否通知到微信机器人:\",\n name: \"notifyWxrobot\",\n choices: [\"Y\", \"N\"],\n },\n ])\n .then((answers) => {\n const { startDate, endDate, notifyWxrobot } = answers;\n const rowTemplate = perfectGitLog(startDate, endDate);\n let fmt = execSync(rowTemplate)\n .toString()\n .trim()\n .replace(/feat: /gi, \"✅: \")\n .replace(/fix: /gi, \"🐛: \")\n .replace(/chore: /gi, \"🎨: \")\n .replace(/perf: /gi, \"⚡: \")\n .replace(/docs: /gi, \"📝: \")\n .replace(/refactor: /gi, \"🔨: \")\n .replace(/anno: /gi, \"🔖: \")\n .replace(/style: /gi, \"👷: \");\n fs.writeFileSync(outputpath, fmt, (err) => {});\n // 通知微信群聊机器人\n if (notifyWxrobot === \"Y\") {\n axios.post(wxrobotHook, {\n msgtype: \"markdown\",\n markdown: {\n content: fmt,\n },\n });\n }\n })\n .catch((error) => {\n if (error.isTtyError) {\n // Prompt couldn't be rendered in the current environment\n } else {\n // Something else went wrong\n }\n });\n```\n\n## 使用 husky+eslint 规范提交\n\n> 需要配合 eslint\n\n`git init`后,`yarn add husky`,在`package.json`配置\n\n```json\n{\n \"husky\": {\n \"hooks\": {\n \"pre-commit\": \"npm run lint\"\n }\n }\n}\n```\n\n## 生成 ssh key\n\n```bash\nssh-keygen -t rsa -C \"himozzie@foxmail.com\"\n```\n\n## 查看 ssh 公钥\n\n```bash\ncat ~/.ssh/id_rsa.pub\n```\n\n# git 代理\n\n> 前提条件是开了扶墙工具\n\ngit clone 拉取方式选择 http/https(默认会让你输入账号密码,比较蛋疼),不要选择 ssl 拉取\n\n```bash\ngit config --global http.proxy 'http://127.0.0.1:1081'\ngit config --global https.proxy 'https://127.0.0.1:1081'\n# 清除\ngit config --global --unset http.proxy\ngit config --global --unset https.proxy\n```\n\n# 终端临时代理\n\n```bash\n# cmd临时代理方案cmd窗口关闭则代理失效\nset http_proxy=http://127.0.0.1:50015\nset https_proxy=http://127.0.0.1:50015\n```\n\n# git 钩子(hooks)\n\n原理:项目 git push 到远程仓库,远程仓库的钩子 post 通知 www/wwwroot 下的站点 pull 远程仓库\n\n> git 钩子需要 git 服务和 pull 在同一环境中\n\n- 创建远程仓库,配置钩子,git post-receive 钩子\n\n```bash\n#!/bin/bash\nunset $(git rev-parse --local-env-vars);\n# post-receive接收到pull指令后,执行bash命令\ncd /www/wwwroot/doc.mozzie.cn/ && git pull origin master\n```\n\n> web 目录下 doc.mozzie.cn 是网站目录,本地项目编译打包后,直接 git push 的目录\n\n## web 钩子\n\n待耍\n\n# 项目\n\n## 统计项目代码行数\n\n统计所有人代码增删量拷贝如下命令 git bash 终端git 项目某分支下执行\n\n```bash\ngit log --format='%aN' | sort -u | while read name; do echo -en \"$name\\t\"; git log --author=\"$name\" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc }' -; done\n\n```\n\n## 统计制定提交者代码量\n\n替换`username`为提交者的名称\n\n```bash\ngit log --author=\"username\" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc }' -\n```\n\n# 搭建 gogs\n\ngogs 官网下载,压缩包解压到`www/wwwroot/`下\n\n```bash\ncd /www/wwwroot/gogs\n# 启服务,默认3000的端口被占用则 ./gogs web -port 3001\n./gogs web\n```\n\n浏览器访问`http://yourip:3000/install`,注意服务器安全组放行 3000 端口\n\n- 为 gogs 添加 mysql 数据库\n- 配置 mysql\n- 配置 gogs 相关信息\n- 配置其他信息\n\n停掉`./gogs web`\n\n在刚安装的 gogs 路径下,找到`/gogs/scripts/systemd/gogs.service` 文件复制一份\n\n```bash\nUser=root\nGroup=root\nWorkingDirectory=/www/wwwroot/git.mozzie.cn\nExecStart=/www/wwwroot/git.mozzie.cn/gogs web\nRestart=always\nEnvironment=USER=root HOME=/www/wwwroot/git.mozzie.cn\n```\n\n将修改好的`gogs.service`文件上传到`/etc/systemd/system`下,并执行以下命令来激活 gogs\n\n```bash\nsudo systemctl enable gogs\n# 启动gogs\nsudo systemctl start gogs\n```\n\n`/gogs/custom/conf/app.ini`,修改该文件可以自定义配置,安装步骤填错了,可以这里修改,重启 gogs 服务即可\n\n## 配置 gogs GIT 钩子\n\n场景以 Gogs 为例,先 git push `A项目` 到远程仓库 `REPO`,服务端 web 目录`webB`文件夹触发钩子执行 git pull\n\n1、gogs 初始化一个仓库`REPO`,仓库设置=>管理 GIT 钩子=>post-receive填入\n\n```bash\n#!/bin/sh\nexport GIT_WORK_TREE=/www/wwwroot/webB\nexport GIT_DIR=${GIT_WORK_TREE}/.git\ncd ${GIT_WORK_TREE}\ngit pull\n```\n\n2、利用 ssh 工具登录服务器\n\n```bash\nssh root@mozzie.cn\n```\n\n3、生成 ssh key\n\n```bash\nssh-keygen -t rsa -C \"himozzie@foxmail.com\"\n```\n\n4、配置公钥到 gogs\n\n```bash\ncat ~/.ssh/id_rsa.pub\n```\n\n把打印出的公钥配置到 ssh 密钥\n\n5、最后一步\n\n配置好服务端的公钥后就可以无需用户名密码`cd /webB`目录下,执行`git pull`,此后每次`git push A项目`,服务端都会触发`GIT钩子`,自动从`REPO`拉取最新的仓库文件\n","source":"_posts/front-end/git.md","raw":"---\ntitle: Git\ncategories:\n - Front-End\nstatus: done\n---\n\n\n# GIT 最佳实践\n\nGIT 本质是一个数据库,用来存代码的\n\n- 工作区一个沙箱环境GIT 不负责管理,你尽管在沙箱里面对文件进行操作\n- 暂存区:`工作区`文件变动先不急着提交,暂存到一定数量,在提交到版本库\n- 版本库:\n\n> !! Linus 永远的神!\n\n## 配置用户\n\n```bash\ngit config --global user.name \"mozzie\"\ngit config --global user.email himozzie@foxmail.com\n```\n\n## alias 别名\n\n解决参数太多记不住的问题\n\n> !! HEAD -> master HEAD 相当于一个指针,指向当前所在分支\n\n```bash\n# 查看项目分支图,\ngit config --global alias.lo \"log --oneline --decorate --graph --all\"\n```\n\n## .git 文件结构\n\n- hooks提交代码前检查代码格式……\n- info包含一个排除性文件\n- logs保存日志信息不太需要\n- `objects`:相当于数据库,存储所有数据内容\n- `refs`:存放提交对象指针,管理分支的\n- config配置文件\n- description仓库描述信息\n- `HEAD`:指示目前被检出的分支\n- `index`:文件保存暂存区信息\n\n## 修改远程仓库\n\n```bash\n# way 1\ngit remote set-url origin [url]\n# way 2\ngit remote rm origin\ngit remote add origin [url]\n# way3\n修改 config 文件\n```\n\n## 高层命令\n\n### 初始化仓库\n\n`git init`\n\n### 修改添加到暂存区\n\n`git add ./`,相当于如下操作:\n\n```bash\n# 有多少文件改动,就执行多少次\ngit hash-object -w 文件名\ngit update-index\n```\n\n> !! git add ./ 先把工作区生成 git 对象,放到版本库,然后再放到暂存区\n\n### 暂存区提交到版本库\n\n`git commit -m 'comment'`,相当于如下操作:\n\n```bash\ngit write-tree\ngit commit-tree\n```\n\n也可以跳过暂存区提交`git commit -a -m `\n\n### 查看哪些修改没有暂存\n\n`git diff`:没有暂存\n\n`git diff --staged`:查看哪些修改以及被暂存了,但没有提交\n\n### 查看提交历史记录\n\n`git log --oneline`,打印出`hash值`是提交对象\n\n## 分支\n\n本质是一个`提交对象`,每次`git branch name`中的`name`,指针`HEAD`,就会根据`name`指向提交对象\n\n如果要开发新功能就新建一个`分支A`,写完再合`master`分支,正常来说`master`分支不会轻易给修改权限。\n\n如果另一个新功能和`分支A`同级、并行的,那就`切到master`分支,在`master`分支基础上,开`分支B`,进行新功能开发\n\n> 一般来说master 分支没有权限,需要自己重新写开一个分支,分支名用 nickname\n\n```bash\nC1 master\n|——C2——C3——C4 mozzie\n```\n\n### 分支列表\n\n`git branch`\n\n### 创建分支\n\n`git branch 分支名`,并不会自动切换到分支\n\n### 切换分支\n\n> !! 最佳实践每次切换分之前git status 查一下,当前分支一定要是干净的\n\n`git checkout 分支名`\n\n### 合并分支\n\n> !! 做任何事情,确保做完了,再合并到 master 分支\n\n场景需要增加功能`feat:#53`\n\n```bash\n# HEAD -> master新开一个分支\ngit checkout -b 'feat53'\n```\n\n突然发现 bug需要修复`bug:#52`\n\n```bash\n# HEAD -> feat53先提交#53分支的工作\ngit commit -a -m 'feat53 完成50%'\n# 切回 master 分支\ngit checkout master\n# HEAD -> master创建 issue52 分支\ngit checkout -b 'issue52'\n# 改完了issue52\ngit commit -a -m 'fix:issue52'\n# HEAD -> master\ngit checkout master\n# 合\ngit merge issue52\n# 删除 issue52分支(hash还在)\ngit branch -d issue52\n```\n\n> 此时,由于`issue52`是在之前的 master 分支上生成的,故而`feat53`的分支仍然存在`issue52`的 bug所以有可能存在冲突需要手动解决\n\n```bash\n# HEAD -> master\ngit merge feat53\n# 此处省略解决冲突\ngit add ./\ngit commit -m 'fix:merge conflict'\n# 删除 feat53\ngit branch -d feat53\n```\n\n### 删除分支\n\n查看哪些分支合并到当前分支`git branch --merged`,这个列表中分支名字前没有\\*号的分支通常可以使用`git branch -d 分支名`删掉\n\n`git branch -D 分支名`,强制删除\n\n### 新建分支并指向指定提交对象\n\n`git branch name commitHash`,例`git log --oneline`如下:\n\n```bash\n* hasfh2asd 1.txt\n* 1shfd2zsw 2.txt\n* 67rf73has 3.txt\n* 03uhr4rug 4.txt\n```\n\n输入`git branch CCC 03uhr4rug`,那么会创建一个名为`CCC`的分支,并且`CCC`分支有`4.txt`\n\n> 通常想看原来的某个版本的代码,就可以这样操作,看完,把这个分支删了\n\n### 远程分支\n\n> `git clone`下来的分支,默认就会建立一个`远程跟踪分支`(同步关系),例如 master 分支\n\n- 本地分支\n\n场景一如果想公开一个`share`分支 ,与他人共同写作:\n\n```bash\n# 过程中会生成生成一个远程跟踪分支 origin/share\ngit push origin share\n```\n\n场景二创建一个本地分支`b1`,直接跟踪远程分支`orgin/b1`\n\n```bash\ngit checkout -b 'b1' 'origin/b1'\n```\n\n场景三已存在一个本地分支`dev`,改成远程跟踪分支\n\n```bash\n# HEAD -> dev建立 本地分支 dev 与 远程分支 origin/dev 关系\ngit branch -u origin/dev\n# 这样就可以直接\ngit push / git pull\n```\n\n- 远程分支\n\n查看远程分支`git remote -v`\n\n查看当前本地分支的远程跟踪分支`git branch -vv`\n\n## 远程分支删除, 本地更新 --prune\n\n```bash\n# 不加 --prune和 fetch 等价, 远程被删除的分支不会同步删除本地origin的分支\ngit remote update origin --prune\n```\n\n# 提交规范\n\n```bash\ntype(scope): subject\n# 例如\nfeat(miniprogram): 增加了小程序模板消息相关功能\n```\n\n通常`type`有如下:\n\n- feat - 新功能 feature\n- fix - 修复 bug\n- docs - 文档注释\n- style - 代码格式(不影响代码运行的变动)\n- refactor - 重构、优化(既不增加新功能,也不是修复 bug)\n- perf - 性能优化\n- test - 增加测试\n- chore - 构建过程或辅助工具的变动\n- revert - 回退\n- build - 打包\n\n## 自动生成 Change log\n\n原理利用 `child_process`获取 `git log`内容,处理字符串\n\n```js\nconst execSync = require(\"child_process\").execSync; //同步子进程\nconst fs = require(\"fs\");\nconst process = require(\"process\");\nconst path = require(\"path\");\nconst inquirer = require(\"inquirer\");\nconst dayjs = require(\"dayjs\");\nconst axios = require(\"axios\");\n\n// env\nconst isForCommanHuman = process.argv.includes(\"--common\");\n\n// changelog.md生成路径\nconst outputpath = path.resolve(process.cwd(), \"./changelog.md\");\n// 非空检测\nif (!fs.existsSync(outputpath)) fs.writeFile(outputpath, \"\", (err) => {});\n// 华丽的gitlog日志\nconst perfectGitLog = (startTime, endTime) =>\n isForCommanHuman\n ? `git log --since=\"${startTime}\" --until=\"${endTime}\" --no-merges --pretty=format:\"%cr %C(cyan)%s\"`\n : `git log --since=\"${startTime}\" --until=\"${endTime}\" --no-merges --pretty=format:\"%C(yellow)%h %C(green)%cn %C(redz)(%cr:%ci) %C(cyan)%s\"`;\n\nconst wxrobotHook =\n \"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=be4d4473-c290-4ddd-a089-41df3ed1d601\";\n\n// 当前时间\nconst now = Date.now();\n// 2周前\nconst weeks_2_ago = now - 14 * 24 * 60 * 60 * 1000;\n\ninquirer\n .prompt([\n {\n type: \"input\",\n name: \"startDate\",\n message: `起始时间,默认13天前 \\n`,\n default: dayjs(weeks_2_ago).format(\"YYYY.MM.DD\"),\n validate: (val) => /\\d{4}.\\d{2}.\\d{2}/.test(val),\n },\n {\n type: \"input\",\n name: \"endDate\",\n message: `结束时间,默认今天 \\n`,\n default: dayjs(now).format(\"YYYY.MM.DD\"),\n validate: (val) => /\\d{4}.\\d{2}.\\d{2}/.test(val),\n },\n {\n type: \"rawlist\",\n message: \"是否通知到微信机器人:\",\n name: \"notifyWxrobot\",\n choices: [\"Y\", \"N\"],\n },\n ])\n .then((answers) => {\n const { startDate, endDate, notifyWxrobot } = answers;\n const rowTemplate = perfectGitLog(startDate, endDate);\n let fmt = execSync(rowTemplate)\n .toString()\n .trim()\n .replace(/feat: /gi, \"✅: \")\n .replace(/fix: /gi, \"🐛: \")\n .replace(/chore: /gi, \"🎨: \")\n .replace(/perf: /gi, \"⚡: \")\n .replace(/docs: /gi, \"📝: \")\n .replace(/refactor: /gi, \"🔨: \")\n .replace(/anno: /gi, \"🔖: \")\n .replace(/style: /gi, \"👷: \");\n fs.writeFileSync(outputpath, fmt, (err) => {});\n // 通知微信群聊机器人\n if (notifyWxrobot === \"Y\") {\n axios.post(wxrobotHook, {\n msgtype: \"markdown\",\n markdown: {\n content: fmt,\n },\n });\n }\n })\n .catch((error) => {\n if (error.isTtyError) {\n // Prompt couldn't be rendered in the current environment\n } else {\n // Something else went wrong\n }\n });\n```\n\n## 使用 husky+eslint 规范提交\n\n> 需要配合 eslint\n\n`git init`后,`yarn add husky`,在`package.json`配置\n\n```json\n{\n \"husky\": {\n \"hooks\": {\n \"pre-commit\": \"npm run lint\"\n }\n }\n}\n```\n\n## 生成 ssh key\n\n```bash\nssh-keygen -t rsa -C \"himozzie@foxmail.com\"\n```\n\n## 查看 ssh 公钥\n\n```bash\ncat ~/.ssh/id_rsa.pub\n```\n\n# git 代理\n\n> 前提条件是开了扶墙工具\n\ngit clone 拉取方式选择 http/https(默认会让你输入账号密码,比较蛋疼),不要选择 ssl 拉取\n\n```bash\ngit config --global http.proxy 'http://127.0.0.1:1081'\ngit config --global https.proxy 'https://127.0.0.1:1081'\n# 清除\ngit config --global --unset http.proxy\ngit config --global --unset https.proxy\n```\n\n# 终端临时代理\n\n```bash\n# cmd临时代理方案cmd窗口关闭则代理失效\nset http_proxy=http://127.0.0.1:50015\nset https_proxy=http://127.0.0.1:50015\n```\n\n# git 钩子(hooks)\n\n原理:项目 git push 到远程仓库,远程仓库的钩子 post 通知 www/wwwroot 下的站点 pull 远程仓库\n\n> git 钩子需要 git 服务和 pull 在同一环境中\n\n- 创建远程仓库,配置钩子,git post-receive 钩子\n\n```bash\n#!/bin/bash\nunset $(git rev-parse --local-env-vars);\n# post-receive接收到pull指令后,执行bash命令\ncd /www/wwwroot/doc.mozzie.cn/ && git pull origin master\n```\n\n> web 目录下 doc.mozzie.cn 是网站目录,本地项目编译打包后,直接 git push 的目录\n\n## web 钩子\n\n待耍\n\n# 项目\n\n## 统计项目代码行数\n\n统计所有人代码增删量拷贝如下命令 git bash 终端git 项目某分支下执行\n\n```bash\ngit log --format='%aN' | sort -u | while read name; do echo -en \"$name\\t\"; git log --author=\"$name\" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc }' -; done\n\n```\n\n## 统计制定提交者代码量\n\n替换`username`为提交者的名称\n\n```bash\ngit log --author=\"username\" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc }' -\n```\n\n# 搭建 gogs\n\ngogs 官网下载,压缩包解压到`www/wwwroot/`下\n\n```bash\ncd /www/wwwroot/gogs\n# 启服务,默认3000的端口被占用则 ./gogs web -port 3001\n./gogs web\n```\n\n浏览器访问`http://yourip:3000/install`,注意服务器安全组放行 3000 端口\n\n- 为 gogs 添加 mysql 数据库\n- 配置 mysql\n- 配置 gogs 相关信息\n- 配置其他信息\n\n停掉`./gogs web`\n\n在刚安装的 gogs 路径下,找到`/gogs/scripts/systemd/gogs.service` 文件复制一份\n\n```bash\nUser=root\nGroup=root\nWorkingDirectory=/www/wwwroot/git.mozzie.cn\nExecStart=/www/wwwroot/git.mozzie.cn/gogs web\nRestart=always\nEnvironment=USER=root HOME=/www/wwwroot/git.mozzie.cn\n```\n\n将修改好的`gogs.service`文件上传到`/etc/systemd/system`下,并执行以下命令来激活 gogs\n\n```bash\nsudo systemctl enable gogs\n# 启动gogs\nsudo systemctl start gogs\n```\n\n`/gogs/custom/conf/app.ini`,修改该文件可以自定义配置,安装步骤填错了,可以这里修改,重启 gogs 服务即可\n\n## 配置 gogs GIT 钩子\n\n场景以 Gogs 为例,先 git push `A项目` 到远程仓库 `REPO`,服务端 web 目录`webB`文件夹触发钩子执行 git pull\n\n1、gogs 初始化一个仓库`REPO`,仓库设置=>管理 GIT 钩子=>post-receive填入\n\n```bash\n#!/bin/sh\nexport GIT_WORK_TREE=/www/wwwroot/webB\nexport GIT_DIR=${GIT_WORK_TREE}/.git\ncd ${GIT_WORK_TREE}\ngit pull\n```\n\n2、利用 ssh 工具登录服务器\n\n```bash\nssh root@mozzie.cn\n```\n\n3、生成 ssh key\n\n```bash\nssh-keygen -t rsa -C \"himozzie@foxmail.com\"\n```\n\n4、配置公钥到 gogs\n\n```bash\ncat ~/.ssh/id_rsa.pub\n```\n\n把打印出的公钥配置到 ssh 密钥\n\n5、最后一步\n\n配置好服务端的公钥后就可以无需用户名密码`cd /webB`目录下,执行`git pull`,此后每次`git push A项目`,服务端都会触发`GIT钩子`,自动从`REPO`拉取最新的仓库文件\n","slug":"front-end/git","published":1,"date":"2023-11-06T08:01:46.362Z","updated":"2023-11-06T08:02:34.511Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58o000e4cz3ffa9d2ke","content":"<h1 id=\"GIT-最佳实践\"><a href=\"#GIT-最佳实践\" class=\"headerlink\" title=\"GIT 最佳实践\"></a>GIT 最佳实践</h1><p>GIT 本质是一个数据库,用来存代码的</p>\n<ul>\n<li>工作区一个沙箱环境GIT 不负责管理,你尽管在沙箱里面对文件进行操作</li>\n<li>暂存区:<code>工作区</code>文件变动先不急着提交,暂存到一定数量,在提交到版本库</li>\n<li>版本库:</li>\n</ul>\n<blockquote>\n<p>!! Linus 永远的神!</p>\n</blockquote>\n<h2 id=\"配置用户\"><a href=\"#配置用户\" class=\"headerlink\" title=\"配置用户\"></a>配置用户</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> user.name <span class=\"token string\">\"mozzie\"</span>\n<span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> user.email himozzie@foxmail.com<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"alias-别名\"><a href=\"#alias-别名\" class=\"headerlink\" title=\"alias 别名\"></a>alias 别名</h2><p>解决参数太多,记不住的问题</p>\n<blockquote>\n<p>!! HEAD -&gt; master HEAD 相当于一个指针,指向当前所在分支</p>\n</blockquote>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 查看项目分支图,</span>\n<span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> alias.lo <span class=\"token string\">\"log --oneline --decorate --graph --all\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"git-文件结构\"><a href=\"#git-文件结构\" class=\"headerlink\" title=\".git 文件结构\"></a>.git 文件结构</h2><ul>\n<li>hooks提交代码前检查代码格式……</li>\n<li>info包含一个排除性文件</li>\n<li>logs保存日志信息不太需要</li>\n<li><code>objects</code>:相当于数据库,存储所有数据内容</li>\n<li><code>refs</code>:存放提交对象指针,管理分支的</li>\n<li>config配置文件</li>\n<li>description仓库描述信息</li>\n<li><code>HEAD</code>:指示目前被检出的分支</li>\n<li><code>index</code>:文件保存暂存区信息</li>\n</ul>\n<h2 id=\"修改远程仓库\"><a href=\"#修改远程仓库\" class=\"headerlink\" title=\"修改远程仓库\"></a>修改远程仓库</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># way 1</span>\n<span class=\"token function\">git</span> remote set-url origin <span class=\"token punctuation\">[</span>url<span class=\"token punctuation\">]</span>\n<span class=\"token comment\"># way 2</span>\n<span class=\"token function\">git</span> remote <span class=\"token function\">rm</span> origin\n<span class=\"token function\">git</span> remote <span class=\"token function\">add</span> origin <span class=\"token punctuation\">[</span>url<span class=\"token punctuation\">]</span>\n<span class=\"token comment\"># way3</span>\n修改 config 文件<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"高层命令\"><a href=\"#高层命令\" class=\"headerlink\" title=\"高层命令\"></a>高层命令</h2><h3 id=\"初始化仓库\"><a href=\"#初始化仓库\" class=\"headerlink\" title=\"初始化仓库\"></a>初始化仓库</h3><p><code>git init</code></p>\n<h3 id=\"修改添加到暂存区\"><a href=\"#修改添加到暂存区\" class=\"headerlink\" title=\"修改添加到暂存区\"></a>修改添加到暂存区</h3><p><code>git add ./</code>,相当于如下操作:</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 有多少文件改动,就执行多少次</span>\n<span class=\"token function\">git</span> hash-object <span class=\"token parameter variable\">-w</span> 文件名\n<span class=\"token function\">git</span> update-index<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>!! git add .&#x2F; 先把工作区生成 git 对象,放到版本库,然后再放到暂存区</p>\n</blockquote>\n<h3 id=\"暂存区提交到版本库\"><a href=\"#暂存区提交到版本库\" class=\"headerlink\" title=\"暂存区提交到版本库\"></a>暂存区提交到版本库</h3><p><code>git commit -m &#39;comment&#39;</code>,相当于如下操作:</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> write-tree\n<span class=\"token function\">git</span> commit-tree<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<p>也可以跳过暂存区提交,<code>git commit -a -m </code></p>\n<h3 id=\"查看哪些修改没有暂存\"><a href=\"#查看哪些修改没有暂存\" class=\"headerlink\" title=\"查看哪些修改没有暂存\"></a>查看哪些修改没有暂存</h3><p><code>git diff</code>:没有暂存</p>\n<p><code>git diff --staged</code>:查看哪些修改以及被暂存了,但没有提交</p>\n<h3 id=\"查看提交历史记录\"><a href=\"#查看提交历史记录\" class=\"headerlink\" title=\"查看提交历史记录\"></a>查看提交历史记录</h3><p><code>git log --oneline</code>,打印出<code>hash值</code>是提交对象</p>\n<h2 id=\"分支\"><a href=\"#分支\" class=\"headerlink\" title=\"分支\"></a>分支</h2><p>本质是一个<code>提交对象</code>,每次<code>git branch name</code>中的<code>name</code>,指针<code>HEAD</code>,就会根据<code>name</code>指向提交对象</p>\n<p>如果要开发新功能,就新建一个<code>分支A</code>,写完再合<code>master</code>分支,正常来说<code>master</code>分支不会轻易给修改权限。</p>\n<p>如果另一个新功能,和<code>分支A</code>同级、并行的,那就<code>切到master</code>分支,在<code>master</code>分支基础上,开<code>分支B</code>,进行新功能开发</p>\n<blockquote>\n<p>一般来说master 分支没有权限,需要自己重新写开一个分支,分支名用 nickname</p>\n</blockquote>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">C1 master\n<span class=\"token operator\">|</span>——C2——C3——C4 mozzie<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h3 id=\"分支列表\"><a href=\"#分支列表\" class=\"headerlink\" title=\"分支列表\"></a>分支列表</h3><p><code>git branch</code></p>\n<h3 id=\"创建分支\"><a href=\"#创建分支\" class=\"headerlink\" title=\"创建分支\"></a>创建分支</h3><p><code>git branch 分支名</code>,并不会自动切换到分支</p>\n<h3 id=\"切换分支\"><a href=\"#切换分支\" class=\"headerlink\" title=\"切换分支\"></a>切换分支</h3><blockquote>\n<p>!! 最佳实践每次切换分之前git status 查一下,当前分支一定要是干净的</p>\n</blockquote>\n<p><code>git checkout 分支名</code></p>\n<h3 id=\"合并分支\"><a href=\"#合并分支\" class=\"headerlink\" title=\"合并分支\"></a>合并分支</h3><blockquote>\n<p>!! 做任何事情,确保做完了,再合并到 master 分支</p>\n</blockquote>\n<p>场景:需要增加功能<code>feat:#53</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># HEAD -> master新开一个分支</span>\n<span class=\"token function\">git</span> checkout <span class=\"token parameter variable\">-b</span> <span class=\"token string\">'feat53'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<p>突然发现 bug需要修复<code>bug:#52</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># HEAD -> feat53先提交#53分支的工作</span>\n<span class=\"token function\">git</span> commit <span class=\"token parameter variable\">-a</span> <span class=\"token parameter variable\">-m</span> <span class=\"token string\">'feat53 完成50%'</span>\n<span class=\"token comment\"># 切回 master 分支</span>\n<span class=\"token function\">git</span> checkout master\n<span class=\"token comment\"># HEAD -> master创建 issue52 分支</span>\n<span class=\"token function\">git</span> checkout <span class=\"token parameter variable\">-b</span> <span class=\"token string\">'issue52'</span>\n<span class=\"token comment\"># 改完了issue52</span>\n<span class=\"token function\">git</span> commit <span class=\"token parameter variable\">-a</span> <span class=\"token parameter variable\">-m</span> <span class=\"token string\">'fix:issue52'</span>\n<span class=\"token comment\"># HEAD -> master</span>\n<span class=\"token function\">git</span> checkout master\n<span class=\"token comment\"># 合</span>\n<span class=\"token function\">git</span> merge issue52\n<span class=\"token comment\"># 删除 issue52分支(hash还在)</span>\n<span class=\"token function\">git</span> branch <span class=\"token parameter variable\">-d</span> issue52<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>此时,由于<code>issue52</code>是在之前的 master 分支上生成的,故而<code>feat53</code>的分支仍然存在<code>issue52</code>的 bug所以有可能存在冲突需要手动解决</p>\n</blockquote>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># HEAD -> master</span>\n<span class=\"token function\">git</span> merge feat53\n<span class=\"token comment\"># 此处省略解决冲突</span>\n<span class=\"token function\">git</span> <span class=\"token function\">add</span> ./\n<span class=\"token function\">git</span> commit <span class=\"token parameter variable\">-m</span> <span class=\"token string\">'fix:merge conflict'</span>\n<span class=\"token comment\"># 删除 feat53</span>\n<span class=\"token function\">git</span> branch <span class=\"token parameter variable\">-d</span> feat53<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h3 id=\"删除分支\"><a href=\"#删除分支\" class=\"headerlink\" title=\"删除分支\"></a>删除分支</h3><p>查看哪些分支合并到当前分支,<code>git branch --merged</code>,这个列表中分支名字前没有*号的分支通常可以使用<code>git branch -d 分支名</code>删掉</p>\n<p><code>git branch -D 分支名</code>,强制删除</p>\n<h3 id=\"新建分支并指向指定提交对象\"><a href=\"#新建分支并指向指定提交对象\" class=\"headerlink\" title=\"新建分支并指向指定提交对象\"></a>新建分支并指向指定提交对象</h3><p><code>git branch name commitHash</code>,例<code>git log --oneline</code>如下:</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">* hasfh2asd <span class=\"token number\">1</span>.txt\n* 1shfd2zsw <span class=\"token number\">2</span>.txt\n* 67rf73has <span class=\"token number\">3</span>.txt\n* 03uhr4rug <span class=\"token number\">4</span>.txt<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>输入<code>git branch CCC 03uhr4rug</code>,那么会创建一个名为<code>CCC</code>的分支,并且<code>CCC</code>分支有<code>4.txt</code></p>\n<blockquote>\n<p>通常想看原来的某个版本的代码,就可以这样操作,看完,把这个分支删了</p>\n</blockquote>\n<h3 id=\"远程分支\"><a href=\"#远程分支\" class=\"headerlink\" title=\"远程分支\"></a>远程分支</h3><blockquote>\n<p><code>git clone</code>下来的分支,默认就会建立一个<code>远程跟踪分支</code>(同步关系),例如 master 分支</p>\n</blockquote>\n<ul>\n<li>本地分支</li>\n</ul>\n<p>场景一:如果想公开一个<code>share</code>分支 ,与他人共同写作:</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 过程中会生成生成一个远程跟踪分支 origin/share</span>\n<span class=\"token function\">git</span> push origin share<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<p>场景二:创建一个本地分支<code>b1</code>,直接跟踪远程分支<code>orgin/b1</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> checkout <span class=\"token parameter variable\">-b</span> <span class=\"token string\">'b1'</span> <span class=\"token string\">'origin/b1'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>场景三:已存在一个本地分支<code>dev</code>,改成远程跟踪分支</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># HEAD -> dev建立 本地分支 dev 与 远程分支 origin/dev 关系</span>\n<span class=\"token function\">git</span> branch <span class=\"token parameter variable\">-u</span> origin/dev\n<span class=\"token comment\"># 这样就可以直接</span>\n<span class=\"token function\">git</span> push / <span class=\"token function\">git</span> pull<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<ul>\n<li>远程分支</li>\n</ul>\n<p>查看远程分支:<code>git remote -v</code></p>\n<p>查看当前本地分支的远程跟踪分支:<code>git branch -vv</code></p>\n<h2 id=\"远程分支删除-本地更新-prune\"><a href=\"#远程分支删除-本地更新-prune\" class=\"headerlink\" title=\"远程分支删除, 本地更新 prune\"></a>远程分支删除, 本地更新 prune</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 不加 --prune和 fetch 等价, 远程被删除的分支不会同步删除本地origin的分支</span>\n<span class=\"token function\">git</span> remote update origin <span class=\"token parameter variable\">--prune</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"提交规范\"><a href=\"#提交规范\" class=\"headerlink\" title=\"提交规范\"></a>提交规范</h1><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">type<span class=\"token punctuation\">(</span>scope<span class=\"token punctuation\">)</span>: subject\n<span class=\"token comment\"># 例如</span>\nfeat<span class=\"token punctuation\">(</span>miniprogram<span class=\"token punctuation\">)</span>: 增加了小程序模板消息相关功能<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>通常<code>type</code>有如下:</p>\n<ul>\n<li>feat - 新功能 feature</li>\n<li>fix - 修复 bug</li>\n<li>docs - 文档注释</li>\n<li>style - 代码格式(不影响代码运行的变动)</li>\n<li>refactor - 重构、优化(既不增加新功能,也不是修复 bug)</li>\n<li>perf - 性能优化</li>\n<li>test - 增加测试</li>\n<li>chore - 构建过程或辅助工具的变动</li>\n<li>revert - 回退</li>\n<li>build - 打包</li>\n</ul>\n<h2 id=\"自动生成-Change-log\"><a href=\"#自动生成-Change-log\" class=\"headerlink\" title=\"自动生成 Change log\"></a>自动生成 Change log</h2><p>原理:利用 <code>child_process</code>获取 <code>git log</code>内容,处理字符串</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> execSync <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"child_process\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>execSync<span class=\"token punctuation\">;</span> <span class=\"token comment\">//同步子进程</span>\n<span class=\"token keyword\">const</span> fs <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"fs\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> process <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"process\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> path <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"path\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> inquirer <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"inquirer\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> dayjs <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"dayjs\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> axios <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"axios\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// env</span>\n<span class=\"token keyword\">const</span> isForCommanHuman <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>argv<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"--common\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// changelog.md生成路径</span>\n<span class=\"token keyword\">const</span> outputpath <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span>process<span class=\"token punctuation\">.</span><span class=\"token function\">cwd</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"./changelog.md\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 非空检测</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>fs<span class=\"token punctuation\">.</span><span class=\"token function\">existsSync</span><span class=\"token punctuation\">(</span>outputpath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> fs<span class=\"token punctuation\">.</span><span class=\"token function\">writeFile</span><span class=\"token punctuation\">(</span>outputpath<span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">err</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 华丽的gitlog日志</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">perfectGitLog</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">startTime<span class=\"token punctuation\">,</span> endTime</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n isForCommanHuman\n <span class=\"token operator\">?</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">git log --since=\"</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>startTime<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">\" --until=\"</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>endTime<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">\" --no-merges --pretty=format:\"%cr %C(cyan)%s\"</span><span class=\"token template-punctuation string\">`</span></span>\n <span class=\"token operator\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">git log --since=\"</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>startTime<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">\" --until=\"</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>endTime<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">\" --no-merges --pretty=format:\"%C(yellow)%h %C(green)%cn %C(redz)(%cr:%ci) %C(cyan)%s\"</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> wxrobotHook <span class=\"token operator\">=</span>\n <span class=\"token string\">\"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=be4d4473-c290-4ddd-a089-41df3ed1d601\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 当前时间</span>\n<span class=\"token keyword\">const</span> now <span class=\"token operator\">=</span> Date<span class=\"token punctuation\">.</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 2周前</span>\n<span class=\"token keyword\">const</span> weeks_2_ago <span class=\"token operator\">=</span> now <span class=\"token operator\">-</span> <span class=\"token number\">14</span> <span class=\"token operator\">*</span> <span class=\"token number\">24</span> <span class=\"token operator\">*</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">;</span>\n\ninquirer\n <span class=\"token punctuation\">.</span><span class=\"token function\">prompt</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">type</span><span class=\"token operator\">:</span> <span class=\"token string\">\"input\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"startDate\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">message</span><span class=\"token operator\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">起始时间,默认13天前 \\n</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span>\n <span class=\"token keyword\">default</span><span class=\"token operator\">:</span> <span class=\"token function\">dayjs</span><span class=\"token punctuation\">(</span>weeks_2_ago<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"YYYY.MM.DD\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">validate</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">val</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">\\d&#123;4&#125;.\\d&#123;2&#125;.\\d&#123;2&#125;</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">.</span><span class=\"token function\">test</span><span class=\"token punctuation\">(</span>val<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">type</span><span class=\"token operator\">:</span> <span class=\"token string\">\"input\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"endDate\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">message</span><span class=\"token operator\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">结束时间,默认今天 \\n</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span>\n <span class=\"token keyword\">default</span><span class=\"token operator\">:</span> <span class=\"token function\">dayjs</span><span class=\"token punctuation\">(</span>now<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"YYYY.MM.DD\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">validate</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">val</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">\\d&#123;4&#125;.\\d&#123;2&#125;.\\d&#123;2&#125;</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">.</span><span class=\"token function\">test</span><span class=\"token punctuation\">(</span>val<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">type</span><span class=\"token operator\">:</span> <span class=\"token string\">\"rawlist\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">message</span><span class=\"token operator\">:</span> <span class=\"token string\">\"是否通知到微信机器人:\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"notifyWxrobot\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">choices</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"Y\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"N\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">answers</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> <span class=\"token punctuation\">&#123;</span> startDate<span class=\"token punctuation\">,</span> endDate<span class=\"token punctuation\">,</span> notifyWxrobot <span class=\"token punctuation\">&#125;</span> <span class=\"token operator\">=</span> answers<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">const</span> rowTemplate <span class=\"token operator\">=</span> <span class=\"token function\">perfectGitLog</span><span class=\"token punctuation\">(</span>startDate<span class=\"token punctuation\">,</span> endDate<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> fmt <span class=\"token operator\">=</span> <span class=\"token function\">execSync</span><span class=\"token punctuation\">(</span>rowTemplate<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">trim</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">feat: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"✅: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">fix: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"🐛: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">chore: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"🎨: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">perf: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"⚡: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">docs: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"📝: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">refactor: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"🔨: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">anno: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"🔖: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">style: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"👷: \"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n fs<span class=\"token punctuation\">.</span><span class=\"token function\">writeFileSync</span><span class=\"token punctuation\">(</span>outputpath<span class=\"token punctuation\">,</span> fmt<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">err</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 通知微信群聊机器人</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>notifyWxrobot <span class=\"token operator\">===</span> <span class=\"token string\">\"Y\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n axios<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span>wxrobotHook<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">msgtype</span><span class=\"token operator\">:</span> <span class=\"token string\">\"markdown\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">markdown</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> fmt<span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">catch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">error</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">.</span>isTtyError<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// Prompt couldn't be rendered in the current environment</span>\n <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// Something else went wrong</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"使用-husky-eslint-规范提交\"><a href=\"#使用-husky-eslint-规范提交\" class=\"headerlink\" title=\"使用 husky+eslint 规范提交\"></a>使用 husky+eslint 规范提交</h2><blockquote>\n<p>需要配合 eslint</p>\n</blockquote>\n<p><code>git init</code>后,<code>yarn add husky</code>,在<code>package.json</code>配置</p>\n<pre class=\"line-numbers language-json\" data-language=\"json\"><code class=\"language-json\"><span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">\"husky\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">\"hooks\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">\"pre-commit\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npm run lint\"</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"生成-ssh-key\"><a href=\"#生成-ssh-key\" class=\"headerlink\" title=\"生成 ssh key\"></a>生成 ssh key</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">ssh-keygen <span class=\"token parameter variable\">-t</span> rsa <span class=\"token parameter variable\">-C</span> <span class=\"token string\">\"himozzie@foxmail.com\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"查看-ssh-公钥\"><a href=\"#查看-ssh-公钥\" class=\"headerlink\" title=\"查看 ssh 公钥\"></a>查看 ssh 公钥</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">cat</span> ~/.ssh/id_rsa.pub<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h1 id=\"git-代理\"><a href=\"#git-代理\" class=\"headerlink\" title=\"git 代理\"></a>git 代理</h1><blockquote>\n<p>前提条件是开了扶墙工具</p>\n</blockquote>\n<p>git clone 拉取方式选择 http&#x2F;https(默认会让你输入账号密码,比较蛋疼),不要选择 ssl 拉取</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> http.proxy <span class=\"token string\">'http://127.0.0.1:1081'</span>\n<span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> https.proxy <span class=\"token string\">'https://127.0.0.1:1081'</span>\n<span class=\"token comment\"># 清除</span>\n<span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> <span class=\"token parameter variable\">--unset</span> http.proxy\n<span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> <span class=\"token parameter variable\">--unset</span> https.proxy<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"终端临时代理\"><a href=\"#终端临时代理\" class=\"headerlink\" title=\"终端临时代理\"></a>终端临时代理</h1><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># cmd临时代理方案cmd窗口关闭则代理失效</span>\n<span class=\"token builtin class-name\">set</span> <span class=\"token assign-left variable\">http_proxy</span><span class=\"token operator\">=</span>http://127.0.0.1:50015\n<span class=\"token builtin class-name\">set</span> <span class=\"token assign-left variable\">https_proxy</span><span class=\"token operator\">=</span>http://127.0.0.1:50015<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"git-钩子-hooks\"><a href=\"#git-钩子-hooks\" class=\"headerlink\" title=\"git 钩子(hooks)\"></a>git 钩子(hooks)</h1><p>原理:项目 git push 到远程仓库,远程仓库的钩子 post 通知 www&#x2F;wwwroot 下的站点 pull 远程仓库</p>\n<blockquote>\n<p>git 钩子需要 git 服务和 pull 在同一环境中</p>\n</blockquote>\n<ul>\n<li>创建远程仓库,配置钩子,git post-receive 钩子</li>\n</ul>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token shebang important\">#!/bin/bash</span>\n<span class=\"token builtin class-name\">unset</span> <span class=\"token variable\"><span class=\"token variable\">$(</span><span class=\"token function\">git</span> rev-parse --local-env-vars<span class=\"token variable\">)</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\"># post-receive接收到pull指令后,执行bash命令</span>\n<span class=\"token builtin class-name\">cd</span> /www/wwwroot/doc.mozzie.cn/ <span class=\"token operator\">&amp;&amp;</span> <span class=\"token function\">git</span> pull origin master<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>web 目录下 doc.mozzie.cn 是网站目录,本地项目编译打包后,直接 git push 的目录</p>\n</blockquote>\n<h2 id=\"web-钩子\"><a href=\"#web-钩子\" class=\"headerlink\" title=\"web 钩子\"></a>web 钩子</h2><p>待耍</p>\n<h1 id=\"项目\"><a href=\"#项目\" class=\"headerlink\" title=\"项目\"></a>项目</h1><h2 id=\"统计项目代码行数\"><a href=\"#统计项目代码行数\" class=\"headerlink\" title=\"统计项目代码行数\"></a>统计项目代码行数</h2><p>统计所有人代码增删量,拷贝如下命令, git bash 终端git 项目某分支下执行</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> log <span class=\"token parameter variable\">--format</span><span class=\"token operator\">=</span><span class=\"token string\">'%aN'</span> <span class=\"token operator\">|</span> <span class=\"token function\">sort</span> <span class=\"token parameter variable\">-u</span> <span class=\"token operator\">|</span> <span class=\"token keyword\">while</span> <span class=\"token builtin class-name\">read</span> name<span class=\"token punctuation\">;</span> <span class=\"token keyword\">do</span> <span class=\"token builtin class-name\">echo</span> <span class=\"token parameter variable\">-en</span> <span class=\"token string\">\"<span class=\"token variable\">$name</span><span class=\"token entity\" title=\"\\t\">\\t</span>\"</span><span class=\"token punctuation\">;</span> <span class=\"token function\">git</span> log <span class=\"token parameter variable\">--author</span><span class=\"token operator\">=</span><span class=\"token string\">\"<span class=\"token variable\">$name</span>\"</span> <span class=\"token parameter variable\">--pretty</span><span class=\"token operator\">=</span>tformat: <span class=\"token parameter variable\">--numstat</span> <span class=\"token operator\">|</span> <span class=\"token function\">awk</span> <span class=\"token string\">'&#123; add += $1; subs += $2; loc += $1 - $2 &#125; END &#123; printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc &#125;'</span> -<span class=\"token punctuation\">;</span> <span class=\"token keyword\">done</span>\n<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"统计制定提交者代码量\"><a href=\"#统计制定提交者代码量\" class=\"headerlink\" title=\"统计制定提交者代码量\"></a>统计制定提交者代码量</h2><p>替换<code>username</code>为提交者的名称</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> log <span class=\"token parameter variable\">--author</span><span class=\"token operator\">=</span><span class=\"token string\">\"username\"</span> <span class=\"token parameter variable\">--pretty</span><span class=\"token operator\">=</span>tformat: <span class=\"token parameter variable\">--numstat</span> <span class=\"token operator\">|</span> <span class=\"token function\">awk</span> <span class=\"token string\">'&#123; add += $1; subs += $2; loc += $1 - $2 &#125; END &#123; printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc &#125;'</span> -<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h1 id=\"搭建-gogs\"><a href=\"#搭建-gogs\" class=\"headerlink\" title=\"搭建 gogs\"></a>搭建 gogs</h1><p>gogs 官网下载,压缩包解压到<code>www/wwwroot/</code>下</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token builtin class-name\">cd</span> /www/wwwroot/gogs\n<span class=\"token comment\"># 启服务,默认3000的端口被占用则 ./gogs web -port 3001</span>\n./gogs web<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>浏览器访问<code>http://yourip:3000/install</code>,注意服务器安全组放行 3000 端口</p>\n<ul>\n<li>为 gogs 添加 mysql 数据库</li>\n<li>配置 mysql</li>\n<li>配置 gogs 相关信息</li>\n<li>配置其他信息</li>\n</ul>\n<p>停掉<code>./gogs web</code></p>\n<p>在刚安装的 gogs 路径下,找到<code>/gogs/scripts/systemd/gogs.service</code> 文件复制一份</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token assign-left variable\">User</span><span class=\"token operator\">=</span>root\n<span class=\"token assign-left variable\">Group</span><span class=\"token operator\">=</span>root\n<span class=\"token assign-left variable\">WorkingDirectory</span><span class=\"token operator\">=</span>/www/wwwroot/git.mozzie.cn\n<span class=\"token assign-left variable\">ExecStart</span><span class=\"token operator\">=</span>/www/wwwroot/git.mozzie.cn/gogs web\n<span class=\"token assign-left variable\">Restart</span><span class=\"token operator\">=</span>always\n<span class=\"token assign-left variable\">Environment</span><span class=\"token operator\">=</span><span class=\"token environment constant\">USER</span><span class=\"token operator\">=</span>root <span class=\"token assign-left variable\"><span class=\"token environment constant\">HOME</span></span><span class=\"token operator\">=</span>/www/wwwroot/git.mozzie.cn<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>将修改好的<code>gogs.service</code>文件上传到<code>/etc/systemd/system</code>下,并执行以下命令来激活 gogs</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">sudo</span> systemctl <span class=\"token builtin class-name\">enable</span> gogs\n<span class=\"token comment\"># 启动gogs</span>\n<span class=\"token function\">sudo</span> systemctl start gogs<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p><code>/gogs/custom/conf/app.ini</code>,修改该文件可以自定义配置,安装步骤填错了,可以这里修改,重启 gogs 服务即可</p>\n<h2 id=\"配置-gogs-GIT-钩子\"><a href=\"#配置-gogs-GIT-钩子\" class=\"headerlink\" title=\"配置 gogs GIT 钩子\"></a>配置 gogs GIT 钩子</h2><p>场景:以 Gogs 为例,先 git push <code>A项目</code> 到远程仓库 <code>REPO</code>,服务端 web 目录<code>webB</code>文件夹触发钩子执行 git pull</p>\n<p>1、gogs 初始化一个仓库<code>REPO</code>,仓库设置&#x3D;&gt;管理 GIT 钩子&#x3D;&gt;post-receive填入</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token shebang important\">#!/bin/sh</span>\n<span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\">GIT_WORK_TREE</span><span class=\"token operator\">=</span>/www/wwwroot/webB\n<span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\">GIT_DIR</span><span class=\"token operator\">=</span><span class=\"token variable\">$&#123;GIT_WORK_TREE&#125;</span>/.git\n<span class=\"token builtin class-name\">cd</span> <span class=\"token variable\">$&#123;GIT_WORK_TREE&#125;</span>\n<span class=\"token function\">git</span> pull<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>2、利用 ssh 工具登录服务器</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">ssh</span> root@mozzie.cn<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>3、生成 ssh key</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">ssh-keygen <span class=\"token parameter variable\">-t</span> rsa <span class=\"token parameter variable\">-C</span> <span class=\"token string\">\"himozzie@foxmail.com\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>4、配置公钥到 gogs</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">cat</span> ~/.ssh/id_rsa.pub<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>把打印出的公钥,配置到 ssh 密钥</p>\n<p>5、最后一步</p>\n<p>配置好服务端的公钥后,就可以无需用户名密码,<code>cd /webB</code>目录下,执行<code>git pull</code>,此后每次<code>git push A项目</code>,服务端都会触发<code>GIT钩子</code>,自动从<code>REPO</code>拉取最新的仓库文件</p>\n","site":{"data":{}},"excerpt":"","more":"<h1 id=\"GIT-最佳实践\"><a href=\"#GIT-最佳实践\" class=\"headerlink\" title=\"GIT 最佳实践\"></a>GIT 最佳实践</h1><p>GIT 本质是一个数据库,用来存代码的</p>\n<ul>\n<li>工作区一个沙箱环境GIT 不负责管理,你尽管在沙箱里面对文件进行操作</li>\n<li>暂存区:<code>工作区</code>文件变动先不急着提交,暂存到一定数量,在提交到版本库</li>\n<li>版本库:</li>\n</ul>\n<blockquote>\n<p>!! Linus 永远的神!</p>\n</blockquote>\n<h2 id=\"配置用户\"><a href=\"#配置用户\" class=\"headerlink\" title=\"配置用户\"></a>配置用户</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> user.name <span class=\"token string\">\"mozzie\"</span>\n<span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> user.email himozzie@foxmail.com<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"alias-别名\"><a href=\"#alias-别名\" class=\"headerlink\" title=\"alias 别名\"></a>alias 别名</h2><p>解决参数太多,记不住的问题</p>\n<blockquote>\n<p>!! HEAD -&gt; master HEAD 相当于一个指针,指向当前所在分支</p>\n</blockquote>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 查看项目分支图,</span>\n<span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> alias.lo <span class=\"token string\">\"log --oneline --decorate --graph --all\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"git-文件结构\"><a href=\"#git-文件结构\" class=\"headerlink\" title=\".git 文件结构\"></a>.git 文件结构</h2><ul>\n<li>hooks提交代码前检查代码格式……</li>\n<li>info包含一个排除性文件</li>\n<li>logs保存日志信息不太需要</li>\n<li><code>objects</code>:相当于数据库,存储所有数据内容</li>\n<li><code>refs</code>:存放提交对象指针,管理分支的</li>\n<li>config配置文件</li>\n<li>description仓库描述信息</li>\n<li><code>HEAD</code>:指示目前被检出的分支</li>\n<li><code>index</code>:文件保存暂存区信息</li>\n</ul>\n<h2 id=\"修改远程仓库\"><a href=\"#修改远程仓库\" class=\"headerlink\" title=\"修改远程仓库\"></a>修改远程仓库</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># way 1</span>\n<span class=\"token function\">git</span> remote set-url origin <span class=\"token punctuation\">[</span>url<span class=\"token punctuation\">]</span>\n<span class=\"token comment\"># way 2</span>\n<span class=\"token function\">git</span> remote <span class=\"token function\">rm</span> origin\n<span class=\"token function\">git</span> remote <span class=\"token function\">add</span> origin <span class=\"token punctuation\">[</span>url<span class=\"token punctuation\">]</span>\n<span class=\"token comment\"># way3</span>\n修改 config 文件<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"高层命令\"><a href=\"#高层命令\" class=\"headerlink\" title=\"高层命令\"></a>高层命令</h2><h3 id=\"初始化仓库\"><a href=\"#初始化仓库\" class=\"headerlink\" title=\"初始化仓库\"></a>初始化仓库</h3><p><code>git init</code></p>\n<h3 id=\"修改添加到暂存区\"><a href=\"#修改添加到暂存区\" class=\"headerlink\" title=\"修改添加到暂存区\"></a>修改添加到暂存区</h3><p><code>git add ./</code>,相当于如下操作:</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 有多少文件改动,就执行多少次</span>\n<span class=\"token function\">git</span> hash-object <span class=\"token parameter variable\">-w</span> 文件名\n<span class=\"token function\">git</span> update-index<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>!! git add .&#x2F; 先把工作区生成 git 对象,放到版本库,然后再放到暂存区</p>\n</blockquote>\n<h3 id=\"暂存区提交到版本库\"><a href=\"#暂存区提交到版本库\" class=\"headerlink\" title=\"暂存区提交到版本库\"></a>暂存区提交到版本库</h3><p><code>git commit -m &#39;comment&#39;</code>,相当于如下操作:</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> write-tree\n<span class=\"token function\">git</span> commit-tree<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<p>也可以跳过暂存区提交,<code>git commit -a -m </code></p>\n<h3 id=\"查看哪些修改没有暂存\"><a href=\"#查看哪些修改没有暂存\" class=\"headerlink\" title=\"查看哪些修改没有暂存\"></a>查看哪些修改没有暂存</h3><p><code>git diff</code>:没有暂存</p>\n<p><code>git diff --staged</code>:查看哪些修改以及被暂存了,但没有提交</p>\n<h3 id=\"查看提交历史记录\"><a href=\"#查看提交历史记录\" class=\"headerlink\" title=\"查看提交历史记录\"></a>查看提交历史记录</h3><p><code>git log --oneline</code>,打印出<code>hash值</code>是提交对象</p>\n<h2 id=\"分支\"><a href=\"#分支\" class=\"headerlink\" title=\"分支\"></a>分支</h2><p>本质是一个<code>提交对象</code>,每次<code>git branch name</code>中的<code>name</code>,指针<code>HEAD</code>,就会根据<code>name</code>指向提交对象</p>\n<p>如果要开发新功能,就新建一个<code>分支A</code>,写完再合<code>master</code>分支,正常来说<code>master</code>分支不会轻易给修改权限。</p>\n<p>如果另一个新功能,和<code>分支A</code>同级、并行的,那就<code>切到master</code>分支,在<code>master</code>分支基础上,开<code>分支B</code>,进行新功能开发</p>\n<blockquote>\n<p>一般来说master 分支没有权限,需要自己重新写开一个分支,分支名用 nickname</p>\n</blockquote>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">C1 master\n<span class=\"token operator\">|</span>——C2——C3——C4 mozzie<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h3 id=\"分支列表\"><a href=\"#分支列表\" class=\"headerlink\" title=\"分支列表\"></a>分支列表</h3><p><code>git branch</code></p>\n<h3 id=\"创建分支\"><a href=\"#创建分支\" class=\"headerlink\" title=\"创建分支\"></a>创建分支</h3><p><code>git branch 分支名</code>,并不会自动切换到分支</p>\n<h3 id=\"切换分支\"><a href=\"#切换分支\" class=\"headerlink\" title=\"切换分支\"></a>切换分支</h3><blockquote>\n<p>!! 最佳实践每次切换分之前git status 查一下,当前分支一定要是干净的</p>\n</blockquote>\n<p><code>git checkout 分支名</code></p>\n<h3 id=\"合并分支\"><a href=\"#合并分支\" class=\"headerlink\" title=\"合并分支\"></a>合并分支</h3><blockquote>\n<p>!! 做任何事情,确保做完了,再合并到 master 分支</p>\n</blockquote>\n<p>场景:需要增加功能<code>feat:#53</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># HEAD -> master新开一个分支</span>\n<span class=\"token function\">git</span> checkout <span class=\"token parameter variable\">-b</span> <span class=\"token string\">'feat53'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<p>突然发现 bug需要修复<code>bug:#52</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># HEAD -> feat53先提交#53分支的工作</span>\n<span class=\"token function\">git</span> commit <span class=\"token parameter variable\">-a</span> <span class=\"token parameter variable\">-m</span> <span class=\"token string\">'feat53 完成50%'</span>\n<span class=\"token comment\"># 切回 master 分支</span>\n<span class=\"token function\">git</span> checkout master\n<span class=\"token comment\"># HEAD -> master创建 issue52 分支</span>\n<span class=\"token function\">git</span> checkout <span class=\"token parameter variable\">-b</span> <span class=\"token string\">'issue52'</span>\n<span class=\"token comment\"># 改完了issue52</span>\n<span class=\"token function\">git</span> commit <span class=\"token parameter variable\">-a</span> <span class=\"token parameter variable\">-m</span> <span class=\"token string\">'fix:issue52'</span>\n<span class=\"token comment\"># HEAD -> master</span>\n<span class=\"token function\">git</span> checkout master\n<span class=\"token comment\"># 合</span>\n<span class=\"token function\">git</span> merge issue52\n<span class=\"token comment\"># 删除 issue52分支(hash还在)</span>\n<span class=\"token function\">git</span> branch <span class=\"token parameter variable\">-d</span> issue52<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>此时,由于<code>issue52</code>是在之前的 master 分支上生成的,故而<code>feat53</code>的分支仍然存在<code>issue52</code>的 bug所以有可能存在冲突需要手动解决</p>\n</blockquote>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># HEAD -> master</span>\n<span class=\"token function\">git</span> merge feat53\n<span class=\"token comment\"># 此处省略解决冲突</span>\n<span class=\"token function\">git</span> <span class=\"token function\">add</span> ./\n<span class=\"token function\">git</span> commit <span class=\"token parameter variable\">-m</span> <span class=\"token string\">'fix:merge conflict'</span>\n<span class=\"token comment\"># 删除 feat53</span>\n<span class=\"token function\">git</span> branch <span class=\"token parameter variable\">-d</span> feat53<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h3 id=\"删除分支\"><a href=\"#删除分支\" class=\"headerlink\" title=\"删除分支\"></a>删除分支</h3><p>查看哪些分支合并到当前分支,<code>git branch --merged</code>,这个列表中分支名字前没有*号的分支通常可以使用<code>git branch -d 分支名</code>删掉</p>\n<p><code>git branch -D 分支名</code>,强制删除</p>\n<h3 id=\"新建分支并指向指定提交对象\"><a href=\"#新建分支并指向指定提交对象\" class=\"headerlink\" title=\"新建分支并指向指定提交对象\"></a>新建分支并指向指定提交对象</h3><p><code>git branch name commitHash</code>,例<code>git log --oneline</code>如下:</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">* hasfh2asd <span class=\"token number\">1</span>.txt\n* 1shfd2zsw <span class=\"token number\">2</span>.txt\n* 67rf73has <span class=\"token number\">3</span>.txt\n* 03uhr4rug <span class=\"token number\">4</span>.txt<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>输入<code>git branch CCC 03uhr4rug</code>,那么会创建一个名为<code>CCC</code>的分支,并且<code>CCC</code>分支有<code>4.txt</code></p>\n<blockquote>\n<p>通常想看原来的某个版本的代码,就可以这样操作,看完,把这个分支删了</p>\n</blockquote>\n<h3 id=\"远程分支\"><a href=\"#远程分支\" class=\"headerlink\" title=\"远程分支\"></a>远程分支</h3><blockquote>\n<p><code>git clone</code>下来的分支,默认就会建立一个<code>远程跟踪分支</code>(同步关系),例如 master 分支</p>\n</blockquote>\n<ul>\n<li>本地分支</li>\n</ul>\n<p>场景一:如果想公开一个<code>share</code>分支 ,与他人共同写作:</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 过程中会生成生成一个远程跟踪分支 origin/share</span>\n<span class=\"token function\">git</span> push origin share<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<p>场景二:创建一个本地分支<code>b1</code>,直接跟踪远程分支<code>orgin/b1</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> checkout <span class=\"token parameter variable\">-b</span> <span class=\"token string\">'b1'</span> <span class=\"token string\">'origin/b1'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>场景三:已存在一个本地分支<code>dev</code>,改成远程跟踪分支</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># HEAD -> dev建立 本地分支 dev 与 远程分支 origin/dev 关系</span>\n<span class=\"token function\">git</span> branch <span class=\"token parameter variable\">-u</span> origin/dev\n<span class=\"token comment\"># 这样就可以直接</span>\n<span class=\"token function\">git</span> push / <span class=\"token function\">git</span> pull<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<ul>\n<li>远程分支</li>\n</ul>\n<p>查看远程分支:<code>git remote -v</code></p>\n<p>查看当前本地分支的远程跟踪分支:<code>git branch -vv</code></p>\n<h2 id=\"远程分支删除-本地更新-prune\"><a href=\"#远程分支删除-本地更新-prune\" class=\"headerlink\" title=\"远程分支删除, 本地更新 prune\"></a>远程分支删除, 本地更新 prune</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 不加 --prune和 fetch 等价, 远程被删除的分支不会同步删除本地origin的分支</span>\n<span class=\"token function\">git</span> remote update origin <span class=\"token parameter variable\">--prune</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"提交规范\"><a href=\"#提交规范\" class=\"headerlink\" title=\"提交规范\"></a>提交规范</h1><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">type<span class=\"token punctuation\">(</span>scope<span class=\"token punctuation\">)</span>: subject\n<span class=\"token comment\"># 例如</span>\nfeat<span class=\"token punctuation\">(</span>miniprogram<span class=\"token punctuation\">)</span>: 增加了小程序模板消息相关功能<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>通常<code>type</code>有如下:</p>\n<ul>\n<li>feat - 新功能 feature</li>\n<li>fix - 修复 bug</li>\n<li>docs - 文档注释</li>\n<li>style - 代码格式(不影响代码运行的变动)</li>\n<li>refactor - 重构、优化(既不增加新功能,也不是修复 bug)</li>\n<li>perf - 性能优化</li>\n<li>test - 增加测试</li>\n<li>chore - 构建过程或辅助工具的变动</li>\n<li>revert - 回退</li>\n<li>build - 打包</li>\n</ul>\n<h2 id=\"自动生成-Change-log\"><a href=\"#自动生成-Change-log\" class=\"headerlink\" title=\"自动生成 Change log\"></a>自动生成 Change log</h2><p>原理:利用 <code>child_process</code>获取 <code>git log</code>内容,处理字符串</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> execSync <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"child_process\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>execSync<span class=\"token punctuation\">;</span> <span class=\"token comment\">//同步子进程</span>\n<span class=\"token keyword\">const</span> fs <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"fs\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> process <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"process\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> path <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"path\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> inquirer <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"inquirer\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> dayjs <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"dayjs\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> axios <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"axios\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// env</span>\n<span class=\"token keyword\">const</span> isForCommanHuman <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>argv<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"--common\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// changelog.md生成路径</span>\n<span class=\"token keyword\">const</span> outputpath <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span>process<span class=\"token punctuation\">.</span><span class=\"token function\">cwd</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"./changelog.md\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 非空检测</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>fs<span class=\"token punctuation\">.</span><span class=\"token function\">existsSync</span><span class=\"token punctuation\">(</span>outputpath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> fs<span class=\"token punctuation\">.</span><span class=\"token function\">writeFile</span><span class=\"token punctuation\">(</span>outputpath<span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">err</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 华丽的gitlog日志</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">perfectGitLog</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">startTime<span class=\"token punctuation\">,</span> endTime</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n isForCommanHuman\n <span class=\"token operator\">?</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">git log --since=\"</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>startTime<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">\" --until=\"</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>endTime<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">\" --no-merges --pretty=format:\"%cr %C(cyan)%s\"</span><span class=\"token template-punctuation string\">`</span></span>\n <span class=\"token operator\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">git log --since=\"</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>startTime<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">\" --until=\"</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>endTime<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">\" --no-merges --pretty=format:\"%C(yellow)%h %C(green)%cn %C(redz)(%cr:%ci) %C(cyan)%s\"</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> wxrobotHook <span class=\"token operator\">=</span>\n <span class=\"token string\">\"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=be4d4473-c290-4ddd-a089-41df3ed1d601\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 当前时间</span>\n<span class=\"token keyword\">const</span> now <span class=\"token operator\">=</span> Date<span class=\"token punctuation\">.</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 2周前</span>\n<span class=\"token keyword\">const</span> weeks_2_ago <span class=\"token operator\">=</span> now <span class=\"token operator\">-</span> <span class=\"token number\">14</span> <span class=\"token operator\">*</span> <span class=\"token number\">24</span> <span class=\"token operator\">*</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">;</span>\n\ninquirer\n <span class=\"token punctuation\">.</span><span class=\"token function\">prompt</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">type</span><span class=\"token operator\">:</span> <span class=\"token string\">\"input\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"startDate\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">message</span><span class=\"token operator\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">起始时间,默认13天前 \\n</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span>\n <span class=\"token keyword\">default</span><span class=\"token operator\">:</span> <span class=\"token function\">dayjs</span><span class=\"token punctuation\">(</span>weeks_2_ago<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"YYYY.MM.DD\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">validate</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">val</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">\\d&#123;4&#125;.\\d&#123;2&#125;.\\d&#123;2&#125;</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">.</span><span class=\"token function\">test</span><span class=\"token punctuation\">(</span>val<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">type</span><span class=\"token operator\">:</span> <span class=\"token string\">\"input\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"endDate\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">message</span><span class=\"token operator\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">结束时间,默认今天 \\n</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span>\n <span class=\"token keyword\">default</span><span class=\"token operator\">:</span> <span class=\"token function\">dayjs</span><span class=\"token punctuation\">(</span>now<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"YYYY.MM.DD\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">validate</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">val</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">\\d&#123;4&#125;.\\d&#123;2&#125;.\\d&#123;2&#125;</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">.</span><span class=\"token function\">test</span><span class=\"token punctuation\">(</span>val<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">type</span><span class=\"token operator\">:</span> <span class=\"token string\">\"rawlist\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">message</span><span class=\"token operator\">:</span> <span class=\"token string\">\"是否通知到微信机器人:\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"notifyWxrobot\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">choices</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"Y\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"N\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">answers</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> <span class=\"token punctuation\">&#123;</span> startDate<span class=\"token punctuation\">,</span> endDate<span class=\"token punctuation\">,</span> notifyWxrobot <span class=\"token punctuation\">&#125;</span> <span class=\"token operator\">=</span> answers<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">const</span> rowTemplate <span class=\"token operator\">=</span> <span class=\"token function\">perfectGitLog</span><span class=\"token punctuation\">(</span>startDate<span class=\"token punctuation\">,</span> endDate<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> fmt <span class=\"token operator\">=</span> <span class=\"token function\">execSync</span><span class=\"token punctuation\">(</span>rowTemplate<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">trim</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">feat: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"✅: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">fix: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"🐛: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">chore: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"🎨: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">perf: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"⚡: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">docs: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"📝: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">refactor: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"🔨: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">anno: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"🔖: \"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">style: </span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">gi</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"👷: \"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n fs<span class=\"token punctuation\">.</span><span class=\"token function\">writeFileSync</span><span class=\"token punctuation\">(</span>outputpath<span class=\"token punctuation\">,</span> fmt<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">err</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 通知微信群聊机器人</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>notifyWxrobot <span class=\"token operator\">===</span> <span class=\"token string\">\"Y\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n axios<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span>wxrobotHook<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">msgtype</span><span class=\"token operator\">:</span> <span class=\"token string\">\"markdown\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">markdown</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> fmt<span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">catch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">error</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">.</span>isTtyError<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// Prompt couldn't be rendered in the current environment</span>\n <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// Something else went wrong</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"使用-husky-eslint-规范提交\"><a href=\"#使用-husky-eslint-规范提交\" class=\"headerlink\" title=\"使用 husky+eslint 规范提交\"></a>使用 husky+eslint 规范提交</h2><blockquote>\n<p>需要配合 eslint</p>\n</blockquote>\n<p><code>git init</code>后,<code>yarn add husky</code>,在<code>package.json</code>配置</p>\n<pre class=\"line-numbers language-json\" data-language=\"json\"><code class=\"language-json\"><span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">\"husky\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">\"hooks\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token property\">\"pre-commit\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npm run lint\"</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"生成-ssh-key\"><a href=\"#生成-ssh-key\" class=\"headerlink\" title=\"生成 ssh key\"></a>生成 ssh key</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">ssh-keygen <span class=\"token parameter variable\">-t</span> rsa <span class=\"token parameter variable\">-C</span> <span class=\"token string\">\"himozzie@foxmail.com\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"查看-ssh-公钥\"><a href=\"#查看-ssh-公钥\" class=\"headerlink\" title=\"查看 ssh 公钥\"></a>查看 ssh 公钥</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">cat</span> ~/.ssh/id_rsa.pub<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h1 id=\"git-代理\"><a href=\"#git-代理\" class=\"headerlink\" title=\"git 代理\"></a>git 代理</h1><blockquote>\n<p>前提条件是开了扶墙工具</p>\n</blockquote>\n<p>git clone 拉取方式选择 http&#x2F;https(默认会让你输入账号密码,比较蛋疼),不要选择 ssl 拉取</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> http.proxy <span class=\"token string\">'http://127.0.0.1:1081'</span>\n<span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> https.proxy <span class=\"token string\">'https://127.0.0.1:1081'</span>\n<span class=\"token comment\"># 清除</span>\n<span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> <span class=\"token parameter variable\">--unset</span> http.proxy\n<span class=\"token function\">git</span> config <span class=\"token parameter variable\">--global</span> <span class=\"token parameter variable\">--unset</span> https.proxy<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"终端临时代理\"><a href=\"#终端临时代理\" class=\"headerlink\" title=\"终端临时代理\"></a>终端临时代理</h1><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># cmd临时代理方案cmd窗口关闭则代理失效</span>\n<span class=\"token builtin class-name\">set</span> <span class=\"token assign-left variable\">http_proxy</span><span class=\"token operator\">=</span>http://127.0.0.1:50015\n<span class=\"token builtin class-name\">set</span> <span class=\"token assign-left variable\">https_proxy</span><span class=\"token operator\">=</span>http://127.0.0.1:50015<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"git-钩子-hooks\"><a href=\"#git-钩子-hooks\" class=\"headerlink\" title=\"git 钩子(hooks)\"></a>git 钩子(hooks)</h1><p>原理:项目 git push 到远程仓库,远程仓库的钩子 post 通知 www&#x2F;wwwroot 下的站点 pull 远程仓库</p>\n<blockquote>\n<p>git 钩子需要 git 服务和 pull 在同一环境中</p>\n</blockquote>\n<ul>\n<li>创建远程仓库,配置钩子,git post-receive 钩子</li>\n</ul>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token shebang important\">#!/bin/bash</span>\n<span class=\"token builtin class-name\">unset</span> <span class=\"token variable\"><span class=\"token variable\">$(</span><span class=\"token function\">git</span> rev-parse --local-env-vars<span class=\"token variable\">)</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\"># post-receive接收到pull指令后,执行bash命令</span>\n<span class=\"token builtin class-name\">cd</span> /www/wwwroot/doc.mozzie.cn/ <span class=\"token operator\">&amp;&amp;</span> <span class=\"token function\">git</span> pull origin master<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>web 目录下 doc.mozzie.cn 是网站目录,本地项目编译打包后,直接 git push 的目录</p>\n</blockquote>\n<h2 id=\"web-钩子\"><a href=\"#web-钩子\" class=\"headerlink\" title=\"web 钩子\"></a>web 钩子</h2><p>待耍</p>\n<h1 id=\"项目\"><a href=\"#项目\" class=\"headerlink\" title=\"项目\"></a>项目</h1><h2 id=\"统计项目代码行数\"><a href=\"#统计项目代码行数\" class=\"headerlink\" title=\"统计项目代码行数\"></a>统计项目代码行数</h2><p>统计所有人代码增删量,拷贝如下命令, git bash 终端git 项目某分支下执行</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> log <span class=\"token parameter variable\">--format</span><span class=\"token operator\">=</span><span class=\"token string\">'%aN'</span> <span class=\"token operator\">|</span> <span class=\"token function\">sort</span> <span class=\"token parameter variable\">-u</span> <span class=\"token operator\">|</span> <span class=\"token keyword\">while</span> <span class=\"token builtin class-name\">read</span> name<span class=\"token punctuation\">;</span> <span class=\"token keyword\">do</span> <span class=\"token builtin class-name\">echo</span> <span class=\"token parameter variable\">-en</span> <span class=\"token string\">\"<span class=\"token variable\">$name</span><span class=\"token entity\" title=\"\\t\">\\t</span>\"</span><span class=\"token punctuation\">;</span> <span class=\"token function\">git</span> log <span class=\"token parameter variable\">--author</span><span class=\"token operator\">=</span><span class=\"token string\">\"<span class=\"token variable\">$name</span>\"</span> <span class=\"token parameter variable\">--pretty</span><span class=\"token operator\">=</span>tformat: <span class=\"token parameter variable\">--numstat</span> <span class=\"token operator\">|</span> <span class=\"token function\">awk</span> <span class=\"token string\">'&#123; add += $1; subs += $2; loc += $1 - $2 &#125; END &#123; printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc &#125;'</span> -<span class=\"token punctuation\">;</span> <span class=\"token keyword\">done</span>\n<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"统计制定提交者代码量\"><a href=\"#统计制定提交者代码量\" class=\"headerlink\" title=\"统计制定提交者代码量\"></a>统计制定提交者代码量</h2><p>替换<code>username</code>为提交者的名称</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> log <span class=\"token parameter variable\">--author</span><span class=\"token operator\">=</span><span class=\"token string\">\"username\"</span> <span class=\"token parameter variable\">--pretty</span><span class=\"token operator\">=</span>tformat: <span class=\"token parameter variable\">--numstat</span> <span class=\"token operator\">|</span> <span class=\"token function\">awk</span> <span class=\"token string\">'&#123; add += $1; subs += $2; loc += $1 - $2 &#125; END &#123; printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc &#125;'</span> -<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h1 id=\"搭建-gogs\"><a href=\"#搭建-gogs\" class=\"headerlink\" title=\"搭建 gogs\"></a>搭建 gogs</h1><p>gogs 官网下载,压缩包解压到<code>www/wwwroot/</code>下</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token builtin class-name\">cd</span> /www/wwwroot/gogs\n<span class=\"token comment\"># 启服务,默认3000的端口被占用则 ./gogs web -port 3001</span>\n./gogs web<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>浏览器访问<code>http://yourip:3000/install</code>,注意服务器安全组放行 3000 端口</p>\n<ul>\n<li>为 gogs 添加 mysql 数据库</li>\n<li>配置 mysql</li>\n<li>配置 gogs 相关信息</li>\n<li>配置其他信息</li>\n</ul>\n<p>停掉<code>./gogs web</code></p>\n<p>在刚安装的 gogs 路径下,找到<code>/gogs/scripts/systemd/gogs.service</code> 文件复制一份</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token assign-left variable\">User</span><span class=\"token operator\">=</span>root\n<span class=\"token assign-left variable\">Group</span><span class=\"token operator\">=</span>root\n<span class=\"token assign-left variable\">WorkingDirectory</span><span class=\"token operator\">=</span>/www/wwwroot/git.mozzie.cn\n<span class=\"token assign-left variable\">ExecStart</span><span class=\"token operator\">=</span>/www/wwwroot/git.mozzie.cn/gogs web\n<span class=\"token assign-left variable\">Restart</span><span class=\"token operator\">=</span>always\n<span class=\"token assign-left variable\">Environment</span><span class=\"token operator\">=</span><span class=\"token environment constant\">USER</span><span class=\"token operator\">=</span>root <span class=\"token assign-left variable\"><span class=\"token environment constant\">HOME</span></span><span class=\"token operator\">=</span>/www/wwwroot/git.mozzie.cn<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>将修改好的<code>gogs.service</code>文件上传到<code>/etc/systemd/system</code>下,并执行以下命令来激活 gogs</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">sudo</span> systemctl <span class=\"token builtin class-name\">enable</span> gogs\n<span class=\"token comment\"># 启动gogs</span>\n<span class=\"token function\">sudo</span> systemctl start gogs<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p><code>/gogs/custom/conf/app.ini</code>,修改该文件可以自定义配置,安装步骤填错了,可以这里修改,重启 gogs 服务即可</p>\n<h2 id=\"配置-gogs-GIT-钩子\"><a href=\"#配置-gogs-GIT-钩子\" class=\"headerlink\" title=\"配置 gogs GIT 钩子\"></a>配置 gogs GIT 钩子</h2><p>场景:以 Gogs 为例,先 git push <code>A项目</code> 到远程仓库 <code>REPO</code>,服务端 web 目录<code>webB</code>文件夹触发钩子执行 git pull</p>\n<p>1、gogs 初始化一个仓库<code>REPO</code>,仓库设置&#x3D;&gt;管理 GIT 钩子&#x3D;&gt;post-receive填入</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token shebang important\">#!/bin/sh</span>\n<span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\">GIT_WORK_TREE</span><span class=\"token operator\">=</span>/www/wwwroot/webB\n<span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\">GIT_DIR</span><span class=\"token operator\">=</span><span class=\"token variable\">$&#123;GIT_WORK_TREE&#125;</span>/.git\n<span class=\"token builtin class-name\">cd</span> <span class=\"token variable\">$&#123;GIT_WORK_TREE&#125;</span>\n<span class=\"token function\">git</span> pull<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>2、利用 ssh 工具登录服务器</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">ssh</span> root@mozzie.cn<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>3、生成 ssh key</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">ssh-keygen <span class=\"token parameter variable\">-t</span> rsa <span class=\"token parameter variable\">-C</span> <span class=\"token string\">\"himozzie@foxmail.com\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>4、配置公钥到 gogs</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">cat</span> ~/.ssh/id_rsa.pub<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>把打印出的公钥,配置到 ssh 密钥</p>\n<p>5、最后一步</p>\n<p>配置好服务端的公钥后,就可以无需用户名密码,<code>cd /webB</code>目录下,执行<code>git pull</code>,此后每次<code>git push A项目</code>,服务端都会触发<code>GIT钩子</code>,自动从<code>REPO</code>拉取最新的仓库文件</p>\n"},{"title":"verdaccio 搭建 npm私库","status":"done","_content":"\n# 使用 docker 搭建 verdaccio\n\n创建 & 配置`config.yaml`文件\n\n```yaml\n# Read about the best practices\n# https://verdaccio.org/docs/best\n\n# path to a directory with all packages\nstorage: /verdaccio/storage/data\n# path to a directory with plugins to include\nplugins: /verdaccio/plugins\n\n# 包体积上限默认10mb\nmax_body_size: 1024mb\n\n\nweb:\n enable: true\n title: Mozzie-NPM\n # gravatar: false\n # login: true\n pkgManagers:\n - npm\n - yarn\n - pnpm\n html_cache: true\n showFooter: false\n\nauth:\n htpasswd:\n file: /verdaccio/storage/htpasswd\n # 关闭注册手动添加用户默认Bcrypt算法随便找个网页生成个密码使用账号:密码添加到 htpasswd 文件中,例如 test:$2a$10$0xPGVnpcdxcfmFxtWyWDx./TRtm/W/gSzib/jck3w.sF9x.Ur8t8W\n max_users: -1\n\n\ni18n:\n web: zh-CN\n\n# notify: # 配置 Webhook 推送到钉钉,记得修改 access_token 和 atMobiles\n# method: POST\n# headers: [{ \"Content-Type\": \"application/json\" }]\n# endpoint: https://oapi.dingtalk.com/robot/send?access_token=xxxx\n# content: '{\"msgtype\":\"text\", \"at\": {\"atMobiles\": [\"13000000000\"] }, \"text\":{\"content\":\"NPM 发布新包:\\n > 包名称:{{name}} \\n > 版本号:{{#each versions}}{{version}}{{/each}} \\n > 发布者:{{publisher.name}} \"}}'\n\nuplinks:\n npmjs:\n url: https://registry.npmjs.org/\n yarn:\n url: https://registry.yarnpkg.com/\n timeout: 10s\n taobao:\n url: https://registry.npmmirror.com/\n timeout: 10s\n\npackages:\n \"@*/*\":\n # 可访问权限web界面看不见不登陆也无法 install 包\n access: $authenticated # $all\n # 发布权限, $authenticated 表示只有通过验证的人\n publish: $authenticated\n # 可取消发布权限\n unpublish: $authenticated\n # 包不存在时的代理\n proxy: npmjs yarn taobao\n \"**\":\n access: $authenticated # $all\n publish: $authenticated\n unpublish: $authenticated\n proxy: npmjs yarn taobao\n\nmiddlewares:\n audit:\n enabled: true\nlisten: 0.0.0.0:4873\nlog: { type: stdout, format: pretty, level: http }\n```\n\n创建容器环境变量`VERDACCIO_PUBLIC_URL`是静态资源的前缀地址由于nginx挂了`ssl`,如果使用`http`可以不添加\n\n```bash\ndocker run \\\n-p 4873:4873 \\\n--restart=always \\\n--network mozzie.cn-net \\\n--network-alias verdaccio \\\n--env VERDACCIO_PORT=4873 \\\n--env VERDACCIO_PUBLIC_URL=https://npm.mozzie.cn \\\n--ip 172.21.0.196 \\\n--name verdaccio \\\n-v /www/wwwroot/nginx/html/verdaccio/storage:/verdaccio/storage \\\n-v /www/wwwroot/nginx/html/verdaccio/config:/verdaccio/conf \\\n-v /www/wwwroot/nginx/html/verdaccio/plugins:/verdaccio/plugins \\\n-d verdaccio/verdaccio\n```\n\n\n\n配置nginx的反向代理conf注意所在的docker网络使用`container_name`\n\n\n\n```conf\nserver {\n # listen 80;\n listen 443 ssl;\n server_name npm.mozzie.cn;\n ssl_certificate /etc/nginx/ssl/npm.mozzie.cn_bundle.pem;\n ssl_certificate_key /etc/nginx/ssl/npm.mozzie.cn.key;\n gzip on;\n\n location / {\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header Host $host;\n proxy_set_header X-NginX-Proxy true;\n proxy_pass http://verdaccio:4873/;\n proxy_redirect off;\n }\n}\n```\n\n运行添加用户报错因为 `htpasswd`默认创建在宿主机,也就是上面挂载的`/www/wwwroot/nginx/html/verdaccio/storage`目录中\n\n```bash\nnpm adduser --registry https://npm.mozzie.cn/\n```\n\n配置`htpasswd`、`storage` 文件夹权限\n\n```bash\n# 宿主机中执行\ncd /www/wwwroot/nginx/html/verdaccio/storage\ntouch htpasswd\nsudo chown 10001:65533 htpasswd\nsudo chown -R 10001:65533 /www/wwwroot/nginx/html/verdaccio/storage\n```\n\n# verdaccio 用户管理\n\n由于在 `config.yml` 中关闭了可访问权限\n\n```yaml\nauth:\n htpasswd:\n file: /verdaccio/storage/htpasswd\n # 关闭注册手动添加用户默认Bcrypt算法\n max_users: -1\n\npackages:\n \"@*/*\":\n # 可访问权限web界面看不见不登陆也无法 install 包\n access: $authenticated # $all\n # 发布权限, $authenticated 表示只有通过验证的人\n publish: $authenticated\n # 可取消发布权限\n unpublish: $authenticated\n \"**\":\n access: $authenticated\n publish: $authenticated\n unpublish: $authenticated\n```\n\n默认的 `addUser` 策略是 `Bcrypt` 生成密码,随便找个网页生成个密码,使用`账号:密码`添加到 `htpasswd` 文件中,例如 \n\n```bash\ntest:$2a$10$0xPGVnpcdxcfmFxtWyWDx./TRtm/W/gSzib/jck3w.sF9x.Ur8t8W\n```\n\n因此在实际开发中管理员手动给用户创建好账号然后根据用户的包管理工具进行登录例如以 `npm` 为例\n\n```bash\nnpm adduser --registry https://npm.mozzie.cn/\n# 输入 Username: mozzie | Password: xxx | Email: (this IS public) himozzie@foxmail.com\n# 提示登陆成功 Logged in as mozzie on https://npm.mozzie.cn/.\n```\n\n在系统的 `cat ~/.npmrc` 中会增加一行,就可以正常的进行以来的安装了\n\n```bash\n//npm.mozzie.cn/:_authToken=\"Do/wrh5QzsnYaNU4x3ZlVA==\"\n```\n\n# 项目 .npmrc Scope区分\n\n需要指定 `.npmrc` 来区别 `Scope` 的安装地址,例如一个包名为 `@mozzie/hook`,对应的私库为 `https://npm.mozzie.cn/`\n\n```bash\nregistry=http://registry.npm.taobao.org/\n@mozzie:registry=https://npm.mozzie.cn\n# npm拉包的校验\n//https://npm.mozzie.cn/:_authToken=xxxxxxxxxxxxx\n```","source":"_posts/front-end/verdaccio.md","raw":"---\ntitle: verdaccio 搭建 npm私库\ncategories:\n - Front-End\nstatus: done\n---\n\n# 使用 docker 搭建 verdaccio\n\n创建 & 配置`config.yaml`文件\n\n```yaml\n# Read about the best practices\n# https://verdaccio.org/docs/best\n\n# path to a directory with all packages\nstorage: /verdaccio/storage/data\n# path to a directory with plugins to include\nplugins: /verdaccio/plugins\n\n# 包体积上限默认10mb\nmax_body_size: 1024mb\n\n\nweb:\n enable: true\n title: Mozzie-NPM\n # gravatar: false\n # login: true\n pkgManagers:\n - npm\n - yarn\n - pnpm\n html_cache: true\n showFooter: false\n\nauth:\n htpasswd:\n file: /verdaccio/storage/htpasswd\n # 关闭注册手动添加用户默认Bcrypt算法随便找个网页生成个密码使用账号:密码添加到 htpasswd 文件中,例如 test:$2a$10$0xPGVnpcdxcfmFxtWyWDx./TRtm/W/gSzib/jck3w.sF9x.Ur8t8W\n max_users: -1\n\n\ni18n:\n web: zh-CN\n\n# notify: # 配置 Webhook 推送到钉钉,记得修改 access_token 和 atMobiles\n# method: POST\n# headers: [{ \"Content-Type\": \"application/json\" }]\n# endpoint: https://oapi.dingtalk.com/robot/send?access_token=xxxx\n# content: '{\"msgtype\":\"text\", \"at\": {\"atMobiles\": [\"13000000000\"] }, \"text\":{\"content\":\"NPM 发布新包:\\n > 包名称:{{name}} \\n > 版本号:{{#each versions}}{{version}}{{/each}} \\n > 发布者:{{publisher.name}} \"}}'\n\nuplinks:\n npmjs:\n url: https://registry.npmjs.org/\n yarn:\n url: https://registry.yarnpkg.com/\n timeout: 10s\n taobao:\n url: https://registry.npmmirror.com/\n timeout: 10s\n\npackages:\n \"@*/*\":\n # 可访问权限web界面看不见不登陆也无法 install 包\n access: $authenticated # $all\n # 发布权限, $authenticated 表示只有通过验证的人\n publish: $authenticated\n # 可取消发布权限\n unpublish: $authenticated\n # 包不存在时的代理\n proxy: npmjs yarn taobao\n \"**\":\n access: $authenticated # $all\n publish: $authenticated\n unpublish: $authenticated\n proxy: npmjs yarn taobao\n\nmiddlewares:\n audit:\n enabled: true\nlisten: 0.0.0.0:4873\nlog: { type: stdout, format: pretty, level: http }\n```\n\n创建容器环境变量`VERDACCIO_PUBLIC_URL`是静态资源的前缀地址由于nginx挂了`ssl`,如果使用`http`可以不添加\n\n```bash\ndocker run \\\n-p 4873:4873 \\\n--restart=always \\\n--network mozzie.cn-net \\\n--network-alias verdaccio \\\n--env VERDACCIO_PORT=4873 \\\n--env VERDACCIO_PUBLIC_URL=https://npm.mozzie.cn \\\n--ip 172.21.0.196 \\\n--name verdaccio \\\n-v /www/wwwroot/nginx/html/verdaccio/storage:/verdaccio/storage \\\n-v /www/wwwroot/nginx/html/verdaccio/config:/verdaccio/conf \\\n-v /www/wwwroot/nginx/html/verdaccio/plugins:/verdaccio/plugins \\\n-d verdaccio/verdaccio\n```\n\n\n\n配置nginx的反向代理conf注意所在的docker网络使用`container_name`\n\n\n\n```conf\nserver {\n # listen 80;\n listen 443 ssl;\n server_name npm.mozzie.cn;\n ssl_certificate /etc/nginx/ssl/npm.mozzie.cn_bundle.pem;\n ssl_certificate_key /etc/nginx/ssl/npm.mozzie.cn.key;\n gzip on;\n\n location / {\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header Host $host;\n proxy_set_header X-NginX-Proxy true;\n proxy_pass http://verdaccio:4873/;\n proxy_redirect off;\n }\n}\n```\n\n运行添加用户报错因为 `htpasswd`默认创建在宿主机,也就是上面挂载的`/www/wwwroot/nginx/html/verdaccio/storage`目录中\n\n```bash\nnpm adduser --registry https://npm.mozzie.cn/\n```\n\n配置`htpasswd`、`storage` 文件夹权限\n\n```bash\n# 宿主机中执行\ncd /www/wwwroot/nginx/html/verdaccio/storage\ntouch htpasswd\nsudo chown 10001:65533 htpasswd\nsudo chown -R 10001:65533 /www/wwwroot/nginx/html/verdaccio/storage\n```\n\n# verdaccio 用户管理\n\n由于在 `config.yml` 中关闭了可访问权限\n\n```yaml\nauth:\n htpasswd:\n file: /verdaccio/storage/htpasswd\n # 关闭注册手动添加用户默认Bcrypt算法\n max_users: -1\n\npackages:\n \"@*/*\":\n # 可访问权限web界面看不见不登陆也无法 install 包\n access: $authenticated # $all\n # 发布权限, $authenticated 表示只有通过验证的人\n publish: $authenticated\n # 可取消发布权限\n unpublish: $authenticated\n \"**\":\n access: $authenticated\n publish: $authenticated\n unpublish: $authenticated\n```\n\n默认的 `addUser` 策略是 `Bcrypt` 生成密码,随便找个网页生成个密码,使用`账号:密码`添加到 `htpasswd` 文件中,例如 \n\n```bash\ntest:$2a$10$0xPGVnpcdxcfmFxtWyWDx./TRtm/W/gSzib/jck3w.sF9x.Ur8t8W\n```\n\n因此在实际开发中管理员手动给用户创建好账号然后根据用户的包管理工具进行登录例如以 `npm` 为例\n\n```bash\nnpm adduser --registry https://npm.mozzie.cn/\n# 输入 Username: mozzie | Password: xxx | Email: (this IS public) himozzie@foxmail.com\n# 提示登陆成功 Logged in as mozzie on https://npm.mozzie.cn/.\n```\n\n在系统的 `cat ~/.npmrc` 中会增加一行,就可以正常的进行以来的安装了\n\n```bash\n//npm.mozzie.cn/:_authToken=\"Do/wrh5QzsnYaNU4x3ZlVA==\"\n```\n\n# 项目 .npmrc Scope区分\n\n需要指定 `.npmrc` 来区别 `Scope` 的安装地址,例如一个包名为 `@mozzie/hook`,对应的私库为 `https://npm.mozzie.cn/`\n\n```bash\nregistry=http://registry.npm.taobao.org/\n@mozzie:registry=https://npm.mozzie.cn\n# npm拉包的校验\n//https://npm.mozzie.cn/:_authToken=xxxxxxxxxxxxx\n```","slug":"front-end/verdaccio","published":1,"date":"2023-10-20T02:25:55.131Z","updated":"2023-11-06T08:02:39.971Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58p000h4cz3305y5675","content":"<h1 id=\"使用-docker-搭建-verdaccio\"><a href=\"#使用-docker-搭建-verdaccio\" class=\"headerlink\" title=\"使用 docker 搭建 verdaccio\"></a>使用 docker 搭建 verdaccio</h1><p>创建 &amp; 配置<code>config.yaml</code>文件</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token comment\"># Read about the best practices</span>\n<span class=\"token comment\"># https://verdaccio.org/docs/best</span>\n\n<span class=\"token comment\"># path to a directory with all packages</span>\n<span class=\"token key atrule\">storage</span><span class=\"token punctuation\">:</span> /verdaccio/storage/data\n<span class=\"token comment\"># path to a directory with plugins to include</span>\n<span class=\"token key atrule\">plugins</span><span class=\"token punctuation\">:</span> /verdaccio/plugins\n\n<span class=\"token comment\"># 包体积上限默认10mb</span>\n<span class=\"token key atrule\">max_body_size</span><span class=\"token punctuation\">:</span> 1024mb\n\n\n<span class=\"token key atrule\">web</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> Mozzie<span class=\"token punctuation\">-</span>NPM\n <span class=\"token comment\"># gravatar: false</span>\n <span class=\"token comment\"># login: true</span>\n <span class=\"token key atrule\">pkgManagers</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> npm\n <span class=\"token punctuation\">-</span> yarn\n <span class=\"token punctuation\">-</span> pnpm\n <span class=\"token key atrule\">html_cache</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">showFooter</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span>\n\n<span class=\"token key atrule\">auth</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">htpasswd</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">file</span><span class=\"token punctuation\">:</span> /verdaccio/storage/htpasswd\n <span class=\"token comment\"># 关闭注册手动添加用户默认Bcrypt算法随便找个网页生成个密码使用账号:密码添加到 htpasswd 文件中,例如 test:$2a$10$0xPGVnpcdxcfmFxtWyWDx./TRtm/W/gSzib/jck3w.sF9x.Ur8t8W</span>\n <span class=\"token key atrule\">max_users</span><span class=\"token punctuation\">:</span> <span class=\"token number\">-1</span>\n\n\n<span class=\"token key atrule\">i18n</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">web</span><span class=\"token punctuation\">:</span> zh<span class=\"token punctuation\">-</span>CN\n\n<span class=\"token comment\"># notify: # 配置 Webhook 推送到钉钉,记得修改 access_token 和 atMobiles</span>\n<span class=\"token comment\"># method: POST</span>\n<span class=\"token comment\"># headers: [&#123; \"Content-Type\": \"application/json\" &#125;]</span>\n<span class=\"token comment\"># endpoint: https://oapi.dingtalk.com/robot/send?access_token=xxxx</span>\n<span class=\"token comment\"># content: '&#123;\"msgtype\":\"text\", \"at\": &#123;\"atMobiles\": [\"13000000000\"] &#125;, \"text\":&#123;\"content\":\"NPM 发布新包:\\n > 包名称:&#123;&#123;name&#125;&#125; \\n > 版本号:&#123;&#123;#each versions&#125;&#125;&#123;&#123;version&#125;&#125;&#123;&#123;/each&#125;&#125; \\n > 发布者:&#123;&#123;publisher.name&#125;&#125; \"&#125;&#125;'</span>\n\n<span class=\"token key atrule\">uplinks</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">npmjs</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//registry.npmjs.org/\n <span class=\"token key atrule\">yarn</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//registry.yarnpkg.com/\n <span class=\"token key atrule\">timeout</span><span class=\"token punctuation\">:</span> 10s\n <span class=\"token key atrule\">taobao</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//registry.npmmirror.com/\n <span class=\"token key atrule\">timeout</span><span class=\"token punctuation\">:</span> 10s\n\n<span class=\"token key atrule\">packages</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">\"@*/*\"</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 可访问权限web界面看不见不登陆也无法 install 包</span>\n <span class=\"token key atrule\">access</span><span class=\"token punctuation\">:</span> $authenticated <span class=\"token comment\"># $all</span>\n <span class=\"token comment\"># 发布权限, $authenticated 表示只有通过验证的人</span>\n <span class=\"token key atrule\">publish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token comment\"># 可取消发布权限</span>\n <span class=\"token key atrule\">unpublish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token comment\"># 包不存在时的代理</span>\n <span class=\"token key atrule\">proxy</span><span class=\"token punctuation\">:</span> npmjs yarn taobao\n <span class=\"token key atrule\">\"**\"</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">access</span><span class=\"token punctuation\">:</span> $authenticated <span class=\"token comment\"># $all</span>\n <span class=\"token key atrule\">publish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token key atrule\">unpublish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token key atrule\">proxy</span><span class=\"token punctuation\">:</span> npmjs yarn taobao\n\n<span class=\"token key atrule\">middlewares</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">audit</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enabled</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n<span class=\"token key atrule\">listen</span><span class=\"token punctuation\">:</span> 0.0.0.0<span class=\"token punctuation\">:</span><span class=\"token number\">4873</span>\n<span class=\"token key atrule\">log</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token key atrule\">type</span><span class=\"token punctuation\">:</span> stdout<span class=\"token punctuation\">,</span> <span class=\"token key atrule\">format</span><span class=\"token punctuation\">:</span> pretty<span class=\"token punctuation\">,</span> <span class=\"token key atrule\">level</span><span class=\"token punctuation\">:</span> http <span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>创建容器,环境变量,<code>VERDACCIO_PUBLIC_URL</code>是静态资源的前缀地址由于nginx挂了<code>ssl</code>,如果使用<code>http</code>可以不添加</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">docker</span> run <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">-p</span> <span class=\"token number\">4873</span>:4873 <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--restart</span><span class=\"token operator\">=</span>always <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--network</span> mozzie.cn-net <span class=\"token punctuation\">\\</span>\n--network-alias verdaccio <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--env</span> <span class=\"token assign-left variable\">VERDACCIO_PORT</span><span class=\"token operator\">=</span><span class=\"token number\">4873</span> <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--env</span> <span class=\"token assign-left variable\">VERDACCIO_PUBLIC_URL</span><span class=\"token operator\">=</span>https://npm.mozzie.cn <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--ip</span> <span class=\"token number\">172.21</span>.0.196 <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--name</span> verdaccio <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">-v</span> /www/wwwroot/nginx/html/verdaccio/storage:/verdaccio/storage <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">-v</span> /www/wwwroot/nginx/html/verdaccio/config:/verdaccio/conf <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">-v</span> /www/wwwroot/nginx/html/verdaccio/plugins:/verdaccio/plugins <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">-d</span> verdaccio/verdaccio<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n\n\n<p>配置nginx的反向代理conf注意所在的docker网络使用<code>container_name</code></p>\n<pre class=\"line-numbers language-conf\" data-language=\"conf\"><code class=\"language-conf\">server &#123;\n # listen 80;\n listen 443 ssl;\n server_name npm.mozzie.cn;\n ssl_certificate &#x2F;etc&#x2F;nginx&#x2F;ssl&#x2F;npm.mozzie.cn_bundle.pem;\n ssl_certificate_key &#x2F;etc&#x2F;nginx&#x2F;ssl&#x2F;npm.mozzie.cn.key;\n gzip on;\n\n location &#x2F; &#123;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header Host $host;\n proxy_set_header X-NginX-Proxy true;\n proxy_pass http:&#x2F;&#x2F;verdaccio:4873&#x2F;;\n proxy_redirect off;\n &#125;\n&#125;<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>运行添加用户,报错,因为 <code>htpasswd</code>默认创建在宿主机,也就是上面挂载的<code>/www/wwwroot/nginx/html/verdaccio/storage</code>目录中</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> adduser <span class=\"token parameter variable\">--registry</span> https://npm.mozzie.cn/<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>配置<code>htpasswd</code>、<code>storage</code> 文件夹权限</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 宿主机中执行</span>\n<span class=\"token builtin class-name\">cd</span> /www/wwwroot/nginx/html/verdaccio/storage\n<span class=\"token function\">touch</span> htpasswd\n<span class=\"token function\">sudo</span> <span class=\"token function\">chown</span> <span class=\"token number\">10001</span>:65533 htpasswd\n<span class=\"token function\">sudo</span> <span class=\"token function\">chown</span> <span class=\"token parameter variable\">-R</span> <span class=\"token number\">10001</span>:65533 /www/wwwroot/nginx/html/verdaccio/storage<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"verdaccio-用户管理\"><a href=\"#verdaccio-用户管理\" class=\"headerlink\" title=\"verdaccio 用户管理\"></a>verdaccio 用户管理</h1><p>由于在 <code>config.yml</code> 中关闭了可访问权限</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">auth</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">htpasswd</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">file</span><span class=\"token punctuation\">:</span> /verdaccio/storage/htpasswd\n <span class=\"token comment\"># 关闭注册手动添加用户默认Bcrypt算法</span>\n <span class=\"token key atrule\">max_users</span><span class=\"token punctuation\">:</span> <span class=\"token number\">-1</span>\n\n<span class=\"token key atrule\">packages</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">\"@*/*\"</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 可访问权限web界面看不见不登陆也无法 install 包</span>\n <span class=\"token key atrule\">access</span><span class=\"token punctuation\">:</span> $authenticated <span class=\"token comment\"># $all</span>\n <span class=\"token comment\"># 发布权限, $authenticated 表示只有通过验证的人</span>\n <span class=\"token key atrule\">publish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token comment\"># 可取消发布权限</span>\n <span class=\"token key atrule\">unpublish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token key atrule\">\"**\"</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">access</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token key atrule\">publish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token key atrule\">unpublish</span><span class=\"token punctuation\">:</span> $authenticated<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>默认的 <code>addUser</code> 策略是 <code>Bcrypt</code> 生成密码,随便找个网页生成个密码,使用<code>账号:密码</code>添加到 <code>htpasswd</code> 文件中,例如 </p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">test:<span class=\"token variable\">$2a</span><span class=\"token variable\">$10</span><span class=\"token variable\">$0xPGVnpcdxcfmFxtWyWDx</span>./TRtm/W/gSzib/jck3w.sF9x.Ur8t8W<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>因此在实际开发中,管理员手动给用户创建好账号,然后根据用户的包管理工具,进行登录,例如以 <code>npm</code> 为例</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> adduser <span class=\"token parameter variable\">--registry</span> https://npm.mozzie.cn/\n<span class=\"token comment\"># 输入 Username: mozzie | Password: xxx | Email: (this IS public) himozzie@foxmail.com</span>\n<span class=\"token comment\"># 提示登陆成功 Logged in as mozzie on https://npm.mozzie.cn/.</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>在系统的 <code>cat ~/.npmrc</code> 中会增加一行,就可以正常的进行以来的安装了</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">//npm.mozzie.cn/:_authToken<span class=\"token operator\">=</span><span class=\"token string\">\"Do/wrh5QzsnYaNU4x3ZlVA==\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h1 id=\"项目-npmrc-Scope区分\"><a href=\"#项目-npmrc-Scope区分\" class=\"headerlink\" title=\"项目 .npmrc Scope区分\"></a>项目 .npmrc Scope区分</h1><p>需要指定 <code>.npmrc</code> 来区别 <code>Scope</code> 的安装地址,例如一个包名为 <code>@mozzie/hook</code>,对应的私库为 <code>https://npm.mozzie.cn/</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token assign-left variable\">registry</span><span class=\"token operator\">=</span>http://registry.npm.taobao.org/\n@mozzie:registry<span class=\"token operator\">=</span>https://npm.mozzie.cn\n<span class=\"token comment\"># npm拉包的校验</span>\n//https://npm.mozzie.cn/:_authToken<span class=\"token operator\">=</span>xxxxxxxxxxxxx<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>","site":{"data":{}},"excerpt":"","more":"<h1 id=\"使用-docker-搭建-verdaccio\"><a href=\"#使用-docker-搭建-verdaccio\" class=\"headerlink\" title=\"使用 docker 搭建 verdaccio\"></a>使用 docker 搭建 verdaccio</h1><p>创建 &amp; 配置<code>config.yaml</code>文件</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token comment\"># Read about the best practices</span>\n<span class=\"token comment\"># https://verdaccio.org/docs/best</span>\n\n<span class=\"token comment\"># path to a directory with all packages</span>\n<span class=\"token key atrule\">storage</span><span class=\"token punctuation\">:</span> /verdaccio/storage/data\n<span class=\"token comment\"># path to a directory with plugins to include</span>\n<span class=\"token key atrule\">plugins</span><span class=\"token punctuation\">:</span> /verdaccio/plugins\n\n<span class=\"token comment\"># 包体积上限默认10mb</span>\n<span class=\"token key atrule\">max_body_size</span><span class=\"token punctuation\">:</span> 1024mb\n\n\n<span class=\"token key atrule\">web</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> Mozzie<span class=\"token punctuation\">-</span>NPM\n <span class=\"token comment\"># gravatar: false</span>\n <span class=\"token comment\"># login: true</span>\n <span class=\"token key atrule\">pkgManagers</span><span class=\"token punctuation\">:</span>\n <span class=\"token punctuation\">-</span> npm\n <span class=\"token punctuation\">-</span> yarn\n <span class=\"token punctuation\">-</span> pnpm\n <span class=\"token key atrule\">html_cache</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n <span class=\"token key atrule\">showFooter</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span>\n\n<span class=\"token key atrule\">auth</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">htpasswd</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">file</span><span class=\"token punctuation\">:</span> /verdaccio/storage/htpasswd\n <span class=\"token comment\"># 关闭注册手动添加用户默认Bcrypt算法随便找个网页生成个密码使用账号:密码添加到 htpasswd 文件中,例如 test:$2a$10$0xPGVnpcdxcfmFxtWyWDx./TRtm/W/gSzib/jck3w.sF9x.Ur8t8W</span>\n <span class=\"token key atrule\">max_users</span><span class=\"token punctuation\">:</span> <span class=\"token number\">-1</span>\n\n\n<span class=\"token key atrule\">i18n</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">web</span><span class=\"token punctuation\">:</span> zh<span class=\"token punctuation\">-</span>CN\n\n<span class=\"token comment\"># notify: # 配置 Webhook 推送到钉钉,记得修改 access_token 和 atMobiles</span>\n<span class=\"token comment\"># method: POST</span>\n<span class=\"token comment\"># headers: [&#123; \"Content-Type\": \"application/json\" &#125;]</span>\n<span class=\"token comment\"># endpoint: https://oapi.dingtalk.com/robot/send?access_token=xxxx</span>\n<span class=\"token comment\"># content: '&#123;\"msgtype\":\"text\", \"at\": &#123;\"atMobiles\": [\"13000000000\"] &#125;, \"text\":&#123;\"content\":\"NPM 发布新包:\\n > 包名称:&#123;&#123;name&#125;&#125; \\n > 版本号:&#123;&#123;#each versions&#125;&#125;&#123;&#123;version&#125;&#125;&#123;&#123;/each&#125;&#125; \\n > 发布者:&#123;&#123;publisher.name&#125;&#125; \"&#125;&#125;'</span>\n\n<span class=\"token key atrule\">uplinks</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">npmjs</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//registry.npmjs.org/\n <span class=\"token key atrule\">yarn</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//registry.yarnpkg.com/\n <span class=\"token key atrule\">timeout</span><span class=\"token punctuation\">:</span> 10s\n <span class=\"token key atrule\">taobao</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//registry.npmmirror.com/\n <span class=\"token key atrule\">timeout</span><span class=\"token punctuation\">:</span> 10s\n\n<span class=\"token key atrule\">packages</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">\"@*/*\"</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 可访问权限web界面看不见不登陆也无法 install 包</span>\n <span class=\"token key atrule\">access</span><span class=\"token punctuation\">:</span> $authenticated <span class=\"token comment\"># $all</span>\n <span class=\"token comment\"># 发布权限, $authenticated 表示只有通过验证的人</span>\n <span class=\"token key atrule\">publish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token comment\"># 可取消发布权限</span>\n <span class=\"token key atrule\">unpublish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token comment\"># 包不存在时的代理</span>\n <span class=\"token key atrule\">proxy</span><span class=\"token punctuation\">:</span> npmjs yarn taobao\n <span class=\"token key atrule\">\"**\"</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">access</span><span class=\"token punctuation\">:</span> $authenticated <span class=\"token comment\"># $all</span>\n <span class=\"token key atrule\">publish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token key atrule\">unpublish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token key atrule\">proxy</span><span class=\"token punctuation\">:</span> npmjs yarn taobao\n\n<span class=\"token key atrule\">middlewares</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">audit</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">enabled</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n<span class=\"token key atrule\">listen</span><span class=\"token punctuation\">:</span> 0.0.0.0<span class=\"token punctuation\">:</span><span class=\"token number\">4873</span>\n<span class=\"token key atrule\">log</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token key atrule\">type</span><span class=\"token punctuation\">:</span> stdout<span class=\"token punctuation\">,</span> <span class=\"token key atrule\">format</span><span class=\"token punctuation\">:</span> pretty<span class=\"token punctuation\">,</span> <span class=\"token key atrule\">level</span><span class=\"token punctuation\">:</span> http <span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>创建容器,环境变量,<code>VERDACCIO_PUBLIC_URL</code>是静态资源的前缀地址由于nginx挂了<code>ssl</code>,如果使用<code>http</code>可以不添加</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">docker</span> run <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">-p</span> <span class=\"token number\">4873</span>:4873 <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--restart</span><span class=\"token operator\">=</span>always <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--network</span> mozzie.cn-net <span class=\"token punctuation\">\\</span>\n--network-alias verdaccio <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--env</span> <span class=\"token assign-left variable\">VERDACCIO_PORT</span><span class=\"token operator\">=</span><span class=\"token number\">4873</span> <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--env</span> <span class=\"token assign-left variable\">VERDACCIO_PUBLIC_URL</span><span class=\"token operator\">=</span>https://npm.mozzie.cn <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--ip</span> <span class=\"token number\">172.21</span>.0.196 <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">--name</span> verdaccio <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">-v</span> /www/wwwroot/nginx/html/verdaccio/storage:/verdaccio/storage <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">-v</span> /www/wwwroot/nginx/html/verdaccio/config:/verdaccio/conf <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">-v</span> /www/wwwroot/nginx/html/verdaccio/plugins:/verdaccio/plugins <span class=\"token punctuation\">\\</span>\n<span class=\"token parameter variable\">-d</span> verdaccio/verdaccio<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n\n\n<p>配置nginx的反向代理conf注意所在的docker网络使用<code>container_name</code></p>\n<pre class=\"line-numbers language-conf\" data-language=\"conf\"><code class=\"language-conf\">server &#123;\n # listen 80;\n listen 443 ssl;\n server_name npm.mozzie.cn;\n ssl_certificate &#x2F;etc&#x2F;nginx&#x2F;ssl&#x2F;npm.mozzie.cn_bundle.pem;\n ssl_certificate_key &#x2F;etc&#x2F;nginx&#x2F;ssl&#x2F;npm.mozzie.cn.key;\n gzip on;\n\n location &#x2F; &#123;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header Host $host;\n proxy_set_header X-NginX-Proxy true;\n proxy_pass http:&#x2F;&#x2F;verdaccio:4873&#x2F;;\n proxy_redirect off;\n &#125;\n&#125;<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>运行添加用户,报错,因为 <code>htpasswd</code>默认创建在宿主机,也就是上面挂载的<code>/www/wwwroot/nginx/html/verdaccio/storage</code>目录中</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> adduser <span class=\"token parameter variable\">--registry</span> https://npm.mozzie.cn/<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>配置<code>htpasswd</code>、<code>storage</code> 文件夹权限</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 宿主机中执行</span>\n<span class=\"token builtin class-name\">cd</span> /www/wwwroot/nginx/html/verdaccio/storage\n<span class=\"token function\">touch</span> htpasswd\n<span class=\"token function\">sudo</span> <span class=\"token function\">chown</span> <span class=\"token number\">10001</span>:65533 htpasswd\n<span class=\"token function\">sudo</span> <span class=\"token function\">chown</span> <span class=\"token parameter variable\">-R</span> <span class=\"token number\">10001</span>:65533 /www/wwwroot/nginx/html/verdaccio/storage<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"verdaccio-用户管理\"><a href=\"#verdaccio-用户管理\" class=\"headerlink\" title=\"verdaccio 用户管理\"></a>verdaccio 用户管理</h1><p>由于在 <code>config.yml</code> 中关闭了可访问权限</p>\n<pre class=\"line-numbers language-yaml\" data-language=\"yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">auth</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">htpasswd</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">file</span><span class=\"token punctuation\">:</span> /verdaccio/storage/htpasswd\n <span class=\"token comment\"># 关闭注册手动添加用户默认Bcrypt算法</span>\n <span class=\"token key atrule\">max_users</span><span class=\"token punctuation\">:</span> <span class=\"token number\">-1</span>\n\n<span class=\"token key atrule\">packages</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">\"@*/*\"</span><span class=\"token punctuation\">:</span>\n <span class=\"token comment\"># 可访问权限web界面看不见不登陆也无法 install 包</span>\n <span class=\"token key atrule\">access</span><span class=\"token punctuation\">:</span> $authenticated <span class=\"token comment\"># $all</span>\n <span class=\"token comment\"># 发布权限, $authenticated 表示只有通过验证的人</span>\n <span class=\"token key atrule\">publish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token comment\"># 可取消发布权限</span>\n <span class=\"token key atrule\">unpublish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token key atrule\">\"**\"</span><span class=\"token punctuation\">:</span>\n <span class=\"token key atrule\">access</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token key atrule\">publish</span><span class=\"token punctuation\">:</span> $authenticated\n <span class=\"token key atrule\">unpublish</span><span class=\"token punctuation\">:</span> $authenticated<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>默认的 <code>addUser</code> 策略是 <code>Bcrypt</code> 生成密码,随便找个网页生成个密码,使用<code>账号:密码</code>添加到 <code>htpasswd</code> 文件中,例如 </p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">test:<span class=\"token variable\">$2a</span><span class=\"token variable\">$10</span><span class=\"token variable\">$0xPGVnpcdxcfmFxtWyWDx</span>./TRtm/W/gSzib/jck3w.sF9x.Ur8t8W<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>因此在实际开发中,管理员手动给用户创建好账号,然后根据用户的包管理工具,进行登录,例如以 <code>npm</code> 为例</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> adduser <span class=\"token parameter variable\">--registry</span> https://npm.mozzie.cn/\n<span class=\"token comment\"># 输入 Username: mozzie | Password: xxx | Email: (this IS public) himozzie@foxmail.com</span>\n<span class=\"token comment\"># 提示登陆成功 Logged in as mozzie on https://npm.mozzie.cn/.</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>在系统的 <code>cat ~/.npmrc</code> 中会增加一行,就可以正常的进行以来的安装了</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">//npm.mozzie.cn/:_authToken<span class=\"token operator\">=</span><span class=\"token string\">\"Do/wrh5QzsnYaNU4x3ZlVA==\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h1 id=\"项目-npmrc-Scope区分\"><a href=\"#项目-npmrc-Scope区分\" class=\"headerlink\" title=\"项目 .npmrc Scope区分\"></a>项目 .npmrc Scope区分</h1><p>需要指定 <code>.npmrc</code> 来区别 <code>Scope</code> 的安装地址,例如一个包名为 <code>@mozzie/hook</code>,对应的私库为 <code>https://npm.mozzie.cn/</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token assign-left variable\">registry</span><span class=\"token operator\">=</span>http://registry.npm.taobao.org/\n@mozzie:registry<span class=\"token operator\">=</span>https://npm.mozzie.cn\n<span class=\"token comment\"># npm拉包的校验</span>\n//https://npm.mozzie.cn/:_authToken<span class=\"token operator\">=</span>xxxxxxxxxxxxx<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>"},{"title":"wsl2","status":"done","_content":"\n# 安装 wsl\n\n前置条件主板 bios 开启 `intel 虚拟化`\n\n> ms app store如果打不开、转圈 -> 关闭小飞机,也可以试试 改 ipv4 host 4.2.2.2\n\n- windows terminal 必备ms store 下载\n\n[巨硬官方文档](https://docs.microsoft.com/en-us/windows/wsl/install)\n\n# ubuntu软件源\n\n[阿里开源镜像站](https://developer.aliyun.com/mirror/)\n\n下面是 ubuntu20.04 用的\n\n```bash\n# 备份apt默认源\nsudo cp /etc/apt/sources.list /etc/apt/sources.list.bak\nsudo vim /etc/apt/sources.list\n# 替换 /srouces.list\ndeb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\n\n# deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse\n# deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\n\n\n# 更新apt\nsudo apt upgrade\nsudo apt update\n```\n\n# 安装 zsh\n\n> 注意`.zshrc`在安装的`用户`目录下,别和`root`搞混了\n\n```bash\n# 安装\nsudo apt install zsh\n# 将 zsh 设置为默认 shell\nchsh -s /bin/zsh\n# 检查,若没成功,重启试试看\necho $SHELL\n```\n\n# 安装 oh-my-zsh\n\n```bash\n# 443 confused 手动 vim oh-my-zsh.sh 然后 bash ./oh-my-zsh.sh \nsh -c \"$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\"\n```\n\n# 配置 oh-my-zsh 主题/插件/alias\n\n安装插件\n\n- 自动补全: \n\n```bash\ngit clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions\n```\n\n- 代码高亮: \n\n```bash\ngit clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting\n```\n\n修改`当前用户`目录下的 `.zshrc`\n\n```bash\n# 主题\nZSH_THEME=\"ys\"\n# 引入插件\nplugins=(git zsh-autosuggestions zsh-syntax-highlighting)\n# alias\nalias cls='clear'\nalias ga='git add'\nalias gc='git commit -m'\nalias gp='git push'\nalias gf='git fetch'\nalias update='sudo apt update'\nalias upgrade='sudo apt upgrade'\nalias install='sudo apt install'\n# windows文件管理器打开wsl文件\nalias open='explorer.exe'\n```\n\n# 安装 Nodejs\n\n[巨硬文档赛高](https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl)\n\n安装完注意文字提示\n\n```bash\n# =>Appending nvm source string to /home/mozzie/.zshrc\n# => Appending bash_completion source string to /home/mozzie/.zshrc\n# => Close and reopen your terminal to start using nvm or run the following to use it now:\n```\n照它说的做\n\n```bash\nexport NVM_DIR=\"$HOME/.nvm\"\n[ -s \"$NVM_DIR/nvm.sh\" ] && \\. \"$NVM_DIR/nvm.sh\" # This loads nvm\n[ -s \"$NVM_DIR/bash_completion\" ] && \\. \"$NVM_DIR/bash_completion\" # This loads nvm bash_completion\n```\n\n验证`nvm`安装 `nvm ls`,会看见类似\n\n```bash\niojs -> N/A (default)\nnode -> stable (-> N/A) (default)\nunstable -> N/A (default)\n```\n\n安装 `nodejs stable`\n\n```bash\nnvm install node\n# node -v | npm -v 验证安装版本\n```\n\n# 外网/LAN 访问 wsl2 服务\n\n[巨硬官方解释](https://docs.microsoft.com/en-us/windows/wsl/networking)\n\nWhen using a WSL 1 distribution, if your computer was set up to be accessed by your LAN, then applications run in WSL could be accessed on your LAN as well.\n\nThis isn't the default case in WSL 2. WSL 2 has a virtualized ethernet adapter with its own unique IP address. Currently, to enable this workflow you will need to go through the same steps as you would for a regular virtual machine. (We are looking into ways to improve this experience.)\n\nHere's an example PowerShell command to add a port proxy that listens on port 4000 on the host and connects it to port 4000 to the WSL 2 VM with IP address 192.168.101.100\n\n```bash\nnetsh interface portproxy add v4tov4 listenport=4000 listenaddress=0.0.0.0 connectport=4000 connectaddress=192.168.101.100\n```\n> 注意端口覆盖的问题,避免 windows 端口和端口 wsl2 冲突\n\n## netsh 端口映射\n\n- listenaddress: 监听地址, 0.0.0.0 表示匹配所有地址\n- listenport: 监听的 windows 端口\n\n- connectaddress: 转发到 wsl2 的 ip地址, 这里设置为localhost默认从 windows 可以通过localhost 访问 wsl2\n- connectport: 转发到 wsl2 的端口\n\n例如 windows 的 ip 为 `192.168.1.100`,监听 windows 的 3000 端口,转发到 wsl2 ip localhost 的 3000 端口\n\n```bash\n# windows-terminal 管理员权限执行\nnetsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=localhost\n# 删除端口监听\nnetsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=3000\n```\n\n## 配置 windows defender 防火墙入站规则\n\n新建规则 -> 端口 -> TCP / 特定本地端口(3000) -> 允许链接 -> 下一步 -> 取个名字 -> Done\n\n# docker \n\nwindows 宿主机安装 `docker desktop``设置 -> 资源 -> WSL INTEGRATION` 打开 对应的 linux发行版即使用\n\n## mysql 容器\n\n```bash\n# brdige\ndocker network create --driver bridge --subnet=172.21.0.0/16 wsl2\n# pull\ndocker pull mysql:5.7.38\n# 生产 mysql 5.7.38 容器\ndocker run --restart=always --privileged=true -p 3306:3306 --name mysql --net wsl2 --ip 172.21.0.5 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7.38\n```\n\n## mongo 容器\n\n```bash\ndocker pull mongo:5.0\n# 宿主机 /mongo/data\ndocker run --restart=always -d -p 27017:27017 -v /mongo/data:/data --name mongo --net wsl2 --ip 172.21.0.6 mongo:5.0 --auth\n# 初始化\ndocker exec -it mongo /bin/bash\n# 进入 mongo shell\nmongo\n# admin\nuse admin\n# 创建root用户管理全部数据库的权限这会可以navicat等gui链接数据库用户名密码root验证数据库admin\ndb.createUser({\n user: \"root\",\n pwd: \"root\",\n roles: [ { role: \"userAdminAnyDatabase\", db: \"admin\" } ]\n})\n# 退出\nexit\n# 再次进入\nmongo\n# 使用root登录授权正确返回 1\ndb.auth(\"root\",\"root\")\n# 创建 testDB 数据库\nuse testDB\n# 创建 test 用户 管理 testDB\ndb.createUser({user:'test',pwd:'test',roles:[{role:'dbOwner',db:'testDB'}]})\n```\n\n使用 navicat 登录,验证数据库 `admin` ,用户名密码 `test`\n\n\n# 默认 wsl root 用户登录\n\n```bash\n# wsl -l 查看 ubuntu版本例如 Ubuntu-20.04\nUbuntu2004 config --default-user root\n```\n","source":"_posts/front-end/wsl2.md","raw":"---\ntitle: wsl2\ncategories:\n - Front-End\nstatus: done\n---\n\n# 安装 wsl\n\n前置条件主板 bios 开启 `intel 虚拟化`\n\n> ms app store如果打不开、转圈 -> 关闭小飞机,也可以试试 改 ipv4 host 4.2.2.2\n\n- windows terminal 必备ms store 下载\n\n[巨硬官方文档](https://docs.microsoft.com/en-us/windows/wsl/install)\n\n# ubuntu软件源\n\n[阿里开源镜像站](https://developer.aliyun.com/mirror/)\n\n下面是 ubuntu20.04 用的\n\n```bash\n# 备份apt默认源\nsudo cp /etc/apt/sources.list /etc/apt/sources.list.bak\nsudo vim /etc/apt/sources.list\n# 替换 /srouces.list\ndeb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\n\n# deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse\n# deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\n\n\n# 更新apt\nsudo apt upgrade\nsudo apt update\n```\n\n# 安装 zsh\n\n> 注意`.zshrc`在安装的`用户`目录下,别和`root`搞混了\n\n```bash\n# 安装\nsudo apt install zsh\n# 将 zsh 设置为默认 shell\nchsh -s /bin/zsh\n# 检查,若没成功,重启试试看\necho $SHELL\n```\n\n# 安装 oh-my-zsh\n\n```bash\n# 443 confused 手动 vim oh-my-zsh.sh 然后 bash ./oh-my-zsh.sh \nsh -c \"$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\"\n```\n\n# 配置 oh-my-zsh 主题/插件/alias\n\n安装插件\n\n- 自动补全: \n\n```bash\ngit clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions\n```\n\n- 代码高亮: \n\n```bash\ngit clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting\n```\n\n修改`当前用户`目录下的 `.zshrc`\n\n```bash\n# 主题\nZSH_THEME=\"ys\"\n# 引入插件\nplugins=(git zsh-autosuggestions zsh-syntax-highlighting)\n# alias\nalias cls='clear'\nalias ga='git add'\nalias gc='git commit -m'\nalias gp='git push'\nalias gf='git fetch'\nalias update='sudo apt update'\nalias upgrade='sudo apt upgrade'\nalias install='sudo apt install'\n# windows文件管理器打开wsl文件\nalias open='explorer.exe'\n```\n\n# 安装 Nodejs\n\n[巨硬文档赛高](https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl)\n\n安装完注意文字提示\n\n```bash\n# =>Appending nvm source string to /home/mozzie/.zshrc\n# => Appending bash_completion source string to /home/mozzie/.zshrc\n# => Close and reopen your terminal to start using nvm or run the following to use it now:\n```\n照它说的做\n\n```bash\nexport NVM_DIR=\"$HOME/.nvm\"\n[ -s \"$NVM_DIR/nvm.sh\" ] && \\. \"$NVM_DIR/nvm.sh\" # This loads nvm\n[ -s \"$NVM_DIR/bash_completion\" ] && \\. \"$NVM_DIR/bash_completion\" # This loads nvm bash_completion\n```\n\n验证`nvm`安装 `nvm ls`,会看见类似\n\n```bash\niojs -> N/A (default)\nnode -> stable (-> N/A) (default)\nunstable -> N/A (default)\n```\n\n安装 `nodejs stable`\n\n```bash\nnvm install node\n# node -v | npm -v 验证安装版本\n```\n\n# 外网/LAN 访问 wsl2 服务\n\n[巨硬官方解释](https://docs.microsoft.com/en-us/windows/wsl/networking)\n\nWhen using a WSL 1 distribution, if your computer was set up to be accessed by your LAN, then applications run in WSL could be accessed on your LAN as well.\n\nThis isn't the default case in WSL 2. WSL 2 has a virtualized ethernet adapter with its own unique IP address. Currently, to enable this workflow you will need to go through the same steps as you would for a regular virtual machine. (We are looking into ways to improve this experience.)\n\nHere's an example PowerShell command to add a port proxy that listens on port 4000 on the host and connects it to port 4000 to the WSL 2 VM with IP address 192.168.101.100\n\n```bash\nnetsh interface portproxy add v4tov4 listenport=4000 listenaddress=0.0.0.0 connectport=4000 connectaddress=192.168.101.100\n```\n> 注意端口覆盖的问题,避免 windows 端口和端口 wsl2 冲突\n\n## netsh 端口映射\n\n- listenaddress: 监听地址, 0.0.0.0 表示匹配所有地址\n- listenport: 监听的 windows 端口\n\n- connectaddress: 转发到 wsl2 的 ip地址, 这里设置为localhost默认从 windows 可以通过localhost 访问 wsl2\n- connectport: 转发到 wsl2 的端口\n\n例如 windows 的 ip 为 `192.168.1.100`,监听 windows 的 3000 端口,转发到 wsl2 ip localhost 的 3000 端口\n\n```bash\n# windows-terminal 管理员权限执行\nnetsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=localhost\n# 删除端口监听\nnetsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=3000\n```\n\n## 配置 windows defender 防火墙入站规则\n\n新建规则 -> 端口 -> TCP / 特定本地端口(3000) -> 允许链接 -> 下一步 -> 取个名字 -> Done\n\n# docker \n\nwindows 宿主机安装 `docker desktop``设置 -> 资源 -> WSL INTEGRATION` 打开 对应的 linux发行版即使用\n\n## mysql 容器\n\n```bash\n# brdige\ndocker network create --driver bridge --subnet=172.21.0.0/16 wsl2\n# pull\ndocker pull mysql:5.7.38\n# 生产 mysql 5.7.38 容器\ndocker run --restart=always --privileged=true -p 3306:3306 --name mysql --net wsl2 --ip 172.21.0.5 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7.38\n```\n\n## mongo 容器\n\n```bash\ndocker pull mongo:5.0\n# 宿主机 /mongo/data\ndocker run --restart=always -d -p 27017:27017 -v /mongo/data:/data --name mongo --net wsl2 --ip 172.21.0.6 mongo:5.0 --auth\n# 初始化\ndocker exec -it mongo /bin/bash\n# 进入 mongo shell\nmongo\n# admin\nuse admin\n# 创建root用户管理全部数据库的权限这会可以navicat等gui链接数据库用户名密码root验证数据库admin\ndb.createUser({\n user: \"root\",\n pwd: \"root\",\n roles: [ { role: \"userAdminAnyDatabase\", db: \"admin\" } ]\n})\n# 退出\nexit\n# 再次进入\nmongo\n# 使用root登录授权正确返回 1\ndb.auth(\"root\",\"root\")\n# 创建 testDB 数据库\nuse testDB\n# 创建 test 用户 管理 testDB\ndb.createUser({user:'test',pwd:'test',roles:[{role:'dbOwner',db:'testDB'}]})\n```\n\n使用 navicat 登录,验证数据库 `admin` ,用户名密码 `test`\n\n\n# 默认 wsl root 用户登录\n\n```bash\n# wsl -l 查看 ubuntu版本例如 Ubuntu-20.04\nUbuntu2004 config --default-user root\n```\n","slug":"front-end/wsl2","published":1,"date":"2023-11-06T07:59:45.720Z","updated":"2023-11-06T08:02:38.239Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58q000i4cz39r1m7266","content":"<h1 id=\"安装-wsl\"><a href=\"#安装-wsl\" class=\"headerlink\" title=\"安装 wsl\"></a>安装 wsl</h1><p>前置条件,主板 bios 开启 <code>intel 虚拟化</code></p>\n<blockquote>\n<p>ms app store如果打不开、转圈 -&gt; 关闭小飞机,也可以试试 改 ipv4 host 4.2.2.2</p>\n</blockquote>\n<ul>\n<li>windows terminal 必备ms store 下载</li>\n</ul>\n<p><a href=\"https://docs.microsoft.com/en-us/windows/wsl/install\">巨硬官方文档</a></p>\n<h1 id=\"ubuntu软件源\"><a href=\"#ubuntu软件源\" class=\"headerlink\" title=\"ubuntu软件源\"></a>ubuntu软件源</h1><p><a href=\"https://developer.aliyun.com/mirror/\">阿里开源镜像站</a></p>\n<p>下面是 ubuntu20.04 用的</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 备份apt默认源</span>\n<span class=\"token function\">sudo</span> <span class=\"token function\">cp</span> /etc/apt/sources.list /etc/apt/sources.list.bak\n<span class=\"token function\">sudo</span> <span class=\"token function\">vim</span> /etc/apt/sources.list\n<span class=\"token comment\"># 替换 /srouces.list</span>\ndeb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\n\n<span class=\"token comment\"># deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse</span>\n<span class=\"token comment\"># deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse</span>\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\n\n\n<span class=\"token comment\"># 更新apt</span>\n<span class=\"token function\">sudo</span> <span class=\"token function\">apt</span> upgrade\n<span class=\"token function\">sudo</span> <span class=\"token function\">apt</span> update<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"安装-zsh\"><a href=\"#安装-zsh\" class=\"headerlink\" title=\"安装 zsh\"></a>安装 zsh</h1><blockquote>\n<p>注意<code>.zshrc</code>在安装的<code>用户</code>目录下,别和<code>root</code>搞混了</p>\n</blockquote>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 安装</span>\n<span class=\"token function\">sudo</span> <span class=\"token function\">apt</span> <span class=\"token function\">install</span> <span class=\"token function\">zsh</span>\n<span class=\"token comment\"># 将 zsh 设置为默认 shell</span>\nchsh <span class=\"token parameter variable\">-s</span> /bin/zsh\n<span class=\"token comment\"># 检查,若没成功,重启试试看</span>\n<span class=\"token builtin class-name\">echo</span> <span class=\"token environment constant\">$SHELL</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"安装-oh-my-zsh\"><a href=\"#安装-oh-my-zsh\" class=\"headerlink\" title=\"安装 oh-my-zsh\"></a>安装 oh-my-zsh</h1><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 443 confused 手动 vim oh-my-zsh.sh 然后 bash ./oh-my-zsh.sh </span>\n<span class=\"token function\">sh</span> <span class=\"token parameter variable\">-c</span> <span class=\"token string\">\"<span class=\"token variable\"><span class=\"token variable\">$(</span><span class=\"token function\">curl</span> <span class=\"token parameter variable\">-fsSL</span> https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh<span class=\"token variable\">)</span></span>\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"配置-oh-my-zsh-主题-x2F-插件-x2F-alias\"><a href=\"#配置-oh-my-zsh-主题-x2F-插件-x2F-alias\" class=\"headerlink\" title=\"配置 oh-my-zsh 主题&#x2F;插件&#x2F;alias\"></a>配置 oh-my-zsh 主题&#x2F;插件&#x2F;alias</h1><p>安装插件</p>\n<ul>\n<li>自动补全:</li>\n</ul>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> clone https://github.com/zsh-users/zsh-autosuggestions <span class=\"token variable\">$&#123;ZSH_CUSTOM<span class=\"token operator\">:-</span>~<span class=\"token operator\">/</span>.oh-my-zsh<span class=\"token operator\">/</span>custom&#125;</span>/plugins/zsh-autosuggestions<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<ul>\n<li>代码高亮:</li>\n</ul>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> clone https://github.com/zsh-users/zsh-syntax-highlighting.git <span class=\"token variable\">$&#123;ZSH_CUSTOM<span class=\"token operator\">:-</span>~<span class=\"token operator\">/</span>.oh-my-zsh<span class=\"token operator\">/</span>custom&#125;</span>/plugins/zsh-syntax-highlighting<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>修改<code>当前用户</code>目录下的 <code>.zshrc</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 主题</span>\n<span class=\"token assign-left variable\">ZSH_THEME</span><span class=\"token operator\">=</span><span class=\"token string\">\"ys\"</span>\n<span class=\"token comment\"># 引入插件</span>\n<span class=\"token assign-left variable\">plugins</span><span class=\"token operator\">=</span><span class=\"token punctuation\">(</span>git zsh-autosuggestions zsh-syntax-highlighting<span class=\"token punctuation\">)</span>\n<span class=\"token comment\"># alias</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">cls</span><span class=\"token operator\">=</span><span class=\"token string\">'clear'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">ga</span><span class=\"token operator\">=</span><span class=\"token string\">'git add'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gc</span><span class=\"token operator\">=</span><span class=\"token string\">'git commit -m'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gp</span><span class=\"token operator\">=</span><span class=\"token string\">'git push'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gf</span><span class=\"token operator\">=</span><span class=\"token string\">'git fetch'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">update</span><span class=\"token operator\">=</span><span class=\"token string\">'sudo apt update'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">upgrade</span><span class=\"token operator\">=</span><span class=\"token string\">'sudo apt upgrade'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">install</span><span class=\"token operator\">=</span><span class=\"token string\">'sudo apt install'</span>\n<span class=\"token comment\"># windows文件管理器打开wsl文件</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">open</span><span class=\"token operator\">=</span><span class=\"token string\">'explorer.exe'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"安装-Nodejs\"><a href=\"#安装-Nodejs\" class=\"headerlink\" title=\"安装 Nodejs\"></a>安装 Nodejs</h1><p><a href=\"https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl\">巨硬文档赛高</a></p>\n<p>安装完注意文字提示</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># =>Appending nvm source string to /home/mozzie/.zshrc</span>\n<span class=\"token comment\"># => Appending bash_completion source string to /home/mozzie/.zshrc</span>\n<span class=\"token comment\"># => Close and reopen your terminal to start using nvm or run the following to use it now:</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n<p>照它说的做</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\">NVM_DIR</span><span class=\"token operator\">=</span><span class=\"token string\">\"<span class=\"token environment constant\">$HOME</span>/.nvm\"</span>\n<span class=\"token punctuation\">[</span> <span class=\"token parameter variable\">-s</span> <span class=\"token string\">\"<span class=\"token variable\">$NVM_DIR</span>/nvm.sh\"</span> <span class=\"token punctuation\">]</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token punctuation\">\\</span>. <span class=\"token string\">\"<span class=\"token variable\">$NVM_DIR</span>/nvm.sh\"</span> <span class=\"token comment\"># This loads nvm</span>\n<span class=\"token punctuation\">[</span> <span class=\"token parameter variable\">-s</span> <span class=\"token string\">\"<span class=\"token variable\">$NVM_DIR</span>/bash_completion\"</span> <span class=\"token punctuation\">]</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token punctuation\">\\</span>. <span class=\"token string\">\"<span class=\"token variable\">$NVM_DIR</span>/bash_completion\"</span> <span class=\"token comment\"># This loads nvm bash_completion</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>验证<code>nvm</code>安装 <code>nvm ls</code>,会看见类似</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">iojs -<span class=\"token operator\">></span> N/A <span class=\"token punctuation\">(</span>default<span class=\"token punctuation\">)</span>\n<span class=\"token function\">node</span> -<span class=\"token operator\">></span> stable <span class=\"token punctuation\">(</span>-<span class=\"token operator\">></span> N/A<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span>default<span class=\"token punctuation\">)</span>\nunstable -<span class=\"token operator\">></span> N/A <span class=\"token punctuation\">(</span>default<span class=\"token punctuation\">)</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>安装 <code>nodejs stable</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">nvm <span class=\"token function\">install</span> <span class=\"token function\">node</span>\n<span class=\"token comment\"># node -v | npm -v 验证安装版本</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"外网-x2F-LAN-访问-wsl2-服务\"><a href=\"#外网-x2F-LAN-访问-wsl2-服务\" class=\"headerlink\" title=\"外网&#x2F;LAN 访问 wsl2 服务\"></a>外网&#x2F;LAN 访问 wsl2 服务</h1><p><a href=\"https://docs.microsoft.com/en-us/windows/wsl/networking\">巨硬官方解释</a></p>\n<p>When using a WSL 1 distribution, if your computer was set up to be accessed by your LAN, then applications run in WSL could be accessed on your LAN as well.</p>\n<p>This isnt the default case in WSL 2. WSL 2 has a virtualized ethernet adapter with its own unique IP address. Currently, to enable this workflow you will need to go through the same steps as you would for a regular virtual machine. (We are looking into ways to improve this experience.)</p>\n<p>Heres an example PowerShell command to add a port proxy that listens on port 4000 on the host and connects it to port 4000 to the WSL 2 VM with IP address 192.168.101.100</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">netsh interface portproxy <span class=\"token function\">add</span> v4tov4 <span class=\"token assign-left variable\">listenport</span><span class=\"token operator\">=</span><span class=\"token number\">4000</span> <span class=\"token assign-left variable\">listenaddress</span><span class=\"token operator\">=</span><span class=\"token number\">0.0</span>.0.0 <span class=\"token assign-left variable\">connectport</span><span class=\"token operator\">=</span><span class=\"token number\">4000</span> <span class=\"token assign-left variable\">connectaddress</span><span class=\"token operator\">=</span><span class=\"token number\">192.168</span>.101.100<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n<blockquote>\n<p>注意端口覆盖的问题,避免 windows 端口和端口 wsl2 冲突</p>\n</blockquote>\n<h2 id=\"netsh-端口映射\"><a href=\"#netsh-端口映射\" class=\"headerlink\" title=\"netsh 端口映射\"></a>netsh 端口映射</h2><ul>\n<li><p>listenaddress: 监听地址, 0.0.0.0 表示匹配所有地址</p>\n</li>\n<li><p>listenport: 监听的 windows 端口</p>\n</li>\n<li><p>connectaddress: 转发到 wsl2 的 ip地址, 这里设置为localhost默认从 windows 可以通过localhost 访问 wsl2</p>\n</li>\n<li><p>connectport: 转发到 wsl2 的端口</p>\n</li>\n</ul>\n<p>例如 windows 的 ip 为 <code>192.168.1.100</code>,监听 windows 的 3000 端口,转发到 wsl2 ip localhost 的 3000 端口</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># windows-terminal 管理员权限执行</span>\nnetsh interface portproxy <span class=\"token function\">add</span> v4tov4 <span class=\"token assign-left variable\">listenport</span><span class=\"token operator\">=</span><span class=\"token number\">3000</span> <span class=\"token assign-left variable\">listenaddress</span><span class=\"token operator\">=</span><span class=\"token number\">0.0</span>.0.0 <span class=\"token assign-left variable\">connectport</span><span class=\"token operator\">=</span><span class=\"token number\">3000</span> <span class=\"token assign-left variable\">connectaddress</span><span class=\"token operator\">=</span>localhost\n<span class=\"token comment\"># 删除端口监听</span>\nnetsh interface portproxy delete v4tov4 <span class=\"token assign-left variable\">listenaddress</span><span class=\"token operator\">=</span><span class=\"token number\">0.0</span>.0.0 <span class=\"token assign-left variable\">listenport</span><span class=\"token operator\">=</span><span class=\"token number\">3000</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"配置-windows-defender-防火墙入站规则\"><a href=\"#配置-windows-defender-防火墙入站规则\" class=\"headerlink\" title=\"配置 windows defender 防火墙入站规则\"></a>配置 windows defender 防火墙入站规则</h2><p>新建规则 -&gt; 端口 -&gt; TCP &#x2F; 特定本地端口(3000) -&gt; 允许链接 -&gt; 下一步 -&gt; 取个名字 -&gt; Done</p>\n<h1 id=\"docker\"><a href=\"#docker\" class=\"headerlink\" title=\"docker\"></a>docker</h1><p>windows 宿主机安装 <code>docker desktop</code><code>设置 -&gt; 资源 -&gt; WSL INTEGRATION</code> 打开 对应的 linux发行版即使用</p>\n<h2 id=\"mysql-容器\"><a href=\"#mysql-容器\" class=\"headerlink\" title=\"mysql 容器\"></a>mysql 容器</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># brdige</span>\n<span class=\"token function\">docker</span> network create <span class=\"token parameter variable\">--driver</span> bridge <span class=\"token parameter variable\">--subnet</span><span class=\"token operator\">=</span><span class=\"token number\">172.21</span>.0.0/16 wsl2\n<span class=\"token comment\"># pull</span>\n<span class=\"token function\">docker</span> pull mysql:5.7.38\n<span class=\"token comment\"># 生产 mysql 5.7.38 容器</span>\n<span class=\"token function\">docker</span> run <span class=\"token parameter variable\">--restart</span><span class=\"token operator\">=</span>always <span class=\"token parameter variable\">--privileged</span><span class=\"token operator\">=</span>true <span class=\"token parameter variable\">-p</span> <span class=\"token number\">3306</span>:3306 <span class=\"token parameter variable\">--name</span> mysql <span class=\"token parameter variable\">--net</span> wsl2 <span class=\"token parameter variable\">--ip</span> <span class=\"token number\">172.21</span>.0.5 <span class=\"token parameter variable\">-e</span> <span class=\"token assign-left variable\">MYSQL_ROOT_PASSWORD</span><span class=\"token operator\">=</span>root <span class=\"token parameter variable\">-d</span> mysql:5.7.38<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"mongo-容器\"><a href=\"#mongo-容器\" class=\"headerlink\" title=\"mongo 容器\"></a>mongo 容器</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">docker</span> pull mongo:5.0\n<span class=\"token comment\"># 宿主机 /mongo/data</span>\n<span class=\"token function\">docker</span> run <span class=\"token parameter variable\">--restart</span><span class=\"token operator\">=</span>always <span class=\"token parameter variable\">-d</span> <span class=\"token parameter variable\">-p</span> <span class=\"token number\">27017</span>:27017 <span class=\"token parameter variable\">-v</span> /mongo/data:/data <span class=\"token parameter variable\">--name</span> mongo <span class=\"token parameter variable\">--net</span> wsl2 <span class=\"token parameter variable\">--ip</span> <span class=\"token number\">172.21</span>.0.6 mongo:5.0 <span class=\"token parameter variable\">--auth</span>\n<span class=\"token comment\"># 初始化</span>\n<span class=\"token function\">docker</span> <span class=\"token builtin class-name\">exec</span> <span class=\"token parameter variable\">-it</span> mongo /bin/bash\n<span class=\"token comment\"># 进入 mongo shell</span>\nmongo\n<span class=\"token comment\"># admin</span>\nuse admin\n<span class=\"token comment\"># 创建root用户管理全部数据库的权限这会可以navicat等gui链接数据库用户名密码root验证数据库admin</span>\ndb.createUser<span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>\n user: <span class=\"token string\">\"root\"</span>,\n pwd: <span class=\"token string\">\"root\"</span>,\n roles: <span class=\"token punctuation\">[</span> <span class=\"token punctuation\">&#123;</span> role: <span class=\"token string\">\"userAdminAnyDatabase\"</span>, db: <span class=\"token string\">\"admin\"</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span>\n<span class=\"token comment\"># 退出</span>\n<span class=\"token builtin class-name\">exit</span>\n<span class=\"token comment\"># 再次进入</span>\nmongo\n<span class=\"token comment\"># 使用root登录授权正确返回 1</span>\ndb.auth<span class=\"token punctuation\">(</span><span class=\"token string\">\"root\"</span>,<span class=\"token string\">\"root\"</span><span class=\"token punctuation\">)</span>\n<span class=\"token comment\"># 创建 testDB 数据库</span>\nuse testDB\n<span class=\"token comment\"># 创建 test 用户 管理 testDB</span>\ndb.createUser<span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>user:<span class=\"token string\">'test'</span>,pwd:<span class=\"token string\">'test'</span>,roles:<span class=\"token punctuation\">[</span><span class=\"token punctuation\">&#123;</span>role:<span class=\"token string\">'dbOwner'</span>,db:<span class=\"token string\">'testDB'</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>使用 navicat 登录,验证数据库 <code>admin</code> ,用户名密码 <code>test</code></p>\n<h1 id=\"默认-wsl-root-用户登录\"><a href=\"#默认-wsl-root-用户登录\" class=\"headerlink\" title=\"默认 wsl root 用户登录\"></a>默认 wsl root 用户登录</h1><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># wsl -l 查看 ubuntu版本例如 Ubuntu-20.04</span>\nUbuntu2004 config --default-user root<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n","site":{"data":{}},"excerpt":"","more":"<h1 id=\"安装-wsl\"><a href=\"#安装-wsl\" class=\"headerlink\" title=\"安装 wsl\"></a>安装 wsl</h1><p>前置条件,主板 bios 开启 <code>intel 虚拟化</code></p>\n<blockquote>\n<p>ms app store如果打不开、转圈 -&gt; 关闭小飞机,也可以试试 改 ipv4 host 4.2.2.2</p>\n</blockquote>\n<ul>\n<li>windows terminal 必备ms store 下载</li>\n</ul>\n<p><a href=\"https://docs.microsoft.com/en-us/windows/wsl/install\">巨硬官方文档</a></p>\n<h1 id=\"ubuntu软件源\"><a href=\"#ubuntu软件源\" class=\"headerlink\" title=\"ubuntu软件源\"></a>ubuntu软件源</h1><p><a href=\"https://developer.aliyun.com/mirror/\">阿里开源镜像站</a></p>\n<p>下面是 ubuntu20.04 用的</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 备份apt默认源</span>\n<span class=\"token function\">sudo</span> <span class=\"token function\">cp</span> /etc/apt/sources.list /etc/apt/sources.list.bak\n<span class=\"token function\">sudo</span> <span class=\"token function\">vim</span> /etc/apt/sources.list\n<span class=\"token comment\"># 替换 /srouces.list</span>\ndeb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\n\n<span class=\"token comment\"># deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse</span>\n<span class=\"token comment\"># deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse</span>\n\ndeb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\n\n\n<span class=\"token comment\"># 更新apt</span>\n<span class=\"token function\">sudo</span> <span class=\"token function\">apt</span> upgrade\n<span class=\"token function\">sudo</span> <span class=\"token function\">apt</span> update<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"安装-zsh\"><a href=\"#安装-zsh\" class=\"headerlink\" title=\"安装 zsh\"></a>安装 zsh</h1><blockquote>\n<p>注意<code>.zshrc</code>在安装的<code>用户</code>目录下,别和<code>root</code>搞混了</p>\n</blockquote>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 安装</span>\n<span class=\"token function\">sudo</span> <span class=\"token function\">apt</span> <span class=\"token function\">install</span> <span class=\"token function\">zsh</span>\n<span class=\"token comment\"># 将 zsh 设置为默认 shell</span>\nchsh <span class=\"token parameter variable\">-s</span> /bin/zsh\n<span class=\"token comment\"># 检查,若没成功,重启试试看</span>\n<span class=\"token builtin class-name\">echo</span> <span class=\"token environment constant\">$SHELL</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"安装-oh-my-zsh\"><a href=\"#安装-oh-my-zsh\" class=\"headerlink\" title=\"安装 oh-my-zsh\"></a>安装 oh-my-zsh</h1><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 443 confused 手动 vim oh-my-zsh.sh 然后 bash ./oh-my-zsh.sh </span>\n<span class=\"token function\">sh</span> <span class=\"token parameter variable\">-c</span> <span class=\"token string\">\"<span class=\"token variable\"><span class=\"token variable\">$(</span><span class=\"token function\">curl</span> <span class=\"token parameter variable\">-fsSL</span> https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh<span class=\"token variable\">)</span></span>\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"配置-oh-my-zsh-主题-x2F-插件-x2F-alias\"><a href=\"#配置-oh-my-zsh-主题-x2F-插件-x2F-alias\" class=\"headerlink\" title=\"配置 oh-my-zsh 主题&#x2F;插件&#x2F;alias\"></a>配置 oh-my-zsh 主题&#x2F;插件&#x2F;alias</h1><p>安装插件</p>\n<ul>\n<li>自动补全:</li>\n</ul>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> clone https://github.com/zsh-users/zsh-autosuggestions <span class=\"token variable\">$&#123;ZSH_CUSTOM<span class=\"token operator\">:-</span>~<span class=\"token operator\">/</span>.oh-my-zsh<span class=\"token operator\">/</span>custom&#125;</span>/plugins/zsh-autosuggestions<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<ul>\n<li>代码高亮:</li>\n</ul>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">git</span> clone https://github.com/zsh-users/zsh-syntax-highlighting.git <span class=\"token variable\">$&#123;ZSH_CUSTOM<span class=\"token operator\">:-</span>~<span class=\"token operator\">/</span>.oh-my-zsh<span class=\"token operator\">/</span>custom&#125;</span>/plugins/zsh-syntax-highlighting<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>修改<code>当前用户</code>目录下的 <code>.zshrc</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># 主题</span>\n<span class=\"token assign-left variable\">ZSH_THEME</span><span class=\"token operator\">=</span><span class=\"token string\">\"ys\"</span>\n<span class=\"token comment\"># 引入插件</span>\n<span class=\"token assign-left variable\">plugins</span><span class=\"token operator\">=</span><span class=\"token punctuation\">(</span>git zsh-autosuggestions zsh-syntax-highlighting<span class=\"token punctuation\">)</span>\n<span class=\"token comment\"># alias</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">cls</span><span class=\"token operator\">=</span><span class=\"token string\">'clear'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">ga</span><span class=\"token operator\">=</span><span class=\"token string\">'git add'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gc</span><span class=\"token operator\">=</span><span class=\"token string\">'git commit -m'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gp</span><span class=\"token operator\">=</span><span class=\"token string\">'git push'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gf</span><span class=\"token operator\">=</span><span class=\"token string\">'git fetch'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">update</span><span class=\"token operator\">=</span><span class=\"token string\">'sudo apt update'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">upgrade</span><span class=\"token operator\">=</span><span class=\"token string\">'sudo apt upgrade'</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">install</span><span class=\"token operator\">=</span><span class=\"token string\">'sudo apt install'</span>\n<span class=\"token comment\"># windows文件管理器打开wsl文件</span>\n<span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">open</span><span class=\"token operator\">=</span><span class=\"token string\">'explorer.exe'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"安装-Nodejs\"><a href=\"#安装-Nodejs\" class=\"headerlink\" title=\"安装 Nodejs\"></a>安装 Nodejs</h1><p><a href=\"https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl\">巨硬文档赛高</a></p>\n<p>安装完注意文字提示</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># =>Appending nvm source string to /home/mozzie/.zshrc</span>\n<span class=\"token comment\"># => Appending bash_completion source string to /home/mozzie/.zshrc</span>\n<span class=\"token comment\"># => Close and reopen your terminal to start using nvm or run the following to use it now:</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n<p>照它说的做</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\">NVM_DIR</span><span class=\"token operator\">=</span><span class=\"token string\">\"<span class=\"token environment constant\">$HOME</span>/.nvm\"</span>\n<span class=\"token punctuation\">[</span> <span class=\"token parameter variable\">-s</span> <span class=\"token string\">\"<span class=\"token variable\">$NVM_DIR</span>/nvm.sh\"</span> <span class=\"token punctuation\">]</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token punctuation\">\\</span>. <span class=\"token string\">\"<span class=\"token variable\">$NVM_DIR</span>/nvm.sh\"</span> <span class=\"token comment\"># This loads nvm</span>\n<span class=\"token punctuation\">[</span> <span class=\"token parameter variable\">-s</span> <span class=\"token string\">\"<span class=\"token variable\">$NVM_DIR</span>/bash_completion\"</span> <span class=\"token punctuation\">]</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token punctuation\">\\</span>. <span class=\"token string\">\"<span class=\"token variable\">$NVM_DIR</span>/bash_completion\"</span> <span class=\"token comment\"># This loads nvm bash_completion</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>验证<code>nvm</code>安装 <code>nvm ls</code>,会看见类似</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">iojs -<span class=\"token operator\">></span> N/A <span class=\"token punctuation\">(</span>default<span class=\"token punctuation\">)</span>\n<span class=\"token function\">node</span> -<span class=\"token operator\">></span> stable <span class=\"token punctuation\">(</span>-<span class=\"token operator\">></span> N/A<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span>default<span class=\"token punctuation\">)</span>\nunstable -<span class=\"token operator\">></span> N/A <span class=\"token punctuation\">(</span>default<span class=\"token punctuation\">)</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>安装 <code>nodejs stable</code></p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">nvm <span class=\"token function\">install</span> <span class=\"token function\">node</span>\n<span class=\"token comment\"># node -v | npm -v 验证安装版本</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h1 id=\"外网-x2F-LAN-访问-wsl2-服务\"><a href=\"#外网-x2F-LAN-访问-wsl2-服务\" class=\"headerlink\" title=\"外网&#x2F;LAN 访问 wsl2 服务\"></a>外网&#x2F;LAN 访问 wsl2 服务</h1><p><a href=\"https://docs.microsoft.com/en-us/windows/wsl/networking\">巨硬官方解释</a></p>\n<p>When using a WSL 1 distribution, if your computer was set up to be accessed by your LAN, then applications run in WSL could be accessed on your LAN as well.</p>\n<p>This isnt the default case in WSL 2. WSL 2 has a virtualized ethernet adapter with its own unique IP address. Currently, to enable this workflow you will need to go through the same steps as you would for a regular virtual machine. (We are looking into ways to improve this experience.)</p>\n<p>Heres an example PowerShell command to add a port proxy that listens on port 4000 on the host and connects it to port 4000 to the WSL 2 VM with IP address 192.168.101.100</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\">netsh interface portproxy <span class=\"token function\">add</span> v4tov4 <span class=\"token assign-left variable\">listenport</span><span class=\"token operator\">=</span><span class=\"token number\">4000</span> <span class=\"token assign-left variable\">listenaddress</span><span class=\"token operator\">=</span><span class=\"token number\">0.0</span>.0.0 <span class=\"token assign-left variable\">connectport</span><span class=\"token operator\">=</span><span class=\"token number\">4000</span> <span class=\"token assign-left variable\">connectaddress</span><span class=\"token operator\">=</span><span class=\"token number\">192.168</span>.101.100<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n<blockquote>\n<p>注意端口覆盖的问题,避免 windows 端口和端口 wsl2 冲突</p>\n</blockquote>\n<h2 id=\"netsh-端口映射\"><a href=\"#netsh-端口映射\" class=\"headerlink\" title=\"netsh 端口映射\"></a>netsh 端口映射</h2><ul>\n<li><p>listenaddress: 监听地址, 0.0.0.0 表示匹配所有地址</p>\n</li>\n<li><p>listenport: 监听的 windows 端口</p>\n</li>\n<li><p>connectaddress: 转发到 wsl2 的 ip地址, 这里设置为localhost默认从 windows 可以通过localhost 访问 wsl2</p>\n</li>\n<li><p>connectport: 转发到 wsl2 的端口</p>\n</li>\n</ul>\n<p>例如 windows 的 ip 为 <code>192.168.1.100</code>,监听 windows 的 3000 端口,转发到 wsl2 ip localhost 的 3000 端口</p>\n<pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># windows-terminal 管理员权限执行</span>\nnetsh interface portproxy <span class=\"token function\">add</span> v4tov4 <span class=\"token assign-left variable\">listenport</span><span class=\"token operator\">=</span><span class=\"token number\">3000</span> <span class=\"token assign-left variable\">listenaddress</span><span class=\"token operator\">=</span><span class=\"token number\">0.0</span>.0.0 <span class=\"token assign-left variable\">connectport</span><span class=\"token operator\">=</span><span class=\"token number\">3000</span> <span class=\"token assign-left variable\">connectaddress</span><span class=\"token operator\">=</span>localhost\n<span class=\"token comment\"># 删除端口监听</span>\nnetsh interface portproxy delete v4tov4 <span class=\"token assign-left variable\">listenaddress</span><span class=\"token operator\">=</span><span class=\"token number\">0.0</span>.0.0 <span class=\"token assign-left variable\">listenport</span><span class=\"token operator\">=</span><span class=\"token number\">3000</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"配置-windows-defender-防火墙入站规则\"><a href=\"#配置-windows-defender-防火墙入站规则\" class=\"headerlink\" title=\"配置 windows defender 防火墙入站规则\"></a>配置 windows defender 防火墙入站规则</h2><p>新建规则 -&gt; 端口 -&gt; TCP &#x2F; 特定本地端口(3000) -&gt; 允许链接 -&gt; 下一步 -&gt; 取个名字 -&gt; Done</p>\n<h1 id=\"docker\"><a href=\"#docker\" class=\"headerlink\" title=\"docker\"></a>docker</h1><p>windows 宿主机安装 <code>docker desktop</code><code>设置 -&gt; 资源 -&gt; WSL INTEGRATION</code> 打开 对应的 linux发行版即使用</p>\n<h2 id=\"mysql-容器\"><a href=\"#mysql-容器\" class=\"headerlink\" title=\"mysql 容器\"></a>mysql 容器</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># brdige</span>\n<span class=\"token function\">docker</span> network create <span class=\"token parameter variable\">--driver</span> bridge <span class=\"token parameter variable\">--subnet</span><span class=\"token operator\">=</span><span class=\"token number\">172.21</span>.0.0/16 wsl2\n<span class=\"token comment\"># pull</span>\n<span class=\"token function\">docker</span> pull mysql:5.7.38\n<span class=\"token comment\"># 生产 mysql 5.7.38 容器</span>\n<span class=\"token function\">docker</span> run <span class=\"token parameter variable\">--restart</span><span class=\"token operator\">=</span>always <span class=\"token parameter variable\">--privileged</span><span class=\"token operator\">=</span>true <span class=\"token parameter variable\">-p</span> <span class=\"token number\">3306</span>:3306 <span class=\"token parameter variable\">--name</span> mysql <span class=\"token parameter variable\">--net</span> wsl2 <span class=\"token parameter variable\">--ip</span> <span class=\"token number\">172.21</span>.0.5 <span class=\"token parameter variable\">-e</span> <span class=\"token assign-left variable\">MYSQL_ROOT_PASSWORD</span><span class=\"token operator\">=</span>root <span class=\"token parameter variable\">-d</span> mysql:5.7.38<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"mongo-容器\"><a href=\"#mongo-容器\" class=\"headerlink\" title=\"mongo 容器\"></a>mongo 容器</h2><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token function\">docker</span> pull mongo:5.0\n<span class=\"token comment\"># 宿主机 /mongo/data</span>\n<span class=\"token function\">docker</span> run <span class=\"token parameter variable\">--restart</span><span class=\"token operator\">=</span>always <span class=\"token parameter variable\">-d</span> <span class=\"token parameter variable\">-p</span> <span class=\"token number\">27017</span>:27017 <span class=\"token parameter variable\">-v</span> /mongo/data:/data <span class=\"token parameter variable\">--name</span> mongo <span class=\"token parameter variable\">--net</span> wsl2 <span class=\"token parameter variable\">--ip</span> <span class=\"token number\">172.21</span>.0.6 mongo:5.0 <span class=\"token parameter variable\">--auth</span>\n<span class=\"token comment\"># 初始化</span>\n<span class=\"token function\">docker</span> <span class=\"token builtin class-name\">exec</span> <span class=\"token parameter variable\">-it</span> mongo /bin/bash\n<span class=\"token comment\"># 进入 mongo shell</span>\nmongo\n<span class=\"token comment\"># admin</span>\nuse admin\n<span class=\"token comment\"># 创建root用户管理全部数据库的权限这会可以navicat等gui链接数据库用户名密码root验证数据库admin</span>\ndb.createUser<span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>\n user: <span class=\"token string\">\"root\"</span>,\n pwd: <span class=\"token string\">\"root\"</span>,\n roles: <span class=\"token punctuation\">[</span> <span class=\"token punctuation\">&#123;</span> role: <span class=\"token string\">\"userAdminAnyDatabase\"</span>, db: <span class=\"token string\">\"admin\"</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span>\n<span class=\"token comment\"># 退出</span>\n<span class=\"token builtin class-name\">exit</span>\n<span class=\"token comment\"># 再次进入</span>\nmongo\n<span class=\"token comment\"># 使用root登录授权正确返回 1</span>\ndb.auth<span class=\"token punctuation\">(</span><span class=\"token string\">\"root\"</span>,<span class=\"token string\">\"root\"</span><span class=\"token punctuation\">)</span>\n<span class=\"token comment\"># 创建 testDB 数据库</span>\nuse testDB\n<span class=\"token comment\"># 创建 test 用户 管理 testDB</span>\ndb.createUser<span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>user:<span class=\"token string\">'test'</span>,pwd:<span class=\"token string\">'test'</span>,roles:<span class=\"token punctuation\">[</span><span class=\"token punctuation\">&#123;</span>role:<span class=\"token string\">'dbOwner'</span>,db:<span class=\"token string\">'testDB'</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>使用 navicat 登录,验证数据库 <code>admin</code> ,用户名密码 <code>test</code></p>\n<h1 id=\"默认-wsl-root-用户登录\"><a href=\"#默认-wsl-root-用户登录\" class=\"headerlink\" title=\"默认 wsl root 用户登录\"></a>默认 wsl root 用户登录</h1><pre class=\"line-numbers language-bash\" data-language=\"bash\"><code class=\"language-bash\"><span class=\"token comment\"># wsl -l 查看 ubuntu版本例如 Ubuntu-20.04</span>\nUbuntu2004 config --default-user root<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n"},{"title":"付鹏展望2023年下半年全球经济格局异常的利差意味着什么","status":"done","_content":"\n![美债10年利差](/img/mz10nq.png)\n\n08年的金融危机或者09年是一个重要的时间节点到今年(2023年),在座各位你们将迎来第二个重要的节点,可能对于很多年轻人来讲,最好的一个时代结束了,我们所有人的下半辈子的投资,注意,也非常简单,抄巴菲特作业。\n\n巴菲特刚去了日本(2011年也去了),你们就知道日本发生了什么。你看到了安倍晋三的三支箭,你看到了日本日元的大幅度的贬值。过去两年,巴菲特一直在买日本的这五大商社:三菱商社、三井物产、伊藤忠商事、住友、丸红,然后大家还看到巴菲特在过去的两年一直在买美孚和西方石油。有人说了巴菲特在赌油价上涨,我只能说如果你讲这种话的话,你金融基本没入门。\n\n我想说的是任何的技术创新在某些环节中它是由资金来决定的技术人员只是其中一环。没有钱没有便宜的钱一切都是假的。所以技术的进步的背后有个很关键的因素就是钱钱多钱少钱贵钱便宜你的投资将完全不同。比如说昨天还是前天你们看到软银的孙正义基本上把所有的阿里巴巴的资金卖掉了开始往回抽回资金。我经常说包括对我自己的子女都讲一句话99%的命运和1%的努力而不是99%的努力1%的命运。大势极其的重要,这个\"大势\"或许也就是我们在金融市场打拼,真正能够获得的。\n\n然后图上右侧我给大家放了最核心的美债利差美债利差是什么东西可以这么简单理解\"全球资金的成本\"。美国是一年期国债收益率和十年期国债收益率的差值,主要是差值。如果懂商品期货的话你们知道,我们的所有东西都有一个概念叫做当期价格和远期价格,那么资金一年期可以简单理解成当期资金价格,十年期你可以理解成十年拉长十年以后的资金价格。这个\"一\"和\"十\"的概念是什么十年期大概等同于经济增长。我们过去的四十年的大部分时间短期利率低于经济增长。比如说你现在干了一个企业你预期你未来的三到五年你能获得10%左右的利润,而当期银行提供给你的借贷成本只有三个点,你知道你该干嘛了吗?借便宜的钱投高息的回报。\n\n本质上金融的核心除了研究经济研究长期回报以外还有个很重要的就是从哪借钱能不能借到便宜的钱能不能在便宜的钱上面借更多的钱但不是说便宜的钱就一定能够刺激起来借贷日本90年房地产泡沫破裂以后利率水平给你干到0你都不借为什么因为没有资产回报这个怎么反映在我们的全球利率上呢简单讲这个数字在0以上它代表着你现在的借贷资金成本在这你的投资回报在下头。\n\n你记住一点你活多大年龄决定了你见过多大市面我们现在在中国从事金融的大部分的人有见过40年前国际市场是什么情况吗巴菲特90多了芒格明年就100了对吧用我的话说你要活到那个年龄你啥都见过了金融理念特别简单借便宜的钱去赚高息的回报就这么简单。\n\n一定要喜欢危机可能是干实体的人不喜欢但我可以告诉你干金融的人我们超级喜欢危机因为每一次危机的到来将带来一次年轻人特别喜欢的机会赌一赌单车变摩托赌的是什么呢你就赌危机爆发之后全球的政府和央行永远只会干一件事放水降息、放水降更多的息、放更多的水降更多的息。\n\n40年前平均的状态实际上就是短期利率永远高于长期经济回报这在经济学中是什么有人会说通胀、通缩其实还有一个状态大家并不喜欢\"滞胀\"这种状态距离我们已经40年了换句话说全球已经40年没太出现过这种情况。但对不起你们有没有想过现在或许来了它导致的我们的所有投资完全不同。\n\n资金越便宜长期投资回报越稳定借越便宜的钱买更高的高息资产借更多。一旦倒过来我就请问你怎么交易银行存款五点几投所有的资产回报只有三点几我就问你大部分人会怎么做不是说就指现金在银行的才叫现金只要在当期能够产生高息回报的资金或者资产都叫现金。我举个例子比如说一个公司股息分10%它算不算高息资产它算不算高息现金它每年都给你分跟你银行存到银行每年拿5%有区别?没区别!所以说这个短期高于长期从最直觉的理解就是资金应该放在现金上。\n\n为什么巴菲特买那些公司那些公司跟上面的现金奶牛ETF之间是什么关系08年金融危机后美国把基准利率水平拉得非常低09年两会口号是\"做大做强金融,万众创业,万众创新\"之后出来的小贷公司担保公司P2P对吧一连串都是在这个大的宏观背景下去搞的。09年之后你真正应该获得的只有两个收益一个卖房炒房卖房炒房、买更多的房炒更多的房。第二个投腾讯投阿里投万众创业投万众创新就这两条路。在中国你记住有些路不是自然形成的它在那个关键的节点上全是由政府这支无形的手在引导两会这个口号一提出来你一看中国居民部门属于\"高储蓄低杠杆\",你知道人生的机会来了。\n\n真正投资的精髓不是买资产是如何去负债。如何在钱便宜的时间点上去负债、付更多的债、如何去付更低的资金成本然后右手才去考虑资产很多人光想资产而不去考虑负债。\n\n房价上涨就一条这个地方有没有人进来。第二这个地方进来的人能不能借更多的钱就是居民部门杠杆率。首先得有居民第二得有杠杆率如果这俩都没了这个资产基本就到头了。09年就是让他们加杠杆扛着进去的现在的经济为什么差我可以告诉你还有人说刺激咋刺激09年能刺激是因为所有的居民部门有储蓄稳定企业低负债现在是没储蓄、不稳定。更重要的是睁眼全是债简单讲年轻人杠杆加不动这才是最大的风险。核心城市核心区域除此之外都别碰因为只有这个核心俩字才能带来人。香港特首前段时间天天在广深在那晃荡的不就是邀请你们去吗但是你跟他说我没钱家里也没钱我就是个穷小子那对不起你别过来。你来我也不要因为我要你的根本是你有钱你能接得住你能加得住杠杆。我认为最核心的一个是房价到达一定程度人自然没法生隔壁韩国如此日本如此中国亦如此。中国现在的大体情况是未来的五到十年基本处在加完杠杆后还债的年代。低增长、低通胀、低利率三低。而过去的三十年中国一直是高增长高通胀、高利率。高和低之间差距是什么杠杆率到一定程度自然就定了隔壁日本就是到了极致崩了\n\n老美的底层老百姓过得并不好但老美的富人更好了富人靠杠杆。记住一点富人靠杠杆、靠金融资产穷人才靠劳动力。在全球化的过程美国居民保持的是最低的生存权利(美国底层人民)他的收入是不增长的。从1982年开始美国的数字是多少呢平均薪资增速3%金字塔的底层25%和顶层25%的薪资性收入差是1%。啥意思呢平均3%的薪资收入增长再减去1%的社会阶层差底层25%的美国居民薪资性收入仅仅是2%。大家发现这个2%是什么?正好就是美国通胀水平。啥意思呢?你可以理解,这美国的底层居民过去的二三十年薪资扣掉通胀是不增长的。\n\n二十多年前索罗斯写那本联名书的时候他就给大家解释过这个话题他说中国庞大的贸易顺差去补偿了美国底层居民。举个例子一个美国人薪资2万保持不变但是呢中国生产的笔记本电脑从5000美金降到了1000美金我的购买力怎么样增强了这就是庞大的中国出口。中国出口的商品绕一圈转回来变成中国的外汇储备中国的外汇储备买的是什么买的是美债。美债用于什么了美债用于两件事打仗、给底层居民补医疗和教育。所以你就会发现。如果你做美国的底层居民的话出现什么情况呢收入没增长但是中国供应的商品的购买力降弱了这个购买力让美国人的购买力增强了。同时中国大量的顺差和外汇储备补偿了美国的教育和医疗。\n\n美国真正发家致富的人都是看明白了这套游戏的。一旦底层居民薪资收入不增长我们教科书里学的货币银行学中央行双目标志将失效也就是说中央银行将永远不用去考虑薪资通胀只需要去考虑经济。此时就会产生我们现在这个模型\"经济不行就降息\"。每一次经济不行的时候就借更多的美元买更多的美国金融性资产。但在82年美国金融监管放开了一个重要的法案金融自由化。啥意思如果监管部门把银行管得死死的银行不许给居民加杠杆就算来了这样的机会社会也没有财富效应。但如果我此时告诉银行金融监管你们可以去创造各种各样的金融衍生产品去给居民部门加杠杆举例子房贷可以变成18种花样于是82年到2022年搞了整整40年。\n\n到了02年的时候美国居民部门突然间反应过来原来富人不是靠着劳动挣钱的富人得去炒金融资产。02年小布什一句话你们得做起美国梦来。什么意思你们手上没有股票得有但问题是在于这帮穷人的美国梦是最可怕的因为他收入不增长还借了更多的房贷02年到08年的这种做法结果就是08年崩掉了。但崩掉以后美国的底层人民麻烦就大了被迫还了15年的债。从08年到现在美国居民部门一直在去杠杆还债但是你知道一个人收入不增长然后还要不停的还债他最终会转成什么欧美有两样东西会让整个社会颠覆的一个是\"选票\"、\"上街大游行\"。他的选票会转化成什么?答案:\"特朗普\"。也就是要么民粹要么你补偿我。补偿只有一个方法提高他的薪资收入。你以为真的是像宏观经济上在跟你讲说因为这场疫情导致供应链导致劳动力市场结构发生了变换那都不是核心真正的核心是当居民部门还了12年、15年债以后这部分人不想还了你要么就是更多的补偿给我、要么就是给我加薪。\n\n目前美国出现的就一个结果底层通胀、顶层通缩。知道美国现在谁最惨吗美国西海岸。硅谷、洛杉矶、旧金山的富人这15年是他们加了杠杆08年后的这漫长的15年创造了我们近乎200年以来全世界最低的资金年代它也创造了全世界几乎是最大的资产。这个资产是什么虚拟资产你们知道为什么会出现虚拟性货币如果这么庞大的流动性这么便宜的资金冲向了实物资产(粮食、房子)这个价格一旦失控我们离战争就不远了。虚拟资产有个好处它仅仅消灭富人财富。西海岸的这帮我们叫美国新贵准确说叫做穷人日子很好富人日子很难受。富人中间是老钱收割新钱老钱是什么呢华盛顿、纽约、休斯顿新钱就是硅谷、洛杉矶。新钱靠的是什么科技、技术、创新。你创造一个东西带来的社会价值可能只创造了1万块。但是金融市场给予你200倍。一次性兑付了几百年的收益。这就是我们的金融市场当利率水平过低的时候它会使得所有资产的估值极高。而科技作为主要的推动力会自然而然地迎来一场高估值的泡沫。\n\n干一级市场投资我可以告诉你估值泡沫出现的时候那特征都是一样的简单说瞎几把随便写PPT都能融到钱。有很多人的利益是建立在利率和资产价格上的。经济行的时候是可以承受高利率的。经济不行的时候(日本)把利率降到负都没用。\n\n这四十年结束以后逻辑是什么科技肯定不行深圳科创你就搞到天上去你拉动整个社会的经济也远着呢技术的进步只有转化成全民生产率才能拉动所有人。中国现在相反是低增长、低通胀、低利率而这3低的背后是高杠杆。有一种情况可以让我们避开这种所谓的内卷型的环境就是走出去。美国在六十年代到现在不是盈利率的增长它获得的是市场份额的扩大。中国现在所有的企业会内卷的会卷得一塌糊涂原因很简单市场只有国内了。2018年开始的中美贸易战逆全球化鬼佬就是要把我们踢出去。因为不走出去我们过去的二三十年所有的产能是给全世界走配套的。如果不走出去单凭我们国内的居民部门消化不了。\n\n我们国内居民部门中还出现了一个问题大部分的90后、95后是在缩的他们是在降低欲望的他们是在消费降级的。高端消费永远是给那些富人的。中产阶级的杠杆达到一定程度就会进入一个很典型的低欲望社会。跟现在比较穷的年轻人打打交道你们就会发现不结婚挺好、不生孩子挺好、这个不买房也不错、这个手机也不用换。然后这个蜜雪冰城的咖啡。虽然难喝点但还可以你。跟富二代富三代打交道就看不出来。中国现在也是典型的K字型。\n\n过去四十年的游戏结束了现金远远地甩开了长期经济增长。巴菲特已经教过大家了最好的公司是什么经济好也好。经济坏也好是刚需、高股息类的公司且不受经济低迷影响的公司。你们有没有发现在最近在炒中草药为啥炒中炒药就是刚需好比通信行业的话费你必须得按月充值。所以巴菲特在买的是什么现金奶牛ETF的配置看看都是啥能源、医药、金融。这些行业就是典型的现金类资产巴菲特想获得一样东西知道是什么吗股息率美孚的几个财务数据叠加会发现第一种情况低油价、经济差它的股价上涨的。并不是巴菲特赌油价上涨。\n\n全球过去40年挣100块钱只有40块钱来自于你们理解中的经济增长带来的回报有60块钱是来自于低利率加杠杆的投资回报。所以这个世界有两个投资人一个叫长期价值投资回报就是获得经济增长带来的贴现。另外一个就是获得利率波动带来的加杠杆房子准确说典型的就是杠杆性资产如果房住不炒那理论上它是没有价格波动的。\n\n今年是蹦了一个ChatGPT明年还必定还会有个啥的。当然我只想说一句当你听到今年AI的时候你们还记得去年大明湖畔的元宇宙吗你们还记得十年前的互联网加万物吗过去几年全球利率低咱们可以你炒一波咱们给90后90后炒一波给95后95后炒一波给00后然后全球流动性一收咱们把00后挂到高位上。为什么是这个路径越年轻的越信技术他们认为技术能改变世界结果世界会残酷地教育你。技术能不能改变世界但绝对不是炒技术炒技术改变不了世界。\n\n从去年十一月份所有的主题性投资只能这样炒当你想给90后的时候你发现90后的元宇宙还没解套呢90后借不来更多的钱所以周期会非常短迅速炒迅速落。可人民币现在利率这么低为什么会没有钱呢因为所有科技性投资不是跟着人民币利率走的。比如ChatGPT是海外现有了这个东西国内跟风元宇宙亦然新能源汽车也是现有了特斯拉。中国在技术方面采取的战略是摸着石头过河、黑猫白猫带着老鼠就行。所以我们会出现一种情况海外有个热点我们马上跟。那问题就来了你的估值怎么定价做过一级市场投资的投资某家企业的时候对标物是美国某某企业。美股最强大的地方是把所有创新的Top级的领军人物均以美元定价导致的一个结果就是它是锚定价了所有估值水平。如果人民币能对资产估值有影响那就必须要求投这家企业的对标物是在中国上市。\n\n能挣钱的企业就是好企业像国内某企业家讲的我五年不给你分红你能把我咋滴这种企业就不是好企业。挣钱分钱经济不好的时候能力还继续挣钱这就是它的垄断性。所以你们会发现别瞧不起老钱老钱投的上游。改革开放之后煤炭、电力、很多行业都是允许民营企业介入的到现在为止我就请问这些上游还有民营企业吗\n\n回到日本的商社跟中国国有企业本质是一样它是家庭组织不由董事会左右。巴菲特去了以后和高管和家族的人员就谈了一个事你是现金奶牛因为它控制了全球的上游。所以在经济不好的时候日本的五大商社就是中国的国有企业也是美国的能源企业。能挣钱、有利润然后有大量的自由现金流。它唯一的问题是\"公司治理\",就是它不一定愿意给你分。现在股息率快到五了,你不分,我就把公司买成我的,然后日本人说的就是:巴菲特先生,你别把我控制,我愿意分钱给你。因此巴菲特干的事情,买了日本的这些高股息的资产,并且在日本发行了无抵押担保的日元债券。啥意思呢?巴菲特一毛钱没掏,用日本人的储蓄以及低利率水平借钱,买了日本人的资产,还强迫日本人分了高股息,这才是资本真正的收割。\n\n未来的5年是10年真正的游戏是如何借低息买高息。美元不便宜了但美元的高息依旧很吸引人。那么问题就来了谁是低息美元如果一直维持高增长高通胀、高利率的话人民币一定是贬值的。而倒过来的交易借人民币转高息资产这个高息资产可以是人民币里边不多有的高息资产也可以是全球范围内的高股息现金奶牛你会发现这就又形成了类似于15年前的套利资本流动、交易机会。","source":"_posts/finance/付鹏展望2023年下半年全球经济格局异常的利差意味着什么.md","raw":"---\ntitle: 付鹏展望2023年下半年全球经济格局异常的利差意味着什么\ncategories:\n - Finance\nstatus: done\n---\n\n![美债10年利差](/img/mz10nq.png)\n\n08年的金融危机或者09年是一个重要的时间节点到今年(2023年),在座各位你们将迎来第二个重要的节点,可能对于很多年轻人来讲,最好的一个时代结束了,我们所有人的下半辈子的投资,注意,也非常简单,抄巴菲特作业。\n\n巴菲特刚去了日本(2011年也去了),你们就知道日本发生了什么。你看到了安倍晋三的三支箭,你看到了日本日元的大幅度的贬值。过去两年,巴菲特一直在买日本的这五大商社:三菱商社、三井物产、伊藤忠商事、住友、丸红,然后大家还看到巴菲特在过去的两年一直在买美孚和西方石油。有人说了巴菲特在赌油价上涨,我只能说如果你讲这种话的话,你金融基本没入门。\n\n我想说的是任何的技术创新在某些环节中它是由资金来决定的技术人员只是其中一环。没有钱没有便宜的钱一切都是假的。所以技术的进步的背后有个很关键的因素就是钱钱多钱少钱贵钱便宜你的投资将完全不同。比如说昨天还是前天你们看到软银的孙正义基本上把所有的阿里巴巴的资金卖掉了开始往回抽回资金。我经常说包括对我自己的子女都讲一句话99%的命运和1%的努力而不是99%的努力1%的命运。大势极其的重要,这个\"大势\"或许也就是我们在金融市场打拼,真正能够获得的。\n\n然后图上右侧我给大家放了最核心的美债利差美债利差是什么东西可以这么简单理解\"全球资金的成本\"。美国是一年期国债收益率和十年期国债收益率的差值,主要是差值。如果懂商品期货的话你们知道,我们的所有东西都有一个概念叫做当期价格和远期价格,那么资金一年期可以简单理解成当期资金价格,十年期你可以理解成十年拉长十年以后的资金价格。这个\"一\"和\"十\"的概念是什么十年期大概等同于经济增长。我们过去的四十年的大部分时间短期利率低于经济增长。比如说你现在干了一个企业你预期你未来的三到五年你能获得10%左右的利润,而当期银行提供给你的借贷成本只有三个点,你知道你该干嘛了吗?借便宜的钱投高息的回报。\n\n本质上金融的核心除了研究经济研究长期回报以外还有个很重要的就是从哪借钱能不能借到便宜的钱能不能在便宜的钱上面借更多的钱但不是说便宜的钱就一定能够刺激起来借贷日本90年房地产泡沫破裂以后利率水平给你干到0你都不借为什么因为没有资产回报这个怎么反映在我们的全球利率上呢简单讲这个数字在0以上它代表着你现在的借贷资金成本在这你的投资回报在下头。\n\n你记住一点你活多大年龄决定了你见过多大市面我们现在在中国从事金融的大部分的人有见过40年前国际市场是什么情况吗巴菲特90多了芒格明年就100了对吧用我的话说你要活到那个年龄你啥都见过了金融理念特别简单借便宜的钱去赚高息的回报就这么简单。\n\n一定要喜欢危机可能是干实体的人不喜欢但我可以告诉你干金融的人我们超级喜欢危机因为每一次危机的到来将带来一次年轻人特别喜欢的机会赌一赌单车变摩托赌的是什么呢你就赌危机爆发之后全球的政府和央行永远只会干一件事放水降息、放水降更多的息、放更多的水降更多的息。\n\n40年前平均的状态实际上就是短期利率永远高于长期经济回报这在经济学中是什么有人会说通胀、通缩其实还有一个状态大家并不喜欢\"滞胀\"这种状态距离我们已经40年了换句话说全球已经40年没太出现过这种情况。但对不起你们有没有想过现在或许来了它导致的我们的所有投资完全不同。\n\n资金越便宜长期投资回报越稳定借越便宜的钱买更高的高息资产借更多。一旦倒过来我就请问你怎么交易银行存款五点几投所有的资产回报只有三点几我就问你大部分人会怎么做不是说就指现金在银行的才叫现金只要在当期能够产生高息回报的资金或者资产都叫现金。我举个例子比如说一个公司股息分10%它算不算高息资产它算不算高息现金它每年都给你分跟你银行存到银行每年拿5%有区别?没区别!所以说这个短期高于长期从最直觉的理解就是资金应该放在现金上。\n\n为什么巴菲特买那些公司那些公司跟上面的现金奶牛ETF之间是什么关系08年金融危机后美国把基准利率水平拉得非常低09年两会口号是\"做大做强金融,万众创业,万众创新\"之后出来的小贷公司担保公司P2P对吧一连串都是在这个大的宏观背景下去搞的。09年之后你真正应该获得的只有两个收益一个卖房炒房卖房炒房、买更多的房炒更多的房。第二个投腾讯投阿里投万众创业投万众创新就这两条路。在中国你记住有些路不是自然形成的它在那个关键的节点上全是由政府这支无形的手在引导两会这个口号一提出来你一看中国居民部门属于\"高储蓄低杠杆\",你知道人生的机会来了。\n\n真正投资的精髓不是买资产是如何去负债。如何在钱便宜的时间点上去负债、付更多的债、如何去付更低的资金成本然后右手才去考虑资产很多人光想资产而不去考虑负债。\n\n房价上涨就一条这个地方有没有人进来。第二这个地方进来的人能不能借更多的钱就是居民部门杠杆率。首先得有居民第二得有杠杆率如果这俩都没了这个资产基本就到头了。09年就是让他们加杠杆扛着进去的现在的经济为什么差我可以告诉你还有人说刺激咋刺激09年能刺激是因为所有的居民部门有储蓄稳定企业低负债现在是没储蓄、不稳定。更重要的是睁眼全是债简单讲年轻人杠杆加不动这才是最大的风险。核心城市核心区域除此之外都别碰因为只有这个核心俩字才能带来人。香港特首前段时间天天在广深在那晃荡的不就是邀请你们去吗但是你跟他说我没钱家里也没钱我就是个穷小子那对不起你别过来。你来我也不要因为我要你的根本是你有钱你能接得住你能加得住杠杆。我认为最核心的一个是房价到达一定程度人自然没法生隔壁韩国如此日本如此中国亦如此。中国现在的大体情况是未来的五到十年基本处在加完杠杆后还债的年代。低增长、低通胀、低利率三低。而过去的三十年中国一直是高增长高通胀、高利率。高和低之间差距是什么杠杆率到一定程度自然就定了隔壁日本就是到了极致崩了\n\n老美的底层老百姓过得并不好但老美的富人更好了富人靠杠杆。记住一点富人靠杠杆、靠金融资产穷人才靠劳动力。在全球化的过程美国居民保持的是最低的生存权利(美国底层人民)他的收入是不增长的。从1982年开始美国的数字是多少呢平均薪资增速3%金字塔的底层25%和顶层25%的薪资性收入差是1%。啥意思呢平均3%的薪资收入增长再减去1%的社会阶层差底层25%的美国居民薪资性收入仅仅是2%。大家发现这个2%是什么?正好就是美国通胀水平。啥意思呢?你可以理解,这美国的底层居民过去的二三十年薪资扣掉通胀是不增长的。\n\n二十多年前索罗斯写那本联名书的时候他就给大家解释过这个话题他说中国庞大的贸易顺差去补偿了美国底层居民。举个例子一个美国人薪资2万保持不变但是呢中国生产的笔记本电脑从5000美金降到了1000美金我的购买力怎么样增强了这就是庞大的中国出口。中国出口的商品绕一圈转回来变成中国的外汇储备中国的外汇储备买的是什么买的是美债。美债用于什么了美债用于两件事打仗、给底层居民补医疗和教育。所以你就会发现。如果你做美国的底层居民的话出现什么情况呢收入没增长但是中国供应的商品的购买力降弱了这个购买力让美国人的购买力增强了。同时中国大量的顺差和外汇储备补偿了美国的教育和医疗。\n\n美国真正发家致富的人都是看明白了这套游戏的。一旦底层居民薪资收入不增长我们教科书里学的货币银行学中央行双目标志将失效也就是说中央银行将永远不用去考虑薪资通胀只需要去考虑经济。此时就会产生我们现在这个模型\"经济不行就降息\"。每一次经济不行的时候就借更多的美元买更多的美国金融性资产。但在82年美国金融监管放开了一个重要的法案金融自由化。啥意思如果监管部门把银行管得死死的银行不许给居民加杠杆就算来了这样的机会社会也没有财富效应。但如果我此时告诉银行金融监管你们可以去创造各种各样的金融衍生产品去给居民部门加杠杆举例子房贷可以变成18种花样于是82年到2022年搞了整整40年。\n\n到了02年的时候美国居民部门突然间反应过来原来富人不是靠着劳动挣钱的富人得去炒金融资产。02年小布什一句话你们得做起美国梦来。什么意思你们手上没有股票得有但问题是在于这帮穷人的美国梦是最可怕的因为他收入不增长还借了更多的房贷02年到08年的这种做法结果就是08年崩掉了。但崩掉以后美国的底层人民麻烦就大了被迫还了15年的债。从08年到现在美国居民部门一直在去杠杆还债但是你知道一个人收入不增长然后还要不停的还债他最终会转成什么欧美有两样东西会让整个社会颠覆的一个是\"选票\"、\"上街大游行\"。他的选票会转化成什么?答案:\"特朗普\"。也就是要么民粹要么你补偿我。补偿只有一个方法提高他的薪资收入。你以为真的是像宏观经济上在跟你讲说因为这场疫情导致供应链导致劳动力市场结构发生了变换那都不是核心真正的核心是当居民部门还了12年、15年债以后这部分人不想还了你要么就是更多的补偿给我、要么就是给我加薪。\n\n目前美国出现的就一个结果底层通胀、顶层通缩。知道美国现在谁最惨吗美国西海岸。硅谷、洛杉矶、旧金山的富人这15年是他们加了杠杆08年后的这漫长的15年创造了我们近乎200年以来全世界最低的资金年代它也创造了全世界几乎是最大的资产。这个资产是什么虚拟资产你们知道为什么会出现虚拟性货币如果这么庞大的流动性这么便宜的资金冲向了实物资产(粮食、房子)这个价格一旦失控我们离战争就不远了。虚拟资产有个好处它仅仅消灭富人财富。西海岸的这帮我们叫美国新贵准确说叫做穷人日子很好富人日子很难受。富人中间是老钱收割新钱老钱是什么呢华盛顿、纽约、休斯顿新钱就是硅谷、洛杉矶。新钱靠的是什么科技、技术、创新。你创造一个东西带来的社会价值可能只创造了1万块。但是金融市场给予你200倍。一次性兑付了几百年的收益。这就是我们的金融市场当利率水平过低的时候它会使得所有资产的估值极高。而科技作为主要的推动力会自然而然地迎来一场高估值的泡沫。\n\n干一级市场投资我可以告诉你估值泡沫出现的时候那特征都是一样的简单说瞎几把随便写PPT都能融到钱。有很多人的利益是建立在利率和资产价格上的。经济行的时候是可以承受高利率的。经济不行的时候(日本)把利率降到负都没用。\n\n这四十年结束以后逻辑是什么科技肯定不行深圳科创你就搞到天上去你拉动整个社会的经济也远着呢技术的进步只有转化成全民生产率才能拉动所有人。中国现在相反是低增长、低通胀、低利率而这3低的背后是高杠杆。有一种情况可以让我们避开这种所谓的内卷型的环境就是走出去。美国在六十年代到现在不是盈利率的增长它获得的是市场份额的扩大。中国现在所有的企业会内卷的会卷得一塌糊涂原因很简单市场只有国内了。2018年开始的中美贸易战逆全球化鬼佬就是要把我们踢出去。因为不走出去我们过去的二三十年所有的产能是给全世界走配套的。如果不走出去单凭我们国内的居民部门消化不了。\n\n我们国内居民部门中还出现了一个问题大部分的90后、95后是在缩的他们是在降低欲望的他们是在消费降级的。高端消费永远是给那些富人的。中产阶级的杠杆达到一定程度就会进入一个很典型的低欲望社会。跟现在比较穷的年轻人打打交道你们就会发现不结婚挺好、不生孩子挺好、这个不买房也不错、这个手机也不用换。然后这个蜜雪冰城的咖啡。虽然难喝点但还可以你。跟富二代富三代打交道就看不出来。中国现在也是典型的K字型。\n\n过去四十年的游戏结束了现金远远地甩开了长期经济增长。巴菲特已经教过大家了最好的公司是什么经济好也好。经济坏也好是刚需、高股息类的公司且不受经济低迷影响的公司。你们有没有发现在最近在炒中草药为啥炒中炒药就是刚需好比通信行业的话费你必须得按月充值。所以巴菲特在买的是什么现金奶牛ETF的配置看看都是啥能源、医药、金融。这些行业就是典型的现金类资产巴菲特想获得一样东西知道是什么吗股息率美孚的几个财务数据叠加会发现第一种情况低油价、经济差它的股价上涨的。并不是巴菲特赌油价上涨。\n\n全球过去40年挣100块钱只有40块钱来自于你们理解中的经济增长带来的回报有60块钱是来自于低利率加杠杆的投资回报。所以这个世界有两个投资人一个叫长期价值投资回报就是获得经济增长带来的贴现。另外一个就是获得利率波动带来的加杠杆房子准确说典型的就是杠杆性资产如果房住不炒那理论上它是没有价格波动的。\n\n今年是蹦了一个ChatGPT明年还必定还会有个啥的。当然我只想说一句当你听到今年AI的时候你们还记得去年大明湖畔的元宇宙吗你们还记得十年前的互联网加万物吗过去几年全球利率低咱们可以你炒一波咱们给90后90后炒一波给95后95后炒一波给00后然后全球流动性一收咱们把00后挂到高位上。为什么是这个路径越年轻的越信技术他们认为技术能改变世界结果世界会残酷地教育你。技术能不能改变世界但绝对不是炒技术炒技术改变不了世界。\n\n从去年十一月份所有的主题性投资只能这样炒当你想给90后的时候你发现90后的元宇宙还没解套呢90后借不来更多的钱所以周期会非常短迅速炒迅速落。可人民币现在利率这么低为什么会没有钱呢因为所有科技性投资不是跟着人民币利率走的。比如ChatGPT是海外现有了这个东西国内跟风元宇宙亦然新能源汽车也是现有了特斯拉。中国在技术方面采取的战略是摸着石头过河、黑猫白猫带着老鼠就行。所以我们会出现一种情况海外有个热点我们马上跟。那问题就来了你的估值怎么定价做过一级市场投资的投资某家企业的时候对标物是美国某某企业。美股最强大的地方是把所有创新的Top级的领军人物均以美元定价导致的一个结果就是它是锚定价了所有估值水平。如果人民币能对资产估值有影响那就必须要求投这家企业的对标物是在中国上市。\n\n能挣钱的企业就是好企业像国内某企业家讲的我五年不给你分红你能把我咋滴这种企业就不是好企业。挣钱分钱经济不好的时候能力还继续挣钱这就是它的垄断性。所以你们会发现别瞧不起老钱老钱投的上游。改革开放之后煤炭、电力、很多行业都是允许民营企业介入的到现在为止我就请问这些上游还有民营企业吗\n\n回到日本的商社跟中国国有企业本质是一样它是家庭组织不由董事会左右。巴菲特去了以后和高管和家族的人员就谈了一个事你是现金奶牛因为它控制了全球的上游。所以在经济不好的时候日本的五大商社就是中国的国有企业也是美国的能源企业。能挣钱、有利润然后有大量的自由现金流。它唯一的问题是\"公司治理\",就是它不一定愿意给你分。现在股息率快到五了,你不分,我就把公司买成我的,然后日本人说的就是:巴菲特先生,你别把我控制,我愿意分钱给你。因此巴菲特干的事情,买了日本的这些高股息的资产,并且在日本发行了无抵押担保的日元债券。啥意思呢?巴菲特一毛钱没掏,用日本人的储蓄以及低利率水平借钱,买了日本人的资产,还强迫日本人分了高股息,这才是资本真正的收割。\n\n未来的5年是10年真正的游戏是如何借低息买高息。美元不便宜了但美元的高息依旧很吸引人。那么问题就来了谁是低息美元如果一直维持高增长高通胀、高利率的话人民币一定是贬值的。而倒过来的交易借人民币转高息资产这个高息资产可以是人民币里边不多有的高息资产也可以是全球范围内的高股息现金奶牛你会发现这就又形成了类似于15年前的套利资本流动、交易机会。","slug":"finance/付鹏展望2023年下半年全球经济格局异常的利差意味着什么","published":1,"date":"2023-11-06T05:14:30.824Z","updated":"2023-11-06T05:22:07.164Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58q000l4cz31hnu8sy9","content":"<p><img src=\"/img/mz10nq.png\" alt=\"美债10年利差\"></p>\n<p>08年的金融危机或者09年是一个重要的时间节点到今年(2023年),在座各位你们将迎来第二个重要的节点,可能对于很多年轻人来讲,最好的一个时代结束了,我们所有人的下半辈子的投资,注意,也非常简单,抄巴菲特作业。</p>\n<p>巴菲特刚去了日本(2011年也去了),你们就知道日本发生了什么。你看到了安倍晋三的三支箭,你看到了日本日元的大幅度的贬值。过去两年,巴菲特一直在买日本的这五大商社:三菱商社、三井物产、伊藤忠商事、住友、丸红,然后大家还看到巴菲特在过去的两年一直在买美孚和西方石油。有人说了巴菲特在赌油价上涨,我只能说如果你讲这种话的话,你金融基本没入门。</p>\n<p>我想说的是任何的技术创新在某些环节中它是由资金来决定的技术人员只是其中一环。没有钱没有便宜的钱一切都是假的。所以技术的进步的背后有个很关键的因素就是钱钱多钱少钱贵钱便宜你的投资将完全不同。比如说昨天还是前天你们看到软银的孙正义基本上把所有的阿里巴巴的资金卖掉了开始往回抽回资金。我经常说包括对我自己的子女都讲一句话99%的命运和1%的努力而不是99%的努力1%的命运。大势极其的重要,这个”大势”或许也就是我们在金融市场打拼,真正能够获得的。</p>\n<p>然后图上右侧我给大家放了最核心的美债利差美债利差是什么东西可以这么简单理解”全球资金的成本”。美国是一年期国债收益率和十年期国债收益率的差值主要是差值。如果懂商品期货的话你们知道我们的所有东西都有一个概念叫做当期价格和远期价格那么资金一年期可以简单理解成当期资金价格十年期你可以理解成十年拉长十年以后的资金价格。这个”一”和”十”的概念是什么十年期大概等同于经济增长。我们过去的四十年的大部分时间短期利率低于经济增长。比如说你现在干了一个企业你预期你未来的三到五年你能获得10%左右的利润,而当期银行提供给你的借贷成本只有三个点,你知道你该干嘛了吗?借便宜的钱投高息的回报。</p>\n<p>本质上金融的核心除了研究经济研究长期回报以外还有个很重要的就是从哪借钱能不能借到便宜的钱能不能在便宜的钱上面借更多的钱但不是说便宜的钱就一定能够刺激起来借贷日本90年房地产泡沫破裂以后利率水平给你干到0你都不借为什么因为没有资产回报这个怎么反映在我们的全球利率上呢简单讲这个数字在0以上它代表着你现在的借贷资金成本在这你的投资回报在下头。</p>\n<p>你记住一点你活多大年龄决定了你见过多大市面我们现在在中国从事金融的大部分的人有见过40年前国际市场是什么情况吗巴菲特90多了芒格明年就100了对吧用我的话说你要活到那个年龄你啥都见过了金融理念特别简单借便宜的钱去赚高息的回报就这么简单。</p>\n<p>一定要喜欢危机,可能是干实体的人不喜欢,但我可以告诉你,干金融的人我们超级喜欢危机,因为每一次危机的到来将带来一次年轻人特别喜欢的机会,赌一赌,单车变摩托,赌的是什么呢?你就赌危机爆发之后,全球的政府和央行永远只会干一件事:放水降息、放水降更多的息、放更多的水降更多的息。</p>\n<p>40年前平均的状态实际上就是短期利率永远高于长期经济回报这在经济学中是什么有人会说通胀、通缩其实还有一个状态大家并不喜欢”滞胀”这种状态距离我们已经40年了换句话说全球已经40年没太出现过这种情况。但对不起你们有没有想过现在或许来了它导致的我们的所有投资完全不同。</p>\n<p>资金越便宜长期投资回报越稳定借越便宜的钱买更高的高息资产借更多。一旦倒过来我就请问你怎么交易银行存款五点几投所有的资产回报只有三点几我就问你大部分人会怎么做不是说就指现金在银行的才叫现金只要在当期能够产生高息回报的资金或者资产都叫现金。我举个例子比如说一个公司股息分10%它算不算高息资产它算不算高息现金它每年都给你分跟你银行存到银行每年拿5%有区别?没区别!所以说这个短期高于长期从最直觉的理解就是资金应该放在现金上。</p>\n<p>为什么巴菲特买那些公司那些公司跟上面的现金奶牛ETF之间是什么关系08年金融危机后美国把基准利率水平拉得非常低09年两会口号是”做大做强金融万众创业万众创新”之后出来的小贷公司担保公司P2P对吧一连串都是在这个大的宏观背景下去搞的。09年之后你真正应该获得的只有两个收益一个卖房炒房卖房炒房、买更多的房炒更多的房。第二个投腾讯投阿里投万众创业投万众创新就这两条路。在中国你记住有些路不是自然形成的它在那个关键的节点上全是由政府这支无形的手在引导两会这个口号一提出来你一看中国居民部门属于”高储蓄低杠杆”你知道人生的机会来了。</p>\n<p>真正投资的精髓不是买资产,是如何去负债。如何在钱便宜的时间点上去负债、付更多的债、如何去付更低的资金成本,然后右手才去考虑资产,很多人光想资产而不去考虑负债。</p>\n<p>房价上涨就一条这个地方有没有人进来。第二这个地方进来的人能不能借更多的钱就是居民部门杠杆率。首先得有居民第二得有杠杆率如果这俩都没了这个资产基本就到头了。09年就是让他们加杠杆扛着进去的现在的经济为什么差我可以告诉你还有人说刺激咋刺激09年能刺激是因为所有的居民部门有储蓄稳定企业低负债现在是没储蓄、不稳定。更重要的是睁眼全是债简单讲年轻人杠杆加不动这才是最大的风险。核心城市核心区域除此之外都别碰因为只有这个核心俩字才能带来人。香港特首前段时间天天在广深在那晃荡的不就是邀请你们去吗但是你跟他说我没钱家里也没钱我就是个穷小子那对不起你别过来。你来我也不要因为我要你的根本是你有钱你能接得住你能加得住杠杆。我认为最核心的一个是房价到达一定程度人自然没法生隔壁韩国如此日本如此中国亦如此。中国现在的大体情况是未来的五到十年基本处在加完杠杆后还债的年代。低增长、低通胀、低利率三低。而过去的三十年中国一直是高增长高通胀、高利率。高和低之间差距是什么杠杆率到一定程度自然就定了隔壁日本就是到了极致崩了</p>\n<p>老美的底层老百姓过得并不好,但老美的富人更好了,富人靠杠杆。记住一点,富人靠杠杆、靠金融资产,穷人才靠劳动力。在全球化的过程,美国居民保持的是最低的生存权利(美国底层人民)他的收入是不增长的。从1982年开始美国的数字是多少呢平均薪资增速3%金字塔的底层25%和顶层25%的薪资性收入差是1%。啥意思呢平均3%的薪资收入增长再减去1%的社会阶层差底层25%的美国居民薪资性收入仅仅是2%。大家发现这个2%是什么?正好就是美国通胀水平。啥意思呢?你可以理解,这美国的底层居民过去的二三十年薪资扣掉通胀是不增长的。</p>\n<p>二十多年前索罗斯写那本联名书的时候他就给大家解释过这个话题他说中国庞大的贸易顺差去补偿了美国底层居民。举个例子一个美国人薪资2万保持不变但是呢中国生产的笔记本电脑从5000美金降到了1000美金我的购买力怎么样增强了这就是庞大的中国出口。中国出口的商品绕一圈转回来变成中国的外汇储备中国的外汇储备买的是什么买的是美债。美债用于什么了美债用于两件事打仗、给底层居民补医疗和教育。所以你就会发现。如果你做美国的底层居民的话出现什么情况呢收入没增长但是中国供应的商品的购买力降弱了这个购买力让美国人的购买力增强了。同时中国大量的顺差和外汇储备补偿了美国的教育和医疗。</p>\n<p>美国真正发家致富的人都是看明白了这套游戏的。一旦底层居民薪资收入不增长我们教科书里学的货币银行学中央行双目标志将失效也就是说中央银行将永远不用去考虑薪资通胀只需要去考虑经济。此时就会产生我们现在这个模型”经济不行就降息”。每一次经济不行的时候就借更多的美元买更多的美国金融性资产。但在82年美国金融监管放开了一个重要的法案金融自由化。啥意思如果监管部门把银行管得死死的银行不许给居民加杠杆就算来了这样的机会社会也没有财富效应。但如果我此时告诉银行金融监管你们可以去创造各种各样的金融衍生产品去给居民部门加杠杆举例子房贷可以变成18种花样于是82年到2022年搞了整整40年。</p>\n<p>到了02年的时候美国居民部门突然间反应过来原来富人不是靠着劳动挣钱的富人得去炒金融资产。02年小布什一句话你们得做起美国梦来。什么意思你们手上没有股票得有但问题是在于这帮穷人的美国梦是最可怕的因为他收入不增长还借了更多的房贷02年到08年的这种做法结果就是08年崩掉了。但崩掉以后美国的底层人民麻烦就大了被迫还了15年的债。从08年到现在美国居民部门一直在去杠杆还债但是你知道一个人收入不增长然后还要不停的还债他最终会转成什么欧美有两样东西会让整个社会颠覆的一个是”选票”、”上街大游行”。他的选票会转化成什么答案”特朗普”。也就是要么民粹要么你补偿我。补偿只有一个方法提高他的薪资收入。你以为真的是像宏观经济上在跟你讲说因为这场疫情导致供应链导致劳动力市场结构发生了变换那都不是核心真正的核心是当居民部门还了12年、15年债以后这部分人不想还了你要么就是更多的补偿给我、要么就是给我加薪。</p>\n<p>目前美国出现的就一个结果底层通胀、顶层通缩。知道美国现在谁最惨吗美国西海岸。硅谷、洛杉矶、旧金山的富人这15年是他们加了杠杆08年后的这漫长的15年创造了我们近乎200年以来全世界最低的资金年代它也创造了全世界几乎是最大的资产。这个资产是什么虚拟资产你们知道为什么会出现虚拟性货币如果这么庞大的流动性这么便宜的资金冲向了实物资产(粮食、房子)这个价格一旦失控我们离战争就不远了。虚拟资产有个好处它仅仅消灭富人财富。西海岸的这帮我们叫美国新贵准确说叫做穷人日子很好富人日子很难受。富人中间是老钱收割新钱老钱是什么呢华盛顿、纽约、休斯顿新钱就是硅谷、洛杉矶。新钱靠的是什么科技、技术、创新。你创造一个东西带来的社会价值可能只创造了1万块。但是金融市场给予你200倍。一次性兑付了几百年的收益。这就是我们的金融市场当利率水平过低的时候它会使得所有资产的估值极高。而科技作为主要的推动力会自然而然地迎来一场高估值的泡沫。</p>\n<p>干一级市场投资我可以告诉你估值泡沫出现的时候那特征都是一样的简单说瞎几把随便写PPT都能融到钱。有很多人的利益是建立在利率和资产价格上的。经济行的时候是可以承受高利率的。经济不行的时候(日本)把利率降到负都没用。</p>\n<p>这四十年结束以后逻辑是什么科技肯定不行深圳科创你就搞到天上去你拉动整个社会的经济也远着呢技术的进步只有转化成全民生产率才能拉动所有人。中国现在相反是低增长、低通胀、低利率而这3低的背后是高杠杆。有一种情况可以让我们避开这种所谓的内卷型的环境就是走出去。美国在六十年代到现在不是盈利率的增长它获得的是市场份额的扩大。中国现在所有的企业会内卷的会卷得一塌糊涂原因很简单市场只有国内了。2018年开始的中美贸易战逆全球化鬼佬就是要把我们踢出去。因为不走出去我们过去的二三十年所有的产能是给全世界走配套的。如果不走出去单凭我们国内的居民部门消化不了。</p>\n<p>我们国内居民部门中还出现了一个问题大部分的90后、95后是在缩的他们是在降低欲望的他们是在消费降级的。高端消费永远是给那些富人的。中产阶级的杠杆达到一定程度就会进入一个很典型的低欲望社会。跟现在比较穷的年轻人打打交道你们就会发现不结婚挺好、不生孩子挺好、这个不买房也不错、这个手机也不用换。然后这个蜜雪冰城的咖啡。虽然难喝点但还可以你。跟富二代富三代打交道就看不出来。中国现在也是典型的K字型。</p>\n<p>过去四十年的游戏结束了现金远远地甩开了长期经济增长。巴菲特已经教过大家了最好的公司是什么经济好也好。经济坏也好是刚需、高股息类的公司且不受经济低迷影响的公司。你们有没有发现在最近在炒中草药为啥炒中炒药就是刚需好比通信行业的话费你必须得按月充值。所以巴菲特在买的是什么现金奶牛ETF的配置看看都是啥能源、医药、金融。这些行业就是典型的现金类资产巴菲特想获得一样东西知道是什么吗股息率美孚的几个财务数据叠加会发现第一种情况低油价、经济差它的股价上涨的。并不是巴菲特赌油价上涨。</p>\n<p>全球过去40年挣100块钱只有40块钱来自于你们理解中的经济增长带来的回报有60块钱是来自于低利率加杠杆的投资回报。所以这个世界有两个投资人一个叫长期价值投资回报就是获得经济增长带来的贴现。另外一个就是获得利率波动带来的加杠杆房子准确说典型的就是杠杆性资产如果房住不炒那理论上它是没有价格波动的。</p>\n<p>今年是蹦了一个ChatGPT明年还必定还会有个啥的。当然我只想说一句当你听到今年AI的时候你们还记得去年大明湖畔的元宇宙吗你们还记得十年前的互联网加万物吗过去几年全球利率低咱们可以你炒一波咱们给90后90后炒一波给95后95后炒一波给00后然后全球流动性一收咱们把00后挂到高位上。为什么是这个路径越年轻的越信技术他们认为技术能改变世界结果世界会残酷地教育你。技术能不能改变世界但绝对不是炒技术炒技术改变不了世界。</p>\n<p>从去年十一月份所有的主题性投资只能这样炒当你想给90后的时候你发现90后的元宇宙还没解套呢90后借不来更多的钱所以周期会非常短迅速炒迅速落。可人民币现在利率这么低为什么会没有钱呢因为所有科技性投资不是跟着人民币利率走的。比如ChatGPT是海外现有了这个东西国内跟风元宇宙亦然新能源汽车也是现有了特斯拉。中国在技术方面采取的战略是摸着石头过河、黑猫白猫带着老鼠就行。所以我们会出现一种情况海外有个热点我们马上跟。那问题就来了你的估值怎么定价做过一级市场投资的投资某家企业的时候对标物是美国某某企业。美股最强大的地方是把所有创新的Top级的领军人物均以美元定价导致的一个结果就是它是锚定价了所有估值水平。如果人民币能对资产估值有影响那就必须要求投这家企业的对标物是在中国上市。</p>\n<p>能挣钱的企业就是好企业?像国内某企业家讲的,我五年不给你分红,你能把我咋滴?这种企业就不是好企业。挣钱分钱,经济不好的时候能力还继续挣钱,这就是它的垄断性。所以你们会发现,别瞧不起老钱,老钱投的上游。改革开放之后,煤炭、电力、很多行业都是允许民营企业介入的,到现在为止我就请问,这些上游还有民营企业吗?</p>\n<p>回到日本的商社,跟中国国有企业本质是一样,它是家庭组织,不由董事会左右。巴菲特去了以后,和高管和家族的人员就谈了一个事,你是现金奶牛,因为它控制了全球的上游。所以在经济不好的时候,日本的五大商社就是中国的国有企业,也是美国的能源企业。能挣钱、有利润,然后有大量的自由现金流。它唯一的问题是:”公司治理”,就是它不一定愿意给你分。现在股息率快到五了,你不分,我就把公司买成我的,然后日本人说的就是:巴菲特先生,你别把我控制,我愿意分钱给你。因此巴菲特干的事情,买了日本的这些高股息的资产,并且在日本发行了无抵押担保的日元债券。啥意思呢?巴菲特一毛钱没掏,用日本人的储蓄以及低利率水平借钱,买了日本人的资产,还强迫日本人分了高股息,这才是资本真正的收割。</p>\n<p>未来的5年是10年真正的游戏是如何借低息买高息。美元不便宜了但美元的高息依旧很吸引人。那么问题就来了谁是低息美元如果一直维持高增长高通胀、高利率的话人民币一定是贬值的。而倒过来的交易借人民币转高息资产这个高息资产可以是人民币里边不多有的高息资产也可以是全球范围内的高股息现金奶牛你会发现这就又形成了类似于15年前的套利资本流动、交易机会。</p>\n","site":{"data":{}},"excerpt":"","more":"<p><img src=\"/img/mz10nq.png\" alt=\"美债10年利差\"></p>\n<p>08年的金融危机或者09年是一个重要的时间节点到今年(2023年),在座各位你们将迎来第二个重要的节点,可能对于很多年轻人来讲,最好的一个时代结束了,我们所有人的下半辈子的投资,注意,也非常简单,抄巴菲特作业。</p>\n<p>巴菲特刚去了日本(2011年也去了),你们就知道日本发生了什么。你看到了安倍晋三的三支箭,你看到了日本日元的大幅度的贬值。过去两年,巴菲特一直在买日本的这五大商社:三菱商社、三井物产、伊藤忠商事、住友、丸红,然后大家还看到巴菲特在过去的两年一直在买美孚和西方石油。有人说了巴菲特在赌油价上涨,我只能说如果你讲这种话的话,你金融基本没入门。</p>\n<p>我想说的是任何的技术创新在某些环节中它是由资金来决定的技术人员只是其中一环。没有钱没有便宜的钱一切都是假的。所以技术的进步的背后有个很关键的因素就是钱钱多钱少钱贵钱便宜你的投资将完全不同。比如说昨天还是前天你们看到软银的孙正义基本上把所有的阿里巴巴的资金卖掉了开始往回抽回资金。我经常说包括对我自己的子女都讲一句话99%的命运和1%的努力而不是99%的努力1%的命运。大势极其的重要,这个”大势”或许也就是我们在金融市场打拼,真正能够获得的。</p>\n<p>然后图上右侧我给大家放了最核心的美债利差美债利差是什么东西可以这么简单理解”全球资金的成本”。美国是一年期国债收益率和十年期国债收益率的差值主要是差值。如果懂商品期货的话你们知道我们的所有东西都有一个概念叫做当期价格和远期价格那么资金一年期可以简单理解成当期资金价格十年期你可以理解成十年拉长十年以后的资金价格。这个”一”和”十”的概念是什么十年期大概等同于经济增长。我们过去的四十年的大部分时间短期利率低于经济增长。比如说你现在干了一个企业你预期你未来的三到五年你能获得10%左右的利润,而当期银行提供给你的借贷成本只有三个点,你知道你该干嘛了吗?借便宜的钱投高息的回报。</p>\n<p>本质上金融的核心除了研究经济研究长期回报以外还有个很重要的就是从哪借钱能不能借到便宜的钱能不能在便宜的钱上面借更多的钱但不是说便宜的钱就一定能够刺激起来借贷日本90年房地产泡沫破裂以后利率水平给你干到0你都不借为什么因为没有资产回报这个怎么反映在我们的全球利率上呢简单讲这个数字在0以上它代表着你现在的借贷资金成本在这你的投资回报在下头。</p>\n<p>你记住一点你活多大年龄决定了你见过多大市面我们现在在中国从事金融的大部分的人有见过40年前国际市场是什么情况吗巴菲特90多了芒格明年就100了对吧用我的话说你要活到那个年龄你啥都见过了金融理念特别简单借便宜的钱去赚高息的回报就这么简单。</p>\n<p>一定要喜欢危机,可能是干实体的人不喜欢,但我可以告诉你,干金融的人我们超级喜欢危机,因为每一次危机的到来将带来一次年轻人特别喜欢的机会,赌一赌,单车变摩托,赌的是什么呢?你就赌危机爆发之后,全球的政府和央行永远只会干一件事:放水降息、放水降更多的息、放更多的水降更多的息。</p>\n<p>40年前平均的状态实际上就是短期利率永远高于长期经济回报这在经济学中是什么有人会说通胀、通缩其实还有一个状态大家并不喜欢”滞胀”这种状态距离我们已经40年了换句话说全球已经40年没太出现过这种情况。但对不起你们有没有想过现在或许来了它导致的我们的所有投资完全不同。</p>\n<p>资金越便宜长期投资回报越稳定借越便宜的钱买更高的高息资产借更多。一旦倒过来我就请问你怎么交易银行存款五点几投所有的资产回报只有三点几我就问你大部分人会怎么做不是说就指现金在银行的才叫现金只要在当期能够产生高息回报的资金或者资产都叫现金。我举个例子比如说一个公司股息分10%它算不算高息资产它算不算高息现金它每年都给你分跟你银行存到银行每年拿5%有区别?没区别!所以说这个短期高于长期从最直觉的理解就是资金应该放在现金上。</p>\n<p>为什么巴菲特买那些公司那些公司跟上面的现金奶牛ETF之间是什么关系08年金融危机后美国把基准利率水平拉得非常低09年两会口号是”做大做强金融万众创业万众创新”之后出来的小贷公司担保公司P2P对吧一连串都是在这个大的宏观背景下去搞的。09年之后你真正应该获得的只有两个收益一个卖房炒房卖房炒房、买更多的房炒更多的房。第二个投腾讯投阿里投万众创业投万众创新就这两条路。在中国你记住有些路不是自然形成的它在那个关键的节点上全是由政府这支无形的手在引导两会这个口号一提出来你一看中国居民部门属于”高储蓄低杠杆”你知道人生的机会来了。</p>\n<p>真正投资的精髓不是买资产,是如何去负债。如何在钱便宜的时间点上去负债、付更多的债、如何去付更低的资金成本,然后右手才去考虑资产,很多人光想资产而不去考虑负债。</p>\n<p>房价上涨就一条这个地方有没有人进来。第二这个地方进来的人能不能借更多的钱就是居民部门杠杆率。首先得有居民第二得有杠杆率如果这俩都没了这个资产基本就到头了。09年就是让他们加杠杆扛着进去的现在的经济为什么差我可以告诉你还有人说刺激咋刺激09年能刺激是因为所有的居民部门有储蓄稳定企业低负债现在是没储蓄、不稳定。更重要的是睁眼全是债简单讲年轻人杠杆加不动这才是最大的风险。核心城市核心区域除此之外都别碰因为只有这个核心俩字才能带来人。香港特首前段时间天天在广深在那晃荡的不就是邀请你们去吗但是你跟他说我没钱家里也没钱我就是个穷小子那对不起你别过来。你来我也不要因为我要你的根本是你有钱你能接得住你能加得住杠杆。我认为最核心的一个是房价到达一定程度人自然没法生隔壁韩国如此日本如此中国亦如此。中国现在的大体情况是未来的五到十年基本处在加完杠杆后还债的年代。低增长、低通胀、低利率三低。而过去的三十年中国一直是高增长高通胀、高利率。高和低之间差距是什么杠杆率到一定程度自然就定了隔壁日本就是到了极致崩了</p>\n<p>老美的底层老百姓过得并不好,但老美的富人更好了,富人靠杠杆。记住一点,富人靠杠杆、靠金融资产,穷人才靠劳动力。在全球化的过程,美国居民保持的是最低的生存权利(美国底层人民)他的收入是不增长的。从1982年开始美国的数字是多少呢平均薪资增速3%金字塔的底层25%和顶层25%的薪资性收入差是1%。啥意思呢平均3%的薪资收入增长再减去1%的社会阶层差底层25%的美国居民薪资性收入仅仅是2%。大家发现这个2%是什么?正好就是美国通胀水平。啥意思呢?你可以理解,这美国的底层居民过去的二三十年薪资扣掉通胀是不增长的。</p>\n<p>二十多年前索罗斯写那本联名书的时候他就给大家解释过这个话题他说中国庞大的贸易顺差去补偿了美国底层居民。举个例子一个美国人薪资2万保持不变但是呢中国生产的笔记本电脑从5000美金降到了1000美金我的购买力怎么样增强了这就是庞大的中国出口。中国出口的商品绕一圈转回来变成中国的外汇储备中国的外汇储备买的是什么买的是美债。美债用于什么了美债用于两件事打仗、给底层居民补医疗和教育。所以你就会发现。如果你做美国的底层居民的话出现什么情况呢收入没增长但是中国供应的商品的购买力降弱了这个购买力让美国人的购买力增强了。同时中国大量的顺差和外汇储备补偿了美国的教育和医疗。</p>\n<p>美国真正发家致富的人都是看明白了这套游戏的。一旦底层居民薪资收入不增长我们教科书里学的货币银行学中央行双目标志将失效也就是说中央银行将永远不用去考虑薪资通胀只需要去考虑经济。此时就会产生我们现在这个模型”经济不行就降息”。每一次经济不行的时候就借更多的美元买更多的美国金融性资产。但在82年美国金融监管放开了一个重要的法案金融自由化。啥意思如果监管部门把银行管得死死的银行不许给居民加杠杆就算来了这样的机会社会也没有财富效应。但如果我此时告诉银行金融监管你们可以去创造各种各样的金融衍生产品去给居民部门加杠杆举例子房贷可以变成18种花样于是82年到2022年搞了整整40年。</p>\n<p>到了02年的时候美国居民部门突然间反应过来原来富人不是靠着劳动挣钱的富人得去炒金融资产。02年小布什一句话你们得做起美国梦来。什么意思你们手上没有股票得有但问题是在于这帮穷人的美国梦是最可怕的因为他收入不增长还借了更多的房贷02年到08年的这种做法结果就是08年崩掉了。但崩掉以后美国的底层人民麻烦就大了被迫还了15年的债。从08年到现在美国居民部门一直在去杠杆还债但是你知道一个人收入不增长然后还要不停的还债他最终会转成什么欧美有两样东西会让整个社会颠覆的一个是”选票”、”上街大游行”。他的选票会转化成什么答案”特朗普”。也就是要么民粹要么你补偿我。补偿只有一个方法提高他的薪资收入。你以为真的是像宏观经济上在跟你讲说因为这场疫情导致供应链导致劳动力市场结构发生了变换那都不是核心真正的核心是当居民部门还了12年、15年债以后这部分人不想还了你要么就是更多的补偿给我、要么就是给我加薪。</p>\n<p>目前美国出现的就一个结果底层通胀、顶层通缩。知道美国现在谁最惨吗美国西海岸。硅谷、洛杉矶、旧金山的富人这15年是他们加了杠杆08年后的这漫长的15年创造了我们近乎200年以来全世界最低的资金年代它也创造了全世界几乎是最大的资产。这个资产是什么虚拟资产你们知道为什么会出现虚拟性货币如果这么庞大的流动性这么便宜的资金冲向了实物资产(粮食、房子)这个价格一旦失控我们离战争就不远了。虚拟资产有个好处它仅仅消灭富人财富。西海岸的这帮我们叫美国新贵准确说叫做穷人日子很好富人日子很难受。富人中间是老钱收割新钱老钱是什么呢华盛顿、纽约、休斯顿新钱就是硅谷、洛杉矶。新钱靠的是什么科技、技术、创新。你创造一个东西带来的社会价值可能只创造了1万块。但是金融市场给予你200倍。一次性兑付了几百年的收益。这就是我们的金融市场当利率水平过低的时候它会使得所有资产的估值极高。而科技作为主要的推动力会自然而然地迎来一场高估值的泡沫。</p>\n<p>干一级市场投资我可以告诉你估值泡沫出现的时候那特征都是一样的简单说瞎几把随便写PPT都能融到钱。有很多人的利益是建立在利率和资产价格上的。经济行的时候是可以承受高利率的。经济不行的时候(日本)把利率降到负都没用。</p>\n<p>这四十年结束以后逻辑是什么科技肯定不行深圳科创你就搞到天上去你拉动整个社会的经济也远着呢技术的进步只有转化成全民生产率才能拉动所有人。中国现在相反是低增长、低通胀、低利率而这3低的背后是高杠杆。有一种情况可以让我们避开这种所谓的内卷型的环境就是走出去。美国在六十年代到现在不是盈利率的增长它获得的是市场份额的扩大。中国现在所有的企业会内卷的会卷得一塌糊涂原因很简单市场只有国内了。2018年开始的中美贸易战逆全球化鬼佬就是要把我们踢出去。因为不走出去我们过去的二三十年所有的产能是给全世界走配套的。如果不走出去单凭我们国内的居民部门消化不了。</p>\n<p>我们国内居民部门中还出现了一个问题大部分的90后、95后是在缩的他们是在降低欲望的他们是在消费降级的。高端消费永远是给那些富人的。中产阶级的杠杆达到一定程度就会进入一个很典型的低欲望社会。跟现在比较穷的年轻人打打交道你们就会发现不结婚挺好、不生孩子挺好、这个不买房也不错、这个手机也不用换。然后这个蜜雪冰城的咖啡。虽然难喝点但还可以你。跟富二代富三代打交道就看不出来。中国现在也是典型的K字型。</p>\n<p>过去四十年的游戏结束了现金远远地甩开了长期经济增长。巴菲特已经教过大家了最好的公司是什么经济好也好。经济坏也好是刚需、高股息类的公司且不受经济低迷影响的公司。你们有没有发现在最近在炒中草药为啥炒中炒药就是刚需好比通信行业的话费你必须得按月充值。所以巴菲特在买的是什么现金奶牛ETF的配置看看都是啥能源、医药、金融。这些行业就是典型的现金类资产巴菲特想获得一样东西知道是什么吗股息率美孚的几个财务数据叠加会发现第一种情况低油价、经济差它的股价上涨的。并不是巴菲特赌油价上涨。</p>\n<p>全球过去40年挣100块钱只有40块钱来自于你们理解中的经济增长带来的回报有60块钱是来自于低利率加杠杆的投资回报。所以这个世界有两个投资人一个叫长期价值投资回报就是获得经济增长带来的贴现。另外一个就是获得利率波动带来的加杠杆房子准确说典型的就是杠杆性资产如果房住不炒那理论上它是没有价格波动的。</p>\n<p>今年是蹦了一个ChatGPT明年还必定还会有个啥的。当然我只想说一句当你听到今年AI的时候你们还记得去年大明湖畔的元宇宙吗你们还记得十年前的互联网加万物吗过去几年全球利率低咱们可以你炒一波咱们给90后90后炒一波给95后95后炒一波给00后然后全球流动性一收咱们把00后挂到高位上。为什么是这个路径越年轻的越信技术他们认为技术能改变世界结果世界会残酷地教育你。技术能不能改变世界但绝对不是炒技术炒技术改变不了世界。</p>\n<p>从去年十一月份所有的主题性投资只能这样炒当你想给90后的时候你发现90后的元宇宙还没解套呢90后借不来更多的钱所以周期会非常短迅速炒迅速落。可人民币现在利率这么低为什么会没有钱呢因为所有科技性投资不是跟着人民币利率走的。比如ChatGPT是海外现有了这个东西国内跟风元宇宙亦然新能源汽车也是现有了特斯拉。中国在技术方面采取的战略是摸着石头过河、黑猫白猫带着老鼠就行。所以我们会出现一种情况海外有个热点我们马上跟。那问题就来了你的估值怎么定价做过一级市场投资的投资某家企业的时候对标物是美国某某企业。美股最强大的地方是把所有创新的Top级的领军人物均以美元定价导致的一个结果就是它是锚定价了所有估值水平。如果人民币能对资产估值有影响那就必须要求投这家企业的对标物是在中国上市。</p>\n<p>能挣钱的企业就是好企业?像国内某企业家讲的,我五年不给你分红,你能把我咋滴?这种企业就不是好企业。挣钱分钱,经济不好的时候能力还继续挣钱,这就是它的垄断性。所以你们会发现,别瞧不起老钱,老钱投的上游。改革开放之后,煤炭、电力、很多行业都是允许民营企业介入的,到现在为止我就请问,这些上游还有民营企业吗?</p>\n<p>回到日本的商社,跟中国国有企业本质是一样,它是家庭组织,不由董事会左右。巴菲特去了以后,和高管和家族的人员就谈了一个事,你是现金奶牛,因为它控制了全球的上游。所以在经济不好的时候,日本的五大商社就是中国的国有企业,也是美国的能源企业。能挣钱、有利润,然后有大量的自由现金流。它唯一的问题是:”公司治理”,就是它不一定愿意给你分。现在股息率快到五了,你不分,我就把公司买成我的,然后日本人说的就是:巴菲特先生,你别把我控制,我愿意分钱给你。因此巴菲特干的事情,买了日本的这些高股息的资产,并且在日本发行了无抵押担保的日元债券。啥意思呢?巴菲特一毛钱没掏,用日本人的储蓄以及低利率水平借钱,买了日本人的资产,还强迫日本人分了高股息,这才是资本真正的收割。</p>\n<p>未来的5年是10年真正的游戏是如何借低息买高息。美元不便宜了但美元的高息依旧很吸引人。那么问题就来了谁是低息美元如果一直维持高增长高通胀、高利率的话人民币一定是贬值的。而倒过来的交易借人民币转高息资产这个高息资产可以是人民币里边不多有的高息资产也可以是全球范围内的高股息现金奶牛你会发现这就又形成了类似于15年前的套利资本流动、交易机会。</p>\n"},{"title":"内部循环与产出意识","status":"done","_content":"\n每天早起、跑步、读书、学习身体和心灵都在路上然而这些都是内部循环不直接对外产出坚持这些习惯可以让我们成为更好的人但不会成为更厉害的人。享受努力奋斗的同时必须要有作品产出参与到社会价值体系的循环当中当感受被他人强烈的需要时就能感受到努力的希望了","source":"_posts/social/内部循环与产出意识.md","raw":"---\ntitle: 内部循环与产出意识\ncategories:\n - EQ\nstatus: done\n---\n\n每天早起、跑步、读书、学习身体和心灵都在路上然而这些都是内部循环不直接对外产出坚持这些习惯可以让我们成为更好的人但不会成为更厉害的人。享受努力奋斗的同时必须要有作品产出参与到社会价值体系的循环当中当感受被他人强烈的需要时就能感受到努力的希望了","slug":"social/内部循环与产出意识","published":1,"date":"2023-11-06T05:18:22.419Z","updated":"2023-11-06T05:19:31.986Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58q000m4cz3dxv034l1","content":"<p>每天早起、跑步、读书、学习,身体和心灵都在路上,然而这些都是内部循环,不直接对外产出,坚持这些习惯可以让我们成为更好的人,但不会成为更厉害的人。享受努力奋斗的同时,必须要有作品产出,参与到社会价值体系的循环当中,当感受被他人强烈的需要时,就能感受到努力的希望了</p>\n","site":{"data":{}},"excerpt":"","more":"<p>每天早起、跑步、读书、学习,身体和心灵都在路上,然而这些都是内部循环,不直接对外产出,坚持这些习惯可以让我们成为更好的人,但不会成为更厉害的人。享受努力奋斗的同时,必须要有作品产出,参与到社会价值体系的循环当中,当感受被他人强烈的需要时,就能感受到努力的希望了</p>\n"},{"title":"码场悟道","status":"doing","_content":"\n# 模板引擎\n\n严格的模板引擎的定义输入模板字符串 + 数据,得到渲染过的字符串。实现上,从正则替换到拼 function 字符串到正经的 AST 解析各种各样,但从定义上来说都是差不多的。字符串渲染的性能其实也就在后端比较有意义,毕竟每一次渲染都是在消耗服务器资源,但在前端,用户只有一个,几十毫秒的渲染时间跟请求延迟比起来根本不算瓶颈。倒是前端的后续更新是字符串模板引擎的软肋,因为用渲染出来的字符串整个替换 innerHTML 是一个效率很低的更新方式。所以这样的模板引擎如今在纯前端情境下已经不再是好的选择,意义更多是在于方便前后端共用模板。\n\n# 古老数据渲染 vm 的方式\n\n这种写法弊端太多了玩具车\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Document</title>\n </head>\n <body>\n <ul id=\"app\"></ul>\n </body>\n <script>\n var arr = [\n { name: \"小明\", age: 11, sex: \"男\" },\n { name: \"小红\", age: 22, sex: \"女\" },\n ];\n var listDOM = document.getElementById(\"app\");\n arr.forEach(function (item) {\n let _li = document.createElement(\"li\");\n _li.innerText = item.name;\n listDOM.appendChild(_li);\n });\n </script>\n</html>\n```\n\n# mustache 原理\n\n- 1、先把模板字符串编译成 tokens(代号)\n- 2、根据 tokens结合数据渲染成 dom\n\n> 本质上tokens 是一个 js 嵌套数组没事模板字符串 js 的表示,他是`抽象语法树``虚拟节点`的开山鼻祖\n\n假设有这么一个模板字符串\n\n```html\n<h1>我买了一个{{thing}},好{{mood}}啊</h1>\n```\n\n会编译成 tokens如下\n\n```js\n// 这里面每一个数组行都是一个 token组起来就是 tokens\n// html 标签也会被看成纯文本\n[\n [\"text\", \"<h1>我买了一个\"],\n [\"name\", \"thing\"],\n [\"text\", \"好\"],\n [\"name\", \"mood\"],\n [\"text\", \"啊</h1>\"],\n];\n```\n\n当模板存在循环式带层级嵌套如下\n\n```html\n<div>\n <ul>\n {{#arr}}\n <li>{{.}}</li>\n {{/arr}}\n </ul>\n</div>\n```\n\n会被编译成\n\n```js\n[\n [\"text\", \"<div><ul>\"],\n [\n \"#\",\n \"arr\",\n [\n [\"text\", \"li\"],\n [\"name\", \".\"],\n [\"text\", \"</li>\"],\n ],\n ],\n [\"text\", \"</ul></div>\"],\n];\n```\n\n如果是双重循环带层级嵌套继续加一层例如\n\n```html\n<div>\n <ol>\n {{#students}}\n <li>\n 学生{{item.name}}的爱好是\n <ol>\n {{#item.hobbies}}\n <li>{{.}}</li>\n {{/#item.hobbies}}\n </ol>\n </li>\n {{/#students}}\n </ol>\n</div>\n```\n\n会被编译成\n\n```js\n[\n [\"text\", \"<div><ol>\"],\n [\n \"#\",\n \"students\",\n null,\n null,\n [[\"text\", \"<li>学生\"], [\"name\", \"name\"], [\"text\", \"的爱好是<ol>\"], [\"#\", \"hobbies\", null, null], [\n ['text','<li>'],\n ['name','.'],\n ['text','</li>']\n ]],\n ['text','<ol></li>'],\n ]],\n ['text','</ol></div>']\n ],\n];\n```\n\n> 在`mustache.js`中完成上述这一过程的函数`parseTemplate`,可以去找源代码看\n\n## tokens 生成算法\n\n用简单的模板字符串举例\n\n```html\n我买了一个{{thing}},好{{mood}}啊\n```\n\n有一个指针往右遍历从`我`开始,遍历到`啊`结束,如下:\n\n```js\n/**\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * Step1指针位置 = 1\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * Step2指针位置 = 2\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * Step3指针位置 = 4\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * Step4指针位置 = 11\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * Step5指针位置 = 15\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * ... while(指针位置 >= 模板字符串.length)\n *\n * /\n```\n\n- Step1:\n\n指针右移 1 个长度,以指针位置切割,字符串被分成`我`+`买了一个{{thing}},好{{mood}}啊`\n\n- Step2:\n\n指针右移 1 个长度,以指针位置切割,字符串被分成`我买`+`了一个{{thing}},好{{mood}}啊`\n\n- Step3:\n\n第一次遇到通过 `indexOf(\"{{\") == 0` 判断\n\n```js\n// 标记为 text 放到 tokens 中\ntoken.push([\"text\", \"我买了一个\"]); // tokens: [['text', '我买了一个']]\n```\n\n结束此时指针位置 = 4\n\n- Step4:\n\n指针右移 2 个长度,跳过`{{`,暂存此时`pos_last = 6`\n\n此时右边字符串(尾字符串)`thing}},好{{mood}}啊`\n\n右移 5 个长度,识别`模板内部数据对象`\n\n```js\nsubstring(post_last, 6 + 5); // thing 5个长度\n// 标记为 name 放到 tokens 中\ntoken.push([\"name\", \"thing\"]); // tokens: [['text', '我买了一个']], ['name', 'thing']]\n```\n\n结束此时指针位置 = 11\n\n- Step5:\n\n> 遇到 `}}`,通过 `indexOf(\"}}\") == 0`判断\n\n指针右移 2 个长度,跳过`}}`,暂存此时`post_last = 13`,继续右移 2 个长度\n\n```js\nsubstring(post_last, 13 + 2); // ,好 2个长度\n// 标记为 text 放到 tokens 中\ntoken.push([\"text\", \",好\"]); // tokens: [['text', '我买了一个']], ['name', 'thing'],['text', ',好' ]]\n```\n\n> 第二次,遇到 `{{`\n\n剩下循环执行就行了这个过程我们可以称作`扫描 Scan`\n\n## 扫描器 Scanner\n\n新建一个 `Scanner.js`,用来扫描模板字符串,实现上面的原理\n\n```js\n/**\n * 模板字符串扫描器\n */\n\nclass Scanner {\n constructor(templ) {\n this.templ = templ; // 模板字符串\n this.tail = templ; // 尾字符串\n this.pPos = 0; // 指针位置\n }\n\n /**\n * 指针跳过模板标签\n * @param {模板语法包围标签} tag\n */\n jumpTag(tag) {\n if (this.tail.indexOf(tag) === 0) {\n this.pPos += tag.length; // 指针右移 tag.length 个长度\n this.tail = this.templ.substring(this.pPos); // 尾字符串更新\n }\n }\n\n /**\n * 指针遇见模板标签 {{\n * @param {模板语法包围标签} tag\n */\n missTag(tag) {\n let pPos_last = this.pPos;\n while (!this.eof() && this.tail.indexOf(tag) !== 0) {\n this.pPos++;\n this.tail = this.templ.substring(this.pPos);\n }\n return this.templ.substring(pPos_last, this.pPos);\n }\n\n eof() {\n return this.pPos >= this.templ.length;\n }\n}\n```\n\n## 分析器 Parser\n\n调用`Scanner.js`\n\n```js\nlet tmpl = `我买了一个{{thing}},好{{mood}}啊`;\n// 编译 模板字符串 => tokens\nconst Parser = {\n createTokens: (tmpl) => {\n let scanner = new Scanner(tmpl);\n let tokens = [];\n // scanner 循环执行\n while (!scanner.eof()) {\n ctx = scanner.missTag(\"{{\"); // 返回 头字符串\n if (ctx != \"\") {\n tokens.push([\"text\", ctx]);\n }\n scanner.jumpTag(\"{{\"); // 跳过 模板字符\n ctx = scanner.missTag(\"}}\"); // 返回 {{ x }}\n if (ctx != \"\") {\n tokens.push([\"name\", ctx]);\n }\n scanner.jumpTag(\"}}\");\n }\n return tokens;\n },\n};\nconsole.log(Parser.createTokens(tmpl));\n// 输出,非常的 奈一丝\n// [\"text\", \"我买了一个\"]\n// [\"name\", \"thing\"]\n// [\"text\", \",好\"]\n// [\"name\", \"mood\"]\n// [\"text\", \"啊\"]\n```\n\n## 扫描器 Scanner 增强\n\n上面的`Parser`只能识别`{{`和`}}`,如果模板语法复杂一点,比如加入 `{{#list}}...{{/list}}`,需要增强`Parser`\n\n```js\nconst template = `\n 哈哈哈\n {{#students}}\n 我买了一个 {{ thing }},好{{mood}}啊{{a}}\n {{item.name}}\n {{/students}}\n `;\nconst Parser = {\n createTokens: (tmpl) => {\n let scanner = new Scanner(tmpl);\n let tokens = [];\n let ctx = \"\";\n // scanner 循环执行\n while (!scanner.eof()) {\n ctx = scanner.missTag(\"{{\"); // 返回 头字符串\n if (ctx != \"\") {\n tokens.push([\"text\", ctx]);\n }\n scanner.jumpTag(\"{{\"); // 跳过 模板字符\n ctx = scanner.missTag(\"}}\"); // 返回 {{ x }}\n if (ctx != \"\") {\n switch (ctx[0]) {\n case \"#\":\n tokens.push([\"#\", ctx.substr(1)]); // {{# x }}\n break;\n case \"/\":\n tokens.push([\"/\", ctx.substr(1)]);\n break;\n default:\n tokens.push([\"name\", ctx]);\n break;\n }\n }\n scanner.jumpTag(\"}}\");\n }\n return tokens;\n },\n};\nconsole.log(Parser.createTokens(template));\n\n// 输出\n// [\"text\", \"↵ 哈哈哈↵ \"]\n// [\"#\", \"students\"]\n// [\"text\", \"↵ 我买了一个 \"]\n// [\"name\", \" thing \"]\n// [\"text\", \",好\"]\n// [\"name\", \"mood\"]\n// [\"text\", \"啊\"]\n// [\"name\", \"a\"]\n// [\"text\", \"↵ \"]\n// [\"name\", \"item.name\"]\n// [\"text\", \"↵ \"]\n// [\"/\", \"students\"]\n// [\"text\", \"↵ \"]\n```\n\n## 栈队列算法\n\n上一步最后的输出只有单层嵌套如果是两层嵌套怎么办\n\n例如模板语法如下\n\n```js\nvar template = `\n 哈哈哈\n {{#students}}\n {{#stu}}\n {{stu.name}}买了一个 {{ thing }},好{{mood}}啊{{a}}\n {{/stu}}\n {{item.name}}\n {{/students}}\n `;\n```\n\n经过`Parser`处理得到:\n\n```js\n/**\n *\n * [\"text\", \"↵ 哈哈哈↵ \"]\n * [\"#\", \"students\"]\n * [\"text\", \"↵ \"]\n * [\"#\", \"stu\"]\n * [\"text\", \"↵ \"]\n * [\"name\", \"stu.name\"]\n * [\"text\", \"买了一个 \"]\n * [\"name\", \" thing \"]\n * [\"text\", \",好\"]\n * [\"name\", \"mood\"]\n * [\"text\", \"啊\"]\n * [\"name\", \"a\"]\n * [\"text\", \"↵ \"]\n * [\"/\", \"stu\"]\n * [\"text\", \"↵ \"]\n * [\"name\", \"item.name\"]\n * [\"text\", \"↵ \"]\n * [\"/\", \"students\"]\n * [\"text\", \"↵ \"]\n *\n * /\n```\n\n此时`students`和`stu`都是`#`标记,我们需要利用算法处理他们的嵌套结构,处理成大约如下这样的结构:\n\n```js\n/**\n *\n * [\"text\", \"↵ 哈哈哈↵ \"]\n * Array(3)\n * \"#\"\n * \"students\"\n * Array(5)\n * [\"text\", \"↵ \"]\n * [\"#\", \"stu\", Array(9)]\n * [\"text\", \"↵ \"]\n * [\"name\", \"item.name\"]\n * [\"text\", \"↵ \"]\n * [\"text\", \"↵ \"]\n *\n * /\n```\n\n# 常用工具类\n\n## 递归\n\n```js\n/**\n * {string} dir 递归根目录\n * {object} list 暂存参数\n */\nconst deep = async (dir, list = []) => {\n const dirs = await fs.promises.readdir(dir)\n for (let i = 0; i < dirs.length; i++) {\n const item = dirs[i]\n const itemPath = path.join(dir, item)\n const isDir = fs.statSync(itemPath).isDirectory()\n isDir ? await deep(itemPath, list) : list.push(itemPath)\n }\n return list\n}\n```\n\n## 自增id短码\n\n用于连接分享\n\n```typescript\nconst createAscString = (id) => {\n const dictionary = [\n \"0123456789\",\n \"abcdefghigklmnopqrstuvwxyz\",\n \"ABCDEFGHIGKLMNOPQRSTUVWXYZ\",\n ];\n let chars = dictionary.join(\"\").split(\"\"),\n radix = chars.length,\n qutient = 1000 * 1000 * 9999 + +id,\n arr = [];\n while (qutient) {\n mod = qutient % radix;\n qutient = (qutient - mod) / radix;\n arr.unshift(chars[mod]);\n }\n return arr.join(\"\");\n};\n\nconsole.log(createAscString(100000000));\n```\n\n## 手动实现 eventBus\n\n```js\nexport default class EventBus {\n constructor() {\n // key-value : eventName-date\n this.callbacks = {};\n }\n\n /**\n * 监听事件\n * @param {事件名} eventName\n * @param {回调函数} callback\n */\n on(eventName, callback) {\n this.checkType(eventName).callbacks[eventName]\n ? callback(this.callbacks[eventName])\n : this.error(`The event has not been declared`);\n }\n\n /**\n * 注册一个事件\n * @param {事件名} eventName\n * @param {传递的对象} data\n */\n emit(eventName, data) {\n this.checkType(eventName).callbacks[eventName] = data;\n }\n\n /**\n * 注销事件,不传参数默认注销全部事件\n * @param {事件名} eventName\n */\n off(eventName) {\n eventName\n ? this.checkType(eventName).removeEvent(eventName)\n : this.emptyEvent();\n }\n\n /**\n * 移出事件\n * @param {事件名} eventName\n */\n removeEvent(eventName) {\n Reflect.deleteProperty(this.callbacks, eventName);\n }\n\n /**\n * 清空全部事件\n */\n emptyEvent() {\n this.callbacks = [];\n }\n\n /**\n * 参数类型校验\n * @param {参数} param\n * @param {合法的类型} validType\n */\n checkType(param, validType = \"string\") {\n if (typeof param !== validType)\n this.error(`(param, ${param}) should be of ${validType} type`);\n return this; // 缅怀jQ链式调用\n }\n\n /**\n * 错误提示\n * @param {提示文字} text\n */\n error(text) {\n throw new Error(text);\n }\n}\n```\n\n调用\n\n```js\n// 省略import\nconst eventBus = new EventBus();\neventBus.emit(\"login\", [{ a: 1, d: 2 }]);\neventBus.on(123, (d) => console.log(d)); // [{...}]\n```\n\n## 判断对象是否有某个 key\n\n```javascript\nlet obj = { alias: \"es6\" };\n\"alias\" in obj; // true\nReflect.has(obj, \"alias\"); // true\n```\n\n## 浏览器\n\n## 版本信息\n\n```javascript\nwindow.navigator.userAgent;\n```\n\n## 兼容事件绑定\n\n```javascript\n/*\n兼容低版本IEele为需要绑定事件的元素\neventName为事件名保持addEventListener语法去掉onfun为事件响应函数\n*/\n\nfunction addEvent(ele, eventName, fun) {\n ele.addEventListener\n ? ele.addEventListener(eventName, fun, false)\n : ele.attachEvent(\"on\" + eventNme, fun);\n}\n```\n\n## 数组对象\n\n## reduce\n\n```javascript\nvar arr = [1, 2, 3, 4];\nvar sum = arr.reduce(function(prev, cur, index, arr) {\n console.log(prev, cur, index);\n return prev + cur;\n}0) //注意这里设置了初始值\nconsole.log(arr, sum);\n\n// 求和\nconst sum = arr.reduce((p,c) => p+c)\n```\n\n## 对象内部根据 key 对 value 进行排序,取前 3\n\n```javascript\nlet datasource = [\n { price: 1, alias: \"watermelon\" },\n { price: 3, alias: \"orange\" },\n { price: 2, alias: \"banana\" },\n { price: 4, alias: \"apple\" },\n];\n// 降序排列\nlet compare = (key) => (a, b) => b[key] - a[key];\nlet sorted = datasource\n .sort(compare(\"price\"))\n .slice(0, 3)\n .map((i) => i[\"alias\"]);\n// 返回 [\"apple\", \"orange\", \"banana\"]\n```\n\n## 随机字符串\n\n```javascript\nconst getRandomRangeNum = (len = 32) => {\n // 略去不宜辨识字符\n let dictionary = \"ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz\";\n let maxPos = dictionary.length;\n let res = \"\";\n for (let i = 0; i < len; i++) {\n res += dictionary.charAt(Math.floor(Math.random() * maxPos));\n }\n return res;\n};\n```\n\n## 类型检测\n\nQ使用`typeof foo === \"object\"`检测`foo`是否为对象有什么缺点?如何避免?\n\nA用 `typeof` 是否能准确判断一个对象变量,答案是否定的,`null` 的结果也是 `object``Array` 的结果也是 `object`,有时候我们需要的是 \"纯粹\" 的 `object` 对象\n\n```js\nObject.prototype.toString.call(obj) === \"[object Object]\";\n```\n\n## 倒计时\n\n```javascript\nclass Countdown {\n constructor(startNum, endNum, interval) {\n [this.startNum, this.endNum, this.interval] = [startNum, endNum, interval];\n }\n execute() {\n var timer = setTimeout(() => {\n if (this.startNum >= this.endNum) {\n console.log(this.startNum);\n this.startNum -= 1;\n this.execute();\n } else {\n clearTimeout(timer);\n }\n }, this.interval);\n }\n}\n// 实例化调用\nvar countdown = new Countdown(5, 0, 1000).execute();\n```\n\n## 范围随机数\n\n```javascript\n// 能取到 min取不到 max\nfunction getRandomRangeNum(min, max) {\n return min + Math.floor(Math.random() * (max - min));\n}\n```\n\n## 获取当前月的天数\n\n```javascript\nconst getCurMonthDays = new Date(\n new Date().getFullYear(),\n new Date().getMonth() + 1,\n 0\n).getDate();\n```\n\n\n# 对象小操作\n\n## 去虚假值\n\n```js\nlet arr4 = [\"小明\", \"小蓝\", \"\", false, \" \", undefined, null, 0, NaN, true];\nconsole.log(arr4.filter(Boolean)); // => ['小明', '小蓝', ' ', true]\n```\n\n## 头尾插入\n\n效率比 `unshift()` 高\n\n```js\nlet arr = [1, 2, 3];\n// 头插入\n[\"haha\"].concat(arr);\n// 尾插入\narr.concat([\"haha\"]);\n```\n\n\n## 删除属性\n\n```js\nfunction deleteA(obj) {\n delete obj.A;\n return obj;\n}\n\n// 使用解构赋值\nconst deleteA = ({ A, ...rest } = {}) => rest;\n```\n\n# 生产、加工、消费分离\n\n- 从接口拿数据到视图 fetch api\n- 加工 computed\n- 消费 v-for\n\n# 元数据\n\n```js\nimport \"reflect-metadata\"; // npm install reflect-metadata\n\nfunction Role(name: string): ClassDecorator {\n return (target) => {\n Reflect.defineMetadata(\"role\", name, target);\n };\n}\n\n@Role(\"admin\")\nclass Post {}\n\nconst metadata = Reflect.getMetadata(\"role\", Post);\n\nReflect.set(Post, \"role2\", metadata);\n\nconsole.log(Reflect.get(Post, \"role2\")); // admin\n```\n\n# 防抖与节流\n\n在页面上监听诸如`scroll`(页面滚动),`mousemove`(鼠标移动) `keydown` `keyup` `keypress`(按下键盘)等等一系列事件的时候,我们并不希望频繁的触发这类监听,尤其当请求非常消耗资源时,这种操作会导致服务器性能急剧下降。\n\n## Debounce\n\n把触发非常频繁的事件合并成一次延迟执行如果对监听函数使用 100ms 的容忍时间,那么时间在第 3.1s 的时候执行\n\n```javascript\n// 默认延时100ms\nfunction debounce(func, dealy = 100) {\n let timer;\n return function () {\n // 暂存this和参数\n let _this = this;\n let args = arguments;\n // 清除定时器确保不执行func\n clearTimeout(timer);\n timer = setTimeout(function () {\n func.apply(_this, args);\n }, dealy);\n };\n}\n// 执行函数\nfunction handler() {\n console.log(`delay 100ms ,then handle`);\n}\n// dom添加监听\ndocument\n .querySelector(\"#someNode\")\n .addEventListener(\"scroll\", debounce(handler));\n```\n\n## Throttle\n\n固定函数执行的速率即所谓的“节流”。设置一个阀值在阀值内把触发的事件合并成一次执行当到达阀值必定执行一次事件。\n\n```javascript\nfunction throttle(func, delay) {\n let statTime = 0;\n return function () {\n let currentTime = +new Date();\n if (currentTime - statTime > delay) {\n func.apply(this, arguments);\n statTime = currentTime;\n }\n };\n}\n// 执行函数\nfunction resizeHandler() {\n console.log(`resize`);\n}\n// window添加监听\nwindow.onresize = throttle(resizeHandler, 300);\n```\n\n# this 指向\n\n## 全局环境\n\n全局环境下this 始终指向全局对象window无论是否严格模式\n\n```javascript\nconsole.log(this === window); // true\nthis.a = 37;\nconsole.log(window.a); // 37\n```\n\n## 函数上下文调用\n\n- 非严格模式\n\n没有被上一级的对象所调用, this 默认指向全局对象 window\n\n```javascript\nfunction f1() {\n return this;\n}\nf1() === window; // true\n```\n\n- 严格模式\n\nthis 指向 undefined\n\n```javascript\nfunction f2() {\n \"use strict\"; // 这里是严格模式\n return this;\n}\nf2() === undefined; // true\n```\n\n## 箭头函数\n\n> 箭头函数中call()、apply()、bind()方法无效\n\n在全局代码中箭头函数被设置为全局对象总之箭头函数不改变 this 指向\n\n```javascript\nvar globalObject = this;\nvar foo = () => this;\nconsole.log(foo() === globalObject); // true\n```\n\n箭头函数作为对象的方法使用指向全局 window 对象\n\n```javascript\nvar obj = {\n i: 10,\n b: () => console.log(this.i, this),\n c: function () {\n console.log(this.i, this);\n },\n};\nobj.b(); // undefined window{...}\nobj.c(); // 10 Object {...}\n```\n\n箭头函数可以让 this 指向固化,这种特性很有利于封装回调函数\n\n```javascript\n// 总是指向 handler 对象。如果不使用箭头函数则指向全局 document 对象\nvar handler = {\n id: \"123456\",\n\n init: function () {\n document.addEventListener(\n \"click\",\n (event) => this.doSomething(event.type),\n false\n );\n },\n\n doSomething: function (type) {\n console.log(\"Handling \" + type + \" for \" + this.id);\n },\n};\n```\n\n# call, apply, bind 与 es6\n\njs 的函数继承于`Function.prototype`对象,因此每个函数都会有 apply、call、bind 方法\n\n> call 和 apply 的作用,完全一样,唯一的区别就是在参数上面。\n\n`call, apply, bind`改变函数中 `this 指向` 的三兄弟,把`this`绑定到第一个参数对象上\n\n```javascript\nfunction displayHobbies(...hobbies) {\n console.log(`${this.name} likes ${hobbies.join(\", \")}.`);\n}\n// 下面两个等价\ndisplayHobbies.call({ name: \"Bob\" }, \"swimming\", \"basketball\", \"anime\"); // Bob likes swimming, basketball, anime.\ndisplayHobbies.apply({ name: \"Bob\" }, [\"swimming\", \"basketball\", \"anime\"]); // Bob likes swimming, basketball, anime.\n```\n\n`bind`返回的是一个函数,需要手动执行\n\n```js\nvar p1 = {\n name: \"张三\",\n age: 12,\n func: function () {\n console.log(`姓名:${this.name},年龄:${this.age}`);\n },\n};\n\nvar p2 = {\n name: \"李四\",\n age: 15,\n};\n\np1.func.bind(p2)(); //姓名:李四,年龄:15\n```\n\n# for 循环优化\n\n```javascript\n// 每次都要计算array.length\nfor (let i = 0; i < array.length; i++) {\n console.log(i);\n}\n\n// 使用leng缓存array长度\nfor (let i = 0, length = array.length; i < length; i++) {\n console.log(i);\n}\n```\n\n# 数组\n\n## 扁平化去重升序排列\n\n```javascript\nlet arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];\narr.flat(Infinity); // [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]\n\nlet result = Array.from(new Set(arr.flat(Infinity)).sort((a, b) => a - b));\n```\n\n# 前端页面埋点 - 1x1.gif\n\n通常用在统计页面点击曝光停留时间签发……等场景\n\n- 比 PNG/JPG 体积小\n- 天然跨域\n\n```html\n<button onClick=\"countClick()\">haorooms</button>\n<script>\n function countClick() {\n new Image().src = `./haorooms.gif?${key}=${value}&${Math.random()} `;\n }\n</script>\n```\n\n# 事件委托\n\n利用冒泡原理委托父元素执行\n\n```html\n<ul>\n <li>苹果</li>\n <li>香蕉</li>\n <li>凤梨</li>\n</ul>\n```\n\n```javascript\ndocument.querySelector(\"ul\").onclick = (event) => {\n let target = event.target;\n if (target.nodeName === \"LI\") {\n console.log(target.innerHTML);\n }\n};\n```\n\n# 构造函数 + 原型模式\n\n```javascript\nfunction Person(name, age, job) {\n this.name = name;\n this.age = age;\n this.job = job;\n}\nPerson.prototype.say = function (text) {\n console.log(`${this.name}say:${text}`);\n};\n```\n\n# 剩余参数...args\n\n剩余参数`args`数个数组,`...`解构符\n\n```javascript\nfunction fun1(param, ...args) {\n alert(args.length);\n}\n```\n\n# 跨页面通信\n\n- cookie\n- web worker\n- localstorage\n\n# iframe 跨域通信和不跨域通信\n\n## 不跨域\n\n```javascript\n// fatherSay是父页面全局方法\nwindow.parent.fatherSay();\n// 父页面Dom\nwindow.parent.document.getElementById(\"元素id\");\n// 副业页面获取frameID为`iframe_ID`的子页面的Dom\nwindow.frames[\"iframe_ID\"].document.getElementById(\"元素id\");\n```\n\n## 跨域 postMessage\n\n子页面\n\n```javascript\nwindow.parent.postMessage(\"hello\", \"http://127.0.0.1:8089\");\n```\n\n父页面接受\n\n```javascript\nwindow.addEventListener(\"message\", function (event) {\n alert(123);\n});\n```\n\n# 对象类型判断\n\n## 数组\n\n```javascript\nlet arr = [];\narr instanceof Array; // true\nArray.isArray(arr); // true\nObject.prototype.toString.call(arr); // \"[object Array]\"\n```\n\n# js 单线程,如何异步\n\n- 主线程 执行 js 中所有的代码。\n\n- 主线程 在执行过程中发现了需要异步的任务任务后扔给浏览器(浏览器创建多个线程执行,顺便创造一个`回调队列`。\n\n- 主线程 已经执行完毕所有同步代码。监听`回调队列`一旦 浏览器 中某个线程任务完成将会改变回调函数的状态。主线程查看到某个函数的状态为已完成,就会执行该`回调队列`中对应的回调函数。\n\n# 移动端最小触控区域\n\n苹果推荐是 44pt x 44pt 「具体看 WWDC 14」,通过`padding`、`margin`、`height`等方式进行点击区域扩展\n\n# js 精度问题\n\n常用类库`Math.js`、`Big.js`、`decimal.js`\n\n# 冻结 Object. freeze()\n\n`const`生命的简单变量不可修改,但是复杂对象可以被修改,`Object. freeze()`:可以冻结对象\n\n- 不能添加新属性\n- 不能删除已有属性\n- 不能修改已有属性的可枚举性、可配置性、可写性\n- 不能修改已有属性的值\n- 不能修改原型\n\n浅冻结\n\n```javascript\nconst obj1 = {\n internal: {},\n};\n\nObject.freeze(obj1);\nobj1.internal.a = \"aValue\";\nconsole.log(obj1.internal.a); // aValue\n```\n\n递归冻结\n\n```javascript\nfunction deepFreeze(obj) {\n // 获取定义在obj上的属性名\n var propNames = Object.getOwnPropertyNames(obj);\n // 在冻结自身之前冻结属性\n propNames.forEach(function (name) {\n var prop = obj[name];\n // 如果prop是个对象冻结它\n if (typeof prop == \"object\" && prop !== null) deepFreeze(prop);\n });\n return Object.freeze(obj);\n}\n```\n\n# Reflect\n\n## Reflect.get(target, propertyKey, value[receiver])\n\n获取对象身上某个属性的值类似于 target[name]。\n\n## Reflect.set(target, propertyKey, value[receiver])\n\n将值分配给属性的函数。返回一个 Boolean如果更新成功则返回 true。\n\n## Reflect.has(target, propertyKey)\n\n判断一个对象是否存在某个属性和 in 运算符 的功能完全相同。\n\n\n# if else 优化\n\n## 表驱动编程\n\n空间换时间设置`obj={key:value}`,通过`obj[key]`取值\n\n```javascript\ncalculateGrade(score){\n const table = {\n 100: 'A',\n 90: 'A',\n 80: 'B',\n 70: 'C',\n 60: 'D',\n others: 'E'\n }\n return table[Math.floor(score/10)*10] || table['others']\n}\n```\n\n## 短路运算\n\nreact 没有`v-if`,运用比较频繁\n\n```js\n// 函数组件\nconst Home = () => {\n return <div>home</div>;\n};\n{\n true && <Home />;\n}\n```\n\n# 使用有意义且易读的变量名\n\n```js\n👎 const yyyymmdstr = moment().format(\"YYYY/MM/DD\");\n\n👍 const currentDate = moment().format(\"YYYY/MM/DD\");\n```\n\n# 使用有意义的变量代替数组下标\n\n```js\n👎\nconst address = \"One Infinite Loop, Cupertino 95014\";\nconst cityZipCodeRegex = /^[^,\\\\]+[,\\\\\\s]+(.+?)\\s*(\\d{5})?$/;\nsaveCityZipCode(\n address.match(cityZipCodeRegex)[1],\n address.match(cityZipCodeRegex)[2]\n);\n\n👍\nconst address = \"One Infinite Loop, Cupertino 95014\";\nconst cityZipCodeRegex = /^[^,\\\\]+[,\\\\\\s]+(.+?)\\s*(\\d{5})?$/;\nconst [_, city, zipCode] = address.match(cityZipCodeRegex) || [];\nsaveCityZipCode(city, zipCode);\n```\n\n# 变量名要简洁\n\n```js\n👎\nconst Car = {\n carMake: \"Honda\",\n carModel: \"Accord\",\n carColor: \"Blue\"\n};\nfunction paintCar(car, color) {\n car.carColor = color;\n}\n\n👍\nconst Car = {\n make: \"Honda\",\n model: \"Accord\",\n color: \"Blue\"\n};\nfunction paintCar(car, color) {\n car.color = color;\n}\n```\n\n# 消除魔术字符串\n\n```js\n👎 setTimeout(blastOff, 86400000);\n\n👍 const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000; //86400000;\nsetTimeout(blastOff, MILLISECONDS_PER_DAY);\n```\n\n# 使用默认参数替代短路运算符\n\n```js\n👎\nfunction createMicrobrewery(name) {\n const breweryName = name || \"Hipster Brew Co.\";\n // ...\n}\n\n👍\nfunction createMicrobrewery(name = \"Hipster Brew Co.\") {\n // ...\n}\n```\n\n# 一个函数\n\n```js\n👎\nfunction emailClients(clients) {\n clients.forEach(client => {\n const clientRecord = database.lookup(client);\n if (clientRecord.isActive()) {\n email(client);\n }\n });\n}\n\n👍\nfunction emailActiveClients(clients) {\n clients.filter(isActiveClient).forEach(email);\n}\nfunction isActiveClient(client) {\n const clientRecord = database.lookup(client);\n return clientRecord.isActive();\n}\n\n---------------------分割线-----------------------\n\n👎\nfunction createFile(name, temp) {\n if (temp) {\n fs.create(`./temp/${name}`);\n } else {\n fs.create(name);\n }\n}\n\n👍\nfunction createFile(name) {\n fs.create(name);\n}\nfunction createTempFile(name) {\n createFile(`./temp/${name}`);\n}\n```\n\n# 函数参数不多于 2 个,如果有很多参数就利用 object 传递,并使用解构\n\n```js\n👎\nfunction createMenu(title, body, buttonText, cancellable) {\n // ...\n}\ncreateMenu(\"Foo\", \"Bar\", \"Baz\", true);\n\n👍\nfunction createMenu({ title, body, buttonText, cancellable }) {\n // ...\n}\ncreateMenu({\n title: \"Foo\",\n body: \"Bar\",\n buttonText: \"Baz\",\n cancellable: true\n});\n```\n\n# 函数名应该直接反映函数的作用\n\n```js\n👎\nfunction addToDate(date, month) {\n // ...\n}\nconst date = new Date();\n// It's hard to tell from the function name what is added\naddToDate(date, 1);\n\n👍\nfunction addMonthToDate(month, date) {\n // ...\n}\nconst date = new Date();\naddMonthToDate(1, date);\n```\n\n# 尽量使用纯函数\n\n```js\n👎\nconst programmerOutput = [\n {\n name: \"Uncle Bobby\",\n linesOfCode: 500\n },\n {\n name: \"Suzie Q\",\n linesOfCode: 1500\n },\n {\n name: \"Jimmy Gosling\",\n linesOfCode: 150\n },\n {\n name: \"Gracie Hopper\",\n linesOfCode: 1000\n }\n];\nlet totalOutput = 0;\nfor (let i = 0; i < programmerOutput.length; i++) {\n totalOutput += programmerOutput[i].linesOfCode;\n}\n\n👍\nconst programmerOutput = [\n {\n name: \"Uncle Bobby\",\n linesOfCode: 500\n },\n {\n name: \"Suzie Q\",\n linesOfCode: 1500\n },\n {\n name: \"Jimmy Gosling\",\n linesOfCode: 150\n },\n {\n name: \"Gracie Hopper\",\n linesOfCode: 1000\n }\n];\nconst totalOutput = programmerOutput.reduce(\n (totalLines, output) => totalLines + output.linesOfCode,\n 0\n);\n```\n\n# 不要过度优化\n\n```js\n👎\n// 现代浏览器对于迭代器做了内部优化\nfor (let i = 0, len = list.length; i < len; i++) {\n // ...\n}\n\n👍\nfor (let i = 0; i < list.length; i++) {\n // ...\n}\n```\n\n\n# 关于模块化\n\n## 无模块化\n\n> 污染全局作用域、维护成本高、依赖关系不明显\n\nscript 标签引入 js 文件,相互罗列,但是被依赖的放在前面,否则使用就会报错。如下:\n\n```js\n<script src=\"jquery.js\"></script>\n<script src=\"main.js\"></script>\n<script src=\"other1.js\"></script>\n<script src=\"other2.js\"></script>\n<script src=\"other3.js\"></script>\n```\n\n## CommonJS 规范(同步)\n\n该规范最初是用在服务器端的 node 的它有四个重要的环境变量为模块化的实现提供支持module、exports、require、global。实际使用时用 module.exports 定义当前模块对外输出的接口(不推荐直接用 exports用 require 加载模块(同步)\n\n> module.exports 本身就是一个对象\n\n```js\nmodule.exports = { foo: \"bar\" }; //true\nmodule.exports.foo = \"bar\"; //true。\n```\n\nCommonJS 用同步的方式加载模块。在服务端模块文件都存在本地磁盘读取非常快所以这样做不会有问题。但是在浏览器端限于网络原因CommonJS 不适合浏览器端模块加载,更合理的方案是使用异步加载,比如下边 AMD 规范。\n\n## AMD 规范(RequireJS)\n\n承接上文AMD 规范则是非同步加载模块允许指定回调函数AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。\n\n- `require([module], callback)`:加载模块\n- `define(id, [depends], callback)`:定义模块\n- `require.config()`:配置路径、依赖关系\n\n## CMD 规范(SeaJS)\n\nCMD 是 在推广过程中对模块定义的规范化产出\n\n## ES6 import/export\n\n通过 babel 将不被支持的 import 编译为当前受到广泛支持的 AMD 规范\n\n# AMD模块化实现\n\n## define 函数\n\n用来声明模块名`module`,依赖数组`deps`,以及模块的作用`callback`\n\n```js\nvar module = (function () {\n var stack = {}; //模块存储栈,存的是模块执行后的结果\n\n function define(module, deps, callback) {\n stack[module] = callback.apply(null, deps); // 压栈\n console.log(stack); // 查看栈存储的模块\n }\n\n return { define: define };\n})();\n```\n\n调用`define`试试,发现 `calc`模块被压入了`stack 模块栈中`\n\n```js\nmodule.define(\"calc\", [], function () {\n return {\n first: function (arr) {\n return arr[0];\n },\n };\n});\n// {calc: { first: ƒ }}\n```\n\n## deps 依赖(导入)\n\n对上面的 `define`函数稍加改造,这一步过程的本质,就是对 deps\n\n```js\nvar module = (function (window) {\n var stack = {}; //模块存储栈,\n\n function define(module, deps, callback) {\n // 把 define 函数依赖数组中的模块从 stack 模块中拿出\n deps.map(function (mod, index) {\n deps[index] = stack[mod]; // 赋值给当前模块的 deps\n });\n stack[module] = callback.apply(null, deps);\n console.log(stack); // 查看栈存储的模块\n }\n\n return { define: define };\n})(window);\n\nmodule.define(\"calc\", [], function () {\n return {\n first: function (arr) {\n return arr[0];\n },\n };\n});\n\nmodule.define(\"number\", [\"calc\"], function (calc) {\n return {\n res: calc.first([4, 3, 2, 1]), //4\n };\n});\n\n// 此时 stack 打印的结果为\n//> calc: {first: ƒ}\n//> number: {res: 4}\n```\n\n> 从本质上看define 函数的第二个参数 deps 数组,相当于 import 导入,并且如果第三个参数 callback 采用 `return { }`,也就相当于 export 导出\n\n## 老生常谈的指针\n\n说到底`stack`中 `a模块` export 是一个指针,`{a:value}`(内存地址),所以,`b 模块`会改变`a.a`的值,这点和 `cmd`不同\n\n```js\nmodule.define(\"a\", [], function () {\n return {\n a: 1,\n };\n});\nmodule.define(\"b\", [\"a\"], function (a) {\n a.a = 2;\n});\nmodule.define(\"c\", [\"a\"], function (a) {\n console.log(a.a); // 2\n});\n```\n\n\n# 缘起 Object.defineProperty()\n\n给`目标对象`上定义一个新属性,或者修改`目标对象`属性,并且返回新对象\n\n# 上帝的钥匙 get & set\n\n属性的`getter`函数,如果没有 `getter`则尾 `undefined`。当访问该属性时,会调用此函数.\n\n```js\nlet obj = {};\n\nObject.defineProperty(obj, \"a\", {\n get() {\n return 7;\n },\n set(val) {\n console.log(`FAILED改变 a 属性,新值为:${val},但是被重写 set 劫持了`);\n },\n});\n\nconsole.log(obj.a);\nobj.a = 4;\n```\n\n> 上帝的钥匙被找到了\n\n劫持劫持还是 TMD 劫持!\n\n```js\nlet obj = {};\nlet tempValue = 0;\n\nObject.defineProperty(obj, \"a\", {\n get() {\n return tempValue;\n },\n set(newValue) {\n tempValue = newValue;\n },\n});\n\nconsole.log(obj.a); // 0\nobj.a = 4;\nconsole.log(obj.a); // 4\n```\n\n# 封装 defineReactive(obj, prop, val)\n\n> 这里 defineReactive 第三个参数 val 替代了上一步中全局变量`tempValue`,对于 get()、set()来说,访问到了其他函数内部的变量,所以形成了闭包\n\n```js\nfunction defineReactive(obj, prop, val) {\n Object.defineProperty(obj, prop, {\n get() {\n console.log(`劫持,你访问了${prop}属性`);\n return val;\n },\n set(newValue) {\n if (val === newValue) return;\n console.log(`劫持,你改变了${prop}属性`);\n val = newValue;\n },\n });\n}\n\nlet obj = {};\ndefineReactive(obj, \"a\", 4);\n\nconsole.log(obj.a); // 劫持你访问了a属性 4\nobj.a = 7; // 劫持你改变了a属性\nconsole.log(obj.a); // 劫持你访问了a属性 7\n```\n\n# 递归侦测\n\n```js\nlet obj = { a: { b: { c: {} } } };\ndefineReactive(obj, \"a\", 4);\n```\n\n> 如何自动让`obj`对象的全部属性都`reactive`呢?\n\n```js\nlet obj = {\n a: {\n b: {\n c: 5,\n },\n },\n d: 4,\n};\n```\n\n定义个方法`observe`,递归 `obj` 的每一层的每个 `prop`,检测是否有`__ob__`,如果没有,`defineReactive`,并且挂一个`Observer`实例在这个`props`上,例如:\n\n`Observer对象`\n\n```js\nclass Observer {\n constructor(value) {\n def(value, \"__ob__\", this, false); // 不可枚举不能给__ob__添加__ob__\n this.walk(value);\n }\n // 遍历每一个 prop的 value\n walk(value) {\n for (let prop in value) {\n defineReactive(value, prop);\n }\n }\n}\n```\n\n`defineReactive.js`\n\n```js\nexport default function defineReactive(obj, prop, val) {\n if (arguments.length === 2) val = obj[prop]; // 如果2个参数\n let childNode = observe(val);\n Object.defineProperty(obj, prop, {\n enumerable: true,\n configurable: true,\n get() {\n console.log(`你访问了${prop}属性`);\n return val;\n },\n set(newValue) {\n if (val === newValue) return;\n console.log(`你改变了${prop}属性`);\n val = newValue;\n childNode = observe(newValue);\n },\n });\n}\n```\n\n`observe.js`\n\n```js\n/**\n * 检测 obj 身上有没有 __ob__(Observer 实例)\n * @param {*} value\n * @returns\n */\nexport default function observe(value) {\n if (typeof value != \"object\") return;\n let ob;\n //! 用__ob__是为了属性不重名被覆盖\n if (typeof value.__ob__ != \"undefined\") {\n ob = value.__ob__;\n } else {\n ob = new Observer(value);\n }\n return ob;\n}\n```\n","source":"_posts/front-end/码场悟道.md","raw":"---\ntitle: 码场悟道\ncategories:\n - Front-End\nstatus: doing\n---\n\n# 模板引擎\n\n严格的模板引擎的定义输入模板字符串 + 数据,得到渲染过的字符串。实现上,从正则替换到拼 function 字符串到正经的 AST 解析各种各样,但从定义上来说都是差不多的。字符串渲染的性能其实也就在后端比较有意义,毕竟每一次渲染都是在消耗服务器资源,但在前端,用户只有一个,几十毫秒的渲染时间跟请求延迟比起来根本不算瓶颈。倒是前端的后续更新是字符串模板引擎的软肋,因为用渲染出来的字符串整个替换 innerHTML 是一个效率很低的更新方式。所以这样的模板引擎如今在纯前端情境下已经不再是好的选择,意义更多是在于方便前后端共用模板。\n\n# 古老数据渲染 vm 的方式\n\n这种写法弊端太多了玩具车\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Document</title>\n </head>\n <body>\n <ul id=\"app\"></ul>\n </body>\n <script>\n var arr = [\n { name: \"小明\", age: 11, sex: \"男\" },\n { name: \"小红\", age: 22, sex: \"女\" },\n ];\n var listDOM = document.getElementById(\"app\");\n arr.forEach(function (item) {\n let _li = document.createElement(\"li\");\n _li.innerText = item.name;\n listDOM.appendChild(_li);\n });\n </script>\n</html>\n```\n\n# mustache 原理\n\n- 1、先把模板字符串编译成 tokens(代号)\n- 2、根据 tokens结合数据渲染成 dom\n\n> 本质上tokens 是一个 js 嵌套数组没事模板字符串 js 的表示,他是`抽象语法树``虚拟节点`的开山鼻祖\n\n假设有这么一个模板字符串\n\n```html\n<h1>我买了一个{{thing}},好{{mood}}啊</h1>\n```\n\n会编译成 tokens如下\n\n```js\n// 这里面每一个数组行都是一个 token组起来就是 tokens\n// html 标签也会被看成纯文本\n[\n [\"text\", \"<h1>我买了一个\"],\n [\"name\", \"thing\"],\n [\"text\", \"好\"],\n [\"name\", \"mood\"],\n [\"text\", \"啊</h1>\"],\n];\n```\n\n当模板存在循环式带层级嵌套如下\n\n```html\n<div>\n <ul>\n {{#arr}}\n <li>{{.}}</li>\n {{/arr}}\n </ul>\n</div>\n```\n\n会被编译成\n\n```js\n[\n [\"text\", \"<div><ul>\"],\n [\n \"#\",\n \"arr\",\n [\n [\"text\", \"li\"],\n [\"name\", \".\"],\n [\"text\", \"</li>\"],\n ],\n ],\n [\"text\", \"</ul></div>\"],\n];\n```\n\n如果是双重循环带层级嵌套继续加一层例如\n\n```html\n<div>\n <ol>\n {{#students}}\n <li>\n 学生{{item.name}}的爱好是\n <ol>\n {{#item.hobbies}}\n <li>{{.}}</li>\n {{/#item.hobbies}}\n </ol>\n </li>\n {{/#students}}\n </ol>\n</div>\n```\n\n会被编译成\n\n```js\n[\n [\"text\", \"<div><ol>\"],\n [\n \"#\",\n \"students\",\n null,\n null,\n [[\"text\", \"<li>学生\"], [\"name\", \"name\"], [\"text\", \"的爱好是<ol>\"], [\"#\", \"hobbies\", null, null], [\n ['text','<li>'],\n ['name','.'],\n ['text','</li>']\n ]],\n ['text','<ol></li>'],\n ]],\n ['text','</ol></div>']\n ],\n];\n```\n\n> 在`mustache.js`中完成上述这一过程的函数`parseTemplate`,可以去找源代码看\n\n## tokens 生成算法\n\n用简单的模板字符串举例\n\n```html\n我买了一个{{thing}},好{{mood}}啊\n```\n\n有一个指针往右遍历从`我`开始,遍历到`啊`结束,如下:\n\n```js\n/**\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * Step1指针位置 = 1\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * Step2指针位置 = 2\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * Step3指针位置 = 4\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * Step4指针位置 = 11\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * Step5指针位置 = 15\n *\n * 我买了一个{{thing}},好{{mood}}啊\n * ↑\n *\n * ... while(指针位置 >= 模板字符串.length)\n *\n * /\n```\n\n- Step1:\n\n指针右移 1 个长度,以指针位置切割,字符串被分成`我`+`买了一个{{thing}},好{{mood}}啊`\n\n- Step2:\n\n指针右移 1 个长度,以指针位置切割,字符串被分成`我买`+`了一个{{thing}},好{{mood}}啊`\n\n- Step3:\n\n第一次遇到通过 `indexOf(\"{{\") == 0` 判断\n\n```js\n// 标记为 text 放到 tokens 中\ntoken.push([\"text\", \"我买了一个\"]); // tokens: [['text', '我买了一个']]\n```\n\n结束此时指针位置 = 4\n\n- Step4:\n\n指针右移 2 个长度,跳过`{{`,暂存此时`pos_last = 6`\n\n此时右边字符串(尾字符串)`thing}},好{{mood}}啊`\n\n右移 5 个长度,识别`模板内部数据对象`\n\n```js\nsubstring(post_last, 6 + 5); // thing 5个长度\n// 标记为 name 放到 tokens 中\ntoken.push([\"name\", \"thing\"]); // tokens: [['text', '我买了一个']], ['name', 'thing']]\n```\n\n结束此时指针位置 = 11\n\n- Step5:\n\n> 遇到 `}}`,通过 `indexOf(\"}}\") == 0`判断\n\n指针右移 2 个长度,跳过`}}`,暂存此时`post_last = 13`,继续右移 2 个长度\n\n```js\nsubstring(post_last, 13 + 2); // ,好 2个长度\n// 标记为 text 放到 tokens 中\ntoken.push([\"text\", \",好\"]); // tokens: [['text', '我买了一个']], ['name', 'thing'],['text', ',好' ]]\n```\n\n> 第二次,遇到 `{{`\n\n剩下循环执行就行了这个过程我们可以称作`扫描 Scan`\n\n## 扫描器 Scanner\n\n新建一个 `Scanner.js`,用来扫描模板字符串,实现上面的原理\n\n```js\n/**\n * 模板字符串扫描器\n */\n\nclass Scanner {\n constructor(templ) {\n this.templ = templ; // 模板字符串\n this.tail = templ; // 尾字符串\n this.pPos = 0; // 指针位置\n }\n\n /**\n * 指针跳过模板标签\n * @param {模板语法包围标签} tag\n */\n jumpTag(tag) {\n if (this.tail.indexOf(tag) === 0) {\n this.pPos += tag.length; // 指针右移 tag.length 个长度\n this.tail = this.templ.substring(this.pPos); // 尾字符串更新\n }\n }\n\n /**\n * 指针遇见模板标签 {{\n * @param {模板语法包围标签} tag\n */\n missTag(tag) {\n let pPos_last = this.pPos;\n while (!this.eof() && this.tail.indexOf(tag) !== 0) {\n this.pPos++;\n this.tail = this.templ.substring(this.pPos);\n }\n return this.templ.substring(pPos_last, this.pPos);\n }\n\n eof() {\n return this.pPos >= this.templ.length;\n }\n}\n```\n\n## 分析器 Parser\n\n调用`Scanner.js`\n\n```js\nlet tmpl = `我买了一个{{thing}},好{{mood}}啊`;\n// 编译 模板字符串 => tokens\nconst Parser = {\n createTokens: (tmpl) => {\n let scanner = new Scanner(tmpl);\n let tokens = [];\n // scanner 循环执行\n while (!scanner.eof()) {\n ctx = scanner.missTag(\"{{\"); // 返回 头字符串\n if (ctx != \"\") {\n tokens.push([\"text\", ctx]);\n }\n scanner.jumpTag(\"{{\"); // 跳过 模板字符\n ctx = scanner.missTag(\"}}\"); // 返回 {{ x }}\n if (ctx != \"\") {\n tokens.push([\"name\", ctx]);\n }\n scanner.jumpTag(\"}}\");\n }\n return tokens;\n },\n};\nconsole.log(Parser.createTokens(tmpl));\n// 输出,非常的 奈一丝\n// [\"text\", \"我买了一个\"]\n// [\"name\", \"thing\"]\n// [\"text\", \",好\"]\n// [\"name\", \"mood\"]\n// [\"text\", \"啊\"]\n```\n\n## 扫描器 Scanner 增强\n\n上面的`Parser`只能识别`{{`和`}}`,如果模板语法复杂一点,比如加入 `{{#list}}...{{/list}}`,需要增强`Parser`\n\n```js\nconst template = `\n 哈哈哈\n {{#students}}\n 我买了一个 {{ thing }},好{{mood}}啊{{a}}\n {{item.name}}\n {{/students}}\n `;\nconst Parser = {\n createTokens: (tmpl) => {\n let scanner = new Scanner(tmpl);\n let tokens = [];\n let ctx = \"\";\n // scanner 循环执行\n while (!scanner.eof()) {\n ctx = scanner.missTag(\"{{\"); // 返回 头字符串\n if (ctx != \"\") {\n tokens.push([\"text\", ctx]);\n }\n scanner.jumpTag(\"{{\"); // 跳过 模板字符\n ctx = scanner.missTag(\"}}\"); // 返回 {{ x }}\n if (ctx != \"\") {\n switch (ctx[0]) {\n case \"#\":\n tokens.push([\"#\", ctx.substr(1)]); // {{# x }}\n break;\n case \"/\":\n tokens.push([\"/\", ctx.substr(1)]);\n break;\n default:\n tokens.push([\"name\", ctx]);\n break;\n }\n }\n scanner.jumpTag(\"}}\");\n }\n return tokens;\n },\n};\nconsole.log(Parser.createTokens(template));\n\n// 输出\n// [\"text\", \"↵ 哈哈哈↵ \"]\n// [\"#\", \"students\"]\n// [\"text\", \"↵ 我买了一个 \"]\n// [\"name\", \" thing \"]\n// [\"text\", \",好\"]\n// [\"name\", \"mood\"]\n// [\"text\", \"啊\"]\n// [\"name\", \"a\"]\n// [\"text\", \"↵ \"]\n// [\"name\", \"item.name\"]\n// [\"text\", \"↵ \"]\n// [\"/\", \"students\"]\n// [\"text\", \"↵ \"]\n```\n\n## 栈队列算法\n\n上一步最后的输出只有单层嵌套如果是两层嵌套怎么办\n\n例如模板语法如下\n\n```js\nvar template = `\n 哈哈哈\n {{#students}}\n {{#stu}}\n {{stu.name}}买了一个 {{ thing }},好{{mood}}啊{{a}}\n {{/stu}}\n {{item.name}}\n {{/students}}\n `;\n```\n\n经过`Parser`处理得到:\n\n```js\n/**\n *\n * [\"text\", \"↵ 哈哈哈↵ \"]\n * [\"#\", \"students\"]\n * [\"text\", \"↵ \"]\n * [\"#\", \"stu\"]\n * [\"text\", \"↵ \"]\n * [\"name\", \"stu.name\"]\n * [\"text\", \"买了一个 \"]\n * [\"name\", \" thing \"]\n * [\"text\", \",好\"]\n * [\"name\", \"mood\"]\n * [\"text\", \"啊\"]\n * [\"name\", \"a\"]\n * [\"text\", \"↵ \"]\n * [\"/\", \"stu\"]\n * [\"text\", \"↵ \"]\n * [\"name\", \"item.name\"]\n * [\"text\", \"↵ \"]\n * [\"/\", \"students\"]\n * [\"text\", \"↵ \"]\n *\n * /\n```\n\n此时`students`和`stu`都是`#`标记,我们需要利用算法处理他们的嵌套结构,处理成大约如下这样的结构:\n\n```js\n/**\n *\n * [\"text\", \"↵ 哈哈哈↵ \"]\n * Array(3)\n * \"#\"\n * \"students\"\n * Array(5)\n * [\"text\", \"↵ \"]\n * [\"#\", \"stu\", Array(9)]\n * [\"text\", \"↵ \"]\n * [\"name\", \"item.name\"]\n * [\"text\", \"↵ \"]\n * [\"text\", \"↵ \"]\n *\n * /\n```\n\n# 常用工具类\n\n## 递归\n\n```js\n/**\n * {string} dir 递归根目录\n * {object} list 暂存参数\n */\nconst deep = async (dir, list = []) => {\n const dirs = await fs.promises.readdir(dir)\n for (let i = 0; i < dirs.length; i++) {\n const item = dirs[i]\n const itemPath = path.join(dir, item)\n const isDir = fs.statSync(itemPath).isDirectory()\n isDir ? await deep(itemPath, list) : list.push(itemPath)\n }\n return list\n}\n```\n\n## 自增id短码\n\n用于连接分享\n\n```typescript\nconst createAscString = (id) => {\n const dictionary = [\n \"0123456789\",\n \"abcdefghigklmnopqrstuvwxyz\",\n \"ABCDEFGHIGKLMNOPQRSTUVWXYZ\",\n ];\n let chars = dictionary.join(\"\").split(\"\"),\n radix = chars.length,\n qutient = 1000 * 1000 * 9999 + +id,\n arr = [];\n while (qutient) {\n mod = qutient % radix;\n qutient = (qutient - mod) / radix;\n arr.unshift(chars[mod]);\n }\n return arr.join(\"\");\n};\n\nconsole.log(createAscString(100000000));\n```\n\n## 手动实现 eventBus\n\n```js\nexport default class EventBus {\n constructor() {\n // key-value : eventName-date\n this.callbacks = {};\n }\n\n /**\n * 监听事件\n * @param {事件名} eventName\n * @param {回调函数} callback\n */\n on(eventName, callback) {\n this.checkType(eventName).callbacks[eventName]\n ? callback(this.callbacks[eventName])\n : this.error(`The event has not been declared`);\n }\n\n /**\n * 注册一个事件\n * @param {事件名} eventName\n * @param {传递的对象} data\n */\n emit(eventName, data) {\n this.checkType(eventName).callbacks[eventName] = data;\n }\n\n /**\n * 注销事件,不传参数默认注销全部事件\n * @param {事件名} eventName\n */\n off(eventName) {\n eventName\n ? this.checkType(eventName).removeEvent(eventName)\n : this.emptyEvent();\n }\n\n /**\n * 移出事件\n * @param {事件名} eventName\n */\n removeEvent(eventName) {\n Reflect.deleteProperty(this.callbacks, eventName);\n }\n\n /**\n * 清空全部事件\n */\n emptyEvent() {\n this.callbacks = [];\n }\n\n /**\n * 参数类型校验\n * @param {参数} param\n * @param {合法的类型} validType\n */\n checkType(param, validType = \"string\") {\n if (typeof param !== validType)\n this.error(`(param, ${param}) should be of ${validType} type`);\n return this; // 缅怀jQ链式调用\n }\n\n /**\n * 错误提示\n * @param {提示文字} text\n */\n error(text) {\n throw new Error(text);\n }\n}\n```\n\n调用\n\n```js\n// 省略import\nconst eventBus = new EventBus();\neventBus.emit(\"login\", [{ a: 1, d: 2 }]);\neventBus.on(123, (d) => console.log(d)); // [{...}]\n```\n\n## 判断对象是否有某个 key\n\n```javascript\nlet obj = { alias: \"es6\" };\n\"alias\" in obj; // true\nReflect.has(obj, \"alias\"); // true\n```\n\n## 浏览器\n\n## 版本信息\n\n```javascript\nwindow.navigator.userAgent;\n```\n\n## 兼容事件绑定\n\n```javascript\n/*\n兼容低版本IEele为需要绑定事件的元素\neventName为事件名保持addEventListener语法去掉onfun为事件响应函数\n*/\n\nfunction addEvent(ele, eventName, fun) {\n ele.addEventListener\n ? ele.addEventListener(eventName, fun, false)\n : ele.attachEvent(\"on\" + eventNme, fun);\n}\n```\n\n## 数组对象\n\n## reduce\n\n```javascript\nvar arr = [1, 2, 3, 4];\nvar sum = arr.reduce(function(prev, cur, index, arr) {\n console.log(prev, cur, index);\n return prev + cur;\n}0) //注意这里设置了初始值\nconsole.log(arr, sum);\n\n// 求和\nconst sum = arr.reduce((p,c) => p+c)\n```\n\n## 对象内部根据 key 对 value 进行排序,取前 3\n\n```javascript\nlet datasource = [\n { price: 1, alias: \"watermelon\" },\n { price: 3, alias: \"orange\" },\n { price: 2, alias: \"banana\" },\n { price: 4, alias: \"apple\" },\n];\n// 降序排列\nlet compare = (key) => (a, b) => b[key] - a[key];\nlet sorted = datasource\n .sort(compare(\"price\"))\n .slice(0, 3)\n .map((i) => i[\"alias\"]);\n// 返回 [\"apple\", \"orange\", \"banana\"]\n```\n\n## 随机字符串\n\n```javascript\nconst getRandomRangeNum = (len = 32) => {\n // 略去不宜辨识字符\n let dictionary = \"ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz\";\n let maxPos = dictionary.length;\n let res = \"\";\n for (let i = 0; i < len; i++) {\n res += dictionary.charAt(Math.floor(Math.random() * maxPos));\n }\n return res;\n};\n```\n\n## 类型检测\n\nQ使用`typeof foo === \"object\"`检测`foo`是否为对象有什么缺点?如何避免?\n\nA用 `typeof` 是否能准确判断一个对象变量,答案是否定的,`null` 的结果也是 `object``Array` 的结果也是 `object`,有时候我们需要的是 \"纯粹\" 的 `object` 对象\n\n```js\nObject.prototype.toString.call(obj) === \"[object Object]\";\n```\n\n## 倒计时\n\n```javascript\nclass Countdown {\n constructor(startNum, endNum, interval) {\n [this.startNum, this.endNum, this.interval] = [startNum, endNum, interval];\n }\n execute() {\n var timer = setTimeout(() => {\n if (this.startNum >= this.endNum) {\n console.log(this.startNum);\n this.startNum -= 1;\n this.execute();\n } else {\n clearTimeout(timer);\n }\n }, this.interval);\n }\n}\n// 实例化调用\nvar countdown = new Countdown(5, 0, 1000).execute();\n```\n\n## 范围随机数\n\n```javascript\n// 能取到 min取不到 max\nfunction getRandomRangeNum(min, max) {\n return min + Math.floor(Math.random() * (max - min));\n}\n```\n\n## 获取当前月的天数\n\n```javascript\nconst getCurMonthDays = new Date(\n new Date().getFullYear(),\n new Date().getMonth() + 1,\n 0\n).getDate();\n```\n\n\n# 对象小操作\n\n## 去虚假值\n\n```js\nlet arr4 = [\"小明\", \"小蓝\", \"\", false, \" \", undefined, null, 0, NaN, true];\nconsole.log(arr4.filter(Boolean)); // => ['小明', '小蓝', ' ', true]\n```\n\n## 头尾插入\n\n效率比 `unshift()` 高\n\n```js\nlet arr = [1, 2, 3];\n// 头插入\n[\"haha\"].concat(arr);\n// 尾插入\narr.concat([\"haha\"]);\n```\n\n\n## 删除属性\n\n```js\nfunction deleteA(obj) {\n delete obj.A;\n return obj;\n}\n\n// 使用解构赋值\nconst deleteA = ({ A, ...rest } = {}) => rest;\n```\n\n# 生产、加工、消费分离\n\n- 从接口拿数据到视图 fetch api\n- 加工 computed\n- 消费 v-for\n\n# 元数据\n\n```js\nimport \"reflect-metadata\"; // npm install reflect-metadata\n\nfunction Role(name: string): ClassDecorator {\n return (target) => {\n Reflect.defineMetadata(\"role\", name, target);\n };\n}\n\n@Role(\"admin\")\nclass Post {}\n\nconst metadata = Reflect.getMetadata(\"role\", Post);\n\nReflect.set(Post, \"role2\", metadata);\n\nconsole.log(Reflect.get(Post, \"role2\")); // admin\n```\n\n# 防抖与节流\n\n在页面上监听诸如`scroll`(页面滚动),`mousemove`(鼠标移动) `keydown` `keyup` `keypress`(按下键盘)等等一系列事件的时候,我们并不希望频繁的触发这类监听,尤其当请求非常消耗资源时,这种操作会导致服务器性能急剧下降。\n\n## Debounce\n\n把触发非常频繁的事件合并成一次延迟执行如果对监听函数使用 100ms 的容忍时间,那么时间在第 3.1s 的时候执行\n\n```javascript\n// 默认延时100ms\nfunction debounce(func, dealy = 100) {\n let timer;\n return function () {\n // 暂存this和参数\n let _this = this;\n let args = arguments;\n // 清除定时器确保不执行func\n clearTimeout(timer);\n timer = setTimeout(function () {\n func.apply(_this, args);\n }, dealy);\n };\n}\n// 执行函数\nfunction handler() {\n console.log(`delay 100ms ,then handle`);\n}\n// dom添加监听\ndocument\n .querySelector(\"#someNode\")\n .addEventListener(\"scroll\", debounce(handler));\n```\n\n## Throttle\n\n固定函数执行的速率即所谓的“节流”。设置一个阀值在阀值内把触发的事件合并成一次执行当到达阀值必定执行一次事件。\n\n```javascript\nfunction throttle(func, delay) {\n let statTime = 0;\n return function () {\n let currentTime = +new Date();\n if (currentTime - statTime > delay) {\n func.apply(this, arguments);\n statTime = currentTime;\n }\n };\n}\n// 执行函数\nfunction resizeHandler() {\n console.log(`resize`);\n}\n// window添加监听\nwindow.onresize = throttle(resizeHandler, 300);\n```\n\n# this 指向\n\n## 全局环境\n\n全局环境下this 始终指向全局对象window无论是否严格模式\n\n```javascript\nconsole.log(this === window); // true\nthis.a = 37;\nconsole.log(window.a); // 37\n```\n\n## 函数上下文调用\n\n- 非严格模式\n\n没有被上一级的对象所调用, this 默认指向全局对象 window\n\n```javascript\nfunction f1() {\n return this;\n}\nf1() === window; // true\n```\n\n- 严格模式\n\nthis 指向 undefined\n\n```javascript\nfunction f2() {\n \"use strict\"; // 这里是严格模式\n return this;\n}\nf2() === undefined; // true\n```\n\n## 箭头函数\n\n> 箭头函数中call()、apply()、bind()方法无效\n\n在全局代码中箭头函数被设置为全局对象总之箭头函数不改变 this 指向\n\n```javascript\nvar globalObject = this;\nvar foo = () => this;\nconsole.log(foo() === globalObject); // true\n```\n\n箭头函数作为对象的方法使用指向全局 window 对象\n\n```javascript\nvar obj = {\n i: 10,\n b: () => console.log(this.i, this),\n c: function () {\n console.log(this.i, this);\n },\n};\nobj.b(); // undefined window{...}\nobj.c(); // 10 Object {...}\n```\n\n箭头函数可以让 this 指向固化,这种特性很有利于封装回调函数\n\n```javascript\n// 总是指向 handler 对象。如果不使用箭头函数则指向全局 document 对象\nvar handler = {\n id: \"123456\",\n\n init: function () {\n document.addEventListener(\n \"click\",\n (event) => this.doSomething(event.type),\n false\n );\n },\n\n doSomething: function (type) {\n console.log(\"Handling \" + type + \" for \" + this.id);\n },\n};\n```\n\n# call, apply, bind 与 es6\n\njs 的函数继承于`Function.prototype`对象,因此每个函数都会有 apply、call、bind 方法\n\n> call 和 apply 的作用,完全一样,唯一的区别就是在参数上面。\n\n`call, apply, bind`改变函数中 `this 指向` 的三兄弟,把`this`绑定到第一个参数对象上\n\n```javascript\nfunction displayHobbies(...hobbies) {\n console.log(`${this.name} likes ${hobbies.join(\", \")}.`);\n}\n// 下面两个等价\ndisplayHobbies.call({ name: \"Bob\" }, \"swimming\", \"basketball\", \"anime\"); // Bob likes swimming, basketball, anime.\ndisplayHobbies.apply({ name: \"Bob\" }, [\"swimming\", \"basketball\", \"anime\"]); // Bob likes swimming, basketball, anime.\n```\n\n`bind`返回的是一个函数,需要手动执行\n\n```js\nvar p1 = {\n name: \"张三\",\n age: 12,\n func: function () {\n console.log(`姓名:${this.name},年龄:${this.age}`);\n },\n};\n\nvar p2 = {\n name: \"李四\",\n age: 15,\n};\n\np1.func.bind(p2)(); //姓名:李四,年龄:15\n```\n\n# for 循环优化\n\n```javascript\n// 每次都要计算array.length\nfor (let i = 0; i < array.length; i++) {\n console.log(i);\n}\n\n// 使用leng缓存array长度\nfor (let i = 0, length = array.length; i < length; i++) {\n console.log(i);\n}\n```\n\n# 数组\n\n## 扁平化去重升序排列\n\n```javascript\nlet arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];\narr.flat(Infinity); // [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]\n\nlet result = Array.from(new Set(arr.flat(Infinity)).sort((a, b) => a - b));\n```\n\n# 前端页面埋点 - 1x1.gif\n\n通常用在统计页面点击曝光停留时间签发……等场景\n\n- 比 PNG/JPG 体积小\n- 天然跨域\n\n```html\n<button onClick=\"countClick()\">haorooms</button>\n<script>\n function countClick() {\n new Image().src = `./haorooms.gif?${key}=${value}&${Math.random()} `;\n }\n</script>\n```\n\n# 事件委托\n\n利用冒泡原理委托父元素执行\n\n```html\n<ul>\n <li>苹果</li>\n <li>香蕉</li>\n <li>凤梨</li>\n</ul>\n```\n\n```javascript\ndocument.querySelector(\"ul\").onclick = (event) => {\n let target = event.target;\n if (target.nodeName === \"LI\") {\n console.log(target.innerHTML);\n }\n};\n```\n\n# 构造函数 + 原型模式\n\n```javascript\nfunction Person(name, age, job) {\n this.name = name;\n this.age = age;\n this.job = job;\n}\nPerson.prototype.say = function (text) {\n console.log(`${this.name}say:${text}`);\n};\n```\n\n# 剩余参数...args\n\n剩余参数`args`数个数组,`...`解构符\n\n```javascript\nfunction fun1(param, ...args) {\n alert(args.length);\n}\n```\n\n# 跨页面通信\n\n- cookie\n- web worker\n- localstorage\n\n# iframe 跨域通信和不跨域通信\n\n## 不跨域\n\n```javascript\n// fatherSay是父页面全局方法\nwindow.parent.fatherSay();\n// 父页面Dom\nwindow.parent.document.getElementById(\"元素id\");\n// 副业页面获取frameID为`iframe_ID`的子页面的Dom\nwindow.frames[\"iframe_ID\"].document.getElementById(\"元素id\");\n```\n\n## 跨域 postMessage\n\n子页面\n\n```javascript\nwindow.parent.postMessage(\"hello\", \"http://127.0.0.1:8089\");\n```\n\n父页面接受\n\n```javascript\nwindow.addEventListener(\"message\", function (event) {\n alert(123);\n});\n```\n\n# 对象类型判断\n\n## 数组\n\n```javascript\nlet arr = [];\narr instanceof Array; // true\nArray.isArray(arr); // true\nObject.prototype.toString.call(arr); // \"[object Array]\"\n```\n\n# js 单线程,如何异步\n\n- 主线程 执行 js 中所有的代码。\n\n- 主线程 在执行过程中发现了需要异步的任务任务后扔给浏览器(浏览器创建多个线程执行,顺便创造一个`回调队列`。\n\n- 主线程 已经执行完毕所有同步代码。监听`回调队列`一旦 浏览器 中某个线程任务完成将会改变回调函数的状态。主线程查看到某个函数的状态为已完成,就会执行该`回调队列`中对应的回调函数。\n\n# 移动端最小触控区域\n\n苹果推荐是 44pt x 44pt 「具体看 WWDC 14」,通过`padding`、`margin`、`height`等方式进行点击区域扩展\n\n# js 精度问题\n\n常用类库`Math.js`、`Big.js`、`decimal.js`\n\n# 冻结 Object. freeze()\n\n`const`生命的简单变量不可修改,但是复杂对象可以被修改,`Object. freeze()`:可以冻结对象\n\n- 不能添加新属性\n- 不能删除已有属性\n- 不能修改已有属性的可枚举性、可配置性、可写性\n- 不能修改已有属性的值\n- 不能修改原型\n\n浅冻结\n\n```javascript\nconst obj1 = {\n internal: {},\n};\n\nObject.freeze(obj1);\nobj1.internal.a = \"aValue\";\nconsole.log(obj1.internal.a); // aValue\n```\n\n递归冻结\n\n```javascript\nfunction deepFreeze(obj) {\n // 获取定义在obj上的属性名\n var propNames = Object.getOwnPropertyNames(obj);\n // 在冻结自身之前冻结属性\n propNames.forEach(function (name) {\n var prop = obj[name];\n // 如果prop是个对象冻结它\n if (typeof prop == \"object\" && prop !== null) deepFreeze(prop);\n });\n return Object.freeze(obj);\n}\n```\n\n# Reflect\n\n## Reflect.get(target, propertyKey, value[receiver])\n\n获取对象身上某个属性的值类似于 target[name]。\n\n## Reflect.set(target, propertyKey, value[receiver])\n\n将值分配给属性的函数。返回一个 Boolean如果更新成功则返回 true。\n\n## Reflect.has(target, propertyKey)\n\n判断一个对象是否存在某个属性和 in 运算符 的功能完全相同。\n\n\n# if else 优化\n\n## 表驱动编程\n\n空间换时间设置`obj={key:value}`,通过`obj[key]`取值\n\n```javascript\ncalculateGrade(score){\n const table = {\n 100: 'A',\n 90: 'A',\n 80: 'B',\n 70: 'C',\n 60: 'D',\n others: 'E'\n }\n return table[Math.floor(score/10)*10] || table['others']\n}\n```\n\n## 短路运算\n\nreact 没有`v-if`,运用比较频繁\n\n```js\n// 函数组件\nconst Home = () => {\n return <div>home</div>;\n};\n{\n true && <Home />;\n}\n```\n\n# 使用有意义且易读的变量名\n\n```js\n👎 const yyyymmdstr = moment().format(\"YYYY/MM/DD\");\n\n👍 const currentDate = moment().format(\"YYYY/MM/DD\");\n```\n\n# 使用有意义的变量代替数组下标\n\n```js\n👎\nconst address = \"One Infinite Loop, Cupertino 95014\";\nconst cityZipCodeRegex = /^[^,\\\\]+[,\\\\\\s]+(.+?)\\s*(\\d{5})?$/;\nsaveCityZipCode(\n address.match(cityZipCodeRegex)[1],\n address.match(cityZipCodeRegex)[2]\n);\n\n👍\nconst address = \"One Infinite Loop, Cupertino 95014\";\nconst cityZipCodeRegex = /^[^,\\\\]+[,\\\\\\s]+(.+?)\\s*(\\d{5})?$/;\nconst [_, city, zipCode] = address.match(cityZipCodeRegex) || [];\nsaveCityZipCode(city, zipCode);\n```\n\n# 变量名要简洁\n\n```js\n👎\nconst Car = {\n carMake: \"Honda\",\n carModel: \"Accord\",\n carColor: \"Blue\"\n};\nfunction paintCar(car, color) {\n car.carColor = color;\n}\n\n👍\nconst Car = {\n make: \"Honda\",\n model: \"Accord\",\n color: \"Blue\"\n};\nfunction paintCar(car, color) {\n car.color = color;\n}\n```\n\n# 消除魔术字符串\n\n```js\n👎 setTimeout(blastOff, 86400000);\n\n👍 const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000; //86400000;\nsetTimeout(blastOff, MILLISECONDS_PER_DAY);\n```\n\n# 使用默认参数替代短路运算符\n\n```js\n👎\nfunction createMicrobrewery(name) {\n const breweryName = name || \"Hipster Brew Co.\";\n // ...\n}\n\n👍\nfunction createMicrobrewery(name = \"Hipster Brew Co.\") {\n // ...\n}\n```\n\n# 一个函数\n\n```js\n👎\nfunction emailClients(clients) {\n clients.forEach(client => {\n const clientRecord = database.lookup(client);\n if (clientRecord.isActive()) {\n email(client);\n }\n });\n}\n\n👍\nfunction emailActiveClients(clients) {\n clients.filter(isActiveClient).forEach(email);\n}\nfunction isActiveClient(client) {\n const clientRecord = database.lookup(client);\n return clientRecord.isActive();\n}\n\n---------------------分割线-----------------------\n\n👎\nfunction createFile(name, temp) {\n if (temp) {\n fs.create(`./temp/${name}`);\n } else {\n fs.create(name);\n }\n}\n\n👍\nfunction createFile(name) {\n fs.create(name);\n}\nfunction createTempFile(name) {\n createFile(`./temp/${name}`);\n}\n```\n\n# 函数参数不多于 2 个,如果有很多参数就利用 object 传递,并使用解构\n\n```js\n👎\nfunction createMenu(title, body, buttonText, cancellable) {\n // ...\n}\ncreateMenu(\"Foo\", \"Bar\", \"Baz\", true);\n\n👍\nfunction createMenu({ title, body, buttonText, cancellable }) {\n // ...\n}\ncreateMenu({\n title: \"Foo\",\n body: \"Bar\",\n buttonText: \"Baz\",\n cancellable: true\n});\n```\n\n# 函数名应该直接反映函数的作用\n\n```js\n👎\nfunction addToDate(date, month) {\n // ...\n}\nconst date = new Date();\n// It's hard to tell from the function name what is added\naddToDate(date, 1);\n\n👍\nfunction addMonthToDate(month, date) {\n // ...\n}\nconst date = new Date();\naddMonthToDate(1, date);\n```\n\n# 尽量使用纯函数\n\n```js\n👎\nconst programmerOutput = [\n {\n name: \"Uncle Bobby\",\n linesOfCode: 500\n },\n {\n name: \"Suzie Q\",\n linesOfCode: 1500\n },\n {\n name: \"Jimmy Gosling\",\n linesOfCode: 150\n },\n {\n name: \"Gracie Hopper\",\n linesOfCode: 1000\n }\n];\nlet totalOutput = 0;\nfor (let i = 0; i < programmerOutput.length; i++) {\n totalOutput += programmerOutput[i].linesOfCode;\n}\n\n👍\nconst programmerOutput = [\n {\n name: \"Uncle Bobby\",\n linesOfCode: 500\n },\n {\n name: \"Suzie Q\",\n linesOfCode: 1500\n },\n {\n name: \"Jimmy Gosling\",\n linesOfCode: 150\n },\n {\n name: \"Gracie Hopper\",\n linesOfCode: 1000\n }\n];\nconst totalOutput = programmerOutput.reduce(\n (totalLines, output) => totalLines + output.linesOfCode,\n 0\n);\n```\n\n# 不要过度优化\n\n```js\n👎\n// 现代浏览器对于迭代器做了内部优化\nfor (let i = 0, len = list.length; i < len; i++) {\n // ...\n}\n\n👍\nfor (let i = 0; i < list.length; i++) {\n // ...\n}\n```\n\n\n# 关于模块化\n\n## 无模块化\n\n> 污染全局作用域、维护成本高、依赖关系不明显\n\nscript 标签引入 js 文件,相互罗列,但是被依赖的放在前面,否则使用就会报错。如下:\n\n```js\n<script src=\"jquery.js\"></script>\n<script src=\"main.js\"></script>\n<script src=\"other1.js\"></script>\n<script src=\"other2.js\"></script>\n<script src=\"other3.js\"></script>\n```\n\n## CommonJS 规范(同步)\n\n该规范最初是用在服务器端的 node 的它有四个重要的环境变量为模块化的实现提供支持module、exports、require、global。实际使用时用 module.exports 定义当前模块对外输出的接口(不推荐直接用 exports用 require 加载模块(同步)\n\n> module.exports 本身就是一个对象\n\n```js\nmodule.exports = { foo: \"bar\" }; //true\nmodule.exports.foo = \"bar\"; //true。\n```\n\nCommonJS 用同步的方式加载模块。在服务端模块文件都存在本地磁盘读取非常快所以这样做不会有问题。但是在浏览器端限于网络原因CommonJS 不适合浏览器端模块加载,更合理的方案是使用异步加载,比如下边 AMD 规范。\n\n## AMD 规范(RequireJS)\n\n承接上文AMD 规范则是非同步加载模块允许指定回调函数AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。\n\n- `require([module], callback)`:加载模块\n- `define(id, [depends], callback)`:定义模块\n- `require.config()`:配置路径、依赖关系\n\n## CMD 规范(SeaJS)\n\nCMD 是 在推广过程中对模块定义的规范化产出\n\n## ES6 import/export\n\n通过 babel 将不被支持的 import 编译为当前受到广泛支持的 AMD 规范\n\n# AMD模块化实现\n\n## define 函数\n\n用来声明模块名`module`,依赖数组`deps`,以及模块的作用`callback`\n\n```js\nvar module = (function () {\n var stack = {}; //模块存储栈,存的是模块执行后的结果\n\n function define(module, deps, callback) {\n stack[module] = callback.apply(null, deps); // 压栈\n console.log(stack); // 查看栈存储的模块\n }\n\n return { define: define };\n})();\n```\n\n调用`define`试试,发现 `calc`模块被压入了`stack 模块栈中`\n\n```js\nmodule.define(\"calc\", [], function () {\n return {\n first: function (arr) {\n return arr[0];\n },\n };\n});\n// {calc: { first: ƒ }}\n```\n\n## deps 依赖(导入)\n\n对上面的 `define`函数稍加改造,这一步过程的本质,就是对 deps\n\n```js\nvar module = (function (window) {\n var stack = {}; //模块存储栈,\n\n function define(module, deps, callback) {\n // 把 define 函数依赖数组中的模块从 stack 模块中拿出\n deps.map(function (mod, index) {\n deps[index] = stack[mod]; // 赋值给当前模块的 deps\n });\n stack[module] = callback.apply(null, deps);\n console.log(stack); // 查看栈存储的模块\n }\n\n return { define: define };\n})(window);\n\nmodule.define(\"calc\", [], function () {\n return {\n first: function (arr) {\n return arr[0];\n },\n };\n});\n\nmodule.define(\"number\", [\"calc\"], function (calc) {\n return {\n res: calc.first([4, 3, 2, 1]), //4\n };\n});\n\n// 此时 stack 打印的结果为\n//> calc: {first: ƒ}\n//> number: {res: 4}\n```\n\n> 从本质上看define 函数的第二个参数 deps 数组,相当于 import 导入,并且如果第三个参数 callback 采用 `return { }`,也就相当于 export 导出\n\n## 老生常谈的指针\n\n说到底`stack`中 `a模块` export 是一个指针,`{a:value}`(内存地址),所以,`b 模块`会改变`a.a`的值,这点和 `cmd`不同\n\n```js\nmodule.define(\"a\", [], function () {\n return {\n a: 1,\n };\n});\nmodule.define(\"b\", [\"a\"], function (a) {\n a.a = 2;\n});\nmodule.define(\"c\", [\"a\"], function (a) {\n console.log(a.a); // 2\n});\n```\n\n\n# 缘起 Object.defineProperty()\n\n给`目标对象`上定义一个新属性,或者修改`目标对象`属性,并且返回新对象\n\n# 上帝的钥匙 get & set\n\n属性的`getter`函数,如果没有 `getter`则尾 `undefined`。当访问该属性时,会调用此函数.\n\n```js\nlet obj = {};\n\nObject.defineProperty(obj, \"a\", {\n get() {\n return 7;\n },\n set(val) {\n console.log(`FAILED改变 a 属性,新值为:${val},但是被重写 set 劫持了`);\n },\n});\n\nconsole.log(obj.a);\nobj.a = 4;\n```\n\n> 上帝的钥匙被找到了\n\n劫持劫持还是 TMD 劫持!\n\n```js\nlet obj = {};\nlet tempValue = 0;\n\nObject.defineProperty(obj, \"a\", {\n get() {\n return tempValue;\n },\n set(newValue) {\n tempValue = newValue;\n },\n});\n\nconsole.log(obj.a); // 0\nobj.a = 4;\nconsole.log(obj.a); // 4\n```\n\n# 封装 defineReactive(obj, prop, val)\n\n> 这里 defineReactive 第三个参数 val 替代了上一步中全局变量`tempValue`,对于 get()、set()来说,访问到了其他函数内部的变量,所以形成了闭包\n\n```js\nfunction defineReactive(obj, prop, val) {\n Object.defineProperty(obj, prop, {\n get() {\n console.log(`劫持,你访问了${prop}属性`);\n return val;\n },\n set(newValue) {\n if (val === newValue) return;\n console.log(`劫持,你改变了${prop}属性`);\n val = newValue;\n },\n });\n}\n\nlet obj = {};\ndefineReactive(obj, \"a\", 4);\n\nconsole.log(obj.a); // 劫持你访问了a属性 4\nobj.a = 7; // 劫持你改变了a属性\nconsole.log(obj.a); // 劫持你访问了a属性 7\n```\n\n# 递归侦测\n\n```js\nlet obj = { a: { b: { c: {} } } };\ndefineReactive(obj, \"a\", 4);\n```\n\n> 如何自动让`obj`对象的全部属性都`reactive`呢?\n\n```js\nlet obj = {\n a: {\n b: {\n c: 5,\n },\n },\n d: 4,\n};\n```\n\n定义个方法`observe`,递归 `obj` 的每一层的每个 `prop`,检测是否有`__ob__`,如果没有,`defineReactive`,并且挂一个`Observer`实例在这个`props`上,例如:\n\n`Observer对象`\n\n```js\nclass Observer {\n constructor(value) {\n def(value, \"__ob__\", this, false); // 不可枚举不能给__ob__添加__ob__\n this.walk(value);\n }\n // 遍历每一个 prop的 value\n walk(value) {\n for (let prop in value) {\n defineReactive(value, prop);\n }\n }\n}\n```\n\n`defineReactive.js`\n\n```js\nexport default function defineReactive(obj, prop, val) {\n if (arguments.length === 2) val = obj[prop]; // 如果2个参数\n let childNode = observe(val);\n Object.defineProperty(obj, prop, {\n enumerable: true,\n configurable: true,\n get() {\n console.log(`你访问了${prop}属性`);\n return val;\n },\n set(newValue) {\n if (val === newValue) return;\n console.log(`你改变了${prop}属性`);\n val = newValue;\n childNode = observe(newValue);\n },\n });\n}\n```\n\n`observe.js`\n\n```js\n/**\n * 检测 obj 身上有没有 __ob__(Observer 实例)\n * @param {*} value\n * @returns\n */\nexport default function observe(value) {\n if (typeof value != \"object\") return;\n let ob;\n //! 用__ob__是为了属性不重名被覆盖\n if (typeof value.__ob__ != \"undefined\") {\n ob = value.__ob__;\n } else {\n ob = new Observer(value);\n }\n return ob;\n}\n```\n","slug":"front-end/码场悟道","published":1,"date":"2023-11-06T07:57:50.766Z","updated":"2023-11-07T06:48:08.822Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58q000p4cz3gxzl7mxo","content":"<h1 id=\"模板引擎\"><a href=\"#模板引擎\" class=\"headerlink\" title=\"模板引擎\"></a>模板引擎</h1><p>严格的模板引擎的定义,输入模板字符串 + 数据,得到渲染过的字符串。实现上,从正则替换到拼 function 字符串到正经的 AST 解析各种各样,但从定义上来说都是差不多的。字符串渲染的性能其实也就在后端比较有意义,毕竟每一次渲染都是在消耗服务器资源,但在前端,用户只有一个,几十毫秒的渲染时间跟请求延迟比起来根本不算瓶颈。倒是前端的后续更新是字符串模板引擎的软肋,因为用渲染出来的字符串整个替换 innerHTML 是一个效率很低的更新方式。所以这样的模板引擎如今在纯前端情境下已经不再是好的选择,意义更多是在于方便前后端共用模板。</p>\n<h1 id=\"古老数据渲染-vm-的方式\"><a href=\"#古老数据渲染-vm-的方式\" class=\"headerlink\" title=\"古老数据渲染 vm 的方式\"></a>古老数据渲染 vm 的方式</h1><p>这种写法,弊端太多了,玩具车</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token doctype\"><span class=\"token punctuation\">&lt;!</span><span class=\"token doctype-tag\">DOCTYPE</span> <span class=\"token name\">html</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span> <span class=\"token attr-name\">lang</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>en<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>head</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">charset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>UTF-8<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">http-equiv</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>X-UA-Compatible<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>IE=edge<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>viewport<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>width=device-width, initial-scale=1.0<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>title</span><span class=\"token punctuation\">></span></span>Document<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>title</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>head</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>body</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>app<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>body</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span><span class=\"token punctuation\">></span></span><span class=\"token script\"><span class=\"token language-javascript\">\n <span class=\"token keyword\">var</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"小明\"</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">age</span><span class=\"token operator\">:</span> <span class=\"token number\">11</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">sex</span><span class=\"token operator\">:</span> <span class=\"token string\">\"男\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"小红\"</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">age</span><span class=\"token operator\">:</span> <span class=\"token number\">22</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">sex</span><span class=\"token operator\">:</span> <span class=\"token string\">\"女\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">var</span> listDOM <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"app\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n arr<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">item</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> _li <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createElement</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"li\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n _li<span class=\"token punctuation\">.</span>innerText <span class=\"token operator\">=</span> item<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">;</span>\n listDOM<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>_li<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n </span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>html</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"mustache-原理\"><a href=\"#mustache-原理\" class=\"headerlink\" title=\"mustache 原理\"></a>mustache 原理</h1><ul>\n<li>1、先把模板字符串编译成 tokens(代号)</li>\n<li>2、根据 tokens结合数据渲染成 dom</li>\n</ul>\n<blockquote>\n<p>本质上tokens 是一个 js 嵌套数组没事模板字符串 js 的表示,他是<code>抽象语法树</code><code>虚拟节点</code>的开山鼻祖</p>\n</blockquote>\n<p>假设有这么一个模板字符串</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span><span class=\"token punctuation\">></span></span>我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>会编译成 tokens如下</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 这里面每一个数组行都是一个 token组起来就是 tokens</span>\n<span class=\"token comment\">// html 标签也会被看成纯文本</span>\n<span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;h1>我买了一个\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"thing\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"好\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"mood\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"啊&lt;/h1>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>当模板存在循环式,带层级嵌套,如下:</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;#arr&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>&#123;&#123;.&#125;&#125;<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;/arr&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>会被编译成</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;div>&lt;ul>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span>\n <span class=\"token string\">\"#\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"arr\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"li\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\".\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;/li>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;/ul>&lt;/div>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>如果是双重循环,带层级嵌套继续加一层,例如:</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ol</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;#students&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>\n 学生&#123;&#123;item.name&#125;&#125;的爱好是\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ol</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;#item.hobbies&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>&#123;&#123;.&#125;&#125;<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;/#item.hobbies&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ol</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;/#students&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ol</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>会被编译成</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;div>&lt;ol>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span>\n <span class=\"token string\">\"#\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"students\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;li>学生\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"的爱好是&lt;ol>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"#\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"hobbies\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">'text'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'&lt;li>'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">'name'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'.'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">'text'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'&lt;/li>'</span><span class=\"token punctuation\">]</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">'text'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'&lt;ol>&lt;/li>'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">'text'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'&lt;/ol>&lt;/div>'</span><span class=\"token punctuation\">]</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>在<code>mustache.js</code>中完成上述这一过程的函数<code>parseTemplate</code>,可以去找源代码看</p>\n</blockquote>\n<h2 id=\"tokens-生成算法\"><a href=\"#tokens-生成算法\" class=\"headerlink\" title=\"tokens 生成算法\"></a>tokens 生成算法</h2><p>用简单的模板字符串举例:</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\">我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>有一个指针往右遍历,从<code>我</code>开始,遍历到<code>啊</code>结束,如下:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * Step1指针位置 = 1\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * Step2指针位置 = 2\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * Step3指针位置 = 4\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * Step4指针位置 = 11\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * Step5指针位置 = 15\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * ... while(指针位置 >= 模板字符串.length)\n *\n * /</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<ul>\n<li>Step1:</li>\n</ul>\n<p>指针右移 1 个长度,以指针位置切割,字符串被分成<code>我</code>+<code>买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊</code></p>\n<ul>\n<li>Step2:</li>\n</ul>\n<p>指针右移 1 个长度,以指针位置切割,字符串被分成<code>我买</code>+<code>了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊</code></p>\n<ul>\n<li>Step3:</li>\n</ul>\n<p>第一次遇到,通过 <code>indexOf(&quot;&#123;&#123;\") == 0` 判断\n\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 标记为 text 放到 tokens 中</span>\ntoken<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"我买了一个\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// tokens: [['text', '我买了一个']]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n结束此时指针位置 = 4\n\n- Step4:\n\n指针右移 2 个长度,跳过`&#123;&#123;`,暂存此时`pos_last = 6`\n\n此时右边字符串(尾字符串)`thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊</code></p>\n<p>右移 5 个长度,识别<code>模板内部数据对象</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">substring</span><span class=\"token punctuation\">(</span>post_last<span class=\"token punctuation\">,</span> <span class=\"token number\">6</span> <span class=\"token operator\">+</span> <span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// thing 5个长度</span>\n<span class=\"token comment\">// 标记为 name 放到 tokens 中</span>\ntoken<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"thing\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// tokens: [['text', '我买了一个']], ['name', 'thing']]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>结束,此时指针位置 &#x3D; 11</p>\n<ul>\n<li>Step5:</li>\n</ul>\n<blockquote>\n<p>遇到 <code>&#125;&#125;</code>,通过 <code>indexOf(&quot;&#125;&#125;&quot;) == 0</code>判断</p>\n</blockquote>\n<p>指针右移 2 个长度,跳过<code>&#125;&#125;</code>,暂存此时<code>post_last = 13</code>,继续右移 2 个长度</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">substring</span><span class=\"token punctuation\">(</span>post_last<span class=\"token punctuation\">,</span> <span class=\"token number\">13</span> <span class=\"token operator\">+</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// ,好 2个长度</span>\n<span class=\"token comment\">// 标记为 text 放到 tokens 中</span>\ntoken<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\",好\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// tokens: [['text', '我买了一个']], ['name', 'thing'],['text', ',好' ]]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>第二次,遇到 <code>&#123;&#123;`\n\n剩下循环执行就行了这个过程我们可以称作`扫描 Scan`\n\n## 扫描器 Scanner\n\n新建一个 `Scanner.js`,用来扫描模板字符串,实现上面的原理\n\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n * 模板字符串扫描器\n */</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Scanner</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">templ</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>templ <span class=\"token operator\">=</span> templ<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 模板字符串</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>tail <span class=\"token operator\">=</span> templ<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 尾字符串</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 指针位置</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 指针跳过模板标签\n * @param &#123;模板语法包围标签&#125; tag\n */</span>\n <span class=\"token function\">jumpTag</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">tag</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>tail<span class=\"token punctuation\">.</span><span class=\"token function\">indexOf</span><span class=\"token punctuation\">(</span>tag<span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos <span class=\"token operator\">+=</span> tag<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 指针右移 tag.length 个长度</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>tail <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>templ<span class=\"token punctuation\">.</span><span class=\"token function\">substring</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 尾字符串更新</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 指针遇见模板标签 &#123;&#123;\n * @param &#123;模板语法包围标签&#125; tag\n */</span>\n <span class=\"token function\">missTag</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">tag</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> pPos_last <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">eof</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>tail<span class=\"token punctuation\">.</span><span class=\"token function\">indexOf</span><span class=\"token punctuation\">(</span>tag<span class=\"token punctuation\">)</span> <span class=\"token operator\">!==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>tail <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>templ<span class=\"token punctuation\">.</span><span class=\"token function\">substring</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>templ<span class=\"token punctuation\">.</span><span class=\"token function\">substring</span><span class=\"token punctuation\">(</span>pPos_last<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token function\">eof</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos <span class=\"token operator\">>=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>templ<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n## 分析器 Parser\n\n调用`Scanner.js`\n\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> tmpl <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 编译 模板字符串 => tokens</span>\n<span class=\"token keyword\">const</span> Parser <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">createTokens</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">tmpl</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> scanner <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Scanner</span><span class=\"token punctuation\">(</span>tmpl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> tokens <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// scanner 循环执行</span>\n <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>scanner<span class=\"token punctuation\">.</span><span class=\"token function\">eof</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n ctx <span class=\"token operator\">=</span> scanner<span class=\"token punctuation\">.</span><span class=\"token function\">missTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#123;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回 头字符串</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ctx <span class=\"token operator\">!=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n scanner<span class=\"token punctuation\">.</span><span class=\"token function\">jumpTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#123;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 跳过 模板字符</span>\n ctx <span class=\"token operator\">=</span> scanner<span class=\"token punctuation\">.</span><span class=\"token function\">missTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#125;&#125;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回 &#123;&#123; x &#125;&#125;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ctx <span class=\"token operator\">!=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n scanner<span class=\"token punctuation\">.</span><span class=\"token function\">jumpTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#125;&#125;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> tokens<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>Parser<span class=\"token punctuation\">.</span><span class=\"token function\">createTokens</span><span class=\"token punctuation\">(</span>tmpl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 输出,非常的 奈一丝</span>\n<span class=\"token comment\">// [\"text\", \"我买了一个\"]</span>\n<span class=\"token comment\">// [\"name\", \"thing\"]</span>\n<span class=\"token comment\">// [\"text\", \",好\"]</span>\n<span class=\"token comment\">// [\"name\", \"mood\"]</span>\n<span class=\"token comment\">// [\"text\", \"啊\"]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n## 扫描器 Scanner 增强\n\n上面的`Parser`只能识别`&#123;&#123;`和`&#125;&#125;</code>,如果模板语法复杂一点,比如加入 <code>&#123;&#123;#list&#125;&#125;...&#123;&#123;/list&#125;&#125;</code>,需要增强<code>Parser</code></p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> template <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">\n 哈哈哈\n &#123;&#123;#students&#125;&#125;\n 我买了一个 &#123;&#123; thing &#125;&#125;,好&#123;&#123;mood&#125;&#125;啊&#123;&#123;a&#125;&#125;\n &#123;&#123;item.name&#125;&#125;\n &#123;&#123;/students&#125;&#125;\n </span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> Parser <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">createTokens</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">tmpl</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> scanner <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Scanner</span><span class=\"token punctuation\">(</span>tmpl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> tokens <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> ctx <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// scanner 循环执行</span>\n <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>scanner<span class=\"token punctuation\">.</span><span class=\"token function\">eof</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n ctx <span class=\"token operator\">=</span> scanner<span class=\"token punctuation\">.</span><span class=\"token function\">missTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#123;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回 头字符串</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ctx <span class=\"token operator\">!=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n scanner<span class=\"token punctuation\">.</span><span class=\"token function\">jumpTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#123;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 跳过 模板字符</span>\n ctx <span class=\"token operator\">=</span> scanner<span class=\"token punctuation\">.</span><span class=\"token function\">missTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#125;&#125;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回 &#123;&#123; x &#125;&#125;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ctx <span class=\"token operator\">!=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>ctx<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">case</span> <span class=\"token string\">\"#\"</span><span class=\"token operator\">:</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"#\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">.</span><span class=\"token function\">substr</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// &#123;&#123;# x &#125;&#125;</span>\n <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">case</span> <span class=\"token string\">\"/\"</span><span class=\"token operator\">:</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"/\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">.</span><span class=\"token function\">substr</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">default</span><span class=\"token operator\">:</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span>\n scanner<span class=\"token punctuation\">.</span><span class=\"token function\">jumpTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#125;&#125;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> tokens<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>Parser<span class=\"token punctuation\">.</span><span class=\"token function\">createTokens</span><span class=\"token punctuation\">(</span>template<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 输出</span>\n<span class=\"token comment\">// [\"text\", \"↵ 哈哈哈↵ \"]</span>\n<span class=\"token comment\">// [\"#\", \"students\"]</span>\n<span class=\"token comment\">// [\"text\", \"↵ 我买了一个 \"]</span>\n<span class=\"token comment\">// [\"name\", \" thing \"]</span>\n<span class=\"token comment\">// [\"text\", \",好\"]</span>\n<span class=\"token comment\">// [\"name\", \"mood\"]</span>\n<span class=\"token comment\">// [\"text\", \"啊\"]</span>\n<span class=\"token comment\">// [\"name\", \"a\"]</span>\n<span class=\"token comment\">// [\"text\", \"↵ \"]</span>\n<span class=\"token comment\">// [\"name\", \"item.name\"]</span>\n<span class=\"token comment\">// [\"text\", \"↵ \"]</span>\n<span class=\"token comment\">// [\"/\", \"students\"]</span>\n<span class=\"token comment\">// [\"text\", \"↵ \"]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"栈队列算法\"><a href=\"#栈队列算法\" class=\"headerlink\" title=\"栈队列算法\"></a>栈队列算法</h2><p>上一步最后的输出,只有单层嵌套,如果是两层嵌套怎么办?</p>\n<p>例如模板语法如下:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> template <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">\n 哈哈哈\n &#123;&#123;#students&#125;&#125;\n &#123;&#123;#stu&#125;&#125;\n &#123;&#123;stu.name&#125;&#125;买了一个 &#123;&#123; thing &#125;&#125;,好&#123;&#123;mood&#125;&#125;啊&#123;&#123;a&#125;&#125;\n &#123;&#123;/stu&#125;&#125;\n &#123;&#123;item.name&#125;&#125;\n &#123;&#123;/students&#125;&#125;\n </span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>经过<code>Parser</code>处理得到:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n *\n * [\"text\", \"↵ 哈哈哈↵ \"]\n * [\"#\", \"students\"]\n * [\"text\", \"↵ \"]\n * [\"#\", \"stu\"]\n * [\"text\", \"↵ \"]\n * [\"name\", \"stu.name\"]\n * [\"text\", \"买了一个 \"]\n * [\"name\", \" thing \"]\n * [\"text\", \",好\"]\n * [\"name\", \"mood\"]\n * [\"text\", \"啊\"]\n * [\"name\", \"a\"]\n * [\"text\", \"↵ \"]\n * [\"/\", \"stu\"]\n * [\"text\", \"↵ \"]\n * [\"name\", \"item.name\"]\n * [\"text\", \"↵ \"]\n * [\"/\", \"students\"]\n * [\"text\", \"↵ \"]\n *\n * /</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>此时<code>students</code>和<code>stu</code>都是<code>#</code>标记,我们需要利用算法处理他们的嵌套结构,处理成大约如下这样的结构:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n *\n * [\"text\", \"↵ 哈哈哈↵ \"]\n * Array(3)\n * \"#\"\n * \"students\"\n * Array(5)\n * [\"text\", \"↵ \"]\n * [\"#\", \"stu\", Array(9)]\n * [\"text\", \"↵ \"]\n * [\"name\", \"item.name\"]\n * [\"text\", \"↵ \"]\n * [\"text\", \"↵ \"]\n *\n * /</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"常用工具类\"><a href=\"#常用工具类\" class=\"headerlink\" title=\"常用工具类\"></a>常用工具类</h1><h2 id=\"递归\"><a href=\"#递归\" class=\"headerlink\" title=\"递归\"></a>递归</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n * &#123;string&#125; dir 递归根目录\n * &#123;object&#125; list 暂存参数\n */</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">deep</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">dir<span class=\"token punctuation\">,</span> list <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> dirs <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> fs<span class=\"token punctuation\">.</span>promises<span class=\"token punctuation\">.</span><span class=\"token function\">readdir</span><span class=\"token punctuation\">(</span>dir<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> dirs<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> item <span class=\"token operator\">=</span> dirs<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span>\n <span class=\"token keyword\">const</span> itemPath <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>dir<span class=\"token punctuation\">,</span> item<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">const</span> isDir <span class=\"token operator\">=</span> fs<span class=\"token punctuation\">.</span><span class=\"token function\">statSync</span><span class=\"token punctuation\">(</span>itemPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">isDirectory</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n isDir <span class=\"token operator\">?</span> <span class=\"token keyword\">await</span> <span class=\"token function\">deep</span><span class=\"token punctuation\">(</span>itemPath<span class=\"token punctuation\">,</span> list<span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> list<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>itemPath<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> list\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"自增id短码\"><a href=\"#自增id短码\" class=\"headerlink\" title=\"自增id短码\"></a>自增id短码</h2><p>用于连接分享</p>\n<pre class=\"line-numbers language-typescript\" data-language=\"typescript\"><code class=\"language-typescript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">createAscString</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> dictionary <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token string\">\"0123456789\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"abcdefghigklmnopqrstuvwxyz\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"ABCDEFGHIGKLMNOPQRSTUVWXYZ\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> chars <span class=\"token operator\">=</span> dictionary<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">split</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n radix <span class=\"token operator\">=</span> chars<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">,</span>\n qutient <span class=\"token operator\">=</span> <span class=\"token number\">1000</span> <span class=\"token operator\">*</span> <span class=\"token number\">1000</span> <span class=\"token operator\">*</span> <span class=\"token number\">9999</span> <span class=\"token operator\">+</span> <span class=\"token operator\">+</span>id<span class=\"token punctuation\">,</span>\n arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>qutient<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n mod <span class=\"token operator\">=</span> qutient <span class=\"token operator\">%</span> radix<span class=\"token punctuation\">;</span>\n qutient <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>qutient <span class=\"token operator\">-</span> mod<span class=\"token punctuation\">)</span> <span class=\"token operator\">/</span> radix<span class=\"token punctuation\">;</span>\n arr<span class=\"token punctuation\">.</span><span class=\"token function\">unshift</span><span class=\"token punctuation\">(</span>chars<span class=\"token punctuation\">[</span>mod<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> arr<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token builtin\">console</span><span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">createAscString</span><span class=\"token punctuation\">(</span><span class=\"token number\">100000000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"手动实现-eventBus\"><a href=\"#手动实现-eventBus\" class=\"headerlink\" title=\"手动实现 eventBus\"></a>手动实现 eventBus</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">EventBus</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// key-value : eventName-date</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>callbacks <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 监听事件\n * @param &#123;事件名&#125; eventName\n * @param &#123;回调函数&#125; callback\n */</span>\n <span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">eventName<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">checkType</span><span class=\"token punctuation\">(</span>eventName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>callbacks<span class=\"token punctuation\">[</span>eventName<span class=\"token punctuation\">]</span>\n <span class=\"token operator\">?</span> <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>callbacks<span class=\"token punctuation\">[</span>eventName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n <span class=\"token operator\">:</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">The event has not been declared</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 注册一个事件\n * @param &#123;事件名&#125; eventName\n * @param &#123;传递的对象&#125; data\n */</span>\n <span class=\"token function\">emit</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">eventName<span class=\"token punctuation\">,</span> data</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">checkType</span><span class=\"token punctuation\">(</span>eventName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>callbacks<span class=\"token punctuation\">[</span>eventName<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> data<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 注销事件,不传参数默认注销全部事件\n * @param &#123;事件名&#125; eventName\n */</span>\n <span class=\"token function\">off</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">eventName</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n eventName\n <span class=\"token operator\">?</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">checkType</span><span class=\"token punctuation\">(</span>eventName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">removeEvent</span><span class=\"token punctuation\">(</span>eventName<span class=\"token punctuation\">)</span>\n <span class=\"token operator\">:</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">emptyEvent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 移出事件\n * @param &#123;事件名&#125; eventName\n */</span>\n <span class=\"token function\">removeEvent</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">eventName</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n Reflect<span class=\"token punctuation\">.</span><span class=\"token function\">deleteProperty</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>callbacks<span class=\"token punctuation\">,</span> eventName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 清空全部事件\n */</span>\n <span class=\"token function\">emptyEvent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>callbacks <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 参数类型校验\n * @param &#123;参数&#125; param\n * @param &#123;合法的类型&#125; validType\n */</span>\n <span class=\"token function\">checkType</span><span class=\"token punctuation\">(</span>param<span class=\"token punctuation\">,</span> validType <span class=\"token operator\">=</span> <span class=\"token string\">\"string\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> param <span class=\"token operator\">!==</span> validType<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">(param, </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>param<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">) should be of </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>validType<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\"> type</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 缅怀jQ链式调用</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 错误提示\n * @param &#123;提示文字&#125; text\n */</span>\n <span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">text</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span>text<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>调用</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 省略import</span>\n<span class=\"token keyword\">const</span> eventBus <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">EventBus</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\neventBus<span class=\"token punctuation\">.</span><span class=\"token function\">emit</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"login\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">a</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">d</span><span class=\"token operator\">:</span> <span class=\"token number\">2</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\neventBus<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token number\">123</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">d</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>d<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [&#123;...&#125;]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"判断对象是否有某个-key\"><a href=\"#判断对象是否有某个-key\" class=\"headerlink\" title=\"判断对象是否有某个 key\"></a>判断对象是否有某个 key</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">alias</span><span class=\"token operator\">:</span> <span class=\"token string\">\"es6\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token string\">\"alias\"</span> <span class=\"token keyword\">in</span> obj<span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span>\nReflect<span class=\"token punctuation\">.</span><span class=\"token function\">has</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> <span class=\"token string\">\"alias\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"浏览器\"><a href=\"#浏览器\" class=\"headerlink\" title=\"浏览器\"></a>浏览器</h2><h2 id=\"版本信息\"><a href=\"#版本信息\" class=\"headerlink\" title=\"版本信息\"></a>版本信息</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">window<span class=\"token punctuation\">.</span>navigator<span class=\"token punctuation\">.</span>userAgent<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"兼容事件绑定\"><a href=\"#兼容事件绑定\" class=\"headerlink\" title=\"兼容事件绑定\"></a>兼容事件绑定</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/*\n兼容低版本IEele为需要绑定事件的元素\neventName为事件名保持addEventListener语法去掉onfun为事件响应函数\n*/</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">addEvent</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">ele<span class=\"token punctuation\">,</span> eventName<span class=\"token punctuation\">,</span> fun</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n ele<span class=\"token punctuation\">.</span>addEventListener\n <span class=\"token operator\">?</span> ele<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>eventName<span class=\"token punctuation\">,</span> fun<span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span>\n <span class=\"token operator\">:</span> ele<span class=\"token punctuation\">.</span><span class=\"token function\">attachEvent</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"on\"</span> <span class=\"token operator\">+</span> eventNme<span class=\"token punctuation\">,</span> fun<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"数组对象\"><a href=\"#数组对象\" class=\"headerlink\" title=\"数组对象\"></a>数组对象</h2><h2 id=\"reduce\"><a href=\"#reduce\" class=\"headerlink\" title=\"reduce\"></a>reduce</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> sum <span class=\"token operator\">=</span> arr<span class=\"token punctuation\">.</span><span class=\"token function\">reduce</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">prev<span class=\"token punctuation\">,</span> cur<span class=\"token punctuation\">,</span> index<span class=\"token punctuation\">,</span> arr</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>prev<span class=\"token punctuation\">,</span> cur<span class=\"token punctuation\">,</span> index<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> prev <span class=\"token operator\">+</span> cur<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">//注意这里设置了初始值</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">,</span> sum<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 求和</span>\n<span class=\"token keyword\">const</span> sum <span class=\"token operator\">=</span> arr<span class=\"token punctuation\">.</span><span class=\"token function\">reduce</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">p<span class=\"token punctuation\">,</span>c</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> p<span class=\"token operator\">+</span>c<span class=\"token punctuation\">)</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"对象内部根据-key-对-value-进行排序-取前-3\"><a href=\"#对象内部根据-key-对-value-进行排序-取前-3\" class=\"headerlink\" title=\"对象内部根据 key 对 value 进行排序,取前 3\"></a>对象内部根据 key 对 value 进行排序,取前 3</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> datasource <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">price</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">alias</span><span class=\"token operator\">:</span> <span class=\"token string\">\"watermelon\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">price</span><span class=\"token operator\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">alias</span><span class=\"token operator\">:</span> <span class=\"token string\">\"orange\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">price</span><span class=\"token operator\">:</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">alias</span><span class=\"token operator\">:</span> <span class=\"token string\">\"banana\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">price</span><span class=\"token operator\">:</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">alias</span><span class=\"token operator\">:</span> <span class=\"token string\">\"apple\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 降序排列</span>\n<span class=\"token keyword\">let</span> <span class=\"token function-variable function\">compare</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">key</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">a<span class=\"token punctuation\">,</span> b</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> b<span class=\"token punctuation\">[</span>key<span class=\"token punctuation\">]</span> <span class=\"token operator\">-</span> a<span class=\"token punctuation\">[</span>key<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> sorted <span class=\"token operator\">=</span> datasource\n <span class=\"token punctuation\">.</span><span class=\"token function\">sort</span><span class=\"token punctuation\">(</span><span class=\"token function\">compare</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"price\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">slice</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">i</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> i<span class=\"token punctuation\">[</span><span class=\"token string\">\"alias\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 返回 [\"apple\", \"orange\", \"banana\"]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"随机字符串\"><a href=\"#随机字符串\" class=\"headerlink\" title=\"随机字符串\"></a>随机字符串</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">getRandomRangeNum</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">len <span class=\"token operator\">=</span> <span class=\"token number\">32</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 略去不宜辨识字符</span>\n <span class=\"token keyword\">let</span> dictionary <span class=\"token operator\">=</span> <span class=\"token string\">\"ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> maxPos <span class=\"token operator\">=</span> dictionary<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> res <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> len<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n res <span class=\"token operator\">+=</span> dictionary<span class=\"token punctuation\">.</span><span class=\"token function\">charAt</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">random</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> maxPos<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"类型检测\"><a href=\"#类型检测\" class=\"headerlink\" title=\"类型检测\"></a>类型检测</h2><p>Q使用<code>typeof foo === &quot;object&quot;</code>检测<code>foo</code>是否为对象有什么缺点?如何避免?</p>\n<p>A用 <code>typeof</code> 是否能准确判断一个对象变量,答案是否定的,<code>null</code> 的结果也是 <code>object</code><code>Array</code> 的结果也是 <code>object</code>,有时候我们需要的是 “纯粹” 的 <code>object</code> 对象</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token class-name\">Object</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> <span class=\"token string\">\"[object Object]\"</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"倒计时\"><a href=\"#倒计时\" class=\"headerlink\" title=\"倒计时\"></a>倒计时</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Countdown</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">startNum<span class=\"token punctuation\">,</span> endNum<span class=\"token punctuation\">,</span> interval</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token punctuation\">[</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>startNum<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>endNum<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>interval<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>startNum<span class=\"token punctuation\">,</span> endNum<span class=\"token punctuation\">,</span> interval<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> timer <span class=\"token operator\">=</span> <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>startNum <span class=\"token operator\">>=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>endNum<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>startNum<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>startNum <span class=\"token operator\">-=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">clearTimeout</span><span class=\"token punctuation\">(</span>timer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>interval<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 实例化调用</span>\n<span class=\"token keyword\">var</span> countdown <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Countdown</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"范围随机数\"><a href=\"#范围随机数\" class=\"headerlink\" title=\"范围随机数\"></a>范围随机数</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 能取到 min取不到 max</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">getRandomRangeNum</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">min<span class=\"token punctuation\">,</span> max</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> min <span class=\"token operator\">+</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">random</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span>max <span class=\"token operator\">-</span> min<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"获取当前月的天数\"><a href=\"#获取当前月的天数\" class=\"headerlink\" title=\"获取当前月的天数\"></a>获取当前月的天数</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> getCurMonthDays <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span>\n <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getFullYear</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getMonth</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n <span class=\"token number\">0</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getDate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n\n<h1 id=\"对象小操作\"><a href=\"#对象小操作\" class=\"headerlink\" title=\"对象小操作\"></a>对象小操作</h1><h2 id=\"去虚假值\"><a href=\"#去虚假值\" class=\"headerlink\" title=\"去虚假值\"></a>去虚假值</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr4 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"小明\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"小蓝\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\" \"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">NaN</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr4<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span>Boolean<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// => ['小明', '小蓝', ' ', true]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"头尾插入\"><a href=\"#头尾插入\" class=\"headerlink\" title=\"头尾插入\"></a>头尾插入</h2><p>效率比 <code>unshift()</code> 高</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 头插入</span>\n<span class=\"token punctuation\">[</span><span class=\"token string\">\"haha\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">concat</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 尾插入</span>\narr<span class=\"token punctuation\">.</span><span class=\"token function\">concat</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"haha\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n\n<h2 id=\"删除属性\"><a href=\"#删除属性\" class=\"headerlink\" title=\"删除属性\"></a>删除属性</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">deleteA</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">obj</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">delete</span> obj<span class=\"token punctuation\">.</span><span class=\"token constant\">A</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> obj<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token comment\">// 使用解构赋值</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">deleteA</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">&#123;</span> <span class=\"token constant\">A</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">...</span>rest <span class=\"token punctuation\">&#125;</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> rest<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"生产、加工、消费分离\"><a href=\"#生产、加工、消费分离\" class=\"headerlink\" title=\"生产、加工、消费分离\"></a>生产、加工、消费分离</h1><ul>\n<li>从接口拿数据到视图 fetch api</li>\n<li>加工 computed</li>\n<li>消费 v-for</li>\n</ul>\n<h1 id=\"元数据\"><a href=\"#元数据\" class=\"headerlink\" title=\"元数据\"></a>元数据</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">import</span> <span class=\"token string\">\"reflect-metadata\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// npm install reflect-metadata</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">Role</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> string</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> ClassDecorator <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">target</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n Reflect<span class=\"token punctuation\">.</span><span class=\"token function\">defineMetadata</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"role\"</span><span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> target<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n@<span class=\"token function\">Role</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"admin\"</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Post</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token keyword\">const</span> metadata <span class=\"token operator\">=</span> Reflect<span class=\"token punctuation\">.</span><span class=\"token function\">getMetadata</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"role\"</span><span class=\"token punctuation\">,</span> Post<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nReflect<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>Post<span class=\"token punctuation\">,</span> <span class=\"token string\">\"role2\"</span><span class=\"token punctuation\">,</span> metadata<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>Reflect<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>Post<span class=\"token punctuation\">,</span> <span class=\"token string\">\"role2\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// admin</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"防抖与节流\"><a href=\"#防抖与节流\" class=\"headerlink\" title=\"防抖与节流\"></a>防抖与节流</h1><p>在页面上监听诸如<code>scroll</code>(页面滚动),<code>mousemove</code>(鼠标移动) <code>keydown</code> <code>keyup</code> <code>keypress</code>(按下键盘)等等一系列事件的时候,我们并不希望频繁的触发这类监听,尤其当请求非常消耗资源时,这种操作会导致服务器性能急剧下降。</p>\n<h2 id=\"Debounce\"><a href=\"#Debounce\" class=\"headerlink\" title=\"Debounce\"></a>Debounce</h2><p>把触发非常频繁的事件合并成一次延迟执行,如果对监听函数使用 100ms 的容忍时间,那么时间在第 3.1s 的时候执行</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 默认延时100ms</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">debounce</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">func<span class=\"token punctuation\">,</span> dealy <span class=\"token operator\">=</span> <span class=\"token number\">100</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> timer<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 暂存this和参数</span>\n <span class=\"token keyword\">let</span> _this <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> args <span class=\"token operator\">=</span> arguments<span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 清除定时器确保不执行func</span>\n <span class=\"token function\">clearTimeout</span><span class=\"token punctuation\">(</span>timer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n timer <span class=\"token operator\">=</span> <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">func</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span>_this<span class=\"token punctuation\">,</span> args<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> dealy<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 执行函数</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">handler</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">delay 100ms ,then handle</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// dom添加监听</span>\ndocument\n <span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#someNode\"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"scroll\"</span><span class=\"token punctuation\">,</span> <span class=\"token function\">debounce</span><span class=\"token punctuation\">(</span>handler<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"Throttle\"><a href=\"#Throttle\" class=\"headerlink\" title=\"Throttle\"></a>Throttle</h2><p>固定函数执行的速率,即所谓的“节流”。设置一个阀值,在阀值内,把触发的事件合并成一次执行;当到达阀值,必定执行一次事件。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">throttle</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">func<span class=\"token punctuation\">,</span> delay</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> statTime <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> currentTime <span class=\"token operator\">=</span> <span class=\"token operator\">+</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>currentTime <span class=\"token operator\">-</span> statTime <span class=\"token operator\">></span> delay<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">func</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">,</span> arguments<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n statTime <span class=\"token operator\">=</span> currentTime<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 执行函数</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">resizeHandler</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">resize</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// window添加监听</span>\nwindow<span class=\"token punctuation\">.</span>onresize <span class=\"token operator\">=</span> <span class=\"token function\">throttle</span><span class=\"token punctuation\">(</span>resizeHandler<span class=\"token punctuation\">,</span> <span class=\"token number\">300</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"this-指向\"><a href=\"#this-指向\" class=\"headerlink\" title=\"this 指向\"></a>this 指向</h1><h2 id=\"全局环境\"><a href=\"#全局环境\" class=\"headerlink\" title=\"全局环境\"></a>全局环境</h2><p>全局环境下this 始终指向全局对象window无论是否严格模式</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span> <span class=\"token operator\">===</span> window<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span>\n<span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">37</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 37</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"函数上下文调用\"><a href=\"#函数上下文调用\" class=\"headerlink\" title=\"函数上下文调用\"></a>函数上下文调用</h2><ul>\n<li>非严格模式</li>\n</ul>\n<p>没有被上一级的对象所调用, this 默认指向全局对象 window</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> window<span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<ul>\n<li>严格模式</li>\n</ul>\n<p>this 指向 undefined</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">f2</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token string\">\"use strict\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 这里是严格模式</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token function\">f2</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"箭头函数\"><a href=\"#箭头函数\" class=\"headerlink\" title=\"箭头函数\"></a>箭头函数</h2><blockquote>\n<p>箭头函数中call()、apply()、bind()方法无效</p>\n</blockquote>\n<p>在全局代码中,箭头函数被设置为全局对象,总之箭头函数不改变 this 指向</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> globalObject <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> <span class=\"token function-variable function\">foo</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">foo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> globalObject<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>箭头函数作为对象的方法使用,指向全局 window 对象</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">i</span><span class=\"token operator\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">b</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>i<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">c</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>i<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\nobj<span class=\"token punctuation\">.</span><span class=\"token function\">b</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined window&#123;...&#125;</span>\nobj<span class=\"token punctuation\">.</span><span class=\"token function\">c</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 10 Object &#123;...&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>箭头函数可以让 this 指向固化,这种特性很有利于封装回调函数</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 总是指向 handler 对象。如果不使用箭头函数则指向全局 document 对象</span>\n<span class=\"token keyword\">var</span> handler <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token string\">\"123456\"</span><span class=\"token punctuation\">,</span>\n\n <span class=\"token function-variable function\">init</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n document<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\n <span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">doSomething</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token boolean\">false</span>\n <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n\n <span class=\"token function-variable function\">doSomething</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">type</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Handling \"</span> <span class=\"token operator\">+</span> type <span class=\"token operator\">+</span> <span class=\"token string\">\" for \"</span> <span class=\"token operator\">+</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"call-apply-bind-与-es6\"><a href=\"#call-apply-bind-与-es6\" class=\"headerlink\" title=\"call, apply, bind 与 es6\"></a>call, apply, bind 与 es6</h1><p>js 的函数继承于<code>Function.prototype</code>对象,因此每个函数都会有 apply、call、bind 方法</p>\n<blockquote>\n<p>call 和 apply 的作用,完全一样,唯一的区别就是在参数上面。</p>\n</blockquote>\n<p><code>call, apply, bind</code>改变函数中 <code>this 指向</code> 的三兄弟,把<code>this</code>绑定到第一个参数对象上</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">displayHobbies</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token operator\">...</span>hobbies</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\"> likes </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>hobbies<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\", \"</span><span class=\"token punctuation\">)</span><span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">.</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 下面两个等价</span>\n<span class=\"token function\">displayHobbies</span><span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Bob\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"swimming\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"basketball\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"anime\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Bob likes swimming, basketball, anime.</span>\n<span class=\"token function\">displayHobbies</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Bob\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"swimming\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"basketball\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"anime\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Bob likes swimming, basketball, anime.</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p><code>bind</code>返回的是一个函数,需要手动执行</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> p1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"张三\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">age</span><span class=\"token operator\">:</span> <span class=\"token number\">12</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">func</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">姓名:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">,年龄:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>age<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">var</span> p2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"李四\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">age</span><span class=\"token operator\">:</span> <span class=\"token number\">15</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\np1<span class=\"token punctuation\">.</span><span class=\"token function\">func</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span>p2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//姓名:李四,年龄:15</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"for-循环优化\"><a href=\"#for-循环优化\" class=\"headerlink\" title=\"for 循环优化\"></a>for 循环优化</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 每次都要计算array.length</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> array<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token comment\">// 使用leng缓存array长度</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> length <span class=\"token operator\">=</span> array<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"数组\"><a href=\"#数组\" class=\"headerlink\" title=\"数组\"></a>数组</h1><h2 id=\"扁平化去重升序排列\"><a href=\"#扁平化去重升序排列\" class=\"headerlink\" title=\"扁平化去重升序排列\"></a>扁平化去重升序排列</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">6</span><span class=\"token punctuation\">,</span> <span class=\"token number\">7</span><span class=\"token punctuation\">,</span> <span class=\"token number\">8</span><span class=\"token punctuation\">,</span> <span class=\"token number\">9</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">11</span><span class=\"token punctuation\">,</span> <span class=\"token number\">12</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">12</span><span class=\"token punctuation\">,</span> <span class=\"token number\">13</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">14</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\narr<span class=\"token punctuation\">.</span><span class=\"token function\">flat</span><span class=\"token punctuation\">(</span><span class=\"token number\">Infinity</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]</span>\n\n<span class=\"token keyword\">let</span> result <span class=\"token operator\">=</span> Array<span class=\"token punctuation\">.</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Set</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">.</span><span class=\"token function\">flat</span><span class=\"token punctuation\">(</span><span class=\"token number\">Infinity</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">sort</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">a<span class=\"token punctuation\">,</span> b</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> a <span class=\"token operator\">-</span> b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"前端页面埋点-1x1-gif\"><a href=\"#前端页面埋点-1x1-gif\" class=\"headerlink\" title=\"前端页面埋点 - 1x1.gif\"></a>前端页面埋点 - 1x1.gif</h1><p>通常用在,统计页面点击,曝光,停留时间,签发……等场景</p>\n<ul>\n<li>比 PNG&#x2F;JPG 体积小</li>\n<li>天然跨域</li>\n</ul>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>button</span> <span class=\"token special-attr\"><span class=\"token attr-name\">onClick</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token value javascript language-javascript\"><span class=\"token function\">countClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">\"</span></span></span><span class=\"token punctuation\">></span></span>haorooms<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>button</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span><span class=\"token punctuation\">></span></span><span class=\"token script\"><span class=\"token language-javascript\">\n <span class=\"token keyword\">function</span> <span class=\"token function\">countClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">new</span> <span class=\"token class-name\">Image</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>src <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">./haorooms.gif?</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>key<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">=</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>value<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">&amp;</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">random</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\"> </span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n</span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"事件委托\"><a href=\"#事件委托\" class=\"headerlink\" title=\"事件委托\"></a>事件委托</h1><p>利用冒泡原理,委托父元素执行</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>苹果<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>香蕉<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>凤梨<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"ul\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function-variable function\">onclick</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> target <span class=\"token operator\">=</span> event<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>target<span class=\"token punctuation\">.</span>nodeName <span class=\"token operator\">===</span> <span class=\"token string\">\"LI\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>target<span class=\"token punctuation\">.</span>innerHTML<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"构造函数-原型模式\"><a href=\"#构造函数-原型模式\" class=\"headerlink\" title=\"构造函数 + 原型模式\"></a>构造函数 + 原型模式</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">Person</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name<span class=\"token punctuation\">,</span> age<span class=\"token punctuation\">,</span> job</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> name<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>age <span class=\"token operator\">=</span> age<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>job <span class=\"token operator\">=</span> job<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token class-name\">Person</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">say</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">text</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">say:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>text<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"剩余参数…args\"><a href=\"#剩余参数…args\" class=\"headerlink\" title=\"剩余参数…args\"></a>剩余参数…args</h1><p>剩余参数<code>args</code>数个数组,<code>...</code>解构符</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">fun1</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">param<span class=\"token punctuation\">,</span> <span class=\"token operator\">...</span>args</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">alert</span><span class=\"token punctuation\">(</span>args<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"跨页面通信\"><a href=\"#跨页面通信\" class=\"headerlink\" title=\"跨页面通信\"></a>跨页面通信</h1><ul>\n<li>cookie</li>\n<li>web worker</li>\n<li>localstorage</li>\n</ul>\n<h1 id=\"iframe-跨域通信和不跨域通信\"><a href=\"#iframe-跨域通信和不跨域通信\" class=\"headerlink\" title=\"iframe 跨域通信和不跨域通信\"></a>iframe 跨域通信和不跨域通信</h1><h2 id=\"不跨域\"><a href=\"#不跨域\" class=\"headerlink\" title=\"不跨域\"></a>不跨域</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// fatherSay是父页面全局方法</span>\nwindow<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">.</span><span class=\"token function\">fatherSay</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 父页面Dom</span>\nwindow<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">.</span>document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"元素id\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 副业页面获取frameID为`iframe_ID`的子页面的Dom</span>\nwindow<span class=\"token punctuation\">.</span>frames<span class=\"token punctuation\">[</span><span class=\"token string\">\"iframe_ID\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"元素id\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"跨域-postMessage\"><a href=\"#跨域-postMessage\" class=\"headerlink\" title=\"跨域 postMessage\"></a>跨域 postMessage</h2><p>子页面</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">window<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">.</span><span class=\"token function\">postMessage</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"http://127.0.0.1:8089\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>父页面接受</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"message\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">alert</span><span class=\"token punctuation\">(</span><span class=\"token number\">123</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"对象类型判断\"><a href=\"#对象类型判断\" class=\"headerlink\" title=\"对象类型判断\"></a>对象类型判断</h1><h2 id=\"数组-1\"><a href=\"#数组-1\" class=\"headerlink\" title=\"数组\"></a>数组</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\narr <span class=\"token keyword\">instanceof</span> <span class=\"token class-name\">Array</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span>\nArray<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span>\n<span class=\"token class-name\">Object</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// \"[object Array]\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"js-单线程,如何异步\"><a href=\"#js-单线程,如何异步\" class=\"headerlink\" title=\"js 单线程,如何异步\"></a>js 单线程,如何异步</h1><ul>\n<li><p>主线程 执行 js 中所有的代码。</p>\n</li>\n<li><p>主线程 在执行过程中发现了需要异步的任务任务后扔给浏览器(浏览器创建多个线程执行,顺便创造一个<code>回调队列</code>。</p>\n</li>\n<li><p>主线程 已经执行完毕所有同步代码。监听<code>回调队列</code>一旦 浏览器 中某个线程任务完成将会改变回调函数的状态。主线程查看到某个函数的状态为已完成,就会执行该<code>回调队列</code>中对应的回调函数。</p>\n</li>\n</ul>\n<h1 id=\"移动端最小触控区域\"><a href=\"#移动端最小触控区域\" class=\"headerlink\" title=\"移动端最小触控区域\"></a>移动端最小触控区域</h1><p>苹果推荐是 44pt x 44pt 「具体看 WWDC 14」,通过<code>padding</code>、<code>margin</code>、<code>height</code>等方式进行点击区域扩展</p>\n<h1 id=\"js-精度问题\"><a href=\"#js-精度问题\" class=\"headerlink\" title=\"js 精度问题\"></a>js 精度问题</h1><p>常用类库:<code>Math.js</code>、<code>Big.js</code>、<code>decimal.js</code></p>\n<h1 id=\"冻结-Object-freeze\"><a href=\"#冻结-Object-freeze\" class=\"headerlink\" title=\"冻结 Object. freeze()\"></a>冻结 Object. freeze()</h1><p><code>const</code>生命的简单变量不可修改,但是复杂对象可以被修改,<code>Object. freeze()</code>:可以冻结对象</p>\n<ul>\n<li>不能添加新属性</li>\n<li>不能删除已有属性</li>\n<li>不能修改已有属性的可枚举性、可配置性、可写性</li>\n<li>不能修改已有属性的值</li>\n<li>不能修改原型</li>\n</ul>\n<p>浅冻结</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> obj1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">internal</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\nObject<span class=\"token punctuation\">.</span><span class=\"token function\">freeze</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nobj1<span class=\"token punctuation\">.</span>internal<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token string\">\"aValue\"</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">.</span>internal<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// aValue</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>递归冻结</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">deepFreeze</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">obj</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 获取定义在obj上的属性名</span>\n <span class=\"token keyword\">var</span> propNames <span class=\"token operator\">=</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">getOwnPropertyNames</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 在冻结自身之前冻结属性</span>\n propNames<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> prop <span class=\"token operator\">=</span> obj<span class=\"token punctuation\">[</span>name<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 如果prop是个对象冻结它</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> prop <span class=\"token operator\">==</span> <span class=\"token string\">\"object\"</span> <span class=\"token operator\">&amp;&amp;</span> prop <span class=\"token operator\">!==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token function\">deepFreeze</span><span class=\"token punctuation\">(</span>prop<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">freeze</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"Reflect\"><a href=\"#Reflect\" class=\"headerlink\" title=\"Reflect\"></a>Reflect</h1><h2 id=\"Reflect-get-target-propertyKey-value-receiver\"><a href=\"#Reflect-get-target-propertyKey-value-receiver\" class=\"headerlink\" title=\"Reflect.get(target, propertyKey, value[receiver])\"></a>Reflect.get(target, propertyKey, value[receiver])</h2><p>获取对象身上某个属性的值,类似于 target[name]。</p>\n<h2 id=\"Reflect-set-target-propertyKey-value-receiver\"><a href=\"#Reflect-set-target-propertyKey-value-receiver\" class=\"headerlink\" title=\"Reflect.set(target, propertyKey, value[receiver])\"></a>Reflect.set(target, propertyKey, value[receiver])</h2><p>将值分配给属性的函数。返回一个 Boolean如果更新成功则返回 true。</p>\n<h2 id=\"Reflect-has-target-propertyKey\"><a href=\"#Reflect-has-target-propertyKey\" class=\"headerlink\" title=\"Reflect.has(target, propertyKey)\"></a>Reflect.has(target, propertyKey)</h2><p>判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。</p>\n<h1 id=\"if-else-优化\"><a href=\"#if-else-优化\" class=\"headerlink\" title=\"if else 优化\"></a>if else 优化</h1><h2 id=\"表驱动编程\"><a href=\"#表驱动编程\" class=\"headerlink\" title=\"表驱动编程\"></a>表驱动编程</h2><p>空间换时间,设置<code>obj=&#123;key:value&#125;</code>,通过<code>obj[key]</code>取值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">calculateGrade</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">score</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> table <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token number\">100</span><span class=\"token operator\">:</span> <span class=\"token string\">'A'</span><span class=\"token punctuation\">,</span>\n <span class=\"token number\">90</span><span class=\"token operator\">:</span> <span class=\"token string\">'A'</span><span class=\"token punctuation\">,</span>\n <span class=\"token number\">80</span><span class=\"token operator\">:</span> <span class=\"token string\">'B'</span><span class=\"token punctuation\">,</span>\n <span class=\"token number\">70</span><span class=\"token operator\">:</span> <span class=\"token string\">'C'</span><span class=\"token punctuation\">,</span>\n <span class=\"token number\">60</span><span class=\"token operator\">:</span> <span class=\"token string\">'D'</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">others</span><span class=\"token operator\">:</span> <span class=\"token string\">'E'</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> table<span class=\"token punctuation\">[</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>score<span class=\"token operator\">/</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token operator\">*</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> table<span class=\"token punctuation\">[</span><span class=\"token string\">'others'</span><span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"短路运算\"><a href=\"#短路运算\" class=\"headerlink\" title=\"短路运算\"></a>短路运算</h2><p>react 没有<code>v-if</code>,运用比较频繁</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 函数组件</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Home</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>home<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#123;</span>\n <span class=\"token boolean\">true</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">&lt;</span>Home <span class=\"token operator\">/</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"使用有意义且易读的变量名\"><a href=\"#使用有意义且易读的变量名\" class=\"headerlink\" title=\"使用有意义且易读的变量名\"></a>使用有意义且易读的变量名</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎 <span class=\"token keyword\">const</span> yyyymmdstr <span class=\"token operator\">=</span> <span class=\"token function\">moment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"YYYY/MM/DD\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n👍 <span class=\"token keyword\">const</span> currentDate <span class=\"token operator\">=</span> <span class=\"token function\">moment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"YYYY/MM/DD\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"使用有意义的变量代替数组下标\"><a href=\"#使用有意义的变量代替数组下标\" class=\"headerlink\" title=\"使用有意义的变量代替数组下标\"></a>使用有意义的变量代替数组下标</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">const</span> address <span class=\"token operator\">=</span> <span class=\"token string\">\"One Infinite Loop, Cupertino 95014\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> cityZipCodeRegex <span class=\"token operator\">=</span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^[^,\\\\]+[,\\\\\\s]+(.+?)\\s*(\\d&#123;5&#125;)?$</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">saveCityZipCode</span><span class=\"token punctuation\">(</span>\n address<span class=\"token punctuation\">.</span><span class=\"token function\">match</span><span class=\"token punctuation\">(</span>cityZipCodeRegex<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n address<span class=\"token punctuation\">.</span><span class=\"token function\">match</span><span class=\"token punctuation\">(</span>cityZipCodeRegex<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n👍\n<span class=\"token keyword\">const</span> address <span class=\"token operator\">=</span> <span class=\"token string\">\"One Infinite Loop, Cupertino 95014\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> cityZipCodeRegex <span class=\"token operator\">=</span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^[^,\\\\]+[,\\\\\\s]+(.+?)\\s*(\\d&#123;5&#125;)?$</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>_<span class=\"token punctuation\">,</span> city<span class=\"token punctuation\">,</span> zipCode<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> address<span class=\"token punctuation\">.</span><span class=\"token function\">match</span><span class=\"token punctuation\">(</span>cityZipCodeRegex<span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">saveCityZipCode</span><span class=\"token punctuation\">(</span>city<span class=\"token punctuation\">,</span> zipCode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"变量名要简洁\"><a href=\"#变量名要简洁\" class=\"headerlink\" title=\"变量名要简洁\"></a>变量名要简洁</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">const</span> Car <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">carMake</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Honda\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">carModel</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Accord\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">carColor</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Blue\"</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">paintCar</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">car<span class=\"token punctuation\">,</span> color</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n car<span class=\"token punctuation\">.</span>carColor <span class=\"token operator\">=</span> color<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">const</span> Car <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">make</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Honda\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">model</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Accord\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">color</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Blue\"</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">paintCar</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">car<span class=\"token punctuation\">,</span> color</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n car<span class=\"token punctuation\">.</span>color <span class=\"token operator\">=</span> color<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"消除魔术字符串\"><a href=\"#消除魔术字符串\" class=\"headerlink\" title=\"消除魔术字符串\"></a>消除魔术字符串</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎 <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span>blastOff<span class=\"token punctuation\">,</span> <span class=\"token number\">86400000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n👍 <span class=\"token keyword\">const</span> <span class=\"token constant\">MILLISECONDS_PER_DAY</span> <span class=\"token operator\">=</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">24</span> <span class=\"token operator\">*</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//86400000;</span>\n<span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span>blastOff<span class=\"token punctuation\">,</span> <span class=\"token constant\">MILLISECONDS_PER_DAY</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"使用默认参数替代短路运算符\"><a href=\"#使用默认参数替代短路运算符\" class=\"headerlink\" title=\"使用默认参数替代短路运算符\"></a>使用默认参数替代短路运算符</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">function</span> <span class=\"token function\">createMicrobrewery</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> breweryName <span class=\"token operator\">=</span> name <span class=\"token operator\">||</span> <span class=\"token string\">\"Hipster Brew Co.\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">function</span> <span class=\"token function\">createMicrobrewery</span><span class=\"token punctuation\">(</span>name <span class=\"token operator\">=</span> <span class=\"token string\">\"Hipster Brew Co.\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"一个函数\"><a href=\"#一个函数\" class=\"headerlink\" title=\"一个函数\"></a>一个函数</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">function</span> <span class=\"token function\">emailClients</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">clients</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n clients<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">client</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> clientRecord <span class=\"token operator\">=</span> database<span class=\"token punctuation\">.</span><span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>client<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>clientRecord<span class=\"token punctuation\">.</span><span class=\"token function\">isActive</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">email</span><span class=\"token punctuation\">(</span>client<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">function</span> <span class=\"token function\">emailActiveClients</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">clients</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n clients<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span>isActiveClient<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span>email<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">isActiveClient</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">client</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> clientRecord <span class=\"token operator\">=</span> database<span class=\"token punctuation\">.</span><span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>client<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> clientRecord<span class=\"token punctuation\">.</span><span class=\"token function\">isActive</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">-</span>分割线<span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">-</span>\n\n👎\n<span class=\"token keyword\">function</span> <span class=\"token function\">createFile</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name<span class=\"token punctuation\">,</span> temp</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>temp<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n fs<span class=\"token punctuation\">.</span><span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">./temp/</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>name<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span>\n fs<span class=\"token punctuation\">.</span><span class=\"token function\">create</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">function</span> <span class=\"token function\">createFile</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n fs<span class=\"token punctuation\">.</span><span class=\"token function\">create</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">createTempFile</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">createFile</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">./temp/</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>name<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"函数参数不多于-2-个,如果有很多参数就利用-object-传递,并使用解构\"><a href=\"#函数参数不多于-2-个,如果有很多参数就利用-object-传递,并使用解构\" class=\"headerlink\" title=\"函数参数不多于 2 个,如果有很多参数就利用 object 传递,并使用解构\"></a>函数参数不多于 2 个,如果有很多参数就利用 object 传递,并使用解构</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">function</span> <span class=\"token function\">createMenu</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">title<span class=\"token punctuation\">,</span> body<span class=\"token punctuation\">,</span> buttonText<span class=\"token punctuation\">,</span> cancellable</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token function\">createMenu</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Foo\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Bar\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Baz\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n👍\n<span class=\"token keyword\">function</span> <span class=\"token function\">createMenu</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">&#123;</span> title<span class=\"token punctuation\">,</span> body<span class=\"token punctuation\">,</span> buttonText<span class=\"token punctuation\">,</span> cancellable <span class=\"token punctuation\">&#125;</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token function\">createMenu</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">title</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Foo\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Bar\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">buttonText</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Baz\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">cancellable</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"函数名应该直接反映函数的作用\"><a href=\"#函数名应该直接反映函数的作用\" class=\"headerlink\" title=\"函数名应该直接反映函数的作用\"></a>函数名应该直接反映函数的作用</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">function</span> <span class=\"token function\">addToDate</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">date<span class=\"token punctuation\">,</span> month</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token keyword\">const</span> date <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// It's hard to tell from the function name what is added</span>\n<span class=\"token function\">addToDate</span><span class=\"token punctuation\">(</span>date<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n👍\n<span class=\"token keyword\">function</span> <span class=\"token function\">addMonthToDate</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">month<span class=\"token punctuation\">,</span> date</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token keyword\">const</span> date <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">addMonthToDate</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> date<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"尽量使用纯函数\"><a href=\"#尽量使用纯函数\" class=\"headerlink\" title=\"尽量使用纯函数\"></a>尽量使用纯函数</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">const</span> programmerOutput <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Uncle Bobby\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">500</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Suzie Q\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">1500</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Jimmy Gosling\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">150</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Gracie Hopper\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">1000</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> totalOutput <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> programmerOutput<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n totalOutput <span class=\"token operator\">+=</span> programmerOutput<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>linesOfCode<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">const</span> programmerOutput <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Uncle Bobby\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">500</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Suzie Q\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">1500</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Jimmy Gosling\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">150</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Gracie Hopper\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">1000</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> totalOutput <span class=\"token operator\">=</span> programmerOutput<span class=\"token punctuation\">.</span><span class=\"token function\">reduce</span><span class=\"token punctuation\">(</span>\n <span class=\"token punctuation\">(</span><span class=\"token parameter\">totalLines<span class=\"token punctuation\">,</span> output</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> totalLines <span class=\"token operator\">+</span> output<span class=\"token punctuation\">.</span>linesOfCode<span class=\"token punctuation\">,</span>\n <span class=\"token number\">0</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"不要过度优化\"><a href=\"#不要过度优化\" class=\"headerlink\" title=\"不要过度优化\"></a>不要过度优化</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token comment\">// 现代浏览器对于迭代器做了内部优化</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> len <span class=\"token operator\">=</span> list<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> len<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> list<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n\n<h1 id=\"关于模块化\"><a href=\"#关于模块化\" class=\"headerlink\" title=\"关于模块化\"></a>关于模块化</h1><h2 id=\"无模块化\"><a href=\"#无模块化\" class=\"headerlink\" title=\"无模块化\"></a>无模块化</h2><blockquote>\n<p>污染全局作用域、维护成本高、依赖关系不明显</p>\n</blockquote>\n<p>script 标签引入 js 文件,相互罗列,但是被依赖的放在前面,否则使用就会报错。如下:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token operator\">&lt;</span>script src<span class=\"token operator\">=</span><span class=\"token string\">\"jquery.js\"</span><span class=\"token operator\">></span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span>script src<span class=\"token operator\">=</span><span class=\"token string\">\"main.js\"</span><span class=\"token operator\">></span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span>script src<span class=\"token operator\">=</span><span class=\"token string\">\"other1.js\"</span><span class=\"token operator\">></span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span>script src<span class=\"token operator\">=</span><span class=\"token string\">\"other2.js\"</span><span class=\"token operator\">></span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span>script src<span class=\"token operator\">=</span><span class=\"token string\">\"other3.js\"</span><span class=\"token operator\">></span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"CommonJS-规范-同步\"><a href=\"#CommonJS-规范-同步\" class=\"headerlink\" title=\"CommonJS 规范(同步)\"></a>CommonJS 规范(同步)</h2><p>该规范最初是用在服务器端的 node 的它有四个重要的环境变量为模块化的实现提供支持module、exports、require、global。实际使用时用 module.exports 定义当前模块对外输出的接口(不推荐直接用 exports用 require 加载模块(同步)</p>\n<blockquote>\n<p>module.exports 本身就是一个对象</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">module<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">foo</span><span class=\"token operator\">:</span> <span class=\"token string\">\"bar\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//true</span>\nmodule<span class=\"token punctuation\">.</span>exports<span class=\"token punctuation\">.</span>foo <span class=\"token operator\">=</span> <span class=\"token string\">\"bar\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//true。</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<p>CommonJS 用同步的方式加载模块。在服务端模块文件都存在本地磁盘读取非常快所以这样做不会有问题。但是在浏览器端限于网络原因CommonJS 不适合浏览器端模块加载,更合理的方案是使用异步加载,比如下边 AMD 规范。</p>\n<h2 id=\"AMD-规范-RequireJS\"><a href=\"#AMD-规范-RequireJS\" class=\"headerlink\" title=\"AMD 规范(RequireJS)\"></a>AMD 规范(RequireJS)</h2><p>承接上文AMD 规范则是非同步加载模块允许指定回调函数AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。</p>\n<ul>\n<li><code>require([module], callback)</code>:加载模块</li>\n<li><code>define(id, [depends], callback)</code>:定义模块</li>\n<li><code>require.config()</code>:配置路径、依赖关系</li>\n</ul>\n<h2 id=\"CMD-规范-SeaJS\"><a href=\"#CMD-规范-SeaJS\" class=\"headerlink\" title=\"CMD 规范(SeaJS)\"></a>CMD 规范(SeaJS)</h2><p>CMD 是 在推广过程中对模块定义的规范化产出</p>\n<h2 id=\"ES6-import-x2F-export\"><a href=\"#ES6-import-x2F-export\" class=\"headerlink\" title=\"ES6 import&#x2F;export\"></a>ES6 import&#x2F;export</h2><p>通过 babel 将不被支持的 import 编译为当前受到广泛支持的 AMD 规范</p>\n<h1 id=\"AMD模块化实现\"><a href=\"#AMD模块化实现\" class=\"headerlink\" title=\"AMD模块化实现\"></a>AMD模块化实现</h1><h2 id=\"define-函数\"><a href=\"#define-函数\" class=\"headerlink\" title=\"define 函数\"></a>define 函数</h2><p>用来声明模块名<code>module</code>,依赖数组<code>deps</code>,以及模块的作用<code>callback</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> stack <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//模块存储栈,存的是模块执行后的结果</span>\n\n <span class=\"token keyword\">function</span> <span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">module<span class=\"token punctuation\">,</span> deps<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n stack<span class=\"token punctuation\">[</span>module<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">callback</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> deps<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 压栈</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>stack<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 查看栈存储的模块</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">define</span><span class=\"token operator\">:</span> define <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>调用<code>define</code>试试,发现 <code>calc</code>模块被压入了<code>stack 模块栈中</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">module<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"calc\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">first</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">arr</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> arr<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// &#123;calc: &#123; first: ƒ &#125;&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"deps-依赖-导入\"><a href=\"#deps-依赖-导入\" class=\"headerlink\" title=\"deps 依赖(导入)\"></a>deps 依赖(导入)</h2><p>对上面的 <code>define</code>函数稍加改造,这一步过程的本质,就是对 deps</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">window</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> stack <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//模块存储栈,</span>\n\n <span class=\"token keyword\">function</span> <span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">module<span class=\"token punctuation\">,</span> deps<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 把 define 函数依赖数组中的模块从 stack 模块中拿出</span>\n deps<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">mod<span class=\"token punctuation\">,</span> index</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n deps<span class=\"token punctuation\">[</span>index<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> stack<span class=\"token punctuation\">[</span>mod<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 赋值给当前模块的 deps</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n stack<span class=\"token punctuation\">[</span>module<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">callback</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> deps<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>stack<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 查看栈存储的模块</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">define</span><span class=\"token operator\">:</span> define <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"calc\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">first</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">arr</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> arr<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"number\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"calc\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">calc</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">res</span><span class=\"token operator\">:</span> calc<span class=\"token punctuation\">.</span><span class=\"token function\">first</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">//4</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 此时 stack 打印的结果为</span>\n<span class=\"token comment\">//> calc: &#123;first: ƒ&#125;</span>\n<span class=\"token comment\">//> number: &#123;res: 4&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>从本质上看define 函数的第二个参数 deps 数组,相当于 import 导入,并且如果第三个参数 callback 采用 <code>return &#123; &#125;</code>,也就相当于 export 导出</p>\n</blockquote>\n<h2 id=\"老生常谈的指针\"><a href=\"#老生常谈的指针\" class=\"headerlink\" title=\"老生常谈的指针\"></a>老生常谈的指针</h2><p>说到底,<code>stack</code>中 <code>a模块</code> export 是一个指针,<code>&#123;a:value&#125;</code>(内存地址),所以,<code>b 模块</code>会改变<code>a.a</code>的值,这点和 <code>cmd</code>不同</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">module<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">a</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nmodule<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"b\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"a\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">a</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n a<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nmodule<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"c\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"a\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">a</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 2</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n\n<h1 id=\"缘起-Object-defineProperty\"><a href=\"#缘起-Object-defineProperty\" class=\"headerlink\" title=\"缘起 Object.defineProperty()\"></a>缘起 Object.defineProperty()</h1><p>给<code>目标对象</code>上定义一个新属性,或者修改<code>目标对象</code>属性,并且返回新对象</p>\n<h1 id=\"上帝的钥匙-get-amp-set\"><a href=\"#上帝的钥匙-get-amp-set\" class=\"headerlink\" title=\"上帝的钥匙 get &amp; set\"></a>上帝的钥匙 get &amp; set</h1><p>属性的<code>getter</code>函数,如果没有 <code>getter</code>则尾 <code>undefined</code>。当访问该属性时,会调用此函数.</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\nObject<span class=\"token punctuation\">.</span><span class=\"token function\">defineProperty</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> <span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token number\">7</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token function\">set</span><span class=\"token punctuation\">(</span>val<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">FAILED改变 a 属性,新值为:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>val<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">,但是被重写 set 劫持了</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nobj<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>上帝的钥匙被找到了</p>\n</blockquote>\n<p>劫持!劫持!还是 TMD 劫持!</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> tempValue <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n\nObject<span class=\"token punctuation\">.</span><span class=\"token function\">defineProperty</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> <span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> tempValue<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token function\">set</span><span class=\"token punctuation\">(</span>newValue<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n tempValue <span class=\"token operator\">=</span> newValue<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 0</span>\nobj<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 4</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"封装-defineReactive-obj-prop-val\"><a href=\"#封装-defineReactive-obj-prop-val\" class=\"headerlink\" title=\"封装 defineReactive(obj, prop, val)\"></a>封装 defineReactive(obj, prop, val)</h1><blockquote>\n<p>这里 defineReactive 第三个参数 val 替代了上一步中全局变量<code>tempValue</code>,对于 get()、set()来说,访问到了其他函数内部的变量,所以形成了闭包</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">defineReactive</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">obj<span class=\"token punctuation\">,</span> prop<span class=\"token punctuation\">,</span> val</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n Object<span class=\"token punctuation\">.</span><span class=\"token function\">defineProperty</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> prop<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">劫持,你访问了</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>prop<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">属性</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> val<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token function\">set</span><span class=\"token punctuation\">(</span>newValue<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>val <span class=\"token operator\">===</span> newValue<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">劫持,你改变了</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>prop<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">属性</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n val <span class=\"token operator\">=</span> newValue<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">defineReactive</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> <span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 劫持你访问了a属性 4</span>\nobj<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">7</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 劫持你改变了a属性</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 劫持你访问了a属性 7</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"递归侦测\"><a href=\"#递归侦测\" class=\"headerlink\" title=\"递归侦测\"></a>递归侦测</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">a</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">b</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">c</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">defineReactive</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> <span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>如何自动让<code>obj</code>对象的全部属性都<code>reactive</code>呢?</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">a</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">b</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">c</span><span class=\"token operator\">:</span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">d</span><span class=\"token operator\">:</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>定义个方法<code>observe</code>,递归 <code>obj</code> 的每一层的每个 <code>prop</code>,检测是否有<code>__ob__</code>,如果没有,<code>defineReactive</code>,并且挂一个<code>Observer</code>实例在这个<code>props</code>上,例如:</p>\n<p><code>Observer对象</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Observer</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">def</span><span class=\"token punctuation\">(</span>value<span class=\"token punctuation\">,</span> <span class=\"token string\">\"__ob__\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 不可枚举不能给__ob__添加__ob__</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">walk</span><span class=\"token punctuation\">(</span>value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token comment\">// 遍历每一个 prop的 value</span>\n <span class=\"token function\">walk</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> prop <span class=\"token keyword\">in</span> value<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">defineReactive</span><span class=\"token punctuation\">(</span>value<span class=\"token punctuation\">,</span> prop<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p><code>defineReactive.js</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">function</span> <span class=\"token function\">defineReactive</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">obj<span class=\"token punctuation\">,</span> prop<span class=\"token punctuation\">,</span> val</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>arguments<span class=\"token punctuation\">.</span>length <span class=\"token operator\">===</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span> val <span class=\"token operator\">=</span> obj<span class=\"token punctuation\">[</span>prop<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 如果2个参数</span>\n <span class=\"token keyword\">let</span> childNode <span class=\"token operator\">=</span> <span class=\"token function\">observe</span><span class=\"token punctuation\">(</span>val<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n Object<span class=\"token punctuation\">.</span><span class=\"token function\">defineProperty</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> prop<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">enumerable</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">configurable</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">你访问了</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>prop<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">属性</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> val<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token function\">set</span><span class=\"token punctuation\">(</span>newValue<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>val <span class=\"token operator\">===</span> newValue<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">你改变了</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>prop<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">属性</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n val <span class=\"token operator\">=</span> newValue<span class=\"token punctuation\">;</span>\n childNode <span class=\"token operator\">=</span> <span class=\"token function\">observe</span><span class=\"token punctuation\">(</span>newValue<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p><code>observe.js</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n * 检测 obj 身上有没有 __ob__(Observer 实例)\n * @param &#123;*&#125; value\n * @returns\n */</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">function</span> <span class=\"token function\">observe</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> value <span class=\"token operator\">!=</span> <span class=\"token string\">\"object\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> ob<span class=\"token punctuation\">;</span>\n <span class=\"token comment\">//! 用__ob__是为了属性不重名被覆盖</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> value<span class=\"token punctuation\">.</span>__ob__ <span class=\"token operator\">!=</span> <span class=\"token string\">\"undefined\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n ob <span class=\"token operator\">=</span> value<span class=\"token punctuation\">.</span>__ob__<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span>\n ob <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Observer</span><span class=\"token punctuation\">(</span>value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> ob<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n","site":{"data":{}},"excerpt":"","more":"<h1 id=\"模板引擎\"><a href=\"#模板引擎\" class=\"headerlink\" title=\"模板引擎\"></a>模板引擎</h1><p>严格的模板引擎的定义,输入模板字符串 + 数据,得到渲染过的字符串。实现上,从正则替换到拼 function 字符串到正经的 AST 解析各种各样,但从定义上来说都是差不多的。字符串渲染的性能其实也就在后端比较有意义,毕竟每一次渲染都是在消耗服务器资源,但在前端,用户只有一个,几十毫秒的渲染时间跟请求延迟比起来根本不算瓶颈。倒是前端的后续更新是字符串模板引擎的软肋,因为用渲染出来的字符串整个替换 innerHTML 是一个效率很低的更新方式。所以这样的模板引擎如今在纯前端情境下已经不再是好的选择,意义更多是在于方便前后端共用模板。</p>\n<h1 id=\"古老数据渲染-vm-的方式\"><a href=\"#古老数据渲染-vm-的方式\" class=\"headerlink\" title=\"古老数据渲染 vm 的方式\"></a>古老数据渲染 vm 的方式</h1><p>这种写法,弊端太多了,玩具车</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token doctype\"><span class=\"token punctuation\">&lt;!</span><span class=\"token doctype-tag\">DOCTYPE</span> <span class=\"token name\">html</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span> <span class=\"token attr-name\">lang</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>en<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>head</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">charset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>UTF-8<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">http-equiv</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>X-UA-Compatible<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>IE=edge<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>viewport<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>width=device-width, initial-scale=1.0<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>title</span><span class=\"token punctuation\">></span></span>Document<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>title</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>head</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>body</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>app<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>body</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span><span class=\"token punctuation\">></span></span><span class=\"token script\"><span class=\"token language-javascript\">\n <span class=\"token keyword\">var</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"小明\"</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">age</span><span class=\"token operator\">:</span> <span class=\"token number\">11</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">sex</span><span class=\"token operator\">:</span> <span class=\"token string\">\"男\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"小红\"</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">age</span><span class=\"token operator\">:</span> <span class=\"token number\">22</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">sex</span><span class=\"token operator\">:</span> <span class=\"token string\">\"女\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">var</span> listDOM <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"app\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n arr<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">item</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> _li <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createElement</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"li\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n _li<span class=\"token punctuation\">.</span>innerText <span class=\"token operator\">=</span> item<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">;</span>\n listDOM<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>_li<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n </span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>html</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"mustache-原理\"><a href=\"#mustache-原理\" class=\"headerlink\" title=\"mustache 原理\"></a>mustache 原理</h1><ul>\n<li>1、先把模板字符串编译成 tokens(代号)</li>\n<li>2、根据 tokens结合数据渲染成 dom</li>\n</ul>\n<blockquote>\n<p>本质上tokens 是一个 js 嵌套数组没事模板字符串 js 的表示,他是<code>抽象语法树</code><code>虚拟节点</code>的开山鼻祖</p>\n</blockquote>\n<p>假设有这么一个模板字符串</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span><span class=\"token punctuation\">></span></span>我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>会编译成 tokens如下</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 这里面每一个数组行都是一个 token组起来就是 tokens</span>\n<span class=\"token comment\">// html 标签也会被看成纯文本</span>\n<span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;h1>我买了一个\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"thing\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"好\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"mood\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"啊&lt;/h1>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>当模板存在循环式,带层级嵌套,如下:</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;#arr&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>&#123;&#123;.&#125;&#125;<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;/arr&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>会被编译成</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;div>&lt;ul>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span>\n <span class=\"token string\">\"#\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"arr\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"li\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\".\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;/li>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;/ul>&lt;/div>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>如果是双重循环,带层级嵌套继续加一层,例如:</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ol</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;#students&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>\n 学生&#123;&#123;item.name&#125;&#125;的爱好是\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ol</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;#item.hobbies&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>&#123;&#123;.&#125;&#125;<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;/#item.hobbies&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ol</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n &#123;&#123;/#students&#125;&#125;\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ol</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>会被编译成</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;div>&lt;ol>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span>\n <span class=\"token string\">\"#\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"students\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;li>学生\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"的爱好是&lt;ol>\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"#\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"hobbies\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">'text'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'&lt;li>'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">'name'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'.'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">'text'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'&lt;/li>'</span><span class=\"token punctuation\">]</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">'text'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'&lt;ol>&lt;/li>'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">[</span><span class=\"token string\">'text'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'&lt;/ol>&lt;/div>'</span><span class=\"token punctuation\">]</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>在<code>mustache.js</code>中完成上述这一过程的函数<code>parseTemplate</code>,可以去找源代码看</p>\n</blockquote>\n<h2 id=\"tokens-生成算法\"><a href=\"#tokens-生成算法\" class=\"headerlink\" title=\"tokens 生成算法\"></a>tokens 生成算法</h2><p>用简单的模板字符串举例:</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\">我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊<span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>有一个指针往右遍历,从<code>我</code>开始,遍历到<code>啊</code>结束,如下:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * Step1指针位置 = 1\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * Step2指针位置 = 2\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * Step3指针位置 = 4\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * Step4指针位置 = 11\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * Step5指针位置 = 15\n *\n * 我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊\n * ↑\n *\n * ... while(指针位置 >= 模板字符串.length)\n *\n * /</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<ul>\n<li>Step1:</li>\n</ul>\n<p>指针右移 1 个长度,以指针位置切割,字符串被分成<code>我</code>+<code>买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊</code></p>\n<ul>\n<li>Step2:</li>\n</ul>\n<p>指针右移 1 个长度,以指针位置切割,字符串被分成<code>我买</code>+<code>了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊</code></p>\n<ul>\n<li>Step3:</li>\n</ul>\n<p>第一次遇到,通过 <code>indexOf(&quot;&#123;&#123;\") == 0` 判断\n\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 标记为 text 放到 tokens 中</span>\ntoken<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"我买了一个\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// tokens: [['text', '我买了一个']]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n结束此时指针位置 = 4\n\n- Step4:\n\n指针右移 2 个长度,跳过`&#123;&#123;`,暂存此时`pos_last = 6`\n\n此时右边字符串(尾字符串)`thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊</code></p>\n<p>右移 5 个长度,识别<code>模板内部数据对象</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">substring</span><span class=\"token punctuation\">(</span>post_last<span class=\"token punctuation\">,</span> <span class=\"token number\">6</span> <span class=\"token operator\">+</span> <span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// thing 5个长度</span>\n<span class=\"token comment\">// 标记为 name 放到 tokens 中</span>\ntoken<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"thing\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// tokens: [['text', '我买了一个']], ['name', 'thing']]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>结束,此时指针位置 &#x3D; 11</p>\n<ul>\n<li>Step5:</li>\n</ul>\n<blockquote>\n<p>遇到 <code>&#125;&#125;</code>,通过 <code>indexOf(&quot;&#125;&#125;&quot;) == 0</code>判断</p>\n</blockquote>\n<p>指针右移 2 个长度,跳过<code>&#125;&#125;</code>,暂存此时<code>post_last = 13</code>,继续右移 2 个长度</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">substring</span><span class=\"token punctuation\">(</span>post_last<span class=\"token punctuation\">,</span> <span class=\"token number\">13</span> <span class=\"token operator\">+</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// ,好 2个长度</span>\n<span class=\"token comment\">// 标记为 text 放到 tokens 中</span>\ntoken<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\",好\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// tokens: [['text', '我买了一个']], ['name', 'thing'],['text', ',好' ]]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>第二次,遇到 <code>&#123;&#123;`\n\n剩下循环执行就行了这个过程我们可以称作`扫描 Scan`\n\n## 扫描器 Scanner\n\n新建一个 `Scanner.js`,用来扫描模板字符串,实现上面的原理\n\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n * 模板字符串扫描器\n */</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Scanner</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">templ</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>templ <span class=\"token operator\">=</span> templ<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 模板字符串</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>tail <span class=\"token operator\">=</span> templ<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 尾字符串</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 指针位置</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 指针跳过模板标签\n * @param &#123;模板语法包围标签&#125; tag\n */</span>\n <span class=\"token function\">jumpTag</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">tag</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>tail<span class=\"token punctuation\">.</span><span class=\"token function\">indexOf</span><span class=\"token punctuation\">(</span>tag<span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos <span class=\"token operator\">+=</span> tag<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 指针右移 tag.length 个长度</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>tail <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>templ<span class=\"token punctuation\">.</span><span class=\"token function\">substring</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 尾字符串更新</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 指针遇见模板标签 &#123;&#123;\n * @param &#123;模板语法包围标签&#125; tag\n */</span>\n <span class=\"token function\">missTag</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">tag</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> pPos_last <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">eof</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>tail<span class=\"token punctuation\">.</span><span class=\"token function\">indexOf</span><span class=\"token punctuation\">(</span>tag<span class=\"token punctuation\">)</span> <span class=\"token operator\">!==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>tail <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>templ<span class=\"token punctuation\">.</span><span class=\"token function\">substring</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>templ<span class=\"token punctuation\">.</span><span class=\"token function\">substring</span><span class=\"token punctuation\">(</span>pPos_last<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token function\">eof</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>pPos <span class=\"token operator\">>=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>templ<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n## 分析器 Parser\n\n调用`Scanner.js`\n\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> tmpl <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">我买了一个&#123;&#123;thing&#125;&#125;,好&#123;&#123;mood&#125;&#125;啊</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 编译 模板字符串 => tokens</span>\n<span class=\"token keyword\">const</span> Parser <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">createTokens</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">tmpl</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> scanner <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Scanner</span><span class=\"token punctuation\">(</span>tmpl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> tokens <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// scanner 循环执行</span>\n <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>scanner<span class=\"token punctuation\">.</span><span class=\"token function\">eof</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n ctx <span class=\"token operator\">=</span> scanner<span class=\"token punctuation\">.</span><span class=\"token function\">missTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#123;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回 头字符串</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ctx <span class=\"token operator\">!=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n scanner<span class=\"token punctuation\">.</span><span class=\"token function\">jumpTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#123;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 跳过 模板字符</span>\n ctx <span class=\"token operator\">=</span> scanner<span class=\"token punctuation\">.</span><span class=\"token function\">missTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#125;&#125;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回 &#123;&#123; x &#125;&#125;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ctx <span class=\"token operator\">!=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n scanner<span class=\"token punctuation\">.</span><span class=\"token function\">jumpTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#125;&#125;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> tokens<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>Parser<span class=\"token punctuation\">.</span><span class=\"token function\">createTokens</span><span class=\"token punctuation\">(</span>tmpl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 输出,非常的 奈一丝</span>\n<span class=\"token comment\">// [\"text\", \"我买了一个\"]</span>\n<span class=\"token comment\">// [\"name\", \"thing\"]</span>\n<span class=\"token comment\">// [\"text\", \",好\"]</span>\n<span class=\"token comment\">// [\"name\", \"mood\"]</span>\n<span class=\"token comment\">// [\"text\", \"啊\"]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n## 扫描器 Scanner 增强\n\n上面的`Parser`只能识别`&#123;&#123;`和`&#125;&#125;</code>,如果模板语法复杂一点,比如加入 <code>&#123;&#123;#list&#125;&#125;...&#123;&#123;/list&#125;&#125;</code>,需要增强<code>Parser</code></p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> template <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">\n 哈哈哈\n &#123;&#123;#students&#125;&#125;\n 我买了一个 &#123;&#123; thing &#125;&#125;,好&#123;&#123;mood&#125;&#125;啊&#123;&#123;a&#125;&#125;\n &#123;&#123;item.name&#125;&#125;\n &#123;&#123;/students&#125;&#125;\n </span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> Parser <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">createTokens</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">tmpl</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> scanner <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Scanner</span><span class=\"token punctuation\">(</span>tmpl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> tokens <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> ctx <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// scanner 循环执行</span>\n <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>scanner<span class=\"token punctuation\">.</span><span class=\"token function\">eof</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n ctx <span class=\"token operator\">=</span> scanner<span class=\"token punctuation\">.</span><span class=\"token function\">missTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#123;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回 头字符串</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ctx <span class=\"token operator\">!=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"text\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n scanner<span class=\"token punctuation\">.</span><span class=\"token function\">jumpTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#123;&#123;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 跳过 模板字符</span>\n ctx <span class=\"token operator\">=</span> scanner<span class=\"token punctuation\">.</span><span class=\"token function\">missTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#125;&#125;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回 &#123;&#123; x &#125;&#125;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ctx <span class=\"token operator\">!=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>ctx<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">case</span> <span class=\"token string\">\"#\"</span><span class=\"token operator\">:</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"#\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">.</span><span class=\"token function\">substr</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// &#123;&#123;# x &#125;&#125;</span>\n <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">case</span> <span class=\"token string\">\"/\"</span><span class=\"token operator\">:</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"/\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">.</span><span class=\"token function\">substr</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">default</span><span class=\"token operator\">:</span>\n tokens<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span>\n scanner<span class=\"token punctuation\">.</span><span class=\"token function\">jumpTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&#125;&#125;\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> tokens<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>Parser<span class=\"token punctuation\">.</span><span class=\"token function\">createTokens</span><span class=\"token punctuation\">(</span>template<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 输出</span>\n<span class=\"token comment\">// [\"text\", \"↵ 哈哈哈↵ \"]</span>\n<span class=\"token comment\">// [\"#\", \"students\"]</span>\n<span class=\"token comment\">// [\"text\", \"↵ 我买了一个 \"]</span>\n<span class=\"token comment\">// [\"name\", \" thing \"]</span>\n<span class=\"token comment\">// [\"text\", \",好\"]</span>\n<span class=\"token comment\">// [\"name\", \"mood\"]</span>\n<span class=\"token comment\">// [\"text\", \"啊\"]</span>\n<span class=\"token comment\">// [\"name\", \"a\"]</span>\n<span class=\"token comment\">// [\"text\", \"↵ \"]</span>\n<span class=\"token comment\">// [\"name\", \"item.name\"]</span>\n<span class=\"token comment\">// [\"text\", \"↵ \"]</span>\n<span class=\"token comment\">// [\"/\", \"students\"]</span>\n<span class=\"token comment\">// [\"text\", \"↵ \"]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"栈队列算法\"><a href=\"#栈队列算法\" class=\"headerlink\" title=\"栈队列算法\"></a>栈队列算法</h2><p>上一步最后的输出,只有单层嵌套,如果是两层嵌套怎么办?</p>\n<p>例如模板语法如下:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> template <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">\n 哈哈哈\n &#123;&#123;#students&#125;&#125;\n &#123;&#123;#stu&#125;&#125;\n &#123;&#123;stu.name&#125;&#125;买了一个 &#123;&#123; thing &#125;&#125;,好&#123;&#123;mood&#125;&#125;啊&#123;&#123;a&#125;&#125;\n &#123;&#123;/stu&#125;&#125;\n &#123;&#123;item.name&#125;&#125;\n &#123;&#123;/students&#125;&#125;\n </span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>经过<code>Parser</code>处理得到:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n *\n * [\"text\", \"↵ 哈哈哈↵ \"]\n * [\"#\", \"students\"]\n * [\"text\", \"↵ \"]\n * [\"#\", \"stu\"]\n * [\"text\", \"↵ \"]\n * [\"name\", \"stu.name\"]\n * [\"text\", \"买了一个 \"]\n * [\"name\", \" thing \"]\n * [\"text\", \",好\"]\n * [\"name\", \"mood\"]\n * [\"text\", \"啊\"]\n * [\"name\", \"a\"]\n * [\"text\", \"↵ \"]\n * [\"/\", \"stu\"]\n * [\"text\", \"↵ \"]\n * [\"name\", \"item.name\"]\n * [\"text\", \"↵ \"]\n * [\"/\", \"students\"]\n * [\"text\", \"↵ \"]\n *\n * /</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>此时<code>students</code>和<code>stu</code>都是<code>#</code>标记,我们需要利用算法处理他们的嵌套结构,处理成大约如下这样的结构:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n *\n * [\"text\", \"↵ 哈哈哈↵ \"]\n * Array(3)\n * \"#\"\n * \"students\"\n * Array(5)\n * [\"text\", \"↵ \"]\n * [\"#\", \"stu\", Array(9)]\n * [\"text\", \"↵ \"]\n * [\"name\", \"item.name\"]\n * [\"text\", \"↵ \"]\n * [\"text\", \"↵ \"]\n *\n * /</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"常用工具类\"><a href=\"#常用工具类\" class=\"headerlink\" title=\"常用工具类\"></a>常用工具类</h1><h2 id=\"递归\"><a href=\"#递归\" class=\"headerlink\" title=\"递归\"></a>递归</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n * &#123;string&#125; dir 递归根目录\n * &#123;object&#125; list 暂存参数\n */</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">deep</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">dir<span class=\"token punctuation\">,</span> list <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> dirs <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> fs<span class=\"token punctuation\">.</span>promises<span class=\"token punctuation\">.</span><span class=\"token function\">readdir</span><span class=\"token punctuation\">(</span>dir<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> dirs<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> item <span class=\"token operator\">=</span> dirs<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span>\n <span class=\"token keyword\">const</span> itemPath <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>dir<span class=\"token punctuation\">,</span> item<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">const</span> isDir <span class=\"token operator\">=</span> fs<span class=\"token punctuation\">.</span><span class=\"token function\">statSync</span><span class=\"token punctuation\">(</span>itemPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">isDirectory</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n isDir <span class=\"token operator\">?</span> <span class=\"token keyword\">await</span> <span class=\"token function\">deep</span><span class=\"token punctuation\">(</span>itemPath<span class=\"token punctuation\">,</span> list<span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> list<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>itemPath<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> list\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"自增id短码\"><a href=\"#自增id短码\" class=\"headerlink\" title=\"自增id短码\"></a>自增id短码</h2><p>用于连接分享</p>\n<pre class=\"line-numbers language-typescript\" data-language=\"typescript\"><code class=\"language-typescript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">createAscString</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> dictionary <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token string\">\"0123456789\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"abcdefghigklmnopqrstuvwxyz\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token string\">\"ABCDEFGHIGKLMNOPQRSTUVWXYZ\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> chars <span class=\"token operator\">=</span> dictionary<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">split</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n radix <span class=\"token operator\">=</span> chars<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">,</span>\n qutient <span class=\"token operator\">=</span> <span class=\"token number\">1000</span> <span class=\"token operator\">*</span> <span class=\"token number\">1000</span> <span class=\"token operator\">*</span> <span class=\"token number\">9999</span> <span class=\"token operator\">+</span> <span class=\"token operator\">+</span>id<span class=\"token punctuation\">,</span>\n arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>qutient<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n mod <span class=\"token operator\">=</span> qutient <span class=\"token operator\">%</span> radix<span class=\"token punctuation\">;</span>\n qutient <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>qutient <span class=\"token operator\">-</span> mod<span class=\"token punctuation\">)</span> <span class=\"token operator\">/</span> radix<span class=\"token punctuation\">;</span>\n arr<span class=\"token punctuation\">.</span><span class=\"token function\">unshift</span><span class=\"token punctuation\">(</span>chars<span class=\"token punctuation\">[</span>mod<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> arr<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token builtin\">console</span><span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">createAscString</span><span class=\"token punctuation\">(</span><span class=\"token number\">100000000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"手动实现-eventBus\"><a href=\"#手动实现-eventBus\" class=\"headerlink\" title=\"手动实现 eventBus\"></a>手动实现 eventBus</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">EventBus</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// key-value : eventName-date</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>callbacks <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 监听事件\n * @param &#123;事件名&#125; eventName\n * @param &#123;回调函数&#125; callback\n */</span>\n <span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">eventName<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">checkType</span><span class=\"token punctuation\">(</span>eventName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>callbacks<span class=\"token punctuation\">[</span>eventName<span class=\"token punctuation\">]</span>\n <span class=\"token operator\">?</span> <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>callbacks<span class=\"token punctuation\">[</span>eventName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n <span class=\"token operator\">:</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">The event has not been declared</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 注册一个事件\n * @param &#123;事件名&#125; eventName\n * @param &#123;传递的对象&#125; data\n */</span>\n <span class=\"token function\">emit</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">eventName<span class=\"token punctuation\">,</span> data</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">checkType</span><span class=\"token punctuation\">(</span>eventName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>callbacks<span class=\"token punctuation\">[</span>eventName<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> data<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 注销事件,不传参数默认注销全部事件\n * @param &#123;事件名&#125; eventName\n */</span>\n <span class=\"token function\">off</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">eventName</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n eventName\n <span class=\"token operator\">?</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">checkType</span><span class=\"token punctuation\">(</span>eventName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">removeEvent</span><span class=\"token punctuation\">(</span>eventName<span class=\"token punctuation\">)</span>\n <span class=\"token operator\">:</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">emptyEvent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 移出事件\n * @param &#123;事件名&#125; eventName\n */</span>\n <span class=\"token function\">removeEvent</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">eventName</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n Reflect<span class=\"token punctuation\">.</span><span class=\"token function\">deleteProperty</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>callbacks<span class=\"token punctuation\">,</span> eventName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 清空全部事件\n */</span>\n <span class=\"token function\">emptyEvent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>callbacks <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 参数类型校验\n * @param &#123;参数&#125; param\n * @param &#123;合法的类型&#125; validType\n */</span>\n <span class=\"token function\">checkType</span><span class=\"token punctuation\">(</span>param<span class=\"token punctuation\">,</span> validType <span class=\"token operator\">=</span> <span class=\"token string\">\"string\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> param <span class=\"token operator\">!==</span> validType<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">(param, </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>param<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">) should be of </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>validType<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\"> type</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 缅怀jQ链式调用</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token comment\">/**\n * 错误提示\n * @param &#123;提示文字&#125; text\n */</span>\n <span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">text</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span>text<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>调用</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 省略import</span>\n<span class=\"token keyword\">const</span> eventBus <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">EventBus</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\neventBus<span class=\"token punctuation\">.</span><span class=\"token function\">emit</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"login\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">a</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">d</span><span class=\"token operator\">:</span> <span class=\"token number\">2</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\neventBus<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token number\">123</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">d</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>d<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [&#123;...&#125;]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"判断对象是否有某个-key\"><a href=\"#判断对象是否有某个-key\" class=\"headerlink\" title=\"判断对象是否有某个 key\"></a>判断对象是否有某个 key</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">alias</span><span class=\"token operator\">:</span> <span class=\"token string\">\"es6\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token string\">\"alias\"</span> <span class=\"token keyword\">in</span> obj<span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span>\nReflect<span class=\"token punctuation\">.</span><span class=\"token function\">has</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> <span class=\"token string\">\"alias\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"浏览器\"><a href=\"#浏览器\" class=\"headerlink\" title=\"浏览器\"></a>浏览器</h2><h2 id=\"版本信息\"><a href=\"#版本信息\" class=\"headerlink\" title=\"版本信息\"></a>版本信息</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">window<span class=\"token punctuation\">.</span>navigator<span class=\"token punctuation\">.</span>userAgent<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"兼容事件绑定\"><a href=\"#兼容事件绑定\" class=\"headerlink\" title=\"兼容事件绑定\"></a>兼容事件绑定</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/*\n兼容低版本IEele为需要绑定事件的元素\neventName为事件名保持addEventListener语法去掉onfun为事件响应函数\n*/</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">addEvent</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">ele<span class=\"token punctuation\">,</span> eventName<span class=\"token punctuation\">,</span> fun</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n ele<span class=\"token punctuation\">.</span>addEventListener\n <span class=\"token operator\">?</span> ele<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>eventName<span class=\"token punctuation\">,</span> fun<span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span>\n <span class=\"token operator\">:</span> ele<span class=\"token punctuation\">.</span><span class=\"token function\">attachEvent</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"on\"</span> <span class=\"token operator\">+</span> eventNme<span class=\"token punctuation\">,</span> fun<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"数组对象\"><a href=\"#数组对象\" class=\"headerlink\" title=\"数组对象\"></a>数组对象</h2><h2 id=\"reduce\"><a href=\"#reduce\" class=\"headerlink\" title=\"reduce\"></a>reduce</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> sum <span class=\"token operator\">=</span> arr<span class=\"token punctuation\">.</span><span class=\"token function\">reduce</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">prev<span class=\"token punctuation\">,</span> cur<span class=\"token punctuation\">,</span> index<span class=\"token punctuation\">,</span> arr</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>prev<span class=\"token punctuation\">,</span> cur<span class=\"token punctuation\">,</span> index<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> prev <span class=\"token operator\">+</span> cur<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">//注意这里设置了初始值</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">,</span> sum<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 求和</span>\n<span class=\"token keyword\">const</span> sum <span class=\"token operator\">=</span> arr<span class=\"token punctuation\">.</span><span class=\"token function\">reduce</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">p<span class=\"token punctuation\">,</span>c</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> p<span class=\"token operator\">+</span>c<span class=\"token punctuation\">)</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"对象内部根据-key-对-value-进行排序-取前-3\"><a href=\"#对象内部根据-key-对-value-进行排序-取前-3\" class=\"headerlink\" title=\"对象内部根据 key 对 value 进行排序,取前 3\"></a>对象内部根据 key 对 value 进行排序,取前 3</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> datasource <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">price</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">alias</span><span class=\"token operator\">:</span> <span class=\"token string\">\"watermelon\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">price</span><span class=\"token operator\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">alias</span><span class=\"token operator\">:</span> <span class=\"token string\">\"orange\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">price</span><span class=\"token operator\">:</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">alias</span><span class=\"token operator\">:</span> <span class=\"token string\">\"banana\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">price</span><span class=\"token operator\">:</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">alias</span><span class=\"token operator\">:</span> <span class=\"token string\">\"apple\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 降序排列</span>\n<span class=\"token keyword\">let</span> <span class=\"token function-variable function\">compare</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">key</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">a<span class=\"token punctuation\">,</span> b</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> b<span class=\"token punctuation\">[</span>key<span class=\"token punctuation\">]</span> <span class=\"token operator\">-</span> a<span class=\"token punctuation\">[</span>key<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> sorted <span class=\"token operator\">=</span> datasource\n <span class=\"token punctuation\">.</span><span class=\"token function\">sort</span><span class=\"token punctuation\">(</span><span class=\"token function\">compare</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"price\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">slice</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">i</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> i<span class=\"token punctuation\">[</span><span class=\"token string\">\"alias\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 返回 [\"apple\", \"orange\", \"banana\"]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"随机字符串\"><a href=\"#随机字符串\" class=\"headerlink\" title=\"随机字符串\"></a>随机字符串</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">getRandomRangeNum</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">len <span class=\"token operator\">=</span> <span class=\"token number\">32</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 略去不宜辨识字符</span>\n <span class=\"token keyword\">let</span> dictionary <span class=\"token operator\">=</span> <span class=\"token string\">\"ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> maxPos <span class=\"token operator\">=</span> dictionary<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> res <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> len<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n res <span class=\"token operator\">+=</span> dictionary<span class=\"token punctuation\">.</span><span class=\"token function\">charAt</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">random</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> maxPos<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"类型检测\"><a href=\"#类型检测\" class=\"headerlink\" title=\"类型检测\"></a>类型检测</h2><p>Q使用<code>typeof foo === &quot;object&quot;</code>检测<code>foo</code>是否为对象有什么缺点?如何避免?</p>\n<p>A用 <code>typeof</code> 是否能准确判断一个对象变量,答案是否定的,<code>null</code> 的结果也是 <code>object</code><code>Array</code> 的结果也是 <code>object</code>,有时候我们需要的是 “纯粹” 的 <code>object</code> 对象</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token class-name\">Object</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> <span class=\"token string\">\"[object Object]\"</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<h2 id=\"倒计时\"><a href=\"#倒计时\" class=\"headerlink\" title=\"倒计时\"></a>倒计时</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Countdown</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">startNum<span class=\"token punctuation\">,</span> endNum<span class=\"token punctuation\">,</span> interval</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token punctuation\">[</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>startNum<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>endNum<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>interval<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>startNum<span class=\"token punctuation\">,</span> endNum<span class=\"token punctuation\">,</span> interval<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> timer <span class=\"token operator\">=</span> <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>startNum <span class=\"token operator\">>=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>endNum<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>startNum<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>startNum <span class=\"token operator\">-=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">clearTimeout</span><span class=\"token punctuation\">(</span>timer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>interval<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 实例化调用</span>\n<span class=\"token keyword\">var</span> countdown <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Countdown</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"范围随机数\"><a href=\"#范围随机数\" class=\"headerlink\" title=\"范围随机数\"></a>范围随机数</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 能取到 min取不到 max</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">getRandomRangeNum</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">min<span class=\"token punctuation\">,</span> max</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> min <span class=\"token operator\">+</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">random</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span>max <span class=\"token operator\">-</span> min<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"获取当前月的天数\"><a href=\"#获取当前月的天数\" class=\"headerlink\" title=\"获取当前月的天数\"></a>获取当前月的天数</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> getCurMonthDays <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span>\n <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getFullYear</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getMonth</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n <span class=\"token number\">0</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getDate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n\n<h1 id=\"对象小操作\"><a href=\"#对象小操作\" class=\"headerlink\" title=\"对象小操作\"></a>对象小操作</h1><h2 id=\"去虚假值\"><a href=\"#去虚假值\" class=\"headerlink\" title=\"去虚假值\"></a>去虚假值</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr4 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"小明\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"小蓝\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\" \"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">NaN</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr4<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span>Boolean<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// => ['小明', '小蓝', ' ', true]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<h2 id=\"头尾插入\"><a href=\"#头尾插入\" class=\"headerlink\" title=\"头尾插入\"></a>头尾插入</h2><p>效率比 <code>unshift()</code> 高</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 头插入</span>\n<span class=\"token punctuation\">[</span><span class=\"token string\">\"haha\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">concat</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 尾插入</span>\narr<span class=\"token punctuation\">.</span><span class=\"token function\">concat</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"haha\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n\n<h2 id=\"删除属性\"><a href=\"#删除属性\" class=\"headerlink\" title=\"删除属性\"></a>删除属性</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">deleteA</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">obj</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">delete</span> obj<span class=\"token punctuation\">.</span><span class=\"token constant\">A</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> obj<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token comment\">// 使用解构赋值</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">deleteA</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">&#123;</span> <span class=\"token constant\">A</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">...</span>rest <span class=\"token punctuation\">&#125;</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> rest<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"生产、加工、消费分离\"><a href=\"#生产、加工、消费分离\" class=\"headerlink\" title=\"生产、加工、消费分离\"></a>生产、加工、消费分离</h1><ul>\n<li>从接口拿数据到视图 fetch api</li>\n<li>加工 computed</li>\n<li>消费 v-for</li>\n</ul>\n<h1 id=\"元数据\"><a href=\"#元数据\" class=\"headerlink\" title=\"元数据\"></a>元数据</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">import</span> <span class=\"token string\">\"reflect-metadata\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// npm install reflect-metadata</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">Role</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> string</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> ClassDecorator <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">target</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n Reflect<span class=\"token punctuation\">.</span><span class=\"token function\">defineMetadata</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"role\"</span><span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> target<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n@<span class=\"token function\">Role</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"admin\"</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Post</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token keyword\">const</span> metadata <span class=\"token operator\">=</span> Reflect<span class=\"token punctuation\">.</span><span class=\"token function\">getMetadata</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"role\"</span><span class=\"token punctuation\">,</span> Post<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nReflect<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>Post<span class=\"token punctuation\">,</span> <span class=\"token string\">\"role2\"</span><span class=\"token punctuation\">,</span> metadata<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>Reflect<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>Post<span class=\"token punctuation\">,</span> <span class=\"token string\">\"role2\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// admin</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"防抖与节流\"><a href=\"#防抖与节流\" class=\"headerlink\" title=\"防抖与节流\"></a>防抖与节流</h1><p>在页面上监听诸如<code>scroll</code>(页面滚动),<code>mousemove</code>(鼠标移动) <code>keydown</code> <code>keyup</code> <code>keypress</code>(按下键盘)等等一系列事件的时候,我们并不希望频繁的触发这类监听,尤其当请求非常消耗资源时,这种操作会导致服务器性能急剧下降。</p>\n<h2 id=\"Debounce\"><a href=\"#Debounce\" class=\"headerlink\" title=\"Debounce\"></a>Debounce</h2><p>把触发非常频繁的事件合并成一次延迟执行,如果对监听函数使用 100ms 的容忍时间,那么时间在第 3.1s 的时候执行</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 默认延时100ms</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">debounce</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">func<span class=\"token punctuation\">,</span> dealy <span class=\"token operator\">=</span> <span class=\"token number\">100</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> timer<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 暂存this和参数</span>\n <span class=\"token keyword\">let</span> _this <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> args <span class=\"token operator\">=</span> arguments<span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 清除定时器确保不执行func</span>\n <span class=\"token function\">clearTimeout</span><span class=\"token punctuation\">(</span>timer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n timer <span class=\"token operator\">=</span> <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">func</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span>_this<span class=\"token punctuation\">,</span> args<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> dealy<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 执行函数</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">handler</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">delay 100ms ,then handle</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// dom添加监听</span>\ndocument\n <span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"#someNode\"</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"scroll\"</span><span class=\"token punctuation\">,</span> <span class=\"token function\">debounce</span><span class=\"token punctuation\">(</span>handler<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"Throttle\"><a href=\"#Throttle\" class=\"headerlink\" title=\"Throttle\"></a>Throttle</h2><p>固定函数执行的速率,即所谓的“节流”。设置一个阀值,在阀值内,把触发的事件合并成一次执行;当到达阀值,必定执行一次事件。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">throttle</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">func<span class=\"token punctuation\">,</span> delay</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> statTime <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> currentTime <span class=\"token operator\">=</span> <span class=\"token operator\">+</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>currentTime <span class=\"token operator\">-</span> statTime <span class=\"token operator\">></span> delay<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">func</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">,</span> arguments<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n statTime <span class=\"token operator\">=</span> currentTime<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 执行函数</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">resizeHandler</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">resize</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// window添加监听</span>\nwindow<span class=\"token punctuation\">.</span>onresize <span class=\"token operator\">=</span> <span class=\"token function\">throttle</span><span class=\"token punctuation\">(</span>resizeHandler<span class=\"token punctuation\">,</span> <span class=\"token number\">300</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"this-指向\"><a href=\"#this-指向\" class=\"headerlink\" title=\"this 指向\"></a>this 指向</h1><h2 id=\"全局环境\"><a href=\"#全局环境\" class=\"headerlink\" title=\"全局环境\"></a>全局环境</h2><p>全局环境下this 始终指向全局对象window无论是否严格模式</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span> <span class=\"token operator\">===</span> window<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span>\n<span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">37</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 37</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"函数上下文调用\"><a href=\"#函数上下文调用\" class=\"headerlink\" title=\"函数上下文调用\"></a>函数上下文调用</h2><ul>\n<li>非严格模式</li>\n</ul>\n<p>没有被上一级的对象所调用, this 默认指向全局对象 window</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> window<span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<ul>\n<li>严格模式</li>\n</ul>\n<p>this 指向 undefined</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">f2</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token string\">\"use strict\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 这里是严格模式</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token function\">f2</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"箭头函数\"><a href=\"#箭头函数\" class=\"headerlink\" title=\"箭头函数\"></a>箭头函数</h2><blockquote>\n<p>箭头函数中call()、apply()、bind()方法无效</p>\n</blockquote>\n<p>在全局代码中,箭头函数被设置为全局对象,总之箭头函数不改变 this 指向</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> globalObject <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> <span class=\"token function-variable function\">foo</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">foo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> globalObject<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<p>箭头函数作为对象的方法使用,指向全局 window 对象</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">i</span><span class=\"token operator\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">b</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>i<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">c</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>i<span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\nobj<span class=\"token punctuation\">.</span><span class=\"token function\">b</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined window&#123;...&#125;</span>\nobj<span class=\"token punctuation\">.</span><span class=\"token function\">c</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 10 Object &#123;...&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>箭头函数可以让 this 指向固化,这种特性很有利于封装回调函数</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 总是指向 handler 对象。如果不使用箭头函数则指向全局 document 对象</span>\n<span class=\"token keyword\">var</span> handler <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token string\">\"123456\"</span><span class=\"token punctuation\">,</span>\n\n <span class=\"token function-variable function\">init</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n document<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span>\n <span class=\"token string\">\"click\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">doSomething</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">.</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n <span class=\"token boolean\">false</span>\n <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n\n <span class=\"token function-variable function\">doSomething</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">type</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Handling \"</span> <span class=\"token operator\">+</span> type <span class=\"token operator\">+</span> <span class=\"token string\">\" for \"</span> <span class=\"token operator\">+</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"call-apply-bind-与-es6\"><a href=\"#call-apply-bind-与-es6\" class=\"headerlink\" title=\"call, apply, bind 与 es6\"></a>call, apply, bind 与 es6</h1><p>js 的函数继承于<code>Function.prototype</code>对象,因此每个函数都会有 apply、call、bind 方法</p>\n<blockquote>\n<p>call 和 apply 的作用,完全一样,唯一的区别就是在参数上面。</p>\n</blockquote>\n<p><code>call, apply, bind</code>改变函数中 <code>this 指向</code> 的三兄弟,把<code>this</code>绑定到第一个参数对象上</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">displayHobbies</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token operator\">...</span>hobbies</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\"> likes </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>hobbies<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\", \"</span><span class=\"token punctuation\">)</span><span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">.</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token comment\">// 下面两个等价</span>\n<span class=\"token function\">displayHobbies</span><span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Bob\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"swimming\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"basketball\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"anime\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Bob likes swimming, basketball, anime.</span>\n<span class=\"token function\">displayHobbies</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Bob\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"swimming\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"basketball\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"anime\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Bob likes swimming, basketball, anime.</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p><code>bind</code>返回的是一个函数,需要手动执行</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> p1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"张三\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">age</span><span class=\"token operator\">:</span> <span class=\"token number\">12</span><span class=\"token punctuation\">,</span>\n <span class=\"token function-variable function\">func</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">姓名:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">,年龄:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>age<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">var</span> p2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"李四\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">age</span><span class=\"token operator\">:</span> <span class=\"token number\">15</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\np1<span class=\"token punctuation\">.</span><span class=\"token function\">func</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span>p2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//姓名:李四,年龄:15</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"for-循环优化\"><a href=\"#for-循环优化\" class=\"headerlink\" title=\"for 循环优化\"></a>for 循环优化</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 每次都要计算array.length</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> array<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token comment\">// 使用leng缓存array长度</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> length <span class=\"token operator\">=</span> array<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"数组\"><a href=\"#数组\" class=\"headerlink\" title=\"数组\"></a>数组</h1><h2 id=\"扁平化去重升序排列\"><a href=\"#扁平化去重升序排列\" class=\"headerlink\" title=\"扁平化去重升序排列\"></a>扁平化去重升序排列</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">6</span><span class=\"token punctuation\">,</span> <span class=\"token number\">7</span><span class=\"token punctuation\">,</span> <span class=\"token number\">8</span><span class=\"token punctuation\">,</span> <span class=\"token number\">9</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">11</span><span class=\"token punctuation\">,</span> <span class=\"token number\">12</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">12</span><span class=\"token punctuation\">,</span> <span class=\"token number\">13</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">14</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\narr<span class=\"token punctuation\">.</span><span class=\"token function\">flat</span><span class=\"token punctuation\">(</span><span class=\"token number\">Infinity</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]</span>\n\n<span class=\"token keyword\">let</span> result <span class=\"token operator\">=</span> Array<span class=\"token punctuation\">.</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Set</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">.</span><span class=\"token function\">flat</span><span class=\"token punctuation\">(</span><span class=\"token number\">Infinity</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">sort</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">a<span class=\"token punctuation\">,</span> b</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> a <span class=\"token operator\">-</span> b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"前端页面埋点-1x1-gif\"><a href=\"#前端页面埋点-1x1-gif\" class=\"headerlink\" title=\"前端页面埋点 - 1x1.gif\"></a>前端页面埋点 - 1x1.gif</h1><p>通常用在,统计页面点击,曝光,停留时间,签发……等场景</p>\n<ul>\n<li>比 PNG&#x2F;JPG 体积小</li>\n<li>天然跨域</li>\n</ul>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>button</span> <span class=\"token special-attr\"><span class=\"token attr-name\">onClick</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token value javascript language-javascript\"><span class=\"token function\">countClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">\"</span></span></span><span class=\"token punctuation\">></span></span>haorooms<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>button</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span><span class=\"token punctuation\">></span></span><span class=\"token script\"><span class=\"token language-javascript\">\n <span class=\"token keyword\">function</span> <span class=\"token function\">countClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">new</span> <span class=\"token class-name\">Image</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>src <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">./haorooms.gif?</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>key<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">=</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>value<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">&amp;</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">random</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\"> </span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n</span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"事件委托\"><a href=\"#事件委托\" class=\"headerlink\" title=\"事件委托\"></a>事件委托</h1><p>利用冒泡原理,委托父元素执行</p>\n<pre class=\"line-numbers language-markup\" data-language=\"markup\"><code class=\"language-markup\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>ul</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>苹果<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>香蕉<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>li</span><span class=\"token punctuation\">></span></span>凤梨<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>li</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>ul</span><span class=\"token punctuation\">></span></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"ul\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function-variable function\">onclick</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">let</span> target <span class=\"token operator\">=</span> event<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>target<span class=\"token punctuation\">.</span>nodeName <span class=\"token operator\">===</span> <span class=\"token string\">\"LI\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>target<span class=\"token punctuation\">.</span>innerHTML<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"构造函数-原型模式\"><a href=\"#构造函数-原型模式\" class=\"headerlink\" title=\"构造函数 + 原型模式\"></a>构造函数 + 原型模式</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">Person</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name<span class=\"token punctuation\">,</span> age<span class=\"token punctuation\">,</span> job</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> name<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>age <span class=\"token operator\">=</span> age<span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>job <span class=\"token operator\">=</span> job<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token class-name\">Person</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">say</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">text</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>name<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">say:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>text<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"剩余参数…args\"><a href=\"#剩余参数…args\" class=\"headerlink\" title=\"剩余参数…args\"></a>剩余参数…args</h1><p>剩余参数<code>args</code>数个数组,<code>...</code>解构符</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">fun1</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">param<span class=\"token punctuation\">,</span> <span class=\"token operator\">...</span>args</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">alert</span><span class=\"token punctuation\">(</span>args<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"跨页面通信\"><a href=\"#跨页面通信\" class=\"headerlink\" title=\"跨页面通信\"></a>跨页面通信</h1><ul>\n<li>cookie</li>\n<li>web worker</li>\n<li>localstorage</li>\n</ul>\n<h1 id=\"iframe-跨域通信和不跨域通信\"><a href=\"#iframe-跨域通信和不跨域通信\" class=\"headerlink\" title=\"iframe 跨域通信和不跨域通信\"></a>iframe 跨域通信和不跨域通信</h1><h2 id=\"不跨域\"><a href=\"#不跨域\" class=\"headerlink\" title=\"不跨域\"></a>不跨域</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// fatherSay是父页面全局方法</span>\nwindow<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">.</span><span class=\"token function\">fatherSay</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 父页面Dom</span>\nwindow<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">.</span>document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"元素id\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 副业页面获取frameID为`iframe_ID`的子页面的Dom</span>\nwindow<span class=\"token punctuation\">.</span>frames<span class=\"token punctuation\">[</span><span class=\"token string\">\"iframe_ID\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"元素id\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"跨域-postMessage\"><a href=\"#跨域-postMessage\" class=\"headerlink\" title=\"跨域 postMessage\"></a>跨域 postMessage</h2><p>子页面</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">window<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">.</span><span class=\"token function\">postMessage</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"http://127.0.0.1:8089\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n\n<p>父页面接受</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"message\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">alert</span><span class=\"token punctuation\">(</span><span class=\"token number\">123</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"对象类型判断\"><a href=\"#对象类型判断\" class=\"headerlink\" title=\"对象类型判断\"></a>对象类型判断</h1><h2 id=\"数组-1\"><a href=\"#数组-1\" class=\"headerlink\" title=\"数组\"></a>数组</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\narr <span class=\"token keyword\">instanceof</span> <span class=\"token class-name\">Array</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span>\nArray<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// true</span>\n<span class=\"token class-name\">Object</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// \"[object Array]\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"js-单线程,如何异步\"><a href=\"#js-单线程,如何异步\" class=\"headerlink\" title=\"js 单线程,如何异步\"></a>js 单线程,如何异步</h1><ul>\n<li><p>主线程 执行 js 中所有的代码。</p>\n</li>\n<li><p>主线程 在执行过程中发现了需要异步的任务任务后扔给浏览器(浏览器创建多个线程执行,顺便创造一个<code>回调队列</code>。</p>\n</li>\n<li><p>主线程 已经执行完毕所有同步代码。监听<code>回调队列</code>一旦 浏览器 中某个线程任务完成将会改变回调函数的状态。主线程查看到某个函数的状态为已完成,就会执行该<code>回调队列</code>中对应的回调函数。</p>\n</li>\n</ul>\n<h1 id=\"移动端最小触控区域\"><a href=\"#移动端最小触控区域\" class=\"headerlink\" title=\"移动端最小触控区域\"></a>移动端最小触控区域</h1><p>苹果推荐是 44pt x 44pt 「具体看 WWDC 14」,通过<code>padding</code>、<code>margin</code>、<code>height</code>等方式进行点击区域扩展</p>\n<h1 id=\"js-精度问题\"><a href=\"#js-精度问题\" class=\"headerlink\" title=\"js 精度问题\"></a>js 精度问题</h1><p>常用类库:<code>Math.js</code>、<code>Big.js</code>、<code>decimal.js</code></p>\n<h1 id=\"冻结-Object-freeze\"><a href=\"#冻结-Object-freeze\" class=\"headerlink\" title=\"冻结 Object. freeze()\"></a>冻结 Object. freeze()</h1><p><code>const</code>生命的简单变量不可修改,但是复杂对象可以被修改,<code>Object. freeze()</code>:可以冻结对象</p>\n<ul>\n<li>不能添加新属性</li>\n<li>不能删除已有属性</li>\n<li>不能修改已有属性的可枚举性、可配置性、可写性</li>\n<li>不能修改已有属性的值</li>\n<li>不能修改原型</li>\n</ul>\n<p>浅冻结</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> obj1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">internal</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\nObject<span class=\"token punctuation\">.</span><span class=\"token function\">freeze</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nobj1<span class=\"token punctuation\">.</span>internal<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token string\">\"aValue\"</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">.</span>internal<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// aValue</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>递归冻结</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">deepFreeze</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">obj</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 获取定义在obj上的属性名</span>\n <span class=\"token keyword\">var</span> propNames <span class=\"token operator\">=</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">getOwnPropertyNames</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 在冻结自身之前冻结属性</span>\n propNames<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> prop <span class=\"token operator\">=</span> obj<span class=\"token punctuation\">[</span>name<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// 如果prop是个对象冻结它</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> prop <span class=\"token operator\">==</span> <span class=\"token string\">\"object\"</span> <span class=\"token operator\">&amp;&amp;</span> prop <span class=\"token operator\">!==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token function\">deepFreeze</span><span class=\"token punctuation\">(</span>prop<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">freeze</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"Reflect\"><a href=\"#Reflect\" class=\"headerlink\" title=\"Reflect\"></a>Reflect</h1><h2 id=\"Reflect-get-target-propertyKey-value-receiver\"><a href=\"#Reflect-get-target-propertyKey-value-receiver\" class=\"headerlink\" title=\"Reflect.get(target, propertyKey, value[receiver])\"></a>Reflect.get(target, propertyKey, value[receiver])</h2><p>获取对象身上某个属性的值,类似于 target[name]。</p>\n<h2 id=\"Reflect-set-target-propertyKey-value-receiver\"><a href=\"#Reflect-set-target-propertyKey-value-receiver\" class=\"headerlink\" title=\"Reflect.set(target, propertyKey, value[receiver])\"></a>Reflect.set(target, propertyKey, value[receiver])</h2><p>将值分配给属性的函数。返回一个 Boolean如果更新成功则返回 true。</p>\n<h2 id=\"Reflect-has-target-propertyKey\"><a href=\"#Reflect-has-target-propertyKey\" class=\"headerlink\" title=\"Reflect.has(target, propertyKey)\"></a>Reflect.has(target, propertyKey)</h2><p>判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。</p>\n<h1 id=\"if-else-优化\"><a href=\"#if-else-优化\" class=\"headerlink\" title=\"if else 优化\"></a>if else 优化</h1><h2 id=\"表驱动编程\"><a href=\"#表驱动编程\" class=\"headerlink\" title=\"表驱动编程\"></a>表驱动编程</h2><p>空间换时间,设置<code>obj=&#123;key:value&#125;</code>,通过<code>obj[key]</code>取值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token function\">calculateGrade</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">score</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> table <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token number\">100</span><span class=\"token operator\">:</span> <span class=\"token string\">'A'</span><span class=\"token punctuation\">,</span>\n <span class=\"token number\">90</span><span class=\"token operator\">:</span> <span class=\"token string\">'A'</span><span class=\"token punctuation\">,</span>\n <span class=\"token number\">80</span><span class=\"token operator\">:</span> <span class=\"token string\">'B'</span><span class=\"token punctuation\">,</span>\n <span class=\"token number\">70</span><span class=\"token operator\">:</span> <span class=\"token string\">'C'</span><span class=\"token punctuation\">,</span>\n <span class=\"token number\">60</span><span class=\"token operator\">:</span> <span class=\"token string\">'D'</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">others</span><span class=\"token operator\">:</span> <span class=\"token string\">'E'</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> table<span class=\"token punctuation\">[</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>score<span class=\"token operator\">/</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token operator\">*</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> table<span class=\"token punctuation\">[</span><span class=\"token string\">'others'</span><span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"短路运算\"><a href=\"#短路运算\" class=\"headerlink\" title=\"短路运算\"></a>短路运算</h2><p>react 没有<code>v-if</code>,运用比较频繁</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 函数组件</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Home</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>home<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#123;</span>\n <span class=\"token boolean\">true</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">&lt;</span>Home <span class=\"token operator\">/</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"使用有意义且易读的变量名\"><a href=\"#使用有意义且易读的变量名\" class=\"headerlink\" title=\"使用有意义且易读的变量名\"></a>使用有意义且易读的变量名</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎 <span class=\"token keyword\">const</span> yyyymmdstr <span class=\"token operator\">=</span> <span class=\"token function\">moment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"YYYY/MM/DD\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n👍 <span class=\"token keyword\">const</span> currentDate <span class=\"token operator\">=</span> <span class=\"token function\">moment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"YYYY/MM/DD\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"使用有意义的变量代替数组下标\"><a href=\"#使用有意义的变量代替数组下标\" class=\"headerlink\" title=\"使用有意义的变量代替数组下标\"></a>使用有意义的变量代替数组下标</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">const</span> address <span class=\"token operator\">=</span> <span class=\"token string\">\"One Infinite Loop, Cupertino 95014\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> cityZipCodeRegex <span class=\"token operator\">=</span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^[^,\\\\]+[,\\\\\\s]+(.+?)\\s*(\\d&#123;5&#125;)?$</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">saveCityZipCode</span><span class=\"token punctuation\">(</span>\n address<span class=\"token punctuation\">.</span><span class=\"token function\">match</span><span class=\"token punctuation\">(</span>cityZipCodeRegex<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n address<span class=\"token punctuation\">.</span><span class=\"token function\">match</span><span class=\"token punctuation\">(</span>cityZipCodeRegex<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n👍\n<span class=\"token keyword\">const</span> address <span class=\"token operator\">=</span> <span class=\"token string\">\"One Infinite Loop, Cupertino 95014\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> cityZipCodeRegex <span class=\"token operator\">=</span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^[^,\\\\]+[,\\\\\\s]+(.+?)\\s*(\\d&#123;5&#125;)?$</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>_<span class=\"token punctuation\">,</span> city<span class=\"token punctuation\">,</span> zipCode<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> address<span class=\"token punctuation\">.</span><span class=\"token function\">match</span><span class=\"token punctuation\">(</span>cityZipCodeRegex<span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">saveCityZipCode</span><span class=\"token punctuation\">(</span>city<span class=\"token punctuation\">,</span> zipCode<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"变量名要简洁\"><a href=\"#变量名要简洁\" class=\"headerlink\" title=\"变量名要简洁\"></a>变量名要简洁</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">const</span> Car <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">carMake</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Honda\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">carModel</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Accord\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">carColor</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Blue\"</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">paintCar</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">car<span class=\"token punctuation\">,</span> color</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n car<span class=\"token punctuation\">.</span>carColor <span class=\"token operator\">=</span> color<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">const</span> Car <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">make</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Honda\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">model</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Accord\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">color</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Blue\"</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">paintCar</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">car<span class=\"token punctuation\">,</span> color</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n car<span class=\"token punctuation\">.</span>color <span class=\"token operator\">=</span> color<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"消除魔术字符串\"><a href=\"#消除魔术字符串\" class=\"headerlink\" title=\"消除魔术字符串\"></a>消除魔术字符串</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎 <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span>blastOff<span class=\"token punctuation\">,</span> <span class=\"token number\">86400000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n👍 <span class=\"token keyword\">const</span> <span class=\"token constant\">MILLISECONDS_PER_DAY</span> <span class=\"token operator\">=</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">24</span> <span class=\"token operator\">*</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//86400000;</span>\n<span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span>blastOff<span class=\"token punctuation\">,</span> <span class=\"token constant\">MILLISECONDS_PER_DAY</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"使用默认参数替代短路运算符\"><a href=\"#使用默认参数替代短路运算符\" class=\"headerlink\" title=\"使用默认参数替代短路运算符\"></a>使用默认参数替代短路运算符</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">function</span> <span class=\"token function\">createMicrobrewery</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> breweryName <span class=\"token operator\">=</span> name <span class=\"token operator\">||</span> <span class=\"token string\">\"Hipster Brew Co.\"</span><span class=\"token punctuation\">;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">function</span> <span class=\"token function\">createMicrobrewery</span><span class=\"token punctuation\">(</span>name <span class=\"token operator\">=</span> <span class=\"token string\">\"Hipster Brew Co.\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"一个函数\"><a href=\"#一个函数\" class=\"headerlink\" title=\"一个函数\"></a>一个函数</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">function</span> <span class=\"token function\">emailClients</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">clients</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n clients<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">client</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> clientRecord <span class=\"token operator\">=</span> database<span class=\"token punctuation\">.</span><span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>client<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>clientRecord<span class=\"token punctuation\">.</span><span class=\"token function\">isActive</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">email</span><span class=\"token punctuation\">(</span>client<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">function</span> <span class=\"token function\">emailActiveClients</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">clients</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n clients<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span>isActiveClient<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span>email<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">isActiveClient</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">client</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">const</span> clientRecord <span class=\"token operator\">=</span> database<span class=\"token punctuation\">.</span><span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>client<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> clientRecord<span class=\"token punctuation\">.</span><span class=\"token function\">isActive</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">-</span>分割线<span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">--</span><span class=\"token operator\">-</span>\n\n👎\n<span class=\"token keyword\">function</span> <span class=\"token function\">createFile</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name<span class=\"token punctuation\">,</span> temp</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>temp<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n fs<span class=\"token punctuation\">.</span><span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">./temp/</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>name<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span>\n fs<span class=\"token punctuation\">.</span><span class=\"token function\">create</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">function</span> <span class=\"token function\">createFile</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n fs<span class=\"token punctuation\">.</span><span class=\"token function\">create</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">createTempFile</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">createFile</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">./temp/</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>name<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"函数参数不多于-2-个,如果有很多参数就利用-object-传递,并使用解构\"><a href=\"#函数参数不多于-2-个,如果有很多参数就利用-object-传递,并使用解构\" class=\"headerlink\" title=\"函数参数不多于 2 个,如果有很多参数就利用 object 传递,并使用解构\"></a>函数参数不多于 2 个,如果有很多参数就利用 object 传递,并使用解构</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">function</span> <span class=\"token function\">createMenu</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">title<span class=\"token punctuation\">,</span> body<span class=\"token punctuation\">,</span> buttonText<span class=\"token punctuation\">,</span> cancellable</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token function\">createMenu</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Foo\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Bar\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Baz\"</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n👍\n<span class=\"token keyword\">function</span> <span class=\"token function\">createMenu</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">&#123;</span> title<span class=\"token punctuation\">,</span> body<span class=\"token punctuation\">,</span> buttonText<span class=\"token punctuation\">,</span> cancellable <span class=\"token punctuation\">&#125;</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token function\">createMenu</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">title</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Foo\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Bar\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">buttonText</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Baz\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">cancellable</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"函数名应该直接反映函数的作用\"><a href=\"#函数名应该直接反映函数的作用\" class=\"headerlink\" title=\"函数名应该直接反映函数的作用\"></a>函数名应该直接反映函数的作用</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">function</span> <span class=\"token function\">addToDate</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">date<span class=\"token punctuation\">,</span> month</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token keyword\">const</span> date <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// It's hard to tell from the function name what is added</span>\n<span class=\"token function\">addToDate</span><span class=\"token punctuation\">(</span>date<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n👍\n<span class=\"token keyword\">function</span> <span class=\"token function\">addMonthToDate</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">month<span class=\"token punctuation\">,</span> date</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n<span class=\"token keyword\">const</span> date <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">addMonthToDate</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> date<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"尽量使用纯函数\"><a href=\"#尽量使用纯函数\" class=\"headerlink\" title=\"尽量使用纯函数\"></a>尽量使用纯函数</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token keyword\">const</span> programmerOutput <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Uncle Bobby\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">500</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Suzie Q\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">1500</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Jimmy Gosling\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">150</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Gracie Hopper\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">1000</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> totalOutput <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> programmerOutput<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n totalOutput <span class=\"token operator\">+=</span> programmerOutput<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>linesOfCode<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">const</span> programmerOutput <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Uncle Bobby\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">500</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Suzie Q\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">1500</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Jimmy Gosling\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">150</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Gracie Hopper\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">linesOfCode</span><span class=\"token operator\">:</span> <span class=\"token number\">1000</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> totalOutput <span class=\"token operator\">=</span> programmerOutput<span class=\"token punctuation\">.</span><span class=\"token function\">reduce</span><span class=\"token punctuation\">(</span>\n <span class=\"token punctuation\">(</span><span class=\"token parameter\">totalLines<span class=\"token punctuation\">,</span> output</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> totalLines <span class=\"token operator\">+</span> output<span class=\"token punctuation\">.</span>linesOfCode<span class=\"token punctuation\">,</span>\n <span class=\"token number\">0</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"不要过度优化\"><a href=\"#不要过度优化\" class=\"headerlink\" title=\"不要过度优化\"></a>不要过度优化</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">👎\n<span class=\"token comment\">// 现代浏览器对于迭代器做了内部优化</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> len <span class=\"token operator\">=</span> list<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> len<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span>\n\n👍\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> list<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n\n<h1 id=\"关于模块化\"><a href=\"#关于模块化\" class=\"headerlink\" title=\"关于模块化\"></a>关于模块化</h1><h2 id=\"无模块化\"><a href=\"#无模块化\" class=\"headerlink\" title=\"无模块化\"></a>无模块化</h2><blockquote>\n<p>污染全局作用域、维护成本高、依赖关系不明显</p>\n</blockquote>\n<p>script 标签引入 js 文件,相互罗列,但是被依赖的放在前面,否则使用就会报错。如下:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token operator\">&lt;</span>script src<span class=\"token operator\">=</span><span class=\"token string\">\"jquery.js\"</span><span class=\"token operator\">></span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span>script src<span class=\"token operator\">=</span><span class=\"token string\">\"main.js\"</span><span class=\"token operator\">></span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span>script src<span class=\"token operator\">=</span><span class=\"token string\">\"other1.js\"</span><span class=\"token operator\">></span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span>script src<span class=\"token operator\">=</span><span class=\"token string\">\"other2.js\"</span><span class=\"token operator\">></span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span>script src<span class=\"token operator\">=</span><span class=\"token string\">\"other3.js\"</span><span class=\"token operator\">></span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"CommonJS-规范-同步\"><a href=\"#CommonJS-规范-同步\" class=\"headerlink\" title=\"CommonJS 规范(同步)\"></a>CommonJS 规范(同步)</h2><p>该规范最初是用在服务器端的 node 的它有四个重要的环境变量为模块化的实现提供支持module、exports、require、global。实际使用时用 module.exports 定义当前模块对外输出的接口(不推荐直接用 exports用 require 加载模块(同步)</p>\n<blockquote>\n<p>module.exports 本身就是一个对象</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">module<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">foo</span><span class=\"token operator\">:</span> <span class=\"token string\">\"bar\"</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//true</span>\nmodule<span class=\"token punctuation\">.</span>exports<span class=\"token punctuation\">.</span>foo <span class=\"token operator\">=</span> <span class=\"token string\">\"bar\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//true。</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<p>CommonJS 用同步的方式加载模块。在服务端模块文件都存在本地磁盘读取非常快所以这样做不会有问题。但是在浏览器端限于网络原因CommonJS 不适合浏览器端模块加载,更合理的方案是使用异步加载,比如下边 AMD 规范。</p>\n<h2 id=\"AMD-规范-RequireJS\"><a href=\"#AMD-规范-RequireJS\" class=\"headerlink\" title=\"AMD 规范(RequireJS)\"></a>AMD 规范(RequireJS)</h2><p>承接上文AMD 规范则是非同步加载模块允许指定回调函数AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。</p>\n<ul>\n<li><code>require([module], callback)</code>:加载模块</li>\n<li><code>define(id, [depends], callback)</code>:定义模块</li>\n<li><code>require.config()</code>:配置路径、依赖关系</li>\n</ul>\n<h2 id=\"CMD-规范-SeaJS\"><a href=\"#CMD-规范-SeaJS\" class=\"headerlink\" title=\"CMD 规范(SeaJS)\"></a>CMD 规范(SeaJS)</h2><p>CMD 是 在推广过程中对模块定义的规范化产出</p>\n<h2 id=\"ES6-import-x2F-export\"><a href=\"#ES6-import-x2F-export\" class=\"headerlink\" title=\"ES6 import&#x2F;export\"></a>ES6 import&#x2F;export</h2><p>通过 babel 将不被支持的 import 编译为当前受到广泛支持的 AMD 规范</p>\n<h1 id=\"AMD模块化实现\"><a href=\"#AMD模块化实现\" class=\"headerlink\" title=\"AMD模块化实现\"></a>AMD模块化实现</h1><h2 id=\"define-函数\"><a href=\"#define-函数\" class=\"headerlink\" title=\"define 函数\"></a>define 函数</h2><p>用来声明模块名<code>module</code>,依赖数组<code>deps</code>,以及模块的作用<code>callback</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> stack <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//模块存储栈,存的是模块执行后的结果</span>\n\n <span class=\"token keyword\">function</span> <span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">module<span class=\"token punctuation\">,</span> deps<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n stack<span class=\"token punctuation\">[</span>module<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">callback</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> deps<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 压栈</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>stack<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 查看栈存储的模块</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">define</span><span class=\"token operator\">:</span> define <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>调用<code>define</code>试试,发现 <code>calc</code>模块被压入了<code>stack 模块栈中</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">module<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"calc\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">first</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">arr</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> arr<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// &#123;calc: &#123; first: ƒ &#125;&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"deps-依赖-导入\"><a href=\"#deps-依赖-导入\" class=\"headerlink\" title=\"deps 依赖(导入)\"></a>deps 依赖(导入)</h2><p>对上面的 <code>define</code>函数稍加改造,这一步过程的本质,就是对 deps</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> module <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">window</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">var</span> stack <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//模块存储栈,</span>\n\n <span class=\"token keyword\">function</span> <span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">module<span class=\"token punctuation\">,</span> deps<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token comment\">// 把 define 函数依赖数组中的模块从 stack 模块中拿出</span>\n deps<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">mod<span class=\"token punctuation\">,</span> index</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n deps<span class=\"token punctuation\">[</span>index<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> stack<span class=\"token punctuation\">[</span>mod<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 赋值给当前模块的 deps</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n stack<span class=\"token punctuation\">[</span>module<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">callback</span><span class=\"token punctuation\">.</span><span class=\"token function\">apply</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> deps<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>stack<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 查看栈存储的模块</span>\n <span class=\"token punctuation\">&#125;</span>\n\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">define</span><span class=\"token operator\">:</span> define <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>window<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"calc\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function-variable function\">first</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">arr</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> arr<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"number\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"calc\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">calc</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">res</span><span class=\"token operator\">:</span> calc<span class=\"token punctuation\">.</span><span class=\"token function\">first</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">//4</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 此时 stack 打印的结果为</span>\n<span class=\"token comment\">//> calc: &#123;first: ƒ&#125;</span>\n<span class=\"token comment\">//> number: &#123;res: 4&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>从本质上看define 函数的第二个参数 deps 数组,相当于 import 导入,并且如果第三个参数 callback 采用 <code>return &#123; &#125;</code>,也就相当于 export 导出</p>\n</blockquote>\n<h2 id=\"老生常谈的指针\"><a href=\"#老生常谈的指针\" class=\"headerlink\" title=\"老生常谈的指针\"></a>老生常谈的指针</h2><p>说到底,<code>stack</code>中 <code>a模块</code> export 是一个指针,<code>&#123;a:value&#125;</code>(内存地址),所以,<code>b 模块</code>会改变<code>a.a</code>的值,这点和 <code>cmd</code>不同</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">module<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">a</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nmodule<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"b\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"a\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">a</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n a<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nmodule<span class=\"token punctuation\">.</span><span class=\"token function\">define</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"c\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"a\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">a</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 2</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n\n<h1 id=\"缘起-Object-defineProperty\"><a href=\"#缘起-Object-defineProperty\" class=\"headerlink\" title=\"缘起 Object.defineProperty()\"></a>缘起 Object.defineProperty()</h1><p>给<code>目标对象</code>上定义一个新属性,或者修改<code>目标对象</code>属性,并且返回新对象</p>\n<h1 id=\"上帝的钥匙-get-amp-set\"><a href=\"#上帝的钥匙-get-amp-set\" class=\"headerlink\" title=\"上帝的钥匙 get &amp; set\"></a>上帝的钥匙 get &amp; set</h1><p>属性的<code>getter</code>函数,如果没有 <code>getter</code>则尾 <code>undefined</code>。当访问该属性时,会调用此函数.</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n\nObject<span class=\"token punctuation\">.</span><span class=\"token function\">defineProperty</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> <span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> <span class=\"token number\">7</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token function\">set</span><span class=\"token punctuation\">(</span>val<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">FAILED改变 a 属性,新值为:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>val<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">,但是被重写 set 劫持了</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nobj<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>上帝的钥匙被找到了</p>\n</blockquote>\n<p>劫持!劫持!还是 TMD 劫持!</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> tempValue <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n\nObject<span class=\"token punctuation\">.</span><span class=\"token function\">defineProperty</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> <span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">return</span> tempValue<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token function\">set</span><span class=\"token punctuation\">(</span>newValue<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n tempValue <span class=\"token operator\">=</span> newValue<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 0</span>\nobj<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 4</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"封装-defineReactive-obj-prop-val\"><a href=\"#封装-defineReactive-obj-prop-val\" class=\"headerlink\" title=\"封装 defineReactive(obj, prop, val)\"></a>封装 defineReactive(obj, prop, val)</h1><blockquote>\n<p>这里 defineReactive 第三个参数 val 替代了上一步中全局变量<code>tempValue</code>,对于 get()、set()来说,访问到了其他函数内部的变量,所以形成了闭包</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">defineReactive</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">obj<span class=\"token punctuation\">,</span> prop<span class=\"token punctuation\">,</span> val</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n Object<span class=\"token punctuation\">.</span><span class=\"token function\">defineProperty</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> prop<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">劫持,你访问了</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>prop<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">属性</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> val<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token function\">set</span><span class=\"token punctuation\">(</span>newValue<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>val <span class=\"token operator\">===</span> newValue<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">劫持,你改变了</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>prop<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">属性</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n val <span class=\"token operator\">=</span> newValue<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span>\n\n<span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">defineReactive</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> <span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 劫持你访问了a属性 4</span>\nobj<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">7</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 劫持你改变了a属性</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 劫持你访问了a属性 7</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h1 id=\"递归侦测\"><a href=\"#递归侦测\" class=\"headerlink\" title=\"递归侦测\"></a>递归侦测</h1><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">a</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">b</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">c</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">defineReactive</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> <span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n\n<blockquote>\n<p>如何自动让<code>obj</code>对象的全部属性都<code>reactive</code>呢?</p>\n</blockquote>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">a</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">b</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">c</span><span class=\"token operator\">:</span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">d</span><span class=\"token operator\">:</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p>定义个方法<code>observe</code>,递归 <code>obj</code> 的每一层的每个 <code>prop</code>,检测是否有<code>__ob__</code>,如果没有,<code>defineReactive</code>,并且挂一个<code>Observer</code>实例在这个<code>props</code>上,例如:</p>\n<p><code>Observer对象</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Observer</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">def</span><span class=\"token punctuation\">(</span>value<span class=\"token punctuation\">,</span> <span class=\"token string\">\"__ob__\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 不可枚举不能给__ob__添加__ob__</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">walk</span><span class=\"token punctuation\">(</span>value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token comment\">// 遍历每一个 prop的 value</span>\n <span class=\"token function\">walk</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> prop <span class=\"token keyword\">in</span> value<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token function\">defineReactive</span><span class=\"token punctuation\">(</span>value<span class=\"token punctuation\">,</span> prop<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token punctuation\">&#125;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p><code>defineReactive.js</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">function</span> <span class=\"token function\">defineReactive</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">obj<span class=\"token punctuation\">,</span> prop<span class=\"token punctuation\">,</span> val</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>arguments<span class=\"token punctuation\">.</span>length <span class=\"token operator\">===</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span> val <span class=\"token operator\">=</span> obj<span class=\"token punctuation\">[</span>prop<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 如果2个参数</span>\n <span class=\"token keyword\">let</span> childNode <span class=\"token operator\">=</span> <span class=\"token function\">observe</span><span class=\"token punctuation\">(</span>val<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n Object<span class=\"token punctuation\">.</span><span class=\"token function\">defineProperty</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> prop<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token literal-property property\">enumerable</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token literal-property property\">configurable</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">你访问了</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>prop<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">属性</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> val<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token function\">set</span><span class=\"token punctuation\">(</span>newValue<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>val <span class=\"token operator\">===</span> newValue<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">你改变了</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>prop<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token string\">属性</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n val <span class=\"token operator\">=</span> newValue<span class=\"token punctuation\">;</span>\n childNode <span class=\"token operator\">=</span> <span class=\"token function\">observe</span><span class=\"token punctuation\">(</span>newValue<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span>\n <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<p><code>observe.js</code></p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n * 检测 obj 身上有没有 __ob__(Observer 实例)\n * @param &#123;*&#125; value\n * @returns\n */</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">function</span> <span class=\"token function\">observe</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> value <span class=\"token operator\">!=</span> <span class=\"token string\">\"object\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> ob<span class=\"token punctuation\">;</span>\n <span class=\"token comment\">//! 用__ob__是为了属性不重名被覆盖</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> value<span class=\"token punctuation\">.</span>__ob__ <span class=\"token operator\">!=</span> <span class=\"token string\">\"undefined\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>\n ob <span class=\"token operator\">=</span> value<span class=\"token punctuation\">.</span>__ob__<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span>\n ob <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Observer</span><span class=\"token punctuation\">(</span>value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">&#125;</span>\n <span class=\"token keyword\">return</span> ob<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">&#125;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n"},{"title":"改掉选择困难症","status":"done","_content":"\n对模糊零容忍。换句话说就是想尽一切办法让自己找出那个最重要的、唯一的选项让自己在某一个时间段里只有一条路可以走。如果不在这些选择的节点想清楚我们就会陷入模糊的状态它会使我们产生本能的反应——娱乐。因为即时满足避难趋易是我们的天性","source":"_posts/social/改掉选择困难症.md","raw":"---\ntitle: 改掉选择困难症\ncategories:\n - EQ\nstatus: done\n---\n\n对模糊零容忍。换句话说就是想尽一切办法让自己找出那个最重要的、唯一的选项让自己在某一个时间段里只有一条路可以走。如果不在这些选择的节点想清楚我们就会陷入模糊的状态它会使我们产生本能的反应——娱乐。因为即时满足避难趋易是我们的天性","slug":"social/改掉选择困难症","published":1,"date":"2023-11-06T05:19:17.107Z","updated":"2023-11-06T05:20:14.555Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58r000q4cz30t6927bz","content":"<p>对模糊零容忍。换句话说,就是想尽一切办法让自己找出那个最重要的、唯一的选项,让自己在某一个时间段里只有一条路可以走。如果不在这些选择的节点想清楚,我们就会陷入模糊的状态,它会使我们产生本能的反应——娱乐。因为,即时满足,避难趋易,是我们的天性</p>\n","site":{"data":{}},"excerpt":"","more":"<p>对模糊零容忍。换句话说,就是想尽一切办法让自己找出那个最重要的、唯一的选项,让自己在某一个时间段里只有一条路可以走。如果不在这些选择的节点想清楚,我们就会陷入模糊的状态,它会使我们产生本能的反应——娱乐。因为,即时满足,避难趋易,是我们的天性</p>\n"},{"title":"烦恼的原因","status":"done","_content":"\n分心开小差很多人感觉可能不是个问题甚至还对自己的一心二用而感觉沾沾自喜。比如跑步的时候考虑明后天的安排吃饭的时候在担忧与他人的关系睡觉的时候思绪像瀑布一样倾泻而出是我们在不知不觉中徒生烦恼、渐生愚钝。从某种意义上来说它是我们烦恼低效的来源因为无法专注。","source":"_posts/social/烦恼的原因.md","raw":"---\ntitle: 烦恼的原因\ncategories:\n - EQ\nstatus: done\n---\n\n分心开小差很多人感觉可能不是个问题甚至还对自己的一心二用而感觉沾沾自喜。比如跑步的时候考虑明后天的安排吃饭的时候在担忧与他人的关系睡觉的时候思绪像瀑布一样倾泻而出是我们在不知不觉中徒生烦恼、渐生愚钝。从某种意义上来说它是我们烦恼低效的来源因为无法专注。","slug":"social/烦恼的原因","published":1,"date":"2023-11-06T05:19:41.350Z","updated":"2023-11-06T05:19:53.454Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58r000t4cz30eqvd8xz","content":"<p>分心开小差,很多人感觉可能不是个问题,甚至还对自己的一心二用而感觉沾沾自喜。比如跑步的时候考虑明后天的安排,吃饭的时候在担忧与他人的关系,睡觉的时候思绪像瀑布一样倾泻而出,是我们在不知不觉中徒生烦恼、渐生愚钝。从某种意义上来说,它是我们烦恼低效的来源,因为无法专注。</p>\n","site":{"data":{}},"excerpt":"","more":"<p>分心开小差,很多人感觉可能不是个问题,甚至还对自己的一心二用而感觉沾沾自喜。比如跑步的时候考虑明后天的安排,吃饭的时候在担忧与他人的关系,睡觉的时候思绪像瀑布一样倾泻而出,是我们在不知不觉中徒生烦恼、渐生愚钝。从某种意义上来说,它是我们烦恼低效的来源,因为无法专注。</p>\n"},{"title":"走神","status":"done","_content":"\n走神可以让我们活在任何时候唯独不能活在当下。分心走神的原因无非\"当下太无聊、当下太痛苦\",因为身体受困于现实,只好让神思天马行空!","source":"_posts/social/走神.md","raw":"---\ntitle: 走神\ncategories:\n - EQ\nstatus: done\n---\n\n走神可以让我们活在任何时候唯独不能活在当下。分心走神的原因无非\"当下太无聊、当下太痛苦\",因为身体受困于现实,只好让神思天马行空!","slug":"social/走神","published":1,"date":"2023-11-06T05:20:01.272Z","updated":"2023-11-06T05:20:13.780Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58r000v4cz3bm2ichic","content":"<p>走神可以让我们活在任何时候,唯独不能活在当下。分心走神的原因,无非”当下太无聊、当下太痛苦”,因为身体受困于现实,只好让神思天马行空!</p>\n","site":{"data":{}},"excerpt":"","more":"<p>走神可以让我们活在任何时候,唯独不能活在当下。分心走神的原因,无非”当下太无聊、当下太痛苦”,因为身体受困于现实,只好让神思天马行空!</p>\n"},{"title":"短视频账号起号逻辑","top":0,"status":"done","_content":"\n# 抖音流量池\n\n| 级别 | 曝光次数 | 播放量范围 |\n| ---------- | -------------------- | ---------- |\n| 初级流量池 | 冷启动 | 0~500 |\n| | 二次曝光 | 3K~5K |\n| | 三次曝光 | 1W~2W |\n| | 四次曝光(人工复审) | 10W~15W |\n| 中级流量池 | 五次曝光 | 30W~70W |\n| 高级流量池 | 六次曝光 | 100W~300W |\n| 热门流量池 | 七次曝光 | 500W~1200W |\n| 全平台曝光 | 八次曝光 | - |\n\n\n# 如何起新号\n\n## 素材整理与发布\n\n- 准备 20 条内容,分成 5 组。\n- 连续 5 天,每天发布 4 条。\n- 每个短视频投入 100 元抖+(选择投放时长 6 小时或 12 小时)。\n- 选取同类账号,确定兴趣标签。\n- 主要关注点赞、评论数据。\n\n## 数据分析与追加投资\n\n- 第二天,基于前一天数据,忽略点赞和评论。\n- 选择完播率最高的视频,追加投资 200 元。\n- 投向粉丝量(选择投放时长 6 小时或 12 小时)。\n\n## 持续操作与评估\n\n- 在 5 天内完成 20 条视频的投放。\n- 总费用 3000 元,目标达到 7.5W 播放量视为合格。\n- 如果有视频完播率大于 40%,可达小热门;大于 50%,可达大热门。\n\n## 数据筛\n\n- 隐藏表现不佳的视频。\n- 选出最佳视频,追加投资 2000 元抖+,针对粉丝量。\n\n## 备注:兴趣标签选择\n\n- 关注二级兴趣标签(整理账号粉丝兴趣分布)。\n- 赛道长尾词通过“创作灵感”找到相关小账号5K-10W 粉丝),避开大 V直接投放吸引其粉丝。\n","source":"_posts/we-media/douyin.md","raw":"---\ntitle: 短视频账号起号逻辑\ntop: 0\ncategories:\n - 自媒体\nstatus: done\n---\n\n# 抖音流量池\n\n| 级别 | 曝光次数 | 播放量范围 |\n| ---------- | -------------------- | ---------- |\n| 初级流量池 | 冷启动 | 0~500 |\n| | 二次曝光 | 3K~5K |\n| | 三次曝光 | 1W~2W |\n| | 四次曝光(人工复审) | 10W~15W |\n| 中级流量池 | 五次曝光 | 30W~70W |\n| 高级流量池 | 六次曝光 | 100W~300W |\n| 热门流量池 | 七次曝光 | 500W~1200W |\n| 全平台曝光 | 八次曝光 | - |\n\n\n# 如何起新号\n\n## 素材整理与发布\n\n- 准备 20 条内容,分成 5 组。\n- 连续 5 天,每天发布 4 条。\n- 每个短视频投入 100 元抖+(选择投放时长 6 小时或 12 小时)。\n- 选取同类账号,确定兴趣标签。\n- 主要关注点赞、评论数据。\n\n## 数据分析与追加投资\n\n- 第二天,基于前一天数据,忽略点赞和评论。\n- 选择完播率最高的视频,追加投资 200 元。\n- 投向粉丝量(选择投放时长 6 小时或 12 小时)。\n\n## 持续操作与评估\n\n- 在 5 天内完成 20 条视频的投放。\n- 总费用 3000 元,目标达到 7.5W 播放量视为合格。\n- 如果有视频完播率大于 40%,可达小热门;大于 50%,可达大热门。\n\n## 数据筛\n\n- 隐藏表现不佳的视频。\n- 选出最佳视频,追加投资 2000 元抖+,针对粉丝量。\n\n## 备注:兴趣标签选择\n\n- 关注二级兴趣标签(整理账号粉丝兴趣分布)。\n- 赛道长尾词通过“创作灵感”找到相关小账号5K-10W 粉丝),避开大 V直接投放吸引其粉丝。\n","slug":"we-media/douyin","published":1,"date":"2023-11-14T07:33:17.858Z","updated":"2023-11-14T07:33:17.858Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58t001b4cz30xaoer0h","content":"<h1 id=\"抖音流量池\"><a href=\"#抖音流量池\" class=\"headerlink\" title=\"抖音流量池\"></a>抖音流量池</h1><table>\n<thead>\n<tr>\n<th>级别</th>\n<th>曝光次数</th>\n<th>播放量范围</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>初级流量池</td>\n<td>冷启动</td>\n<td>0~500</td>\n</tr>\n<tr>\n<td></td>\n<td>二次曝光</td>\n<td>3K~5K</td>\n</tr>\n<tr>\n<td></td>\n<td>三次曝光</td>\n<td>1W~2W</td>\n</tr>\n<tr>\n<td></td>\n<td>四次曝光(人工复审)</td>\n<td>10W~15W</td>\n</tr>\n<tr>\n<td>中级流量池</td>\n<td>五次曝光</td>\n<td>30W~70W</td>\n</tr>\n<tr>\n<td>高级流量池</td>\n<td>六次曝光</td>\n<td>100W~300W</td>\n</tr>\n<tr>\n<td>热门流量池</td>\n<td>七次曝光</td>\n<td>500W~1200W</td>\n</tr>\n<tr>\n<td>全平台曝光</td>\n<td>八次曝光</td>\n<td>-</td>\n</tr>\n</tbody></table>\n<h1 id=\"如何起新号\"><a href=\"#如何起新号\" class=\"headerlink\" title=\"如何起新号\"></a>如何起新号</h1><h2 id=\"素材整理与发布\"><a href=\"#素材整理与发布\" class=\"headerlink\" title=\"素材整理与发布\"></a>素材整理与发布</h2><ul>\n<li>准备 20 条内容,分成 5 组。</li>\n<li>连续 5 天,每天发布 4 条。</li>\n<li>每个短视频投入 100 元抖+(选择投放时长 6 小时或 12 小时)。</li>\n<li>选取同类账号,确定兴趣标签。</li>\n<li>主要关注点赞、评论数据。</li>\n</ul>\n<h2 id=\"数据分析与追加投资\"><a href=\"#数据分析与追加投资\" class=\"headerlink\" title=\"数据分析与追加投资\"></a>数据分析与追加投资</h2><ul>\n<li>第二天,基于前一天数据,忽略点赞和评论。</li>\n<li>选择完播率最高的视频,追加投资 200 元。</li>\n<li>投向粉丝量(选择投放时长 6 小时或 12 小时)。</li>\n</ul>\n<h2 id=\"持续操作与评估\"><a href=\"#持续操作与评估\" class=\"headerlink\" title=\"持续操作与评估\"></a>持续操作与评估</h2><ul>\n<li>在 5 天内完成 20 条视频的投放。</li>\n<li>总费用 3000 元,目标达到 7.5W 播放量视为合格。</li>\n<li>如果有视频完播率大于 40%,可达小热门;大于 50%,可达大热门。</li>\n</ul>\n<h2 id=\"数据筛\"><a href=\"#数据筛\" class=\"headerlink\" title=\"数据筛\"></a>数据筛</h2><ul>\n<li>隐藏表现不佳的视频。</li>\n<li>选出最佳视频,追加投资 2000 元抖+,针对粉丝量。</li>\n</ul>\n<h2 id=\"备注:兴趣标签选择\"><a href=\"#备注:兴趣标签选择\" class=\"headerlink\" title=\"备注:兴趣标签选择\"></a>备注:兴趣标签选择</h2><ul>\n<li>关注二级兴趣标签(整理账号粉丝兴趣分布)。</li>\n<li>赛道长尾词通过“创作灵感”找到相关小账号5K-10W 粉丝),避开大 V直接投放吸引其粉丝。</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h1 id=\"抖音流量池\"><a href=\"#抖音流量池\" class=\"headerlink\" title=\"抖音流量池\"></a>抖音流量池</h1><table>\n<thead>\n<tr>\n<th>级别</th>\n<th>曝光次数</th>\n<th>播放量范围</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>初级流量池</td>\n<td>冷启动</td>\n<td>0~500</td>\n</tr>\n<tr>\n<td></td>\n<td>二次曝光</td>\n<td>3K~5K</td>\n</tr>\n<tr>\n<td></td>\n<td>三次曝光</td>\n<td>1W~2W</td>\n</tr>\n<tr>\n<td></td>\n<td>四次曝光(人工复审)</td>\n<td>10W~15W</td>\n</tr>\n<tr>\n<td>中级流量池</td>\n<td>五次曝光</td>\n<td>30W~70W</td>\n</tr>\n<tr>\n<td>高级流量池</td>\n<td>六次曝光</td>\n<td>100W~300W</td>\n</tr>\n<tr>\n<td>热门流量池</td>\n<td>七次曝光</td>\n<td>500W~1200W</td>\n</tr>\n<tr>\n<td>全平台曝光</td>\n<td>八次曝光</td>\n<td>-</td>\n</tr>\n</tbody></table>\n<h1 id=\"如何起新号\"><a href=\"#如何起新号\" class=\"headerlink\" title=\"如何起新号\"></a>如何起新号</h1><h2 id=\"素材整理与发布\"><a href=\"#素材整理与发布\" class=\"headerlink\" title=\"素材整理与发布\"></a>素材整理与发布</h2><ul>\n<li>准备 20 条内容,分成 5 组。</li>\n<li>连续 5 天,每天发布 4 条。</li>\n<li>每个短视频投入 100 元抖+(选择投放时长 6 小时或 12 小时)。</li>\n<li>选取同类账号,确定兴趣标签。</li>\n<li>主要关注点赞、评论数据。</li>\n</ul>\n<h2 id=\"数据分析与追加投资\"><a href=\"#数据分析与追加投资\" class=\"headerlink\" title=\"数据分析与追加投资\"></a>数据分析与追加投资</h2><ul>\n<li>第二天,基于前一天数据,忽略点赞和评论。</li>\n<li>选择完播率最高的视频,追加投资 200 元。</li>\n<li>投向粉丝量(选择投放时长 6 小时或 12 小时)。</li>\n</ul>\n<h2 id=\"持续操作与评估\"><a href=\"#持续操作与评估\" class=\"headerlink\" title=\"持续操作与评估\"></a>持续操作与评估</h2><ul>\n<li>在 5 天内完成 20 条视频的投放。</li>\n<li>总费用 3000 元,目标达到 7.5W 播放量视为合格。</li>\n<li>如果有视频完播率大于 40%,可达小热门;大于 50%,可达大热门。</li>\n</ul>\n<h2 id=\"数据筛\"><a href=\"#数据筛\" class=\"headerlink\" title=\"数据筛\"></a>数据筛</h2><ul>\n<li>隐藏表现不佳的视频。</li>\n<li>选出最佳视频,追加投资 2000 元抖+,针对粉丝量。</li>\n</ul>\n<h2 id=\"备注:兴趣标签选择\"><a href=\"#备注:兴趣标签选择\" class=\"headerlink\" title=\"备注:兴趣标签选择\"></a>备注:兴趣标签选择</h2><ul>\n<li>关注二级兴趣标签(整理账号粉丝兴趣分布)。</li>\n<li>赛道长尾词通过“创作灵感”找到相关小账号5K-10W 粉丝),避开大 V直接投放吸引其粉丝。</li>\n</ul>\n"},{"title":"非暴力沟通","status":"done","_content":"\n心理学有个史诗级的剧作叫做非暴力沟通它能让一个人温柔而坚定的去说服对方。非暴力沟通大白话讲就是对他人足够的尊重换取他人对你一次积极倾听的机会所以这个技巧的核心是怎么做到尊重。一共分为四步\n\n1.表达事实而非评价比如把你怎么这么不靠谱改成你今天开会迟到了10分钟。\n2.表达情绪而非想法:比如把你一点都不在乎我,改成你这样做我很伤心。\n3.表达需求而非指责:比如把这点小事都做不好,改成这个小事,我们以后不要再犯了。\n4.表达请求而非命令:比如把没做完不许下班,改成下班前可以先给我一个初版?\n\n所以还记得开头那句话吗温柔是对他人尊重而坚定是保护自己不被伤害愿你温柔而坚定\n","source":"_posts/social/非暴力沟通.md","raw":"---\ntitle: 非暴力沟通\ncategories:\n - EQ\nstatus: done\n---\n\n心理学有个史诗级的剧作叫做非暴力沟通它能让一个人温柔而坚定的去说服对方。非暴力沟通大白话讲就是对他人足够的尊重换取他人对你一次积极倾听的机会所以这个技巧的核心是怎么做到尊重。一共分为四步\n\n1.表达事实而非评价比如把你怎么这么不靠谱改成你今天开会迟到了10分钟。\n2.表达情绪而非想法:比如把你一点都不在乎我,改成你这样做我很伤心。\n3.表达需求而非指责:比如把这点小事都做不好,改成这个小事,我们以后不要再犯了。\n4.表达请求而非命令:比如把没做完不许下班,改成下班前可以先给我一个初版?\n\n所以还记得开头那句话吗温柔是对他人尊重而坚定是保护自己不被伤害愿你温柔而坚定\n","slug":"social/非暴力沟通","published":1,"date":"2023-11-06T05:18:46.853Z","updated":"2023-11-06T05:18:59.336Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58t001c4cz3hsj15usi","content":"<p>心理学有个史诗级的剧作叫做非暴力沟通,它能让一个人温柔而坚定的去说服对方。非暴力沟通大白话讲就是对他人足够的尊重,换取他人对你一次积极倾听的机会,所以这个技巧的核心是怎么做到尊重。一共分为四步</p>\n<p>1.表达事实而非评价比如把你怎么这么不靠谱改成你今天开会迟到了10分钟。<br>2.表达情绪而非想法:比如把你一点都不在乎我,改成你这样做我很伤心。<br>3.表达需求而非指责:比如把这点小事都做不好,改成这个小事,我们以后不要再犯了。<br>4.表达请求而非命令:比如把没做完不许下班,改成下班前可以先给我一个初版?</p>\n<p>所以还记得开头那句话吗?温柔是对他人尊重,而坚定是保护自己不被伤害,愿你温柔而坚定</p>\n","site":{"data":{}},"excerpt":"","more":"<p>心理学有个史诗级的剧作叫做非暴力沟通,它能让一个人温柔而坚定的去说服对方。非暴力沟通大白话讲就是对他人足够的尊重,换取他人对你一次积极倾听的机会,所以这个技巧的核心是怎么做到尊重。一共分为四步</p>\n<p>1.表达事实而非评价比如把你怎么这么不靠谱改成你今天开会迟到了10分钟。<br>2.表达情绪而非想法:比如把你一点都不在乎我,改成你这样做我很伤心。<br>3.表达需求而非指责:比如把这点小事都做不好,改成这个小事,我们以后不要再犯了。<br>4.表达请求而非命令:比如把没做完不许下班,改成下班前可以先给我一个初版?</p>\n<p>所以还记得开头那句话吗?温柔是对他人尊重,而坚定是保护自己不被伤害,愿你温柔而坚定</p>\n"},{"title":"有效对话指南","status":"done","_content":"\n卡耐基说过要说服别人同意你的观点你就要让他觉得这是他自己的观点。也就是说本质上没有人真正被别人说服听或者不听都是他们自己的主动选择\n\n# 目的\n\n沟通目的无非两个\n\n- 让对方认同我们的观点\n- 或者按我们说的做\n\n# 搞定情绪\n\n大多数人的立场和行为是由情绪决定的对方不喜欢你你再怎么努力也很难说服他只有他认可你这个人你的话他才会听。所以动之以理之前要先小之以轻你把他情绪搞定了沟通也就成功了一半\n\n## 夸 - 细节\n\n不吝赞美就一个字“夸”具体怎么夸呢\n\n细节就是不要太笼统\n\n- 😭 你穿的真好看 \n- 😊 今天的上衣显得你很白,太美了\n\n## 夸 - 对比\n\n- 😭 你今天穿的真好看\n- 😊 你今天穿的真好看,一般人可传不出这种气质\n\n## 我能理解你,换我也生气\n\n接纳对方的负面情绪把双方情绪拉回到安全范围内。\n\n## 肢体同步\n\n如果你的肢体动作跟对方同步它会产生一种被共情的感觉\n\n- 对方说的火热,身体前倾,伺机凑近\n- 思考一到两秒钟再反馈,这个简单的停顿\n\n# 只陈述不评论\n\n事实不会引起争议\n\n比如孩子考试没及格是事实说他笨死了就是评论了。\n\n再比如你这周上班迟到两次这是事实说你经常迟到就是评论了。\n\n## 评论副词\n\n尽量规避一些跟评论相关的糊的频率副词比如\n- 笨\n- 懒\n- 坏\n- 总是\n- 永远\n- 每次\n\n# 保持开放性\n\n还拿上面的例子这些话对方只能回答好或者不好然后结束沟通\n\n- 孩子没及格,老爸说下次必须及格。\n- 你上班迟到,老板说再迟到扣薪水。\n\n如果换成开放式沟通\n\n- 老爸说咱们聊聊哪些题没有搞清楚\n- 老板说生活上是不是遇到了什么问题,没着我可以帮你\n\n# 反馈事实\n\n这些话对方不仅听着舒服而且能给你反馈事实。具体怎么开放呢咱们只需要记住两个关键词\n\n- 问题开放:不要让对方只能回答是或否,例如:像愿闻其详、展开说说、欢迎补充之类\n- 让出话语权:真正的沟通高手,是让对方觉得自己很牛,主导聊天的往往是能提出问题的人,或者让别人多说的人\n\n","source":"_posts/social/有效对话指南.md","raw":"---\ntitle: 有效对话指南\ncategories:\n - EQ\nstatus: done\n---\n\n卡耐基说过要说服别人同意你的观点你就要让他觉得这是他自己的观点。也就是说本质上没有人真正被别人说服听或者不听都是他们自己的主动选择\n\n# 目的\n\n沟通目的无非两个\n\n- 让对方认同我们的观点\n- 或者按我们说的做\n\n# 搞定情绪\n\n大多数人的立场和行为是由情绪决定的对方不喜欢你你再怎么努力也很难说服他只有他认可你这个人你的话他才会听。所以动之以理之前要先小之以轻你把他情绪搞定了沟通也就成功了一半\n\n## 夸 - 细节\n\n不吝赞美就一个字“夸”具体怎么夸呢\n\n细节就是不要太笼统\n\n- 😭 你穿的真好看 \n- 😊 今天的上衣显得你很白,太美了\n\n## 夸 - 对比\n\n- 😭 你今天穿的真好看\n- 😊 你今天穿的真好看,一般人可传不出这种气质\n\n## 我能理解你,换我也生气\n\n接纳对方的负面情绪把双方情绪拉回到安全范围内。\n\n## 肢体同步\n\n如果你的肢体动作跟对方同步它会产生一种被共情的感觉\n\n- 对方说的火热,身体前倾,伺机凑近\n- 思考一到两秒钟再反馈,这个简单的停顿\n\n# 只陈述不评论\n\n事实不会引起争议\n\n比如孩子考试没及格是事实说他笨死了就是评论了。\n\n再比如你这周上班迟到两次这是事实说你经常迟到就是评论了。\n\n## 评论副词\n\n尽量规避一些跟评论相关的糊的频率副词比如\n- 笨\n- 懒\n- 坏\n- 总是\n- 永远\n- 每次\n\n# 保持开放性\n\n还拿上面的例子这些话对方只能回答好或者不好然后结束沟通\n\n- 孩子没及格,老爸说下次必须及格。\n- 你上班迟到,老板说再迟到扣薪水。\n\n如果换成开放式沟通\n\n- 老爸说咱们聊聊哪些题没有搞清楚\n- 老板说生活上是不是遇到了什么问题,没着我可以帮你\n\n# 反馈事实\n\n这些话对方不仅听着舒服而且能给你反馈事实。具体怎么开放呢咱们只需要记住两个关键词\n\n- 问题开放:不要让对方只能回答是或否,例如:像愿闻其详、展开说说、欢迎补充之类\n- 让出话语权:真正的沟通高手,是让对方觉得自己很牛,主导聊天的往往是能提出问题的人,或者让别人多说的人\n\n","slug":"social/有效对话指南","published":1,"date":"2023-10-24T01:47:38.891Z","updated":"2023-11-06T05:18:11.496Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clp25y58t001e4cz330le440v","content":"<p>卡耐基说过:要说服别人同意你的观点,你就要让他觉得这是他自己的观点。也就是说,本质上没有人真正被别人说服,听或者不听都是他们自己的主动选择</p>\n<h1 id=\"目的\"><a href=\"#目的\" class=\"headerlink\" title=\"目的\"></a>目的</h1><p>沟通目的无非两个:</p>\n<ul>\n<li>让对方认同我们的观点</li>\n<li>或者按我们说的做</li>\n</ul>\n<h1 id=\"搞定情绪\"><a href=\"#搞定情绪\" class=\"headerlink\" title=\"搞定情绪\"></a>搞定情绪</h1><p>大多数人的立场和行为,是由情绪决定的,对方不喜欢你,你再怎么努力也很难说服他,只有他认可你这个人你的话他才会听。所以动之以理之前要先小之以轻,你把他情绪搞定了,沟通也就成功了一半</p>\n<h2 id=\"夸-细节\"><a href=\"#夸-细节\" class=\"headerlink\" title=\"夸 - 细节\"></a>夸 - 细节</h2><p>不吝赞美,就一个字“夸”,具体怎么夸呢?</p>\n<p>细节就是不要太笼统:</p>\n<ul>\n<li>😭 你穿的真好看 </li>\n<li>😊 今天的上衣显得你很白,太美了</li>\n</ul>\n<h2 id=\"夸-对比\"><a href=\"#夸-对比\" class=\"headerlink\" title=\"夸 - 对比\"></a>夸 - 对比</h2><ul>\n<li>😭 你今天穿的真好看</li>\n<li>😊 你今天穿的真好看,一般人可传不出这种气质</li>\n</ul>\n<h2 id=\"我能理解你,换我也生气\"><a href=\"#我能理解你,换我也生气\" class=\"headerlink\" title=\"我能理解你,换我也生气\"></a>我能理解你,换我也生气</h2><p>接纳对方的负面情绪,把双方情绪拉回到安全范围内。</p>\n<h2 id=\"肢体同步\"><a href=\"#肢体同步\" class=\"headerlink\" title=\"肢体同步\"></a>肢体同步</h2><p>如果你的肢体动作跟对方同步,它会产生一种被共情的感觉</p>\n<ul>\n<li>对方说的火热,身体前倾,伺机凑近</li>\n<li>思考一到两秒钟再反馈,这个简单的停顿</li>\n</ul>\n<h1 id=\"只陈述不评论\"><a href=\"#只陈述不评论\" class=\"headerlink\" title=\"只陈述不评论\"></a>只陈述不评论</h1><p>事实不会引起争议</p>\n<p>比如:孩子考试没及格是事实,说他笨死了就是评论了。</p>\n<p>再比如:你这周上班迟到两次,这是事实,说你经常迟到就是评论了。</p>\n<h2 id=\"评论副词\"><a href=\"#评论副词\" class=\"headerlink\" title=\"评论副词\"></a>评论副词</h2><p>尽量规避一些跟评论相关的糊的频率副词,比如</p>\n<ul>\n<li>笨</li>\n<li>懒</li>\n<li>坏</li>\n<li>总是</li>\n<li>永远</li>\n<li>每次</li>\n</ul>\n<h1 id=\"保持开放性\"><a href=\"#保持开放性\" class=\"headerlink\" title=\"保持开放性\"></a>保持开放性</h1><p>还拿上面的例子,这些话对方只能回答好或者不好,然后结束沟通</p>\n<ul>\n<li>孩子没及格,老爸说下次必须及格。</li>\n<li>你上班迟到,老板说再迟到扣薪水。</li>\n</ul>\n<p>如果换成开放式沟通:</p>\n<ul>\n<li>老爸说咱们聊聊哪些题没有搞清楚</li>\n<li>老板说生活上是不是遇到了什么问题,没着我可以帮你</li>\n</ul>\n<h1 id=\"反馈事实\"><a href=\"#反馈事实\" class=\"headerlink\" title=\"反馈事实\"></a>反馈事实</h1><p>这些话对方不仅听着舒服,而且能给你反馈事实。具体怎么开放呢?咱们只需要记住两个关键词</p>\n<ul>\n<li>问题开放:不要让对方只能回答是或否,例如:像愿闻其详、展开说说、欢迎补充之类</li>\n<li>让出话语权:真正的沟通高手,是让对方觉得自己很牛,主导聊天的往往是能提出问题的人,或者让别人多说的人</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<p>卡耐基说过:要说服别人同意你的观点,你就要让他觉得这是他自己的观点。也就是说,本质上没有人真正被别人说服,听或者不听都是他们自己的主动选择</p>\n<h1 id=\"目的\"><a href=\"#目的\" class=\"headerlink\" title=\"目的\"></a>目的</h1><p>沟通目的无非两个:</p>\n<ul>\n<li>让对方认同我们的观点</li>\n<li>或者按我们说的做</li>\n</ul>\n<h1 id=\"搞定情绪\"><a href=\"#搞定情绪\" class=\"headerlink\" title=\"搞定情绪\"></a>搞定情绪</h1><p>大多数人的立场和行为,是由情绪决定的,对方不喜欢你,你再怎么努力也很难说服他,只有他认可你这个人你的话他才会听。所以动之以理之前要先小之以轻,你把他情绪搞定了,沟通也就成功了一半</p>\n<h2 id=\"夸-细节\"><a href=\"#夸-细节\" class=\"headerlink\" title=\"夸 - 细节\"></a>夸 - 细节</h2><p>不吝赞美,就一个字“夸”,具体怎么夸呢?</p>\n<p>细节就是不要太笼统:</p>\n<ul>\n<li>😭 你穿的真好看 </li>\n<li>😊 今天的上衣显得你很白,太美了</li>\n</ul>\n<h2 id=\"夸-对比\"><a href=\"#夸-对比\" class=\"headerlink\" title=\"夸 - 对比\"></a>夸 - 对比</h2><ul>\n<li>😭 你今天穿的真好看</li>\n<li>😊 你今天穿的真好看,一般人可传不出这种气质</li>\n</ul>\n<h2 id=\"我能理解你,换我也生气\"><a href=\"#我能理解你,换我也生气\" class=\"headerlink\" title=\"我能理解你,换我也生气\"></a>我能理解你,换我也生气</h2><p>接纳对方的负面情绪,把双方情绪拉回到安全范围内。</p>\n<h2 id=\"肢体同步\"><a href=\"#肢体同步\" class=\"headerlink\" title=\"肢体同步\"></a>肢体同步</h2><p>如果你的肢体动作跟对方同步,它会产生一种被共情的感觉</p>\n<ul>\n<li>对方说的火热,身体前倾,伺机凑近</li>\n<li>思考一到两秒钟再反馈,这个简单的停顿</li>\n</ul>\n<h1 id=\"只陈述不评论\"><a href=\"#只陈述不评论\" class=\"headerlink\" title=\"只陈述不评论\"></a>只陈述不评论</h1><p>事实不会引起争议</p>\n<p>比如:孩子考试没及格是事实,说他笨死了就是评论了。</p>\n<p>再比如:你这周上班迟到两次,这是事实,说你经常迟到就是评论了。</p>\n<h2 id=\"评论副词\"><a href=\"#评论副词\" class=\"headerlink\" title=\"评论副词\"></a>评论副词</h2><p>尽量规避一些跟评论相关的糊的频率副词,比如</p>\n<ul>\n<li>笨</li>\n<li>懒</li>\n<li>坏</li>\n<li>总是</li>\n<li>永远</li>\n<li>每次</li>\n</ul>\n<h1 id=\"保持开放性\"><a href=\"#保持开放性\" class=\"headerlink\" title=\"保持开放性\"></a>保持开放性</h1><p>还拿上面的例子,这些话对方只能回答好或者不好,然后结束沟通</p>\n<ul>\n<li>孩子没及格,老爸说下次必须及格。</li>\n<li>你上班迟到,老板说再迟到扣薪水。</li>\n</ul>\n<p>如果换成开放式沟通:</p>\n<ul>\n<li>老爸说咱们聊聊哪些题没有搞清楚</li>\n<li>老板说生活上是不是遇到了什么问题,没着我可以帮你</li>\n</ul>\n<h1 id=\"反馈事实\"><a href=\"#反馈事实\" class=\"headerlink\" title=\"反馈事实\"></a>反馈事实</h1><p>这些话对方不仅听着舒服,而且能给你反馈事实。具体怎么开放呢?咱们只需要记住两个关键词</p>\n<ul>\n<li>问题开放:不要让对方只能回答是或否,例如:像愿闻其详、展开说说、欢迎补充之类</li>\n<li>让出话语权:真正的沟通高手,是让对方觉得自己很牛,主导聊天的往往是能提出问题的人,或者让别人多说的人</li>\n</ul>\n"}],"PostAsset":[],"PostCategory":[{"post_id":"clp25y58i00014cz3goob8drj","category_id":"clp25y58l00044cz306yca7vp","_id":"clp25y58n000b4cz3g38jd2fg"},{"post_id":"clp25y58k00034cz3f1qn2ems","category_id":"clp25y58m00084cz3cojwdpah","_id":"clp25y58p000g4cz3cewaa4bo"},{"post_id":"clp25y58l00054cz36gn8061p","category_id":"clp25y58m00084cz3cojwdpah","_id":"clp25y58q000j4cz3dwxbfils"},{"post_id":"clp25y58m00064cz35salcgt5","category_id":"clp25y58p000f4cz31o7a47jo","_id":"clp25y58q000n4cz37w0p9b7p"},{"post_id":"clp25y58q000l4cz31hnu8sy9","category_id":"clp25y58p000f4cz31o7a47jo","_id":"clp25y58r000r4cz3b10z8cqz"},{"post_id":"clp25y58m00074cz31y3lcvvy","category_id":"clp25y58q000k4cz311896all","_id":"clp25y58r000u4cz32cem8tlu"},{"post_id":"clp25y58q000m4cz3dxv034l1","category_id":"clp25y58l00044cz306yca7vp","_id":"clp25y58s000w4cz36fhg1i1i"},{"post_id":"clp25y58q000p4cz3gxzl7mxo","category_id":"clp25y58q000k4cz311896all","_id":"clp25y58s000y4cz3h1bq2dvt"},{"post_id":"clp25y58n00094cz3bshsgix4","category_id":"clp25y58q000k4cz311896all","_id":"clp25y58s000z4cz31mlwf28y"},{"post_id":"clp25y58r000q4cz30t6927bz","category_id":"clp25y58l00044cz306yca7vp","_id":"clp25y58s00114cz30r0830da"},{"post_id":"clp25y58r000t4cz30eqvd8xz","category_id":"clp25y58l00044cz306yca7vp","_id":"clp25y58s00124cz31ucphggd"},{"post_id":"clp25y58n000a4cz39b6r5kmh","category_id":"clp25y58q000k4cz311896all","_id":"clp25y58s00144cz39gv25mpc"},{"post_id":"clp25y58r000v4cz3bm2ichic","category_id":"clp25y58l00044cz306yca7vp","_id":"clp25y58s00154cz3b75u3q5n"},{"post_id":"clp25y58o000d4cz39b94fqx5","category_id":"clp25y58q000k4cz311896all","_id":"clp25y58s00174cz37gi71bpp"},{"post_id":"clp25y58o000e4cz3ffa9d2ke","category_id":"clp25y58q000k4cz311896all","_id":"clp25y58s00184cz355kxhrd3"},{"post_id":"clp25y58p000h4cz3305y5675","category_id":"clp25y58q000k4cz311896all","_id":"clp25y58s00194cz37kgcbcd8"},{"post_id":"clp25y58q000i4cz39r1m7266","category_id":"clp25y58q000k4cz311896all","_id":"clp25y58s001a4cz30nu5ahfb"},{"post_id":"clp25y58t001c4cz3hsj15usi","category_id":"clp25y58l00044cz306yca7vp","_id":"clp25y58t001f4cz310cphg8h"},{"post_id":"clp25y58t001e4cz330le440v","category_id":"clp25y58l00044cz306yca7vp","_id":"clp25y58u001g4cz3crg75hve"},{"post_id":"clp25y58t001b4cz30xaoer0h","category_id":"clp25y58t001d4cz35av6hd5e","_id":"clp25y58u001h4cz38geyhh1z"}],"PostTag":[],"Tag":[]}}