-
Notifications
You must be signed in to change notification settings - Fork 0
/
db.json
1 lines (1 loc) · 482 KB
/
db.json
1
{"meta":{"version":1,"warehouse":"4.0.2"},"models":{"Asset":[{"_id":"source/images/1.png","path":"images/1.png","modified":1,"renderable":0},{"_id":"source/images/10.png","path":"images/10.png","modified":1,"renderable":0},{"_id":"source/images/2.png","path":"images/2.png","modified":1,"renderable":0},{"_id":"source/images/3.png","path":"images/3.png","modified":1,"renderable":0},{"_id":"source/images/4.png","path":"images/4.png","modified":1,"renderable":0},{"_id":"source/images/5.png","path":"images/5.png","modified":1,"renderable":0},{"_id":"source/images/6.png","path":"images/6.png","modified":1,"renderable":0},{"_id":"source/images/7.png","path":"images/7.png","modified":1,"renderable":0},{"_id":"source/images/8.png","path":"images/8.png","modified":1,"renderable":0},{"_id":"source/images/9.png","path":"images/9.png","modified":1,"renderable":0},{"_id":"themes/butterfly/source/css/index.styl","path":"css/index.styl","modified":1,"renderable":1},{"_id":"themes/butterfly/source/css/var.styl","path":"css/var.styl","modified":1,"renderable":1},{"_id":"themes/butterfly/source/js/main.js","path":"js/main.js","modified":1,"renderable":1},{"_id":"themes/butterfly/source/js/tw_cn.js","path":"js/tw_cn.js","modified":1,"renderable":1},{"_id":"themes/butterfly/source/js/utils.js","path":"js/utils.js","modified":1,"renderable":1},{"_id":"themes/butterfly/source/img/404.jpg","path":"img/404.jpg","modified":1,"renderable":1},{"_id":"themes/butterfly/source/img/favicon.png","path":"img/favicon.png","modified":1,"renderable":1},{"_id":"themes/butterfly/source/img/friend_404.gif","path":"img/friend_404.gif","modified":1,"renderable":1},{"_id":"themes/butterfly/source/js/search/algolia.js","path":"js/search/algolia.js","modified":1,"renderable":1},{"_id":"themes/butterfly/source/js/search/local-search.js","path":"js/search/local-search.js","modified":1,"renderable":1}],"Cache":[{"_id":"source/_posts/csrf和xss.md","hash":"1232c06588cf7ffcd0318c419e48ab9b3bab2311","modified":1715242513768},{"_id":"source/_posts/bug.md","hash":"a5a7dd8d8b52362ed6de9c09f1cc48fd230b820f","modified":1688790638591},{"_id":"source/_posts/commitlint.md","hash":"ae9a7beae895537efe6ecc337e5b8403450edd5b","modified":1688790638591},{"_id":"source/_posts/css-modules.md","hash":"13021007ca0936abcde5aa220f6f823eeb0c3b71","modified":1688790638591},{"_id":"source/_posts/dayjs.md","hash":"24cb9f45090e1aeef589343a8db1d5cc298c1954","modified":1688790638592},{"_id":"source/_posts/el-form.md","hash":"39a10bbcc929c6825ec1604a661c93544f119dd1","modified":1688790638592},{"_id":"source/_posts/flex.md","hash":"706aab17ed2e0db68359ca71782520d401155da7","modified":1688790638593},{"_id":"source/_posts/eslint-prettier.md","hash":"d2610c6a069442ebe0b5e02db3596004354dd95f","modified":1688790638592},{"_id":"source/_posts/hello-world.md","hash":"bed22694da31a79bd732e8ec1fef132aaeb3b410","modified":1688790638593},{"_id":"source/_posts/loadsh.md","hash":"1b0887629e93efb353e9df18eb70e7f1fdb7937e","modified":1688790638593},{"_id":"source/_posts/nextjs.md","hash":"976aadaddd0fe91e411512a57083ce23290aee3f","modified":1703581176102},{"_id":"source/_posts/loading.md","hash":"6b5a5136cbc5a694e837ab07fa4c013097bfac36","modified":1692506312793},{"_id":"source/_posts/protable|proform.md","hash":"5244e6849b408f747ef6842c588fa5bdc2aa7223","modified":1688790638594},{"_id":"source/_posts/vue响应式.md","hash":"58300cc6c98e5fb9e2a4eb8651295bce96fd59f3","modified":1688790638594},{"_id":"source/_posts/video.md","hash":"0b9cddb2bbe75a8a87c712237ebf8dc26cbd375c","modified":1703148987984},{"_id":"source/_posts/二次封装el-input.md","hash":"7911b4be9bfdc38afc2af44ab1b408333d859d89","modified":1688790638595},{"_id":"source/_posts/webpack.md","hash":"76eeb669f570c2d8bf1a5d46c5245477b0d75f0e","modified":1688790638595},{"_id":"source/_posts/文件上传.md","hash":"cb1067b95debe5d37d2a695e52f5a8132d6494fc","modified":1688790638595},{"_id":"source/_posts/正则.md","hash":"367f51b832ac5340160ec7096c3b9d9b954240fb","modified":1688790638595},{"_id":"source/categories/index.md","hash":"1cf9b8460be39741dd9f083bb050b0de8f30e9cd","modified":1688790638596},{"_id":"source/_posts/无感刷新token.md","hash":"8437ca47015a300471588e9aa245cb659251adc2","modified":1689503297733},{"_id":"source/_posts/枚举.md","hash":"fbae23f97094f2989b8fb22ccbfb3591f594d3ca","modified":1703487793554},{"_id":"source/my-page/index.md","hash":"9023507d0844beae21c7f34ae4ec666abcfff3a1","modified":1684307833974},{"_id":"source/tags/index.md","hash":"09c22380e155c076729f25dd519256caa2b73f33","modified":1688790638608},{"_id":"source/images/6.png","hash":"6af20d777f03801829a62957dc493504954dc131","modified":1688790638604},{"_id":"source/images/10.png","hash":"7ba4f2323ba669aeec4f1e041e92470f20ca7e0b","modified":1688790638598},{"_id":"source/images/1.png","hash":"912224038210aed13060bef917b97a42a85a926a","modified":1688790638597},{"_id":"source/images/4.png","hash":"5076f16adbe18441a12b8448d76bac87092b5be2","modified":1688790638602},{"_id":"source/images/3.png","hash":"fef819c0dea48117717d0f90c5dfe5e3f1d2ed43","modified":1688790638601},{"_id":"source/images/5.png","hash":"03ea8c494d0dd543209f189f97472526afa8aa64","modified":1688790638603},{"_id":"source/images/7.png","hash":"569c6cf5d0e853930ed96cf53ac78c8a07a65688","modified":1688790638605},{"_id":"source/images/8.png","hash":"886d35fd33e3d357ef0d696eab57c0630500a6fe","modified":1688790638607},{"_id":"source/images/9.png","hash":"9d05164593857d9d45f9b7b4b5955b6c4f7aeed0","modified":1688790638608},{"_id":"source/images/2.png","hash":"566c456d2638403993fd08aabaf968d4c1cedac0","modified":1688790638600},{"_id":"themes/butterfly/README.md","hash":"52967a864c244af4db8c63902586cb617ee5b8aa","modified":1684304955226},{"_id":"themes/butterfly/LICENSE","hash":"1128f8f91104ba9ef98d37eea6523a888dcfa5de","modified":1684304955226},{"_id":"themes/butterfly/README_CN.md","hash":"e19021371184361261ddef1d98eb308d78922714","modified":1684304955226},{"_id":"themes/butterfly/_config.yml","hash":"adc8f25ce9d499c18731b55735e5bc37262383ca","modified":1684304955226},{"_id":"themes/butterfly/package.json","hash":"f19dc1e0af33b877bab3c2f50257430ccfcc064d","modified":1684304955248},{"_id":"themes/butterfly/plugins.yml","hash":"acc74f24c7e94fe9ded264307a4201c9b410cd9b","modified":1684304955248},{"_id":"themes/butterfly/languages/default.yml","hash":"4025c0ba440eb24705dd0293ca9ca84efb3105cc","modified":1684304955227},{"_id":"themes/butterfly/languages/en.yml","hash":"4e9cdb7a3570929bcf082de7a4eac49140dddc73","modified":1684304955227},{"_id":"themes/butterfly/languages/zh-CN.yml","hash":"7dd849c3ba34986c57c764d9e36150b4bfffd2e9","modified":1684304955227},{"_id":"themes/butterfly/languages/zh-TW.yml","hash":"ee01e068f12dc33adfae5733824ea1255deb5ca6","modified":1684304955227},{"_id":"themes/butterfly/layout/archive.pug","hash":"a0c034c2d319320a54046805e80b58dc48b7e233","modified":1684304955228},{"_id":"themes/butterfly/layout/category.pug","hash":"710708cfdb436bc875602abf096c919ccdf544db","modified":1684304955228},{"_id":"themes/butterfly/layout/page.pug","hash":"baf469784aef227e4cc840550888554588e87a13","modified":1684304955247},{"_id":"themes/butterfly/layout/index.pug","hash":"e1c3146834c16e6077406180858add0a8183875a","modified":1684304955247},{"_id":"themes/butterfly/layout/post.pug","hash":"fc9f45252d78fcd15e4a82bfd144401cba5b169a","modified":1684304955247},{"_id":"themes/butterfly/layout/tag.pug","hash":"0440f42569df2676273c026a92384fa7729bc4e9","modified":1684304955248},{"_id":"themes/butterfly/.github/ISSUE_TEMPLATE/bug_report.yml","hash":"fc468a93a64c7a3e408fbac921c9f5a5a8f32027","modified":1684304955225},{"_id":"themes/butterfly/.github/ISSUE_TEMPLATE/config.yml","hash":"7dfe7189ffeaebb6db13842237f8e124649bea3d","modified":1684304955225},{"_id":"themes/butterfly/.github/ISSUE_TEMPLATE/feature_request.yml","hash":"996640605ed1e8e35182f0fd9a60a88783b24b03","modified":1684304955225},{"_id":"themes/butterfly/.github/workflows/publish.yml","hash":"05857c2f265246d8de00e31037f2720709540c09","modified":1684304955225},{"_id":"themes/butterfly/.github/workflows/stale.yml","hash":"ac62b989b5550c756e1986fcc68f243170705383","modified":1684304955226},{"_id":"themes/butterfly/layout/includes/404.pug","hash":"cb49f737aca272ccfeb62880bd651eccee72a129","modified":1684304955228},{"_id":"themes/butterfly/layout/includes/footer.pug","hash":"02390a5b6ae1f57497b22ba2e6be9f13cfb7acac","modified":1684304955228},{"_id":"themes/butterfly/layout/includes/additional-js.pug","hash":"aca0ec7ef69b21d1f242c62fed389468a0f0e1a2","modified":1684304955228},{"_id":"themes/butterfly/layout/includes/head.pug","hash":"dd9fde431add984330e3178e06a8d74705e7340e","modified":1684304955228},{"_id":"themes/butterfly/layout/includes/layout.pug","hash":"7fa9ae4b70b87fc97e992dde5944681f92b59bea","modified":1684304955231},{"_id":"themes/butterfly/layout/includes/pagination.pug","hash":"4c85de4dea4dca4e5088097a79bd6d7009cbf8ef","modified":1684304955233},{"_id":"themes/butterfly/layout/includes/sidebar.pug","hash":"8d39473ed112d113674a0f689f63fae06c72abd2","modified":1684304955234},{"_id":"themes/butterfly/scripts/events/404.js","hash":"83cd7f73225ccad123afbd526ce1834eb1eb6a6d","modified":1684304955248},{"_id":"themes/butterfly/layout/includes/rightside.pug","hash":"83a1f2d31792206d432e8e2041e284d88327c02e","modified":1684304955234},{"_id":"themes/butterfly/scripts/events/cdn.js","hash":"21fb5aabe043486d095c4c8cce361ed85ba88a26","modified":1684304955248},{"_id":"themes/butterfly/scripts/events/init.js","hash":"3ace1139182d3d367149db138990891427f3356e","modified":1684304955249},{"_id":"themes/butterfly/scripts/events/comment.js","hash":"5351e0bc09e6b5b3f6d30f333a2520626a28ca3a","modified":1684304955249},{"_id":"themes/butterfly/scripts/events/stylus.js","hash":"9819f0996234fbd80d6c50a9e526c56ebf22588d","modified":1684304955249},{"_id":"themes/butterfly/scripts/events/welcome.js","hash":"8ad9911b755cba13dde2cc055c3f857a6b0dd20e","modified":1684304955249},{"_id":"themes/butterfly/scripts/helpers/aside_archives.js","hash":"2ec66513d5322f185d2071acc052978ba9415a8e","modified":1684304955250},{"_id":"themes/butterfly/scripts/helpers/aside_categories.js","hash":"e00efdb5d02bc5c6eb4159e498af69fa61a7dbb9","modified":1684304955250},{"_id":"themes/butterfly/scripts/helpers/findArchiveLength.js","hash":"9ea86bd7a3c3fca3324f70b1cd4d9e42f9efb08d","modified":1684304955250},{"_id":"themes/butterfly/scripts/helpers/inject_head_js.js","hash":"4238e06ff448ff2ee717cd4c874f37f04d35da06","modified":1684304955250},{"_id":"themes/butterfly/scripts/helpers/page.js","hash":"ce5d5a3d07b0d76ac5e96e5f9e5783f4b601b6be","modified":1684304955251},{"_id":"themes/butterfly/scripts/helpers/related_post.js","hash":"4677be4175da6800c0b3b8c1614e593f73df8831","modified":1684304955251},{"_id":"themes/butterfly/scripts/tag/button.js","hash":"91d954f6e9fe6e571eb8ec9f8996294b2dc3688e","modified":1684304955251},{"_id":"themes/butterfly/scripts/tag/flink.js","hash":"ab62919fa567b95fbe14889517abda649991b1ee","modified":1684304955251},{"_id":"themes/butterfly/scripts/tag/gallery.js","hash":"950b3dbac0b21717458a8d1769cbfc454d0eff54","modified":1684304955254},{"_id":"themes/butterfly/scripts/tag/inlineImg.js","hash":"a43ee2c7871bdd93cb6beb804429e404570f7929","modified":1684304955254},{"_id":"themes/butterfly/scripts/tag/hide.js","hash":"396c3ab1bcf1c7693ad7e506eadd13016c6769b6","modified":1684304955254},{"_id":"themes/butterfly/scripts/tag/label.js","hash":"03b2afef41d02bd1045c89578a02402c28356006","modified":1684304955254},{"_id":"themes/butterfly/scripts/tag/mermaid.js","hash":"531808a290b8bdd66bac2faab211ada8e9646a37","modified":1684304955254},{"_id":"themes/butterfly/scripts/tag/note.js","hash":"d51812b43924f1bbf413c67499510dd125022005","modified":1684304955255},{"_id":"themes/butterfly/scripts/tag/score.js","hash":"ea679dfe12d0e2290113b4a9d00663ce7a5ee5ad","modified":1684304955255},{"_id":"themes/butterfly/scripts/tag/tabs.js","hash":"6c6e415623d0fd39da016d9e353bb4f5cca444f5","modified":1684304955255},{"_id":"themes/butterfly/scripts/tag/timeline.js","hash":"300eb779588bf35a1b687d9f829d866074b707e3","modified":1684304955255},{"_id":"themes/butterfly/scripts/filters/post_lazyload.js","hash":"932df912976261929f809b7dbd4eb473e7787345","modified":1684304955249},{"_id":"themes/butterfly/scripts/filters/random_cover.js","hash":"8d25f47434deae870bbffd07efe528a40363ab4d","modified":1684304955250},{"_id":"themes/butterfly/source/css/index.styl","hash":"861998e4ac67a59529a8245a9130d68f826c9c12","modified":1684304955265},{"_id":"themes/butterfly/source/css/var.styl","hash":"30abbb8eed880d51f61f336064d93abd709e0115","modified":1684304955265},{"_id":"themes/butterfly/source/js/main.js","hash":"dca55899b7c92ebee6191bef127ea5e2283ecc63","modified":1684304955267},{"_id":"themes/butterfly/source/js/tw_cn.js","hash":"42b106354d72a0ea1fe62587b313a5b7de3cc393","modified":1684304955268},{"_id":"themes/butterfly/source/img/404.jpg","hash":"fb4489bc1d30c93d28f7332158c1c6c1416148de","modified":1684304955266},{"_id":"themes/butterfly/layout/includes/head/Open_Graph.pug","hash":"8aa8d799aedbfd811195b84a451bc4b6e2647c12","modified":1684304955229},{"_id":"themes/butterfly/layout/includes/head/analytics.pug","hash":"67e1c3b48e4ca7ee0b2c76d3ca7476b9883cf105","modified":1684304955229},{"_id":"themes/butterfly/layout/includes/head/config.pug","hash":"75e7a524af64fbaaaf7b05a1b1922bf6940d7afe","modified":1684304955229},{"_id":"themes/butterfly/layout/includes/head/config_site.pug","hash":"7df90c8e432e33716517ab918b0a125bc284041b","modified":1684304955229},{"_id":"themes/butterfly/layout/includes/head/google_adsense.pug","hash":"95a37e92b39c44bcbea4be7e29ddb3921c5b8220","modified":1684304955229},{"_id":"themes/butterfly/layout/includes/head/noscript.pug","hash":"d16ad2ee0ff5751fd7f8a5ce1b83935518674977","modified":1684304955230},{"_id":"themes/butterfly/layout/includes/head/pwa.pug","hash":"3d492cfe645d37c94d30512e0b230b0a09913148","modified":1684304955230},{"_id":"themes/butterfly/layout/includes/head/preconnect.pug","hash":"a03b3ddc06e7aa9fd07eea0d5f97c8d5addd2315","modified":1684304955230},{"_id":"themes/butterfly/source/js/utils.js","hash":"7bec147ae2b313fbd0331d87018f99715368fc4b","modified":1684304955268},{"_id":"themes/butterfly/layout/includes/head/site_verification.pug","hash":"e2e8d681f183f00ce5ee239c42d2e36b3744daad","modified":1684304955230},{"_id":"themes/butterfly/source/img/favicon.png","hash":"3cf89864b4f6c9b532522a4d260a2e887971c92d","modified":1684304955266},{"_id":"themes/butterfly/layout/includes/header/index.pug","hash":"0c1551ef80bbece550fe520d91e21f083cbc14fe","modified":1684304955230},{"_id":"themes/butterfly/source/img/friend_404.gif","hash":"8d2d0ebef70a8eb07329f57e645889b0e420fa48","modified":1684304955267},{"_id":"themes/butterfly/layout/includes/header/menu_item.pug","hash":"31346a210f4f9912c5b29f51d8f659913492f388","modified":1684304955230},{"_id":"themes/butterfly/layout/includes/header/nav.pug","hash":"f61659aa457d1a2d1baa3a13157996cfac4d6609","modified":1684304955231},{"_id":"themes/butterfly/layout/includes/header/social.pug","hash":"5de9a82032cdad1db3b868b797460921cd775fc2","modified":1684304955231},{"_id":"themes/butterfly/layout/includes/header/post-info.pug","hash":"9698f22751778dde063cbfbd01c59ca4462ccd85","modified":1684304955231},{"_id":"themes/butterfly/layout/includes/loading/index.pug","hash":"131f344d68b4c241d6e03849b243ee792fcd3cea","modified":1684304955232},{"_id":"themes/butterfly/layout/includes/loading/fullpage-loading.pug","hash":"68cda524337dfe2e1467318a4a6c124b4c3845a7","modified":1684304955231},{"_id":"themes/butterfly/layout/includes/loading/pace.pug","hash":"6ab4e301c92586505d6cddce1b3ad23b7c79010d","modified":1684304955232},{"_id":"themes/butterfly/layout/includes/mixins/article-sort.pug","hash":"90554c2ca5ba946f4c02e1bc5fe2859cef1b1594","modified":1684304955232},{"_id":"themes/butterfly/layout/includes/mixins/post-ui.pug","hash":"294df7a74cf36af3a7030274d8b745979c1c8c70","modified":1684304955232},{"_id":"themes/butterfly/layout/includes/page/categories.pug","hash":"5276a8d2835e05bd535fedc9f593a0ce8c3e8437","modified":1684304955232},{"_id":"themes/butterfly/layout/includes/page/default-page.pug","hash":"12c65c174d26a41821df9bad26cdf1087ec5b0ca","modified":1684304955232},{"_id":"themes/butterfly/layout/includes/page/flink.pug","hash":"a59bcfbb609a099c1bf5be40b7a94e7e2b06fc4a","modified":1684304955233},{"_id":"themes/butterfly/layout/includes/post/post-copyright.pug","hash":"ebecba46a5f4efe1c98a386df06c56e26fbd07b9","modified":1684304955233},{"_id":"themes/butterfly/layout/includes/page/tags.pug","hash":"9621991359e22b14049346f1cf87bdedc94edf5a","modified":1684304955233},{"_id":"themes/butterfly/layout/includes/post/reward.pug","hash":"864869c43fe5b5bb6f4ac6b13dd4bfb16ea47550","modified":1684304955233},{"_id":"themes/butterfly/layout/includes/third-party/aplayer.pug","hash":"c7cfade2b160380432c47eef4cd62273b6508c58","modified":1684304955234},{"_id":"themes/butterfly/layout/includes/third-party/pangu.pug","hash":"0f024e36b8116118233e10118714bde304e01e12","modified":1684304955243},{"_id":"themes/butterfly/layout/includes/third-party/pjax.pug","hash":"fc0b09068009edd4026d90a669608cbe211aeecf","modified":1684304955243},{"_id":"themes/butterfly/layout/includes/third-party/effect.pug","hash":"6528e86656906117a1af6b90e0349c2c4651d5e1","modified":1684304955240},{"_id":"themes/butterfly/layout/includes/third-party/prismjs.pug","hash":"ffb9ea15a2b54423cd4cd441e2d061b8233e9b58","modified":1684304955243},{"_id":"themes/butterfly/layout/includes/third-party/subtitle.pug","hash":"13015a98d0d5e1ef2cec294231529010395b19de","modified":1684304955245},{"_id":"themes/butterfly/layout/includes/widget/card_announcement.pug","hash":"ae392459ad401a083ca51ee0b27526b3c1e1faed","modified":1684304955245},{"_id":"themes/butterfly/layout/includes/widget/card_archives.pug","hash":"86897010fe71503e239887fd8f6a4f5851737be9","modified":1684304955245},{"_id":"themes/butterfly/layout/includes/widget/card_ad.pug","hash":"60dc48a7b5d89c2a49123c3fc5893ab9c57dd225","modified":1684304955245},{"_id":"themes/butterfly/layout/includes/widget/card_bottom_self.pug","hash":"13dc8ce922e2e2332fe6ad5856ebb5dbf9ea4444","modified":1684304955246},{"_id":"themes/butterfly/layout/includes/widget/card_author.pug","hash":"e37468e63db2a0ac09b65d21b7de3e62425bb455","modified":1684304955246},{"_id":"themes/butterfly/layout/includes/widget/card_categories.pug","hash":"d1a416d0a8a7916d0b1a41d73adc66f8c811e493","modified":1684304955246},{"_id":"themes/butterfly/layout/includes/widget/card_post_toc.pug","hash":"3057a2f6f051355e35d3b205121af8735100eacf","modified":1684304955246},{"_id":"themes/butterfly/layout/includes/widget/card_newest_comment.pug","hash":"6d93564a8bd13cb9b52ee5e178db3bcbf18b1bc6","modified":1684304955246},{"_id":"themes/butterfly/layout/includes/widget/card_recent_post.pug","hash":"e5aac7b28ed4123d75797263c64e74ac547945bc","modified":1684304955246},{"_id":"themes/butterfly/layout/includes/widget/card_tags.pug","hash":"eceb4420a64c720f0d2741e89d6229bbb3d87353","modified":1684304955246},{"_id":"themes/butterfly/layout/includes/widget/card_webinfo.pug","hash":"35ce167c5a275211bfc1fa3d49adfde5b404d98f","modified":1684304955247},{"_id":"themes/butterfly/layout/includes/widget/card_top_self.pug","hash":"ae67c6d4130a6c075058a9c1faea1648bcc6f83e","modified":1684304955247},{"_id":"themes/butterfly/layout/includes/widget/index.pug","hash":"010e3d548ababca2280c4fc4168d9a4a1ee4f536","modified":1684304955247},{"_id":"themes/butterfly/source/css/_highlight/highlight.styl","hash":"57a19eb0c418d92a88b143f56ccb8cd60e6d7ad0","modified":1684304955256},{"_id":"themes/butterfly/source/css/_highlight/theme.styl","hash":"bcd384c8b2aa0390c9eb69ac1abbfd1240ce1da4","modified":1684304955258},{"_id":"themes/butterfly/source/css/_global/function.styl","hash":"7fdfbe8f97b41588bbd5c6f27e7e85a881b28954","modified":1684304955256},{"_id":"themes/butterfly/source/css/_layout/aside.styl","hash":"57adf29a3e36e4ea84384e36c034eb294dffb208","modified":1684304955258},{"_id":"themes/butterfly/source/css/_global/index.styl","hash":"de10b113f9cb9a68d257a39d6409905acfd559ef","modified":1684304955256},{"_id":"themes/butterfly/source/css/_layout/chat.styl","hash":"f9a5d3f1fc5ed0ed2ee4c1eaa58ed650d11ddebd","modified":1684304955258},{"_id":"themes/butterfly/source/css/_layout/comments.styl","hash":"c61dccca690d486c3d9c29cf028d87b777385141","modified":1684304955258},{"_id":"themes/butterfly/source/css/_layout/head.styl","hash":"45d71dbb2a61e30989851ba29bb8be7094574d14","modified":1684304955259},{"_id":"themes/butterfly/source/css/_layout/footer.styl","hash":"83553445fbc92cad4ad220fbd87b4c3db958c32a","modified":1684304955259},{"_id":"themes/butterfly/source/css/_layout/post.styl","hash":"e24046fad288a13897195038cb7a63d1014cd7b8","modified":1684304955259},{"_id":"themes/butterfly/source/css/_layout/loading.styl","hash":"ac2aeee9926f75b2a0098efe1c114126987430f2","modified":1684304955259},{"_id":"themes/butterfly/source/css/_layout/relatedposts.styl","hash":"d53de408cb27a2e704aba7f7402b7caebe0410d8","modified":1684304955260},{"_id":"themes/butterfly/source/css/_layout/pagination.styl","hash":"fb9f78bfbb79579f1d752cb73fb6d25c8418e0fd","modified":1684304955259},{"_id":"themes/butterfly/source/css/_layout/rightside.styl","hash":"bbc884d6b2158a833b77a1bbc07248e17874b22e","modified":1684304955260},{"_id":"themes/butterfly/source/css/_layout/sidebar.styl","hash":"631ca35a38bc4ac052e9caf47508ff1f99842fc7","modified":1684304955260},{"_id":"themes/butterfly/source/css/_layout/reward.styl","hash":"c5cfed620708807a48076b5ee59b0ba84e29aa80","modified":1684304955260},{"_id":"themes/butterfly/source/css/_layout/third-party.styl","hash":"ca39e634668ed4fbb43267ec4782c2b55c44e698","modified":1684304955260},{"_id":"themes/butterfly/source/css/_mode/darkmode.styl","hash":"7ff0c456fae2717ddbbb9f8fae2734d449a5448b","modified":1684304955261},{"_id":"themes/butterfly/source/css/_mode/readmode.styl","hash":"ffea9e7c1543edcf080381e7b99828954c2f2cef","modified":1684304955261},{"_id":"themes/butterfly/source/css/_search/algolia.styl","hash":"649a054e73278b6724bd4dd9b94724791ec5c928","modified":1684304955262},{"_id":"themes/butterfly/source/css/_search/index.styl","hash":"678e56ad2e46b630364540fc6a881d6801192dcd","modified":1684304955263},{"_id":"themes/butterfly/source/css/_search/local-search.styl","hash":"a86e4e9198b225b4b73a7a45f04b86cbbed0d231","modified":1684304955263},{"_id":"themes/butterfly/source/css/_page/404.styl","hash":"50dbb9e6d98c71ffe16741b8c1b0c1b9771efd2b","modified":1684304955261},{"_id":"themes/butterfly/source/css/_page/archives.styl","hash":"c9e98027f2dd730ce389c2047f62ebb748955fcf","modified":1684304955261},{"_id":"themes/butterfly/source/css/_page/common.styl","hash":"e4b9d6164e97b30c84e1218c7543c60f6b29edcc","modified":1684304955262},{"_id":"themes/butterfly/source/css/_page/categories.styl","hash":"f01ee74948cedb44e53cd3bb1ef36b7d2778ede7","modified":1684304955261},{"_id":"themes/butterfly/source/css/_page/flink.styl","hash":"98d755b686ee833e9da10afaa40c4ec2bd66c19a","modified":1684304955262},{"_id":"themes/butterfly/source/css/_page/homepage.styl","hash":"bb470da1d2ba292cae0a30a252f82f37c4130d2d","modified":1684304955262},{"_id":"themes/butterfly/source/css/_page/tags.styl","hash":"580feb7e8b0822a1be48ac380f8c5c53b1523321","modified":1684304955262},{"_id":"themes/butterfly/source/css/_tags/button.styl","hash":"45f0c32bdea117540f6b14ebac6450d7142bd710","modified":1684304955263},{"_id":"themes/butterfly/source/css/_tags/gallery.styl","hash":"81ad85acf0e0fe7f9ee23c16a700e7154574d5dd","modified":1684304955263},{"_id":"themes/butterfly/source/css/_tags/hexo.styl","hash":"d76c38adf1d9c1279ef4241835667789f5b736e0","modified":1684304955263},{"_id":"themes/butterfly/source/css/_tags/hide.styl","hash":"ce489ca2e249e2a3cf71584e20d84bdb022e3475","modified":1684304955264},{"_id":"themes/butterfly/source/css/_tags/inlineImg.styl","hash":"df9d405c33a9a68946b530410f64096bcb72560c","modified":1684304955264},{"_id":"themes/butterfly/source/css/_tags/label.styl","hash":"66c59e193d794cdb02cca7bd1dc4aea5a19d7e84","modified":1684304955264},{"_id":"themes/butterfly/source/css/_tags/tabs.styl","hash":"bf9568444dd54e39dc59b461323dcd38942f27d9","modified":1684304955265},{"_id":"themes/butterfly/source/css/_tags/note.styl","hash":"85ae91c83691ea4511f4277da1194a185251cc78","modified":1684304955265},{"_id":"themes/butterfly/source/css/_tags/timeline.styl","hash":"f071156d439556e7463ed4bc61ceee87170d5d08","modified":1684304955265},{"_id":"themes/butterfly/source/js/search/algolia.js","hash":"fd86281d4f0f99ce173e49c1a0df3507fe268d37","modified":1684304955268},{"_id":"themes/butterfly/source/js/search/local-search.js","hash":"8509cbd954ee9e099dcfbbfdafba70893a56e9ae","modified":1684304955268},{"_id":"themes/butterfly/layout/includes/third-party/abcjs/abcjs.pug","hash":"ed6906b7c6aa7046bbad95dfdda9211997be7099","modified":1684304955234},{"_id":"themes/butterfly/source/css/_third-party/normalize.min.css","hash":"2c18a1c9604af475b4749def8f1959df88d8b276","modified":1684304955265},{"_id":"themes/butterfly/layout/includes/third-party/abcjs/index.pug","hash":"f58f1648d2d71311bafca4833f20b605bb5f18c8","modified":1684304955234},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/artalk.pug","hash":"4ff8e67cd1c9058c0c894737b9b247a812079ae2","modified":1684304955235},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/disqus.pug","hash":"d85c3737b5c9548553a78b757a7698df126a52cf","modified":1684304955235},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/fb.pug","hash":"0344477a2cf38698318ead2681c63ac12f01586e","modified":1684304955235},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/index.pug","hash":"b2d274db84ef22fbd6d5ea8f4404821898934209","modified":1684304955235},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/remark42.pug","hash":"001e8be47854b891efe04013c240c38fed4185eb","modified":1684304955235},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/twikoo.pug","hash":"56c028ba0ea8fac19f0125114d765dfc56ce2b48","modified":1684304955235},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/valine.pug","hash":"39427e107230a10790972349c9dd4c4f31d55eb7","modified":1684304955236},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/waline.pug","hash":"55acc455ca8e13211e3906cf78e487cc92accee5","modified":1684304955236},{"_id":"themes/butterfly/layout/includes/third-party/chat/chatra.pug","hash":"481cd5053bafb1a19f623554a27d3aa077ea59c3","modified":1684304955236},{"_id":"themes/butterfly/layout/includes/third-party/chat/crisp.pug","hash":"76634112c64023177260d1317ae39cef2a68e35f","modified":1684304955237},{"_id":"themes/butterfly/layout/includes/third-party/chat/daovoice.pug","hash":"cfe63e7d26a6665df6aa32ca90868ad48e05ec04","modified":1684304955237},{"_id":"themes/butterfly/layout/includes/third-party/chat/index.pug","hash":"618e1b7f9204049b07beb9e1363c844a78a9ace3","modified":1684304955237},{"_id":"themes/butterfly/layout/includes/third-party/chat/messenger.pug","hash":"3ce0461534b786cb71d9141dff35fa5cb70e22b9","modified":1684304955237},{"_id":"themes/butterfly/layout/includes/third-party/chat/tidio.pug","hash":"24a926756c2300b9c561aaab6bd3a71fdd16e16d","modified":1684304955237},{"_id":"themes/butterfly/layout/includes/third-party/comments/artalk.pug","hash":"90779382c8675e5a0b2d1ef2250294de926707f4","modified":1684304955238},{"_id":"themes/butterfly/layout/includes/third-party/comments/disqus.pug","hash":"9ef303da16d180619da18b146ddb9bc35f66bdbf","modified":1684304955238},{"_id":"themes/butterfly/layout/includes/third-party/comments/disqusjs.pug","hash":"6e17b2cea503eabeb328835038812cfa95f15871","modified":1684304955238},{"_id":"themes/butterfly/layout/includes/third-party/comments/facebook_comments.pug","hash":"0704efed9079c867ab5f7bee7381a6c869154c73","modified":1684304955238},{"_id":"themes/butterfly/layout/includes/third-party/comments/gitalk.pug","hash":"2fc5627eb63118c83df9422b47c801822e28df98","modified":1684304955239},{"_id":"themes/butterfly/layout/includes/third-party/comments/giscus.pug","hash":"5127bc550a2edb1ab9f45416e1964c76e8201544","modified":1684304955238},{"_id":"themes/butterfly/layout/includes/third-party/comments/index.pug","hash":"351fe25fbf02635b1f9e86e5e244c7d61f69baa7","modified":1684304955239},{"_id":"themes/butterfly/layout/includes/third-party/comments/js.pug","hash":"00ed91c52939b9675b316137f854d13684c895a6","modified":1684304955239},{"_id":"themes/butterfly/layout/includes/third-party/comments/livere.pug","hash":"52ea8aa26b84d3ad38ae28cdf0f163e9ca8dced7","modified":1684304955239},{"_id":"themes/butterfly/layout/includes/third-party/comments/twikoo.pug","hash":"4d78f6266d0870c06c10eaf47c951bd4d9a7732e","modified":1684304955240},{"_id":"themes/butterfly/layout/includes/third-party/comments/remark42.pug","hash":"598790433e3c9be28b0063bff08d257acd0abf75","modified":1684304955239},{"_id":"themes/butterfly/layout/includes/third-party/comments/valine.pug","hash":"e55b9c0f8ced231f47eb88bd7f4ec99f29c5c29d","modified":1684304955240},{"_id":"themes/butterfly/layout/includes/third-party/comments/utterances.pug","hash":"2a8d02ed9303092e8816f6489a443e7388102470","modified":1684304955240},{"_id":"themes/butterfly/layout/includes/third-party/comments/waline.pug","hash":"26ba1fc99117993087b1c6e02daa2626627d8eb1","modified":1684304955240},{"_id":"themes/butterfly/layout/includes/third-party/math/index.pug","hash":"b8ae5fd7d74e1edcef21f5004fc96147e064d219","modified":1684304955241},{"_id":"themes/butterfly/layout/includes/third-party/math/katex.pug","hash":"dfcbd9881be569ea420eff1a6b00e4f4dbe2138e","modified":1684304955241},{"_id":"themes/butterfly/layout/includes/third-party/math/mathjax.pug","hash":"0ea633b11b357afa50c200290d19c32467d58a1d","modified":1684304955241},{"_id":"themes/butterfly/layout/includes/third-party/math/mermaid.pug","hash":"d92bbf51626fcc5608b53273cf40db0b5b69c0d4","modified":1684304955241},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/artalk.pug","hash":"3942d6643683a3c42bbb5f4cf4a7df21debb8498","modified":1684304955241},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/disqus-comment.pug","hash":"4fe8faf77b8420fc031ae1b54f78b2ece9fcc07e","modified":1684304955242},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/github-issues.pug","hash":"0330e3063ccf0ce40e4828b8d4fbef62362e8195","modified":1684304955242},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/index.pug","hash":"4ec0642f2d5444acfab570a6f8c7868e7ff43fde","modified":1684304955242},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/remark42.pug","hash":"aa6061183a32472cd1882fce445a5049108a984b","modified":1684304955242},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/twikoo-comment.pug","hash":"44991d67abb81784c5cdb4337b2b9798fc4361e1","modified":1684304955242},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/valine.pug","hash":"b7b2aa5be4112065d5066c0f066f5f58721153bf","modified":1684304955242},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/waline.pug","hash":"531d7b6992a737742f7b3ae343e1f03aab947f4c","modified":1684304955243},{"_id":"themes/butterfly/layout/includes/third-party/search/algolia.pug","hash":"9c3c109a12d2b6916e8b4965cca12f521510ead9","modified":1684304955243},{"_id":"themes/butterfly/layout/includes/third-party/search/docsearch.pug","hash":"1c3e101445c5571ba998ce293d3984319df1b3b0","modified":1684304955244},{"_id":"themes/butterfly/layout/includes/third-party/search/index.pug","hash":"a99a41334387ee9a46c6f8e8212331a29a10d159","modified":1684304955244},{"_id":"themes/butterfly/layout/includes/third-party/search/local-search.pug","hash":"5ebd5e8d39c9f77f5b2d983f6cd6802ccaf98746","modified":1684304955244},{"_id":"themes/butterfly/layout/includes/third-party/share/add-this.pug","hash":"2980f1889226ca981aa23b8eb1853fde26dcf89a","modified":1684304955244},{"_id":"themes/butterfly/layout/includes/third-party/share/addtoany.pug","hash":"85c92f8a7e44d7cd1c86f089a05be438535e5362","modified":1684304955244},{"_id":"themes/butterfly/layout/includes/third-party/share/index.pug","hash":"4c4a9c15215ae8ac5eadb0e086b278f76db9ee92","modified":1684304955244},{"_id":"themes/butterfly/layout/includes/third-party/share/share-js.pug","hash":"c7dd2b2ae9b23aa0a60fffd7df9e9f76ef52033e","modified":1684304955245},{"_id":"themes/butterfly/source/css/_highlight/highlight/diff.styl","hash":"cf1fae641c927621a4df1be5ca4a853b9b526e23","modified":1684304955256},{"_id":"themes/butterfly/source/css/_highlight/highlight/index.styl","hash":"18804c58239d95798fa86d0597f32d7f7dd30051","modified":1684304955257},{"_id":"themes/butterfly/source/css/_highlight/prismjs/diff.styl","hash":"5972c61f5125068cbe0af279a0c93a54847fdc3b","modified":1684304955257},{"_id":"themes/butterfly/source/css/_highlight/prismjs/index.styl","hash":"5dc2e0bcae9a54bfb9bdcc82d02ae5a3cf1ca97d","modified":1684304955257},{"_id":"themes/butterfly/source/css/_highlight/prismjs/line-number.styl","hash":"8970cc1916c982b64a1478792b2822d1d31e276d","modified":1684304955257},{"_id":"public/my-page/index.html","hash":"7ec144ead6c5ac8ba95d76b8aa590b18c1360109","modified":1715242556185},{"_id":"public/tags/index.html","hash":"c5a2fa4df0856e355a1aba4240c5f0d93a49250f","modified":1715242556185},{"_id":"public/2023/07/08/bug/index.html","hash":"d86facaec0b9f75040bbf46bf37ed429557a8128","modified":1715242556185},{"_id":"public/2023/07/08/flex/index.html","hash":"2bfad9a061f2b1a1e45b2e239a8d552291ee22a8","modified":1715242556185},{"_id":"public/2023/07/08/正则/index.html","hash":"d696b8d993ca7e2c48e815ff9d7d1ddfe943f769","modified":1715242556185},{"_id":"public/archives/2023/05/index.html","hash":"6cac9ab71130b3e05cda19e56613dfcda4613efd","modified":1715242556185},{"_id":"public/archives/2023/08/index.html","hash":"54153e67069e4213105b6edc8ee8b177b329e648","modified":1715242556185},{"_id":"public/archives/2024/index.html","hash":"09f5ef4eb1890d044764b6c328c8131e571f6f04","modified":1715242556185},{"_id":"public/archives/2024/05/index.html","hash":"2bef686b8c5a4ef013ae8f24a82cf7bd0e8b9b5a","modified":1715242556185},{"_id":"public/categories/vue/index.html","hash":"017dab0aa275b757e375a539b40a5cbc0ae0b9c6","modified":1715242556185},{"_id":"public/categories/代码规范/index.html","hash":"fdf4d4674f5198dbdbe4b285522901b356966410","modified":1715242556185},{"_id":"public/categories/打包工具/index.html","hash":"034542520d08da5d90c57c4ecc88200bfe9f23a7","modified":1715242556185},{"_id":"public/categories/插件使用/index.html","hash":"a8e52271f6b530bcd4f32617bcf89e60fcbdeff6","modified":1715242556185},{"_id":"public/categories/css/index.html","hash":"3aad7170dcd8bb1ec35b1cd48b77aa40e270b62b","modified":1715242556185},{"_id":"public/categories/性能优化/index.html","hash":"3a32b380fedf189e372e0dad493b4a9f0e0bc065","modified":1715242556185},{"_id":"public/tags/dayjs/index.html","hash":"ec2de9d6efa862b34ef6a968d6416c54907c2c7c","modified":1715242556185},{"_id":"public/categories/index.html","hash":"484494b7be738deb9a8f4983934cadda0f61c57e","modified":1715242556185},{"_id":"public/2024/05/09/csrf和xss/index.html","hash":"273cebd6fc492f99c5a4798c3d15fcd2a2246405","modified":1715242556185},{"_id":"public/2023/12/26/nextjs/index.html","hash":"943b7ed00935545643e7467365d60dd42c3aeb01","modified":1715242556185},{"_id":"public/2023/12/25/枚举/index.html","hash":"c9c972ad5d2b7d5f43cfdfe00a3a58b944e0bba8","modified":1715242556185},{"_id":"public/2023/12/21/video/index.html","hash":"3d20c89ef4a593f38bd1a79912455b187ccb9baa","modified":1715242556185},{"_id":"public/2023/08/20/loading/index.html","hash":"dc99ece00ef9616e4aaf469df283cb929c845a82","modified":1715242556185},{"_id":"public/2023/07/16/无感刷新token/index.html","hash":"6286322d19ba3a9f5677c142eca5c407bd720f43","modified":1715242556185},{"_id":"public/2023/07/08/webpack/index.html","hash":"97619e8134b0bc3d0ce2bd832ca5eaf5143e4158","modified":1715242556185},{"_id":"public/2023/07/08/hello-world/index.html","hash":"727958a2f6b408469ef2374ff3a362415b1f93d6","modified":1715242556185},{"_id":"public/2023/07/08/commitlint/index.html","hash":"c34e124a55486cde662d0a227397cc728cd9fdc6","modified":1715242556185},{"_id":"public/2023/07/08/css-modules/index.html","hash":"92a3d7085880ca658593d6646418b744a4502a36","modified":1715242556185},{"_id":"public/2023/07/08/二次封装el-input/index.html","hash":"aaccfa522726632175f89c27e371ab85c517f6d1","modified":1715242556185},{"_id":"public/2023/07/08/protable|proform/index.html","hash":"f7f3d990bcc09bb312f1f521cf839ca7268383a7","modified":1715242556185},{"_id":"public/2023/07/08/文件上传/index.html","hash":"1655d1de96dfa96ed4db83145b35b837cb4b1b38","modified":1715242556185},{"_id":"public/2023/07/08/el-form/index.html","hash":"8b21bcb220f0426953b2f64e1fa8b16593d469a4","modified":1715242556185},{"_id":"public/2023/07/08/vue响应式/index.html","hash":"72df9f30dee584aa7f4fadff9dea5019b842e073","modified":1715242556185},{"_id":"public/2023/07/08/dayjs/index.html","hash":"c3a7c65850397178c8a480f686258033106ef026","modified":1715242556185},{"_id":"public/2023/05/16/eslint-prettier/index.html","hash":"fa93ba0e717e663f35d69a5273f1c9dbf31fe0b1","modified":1715242556185},{"_id":"public/archives/index.html","hash":"7ca195658474f3662f2ab1a42a7ad51921fb884d","modified":1715242556185},{"_id":"public/archives/page/2/index.html","hash":"bbc2d2e3ac0fe8b35ee3afea002ce91138a2a80b","modified":1715242556185},{"_id":"public/archives/2023/index.html","hash":"b36d3a090e505166ae05c3817dcc386a5ab0713e","modified":1715242556185},{"_id":"public/archives/2023/page/2/index.html","hash":"ce2784eed071202c259e95b48124ed4981040db1","modified":1715242556185},{"_id":"public/archives/2023/07/index.html","hash":"0ef2e2043150813e5aab668e455211e02d9fdced","modified":1715242556185},{"_id":"public/archives/2023/07/page/2/index.html","hash":"279b3c3a21bbd77c526e6bdbc2071e17a5187816","modified":1715242556185},{"_id":"public/archives/2023/12/index.html","hash":"c3bc790342599e913cfeaf362d5e8938fbcaa1d8","modified":1715242556185},{"_id":"public/categories/UI组件/index.html","hash":"092c47bb0dc1137ef4cdea5166a23afe9c40c3f6","modified":1715242556185},{"_id":"public/index.html","hash":"c37a9385899008eca32d38458b38be3166e1171d","modified":1715242556185},{"_id":"public/page/2/index.html","hash":"3d344d036a8af194fc3c1492573a0b3d7a22a139","modified":1715242556185},{"_id":"public/img/404.jpg","hash":"fb4489bc1d30c93d28f7332158c1c6c1416148de","modified":1715242556185},{"_id":"public/img/favicon.png","hash":"3cf89864b4f6c9b532522a4d260a2e887971c92d","modified":1715242556185},{"_id":"public/img/friend_404.gif","hash":"8d2d0ebef70a8eb07329f57e645889b0e420fa48","modified":1715242556185},{"_id":"public/js/search/algolia.js","hash":"fd86281d4f0f99ce173e49c1a0df3507fe268d37","modified":1715242556185},{"_id":"public/js/utils.js","hash":"7bec147ae2b313fbd0331d87018f99715368fc4b","modified":1715242556185},{"_id":"public/js/search/local-search.js","hash":"8509cbd954ee9e099dcfbbfdafba70893a56e9ae","modified":1715242556185},{"_id":"public/css/var.css","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1715242556185},{"_id":"public/js/tw_cn.js","hash":"42b106354d72a0ea1fe62587b313a5b7de3cc393","modified":1715242556185},{"_id":"public/js/main.js","hash":"dca55899b7c92ebee6191bef127ea5e2283ecc63","modified":1715242556185},{"_id":"public/css/index.css","hash":"2909ac961debcc749507ff42036e833d52207050","modified":1715242556185},{"_id":"public/images/6.png","hash":"6af20d777f03801829a62957dc493504954dc131","modified":1715242556185},{"_id":"public/images/4.png","hash":"5076f16adbe18441a12b8448d76bac87092b5be2","modified":1715242556185},{"_id":"public/images/1.png","hash":"912224038210aed13060bef917b97a42a85a926a","modified":1715242556185},{"_id":"public/images/3.png","hash":"fef819c0dea48117717d0f90c5dfe5e3f1d2ed43","modified":1715242556185},{"_id":"public/images/7.png","hash":"569c6cf5d0e853930ed96cf53ac78c8a07a65688","modified":1715242556185},{"_id":"public/images/8.png","hash":"886d35fd33e3d357ef0d696eab57c0630500a6fe","modified":1715242556185},{"_id":"public/images/5.png","hash":"03ea8c494d0dd543209f189f97472526afa8aa64","modified":1715242556185},{"_id":"public/images/10.png","hash":"7ba4f2323ba669aeec4f1e041e92470f20ca7e0b","modified":1715242556185},{"_id":"public/images/9.png","hash":"9d05164593857d9d45f9b7b4b5955b6c4f7aeed0","modified":1715242556185},{"_id":"public/images/2.png","hash":"566c456d2638403993fd08aabaf968d4c1cedac0","modified":1715242556185}],"Category":[{"name":"vue","_id":"clvyz4r010004a9liahasavcd"},{"name":"代码规范","_id":"clvyz4r060009a9li57k60iuf"},{"name":"打包工具","_id":"clvyz4r0a000ea9libg6ggbzh"},{"name":"插件使用","_id":"clvyz4r0d000ia9lidlqzbrgg"},{"name":"UI组件","_id":"clvyz4r0f000oa9lie44x0c2e"},{"name":"css","_id":"clvyz4r0i000ta9lifjdo18yv"},{"name":"性能优化","_id":"clvyz4r0o0014a9li5yrj9bop"}],"Data":[],"Page":[{"title":"categories","date":"2023-07-07T11:24:11.000Z","type":"categories","_content":"","source":"categories/index.md","raw":"---\ntitle: categories\ndate: 2023-07-07 19:24:11\ntype: 'categories'\n---\n","updated":"2023-07-08T04:30:38.596Z","path":"categories/index.html","comments":1,"layout":"page","_id":"clvyz4qzq0000a9li9nljhe9p","content":"","site":{"data":{}},"cover":false,"excerpt":"","more":""},{"title":"my-page","date":"2023-05-17T06:55:30.000Z","_content":"","source":"my-page/index.md","raw":"---\ntitle: my-page\ndate: 2023-05-17 14:55:30\n---\n","updated":"2023-05-17T07:17:13.974Z","path":"my-page/index.html","comments":1,"layout":"page","_id":"clvyz4qzy0002a9liemqnf7vp","content":"","site":{"data":{}},"cover":false,"excerpt":"","more":""},{"title":"tags","date":"2023-07-07T11:31:32.000Z","type":"tags","_content":"","source":"tags/index.md","raw":"---\ntitle: tags\ndate: 2023-07-07 19:31:32\ntype: 'tags'\n---\n","updated":"2023-07-08T04:30:38.608Z","path":"tags/index.html","comments":1,"layout":"page","_id":"clvyz4r020005a9li8r9ee8gi","content":"","site":{"data":{}},"cover":false,"excerpt":"","more":""}],"Post":[{"title":"bug","date":"2023-07-08T02:55:28.000Z","_content":"\nv-for中设置:key=\"index\",在数组中使用splice方法,结果造成数据删除或增加数据时混乱,这是因为虚拟dom时会将旧和新的vnode进行比较,但是两者之间的key又没有发生变化,造成了数据混乱,所以尽量不要使用index作为key\n![](../images/9.png)\n![](../images/10.png)\n","source":"_posts/bug.md","raw":"---\ntitle: bug\ndate: 2023-07-08 10:55:28\ntags:\ncategories:\n - vue\n---\n\nv-for中设置:key=\"index\",在数组中使用splice方法,结果造成数据删除或增加数据时混乱,这是因为虚拟dom时会将旧和新的vnode进行比较,但是两者之间的key又没有发生变化,造成了数据混乱,所以尽量不要使用index作为key\n![](../images/9.png)\n![](../images/10.png)\n","slug":"bug","published":1,"updated":"2023-07-08T04:30:38.591Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4qzu0001a9libld10tob","content":"<p>v-for中设置:key=”index”,在数组中使用splice方法,结果造成数据删除或增加数据时混乱,这是因为虚拟dom时会将旧和新的vnode进行比较,但是两者之间的key又没有发生变化,造成了数据混乱,所以尽量不要使用index作为key<br><img src=\"/../images/9.png\"><br><img src=\"/../images/10.png\"></p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<p>v-for中设置:key=”index”,在数组中使用splice方法,结果造成数据删除或增加数据时混乱,这是因为虚拟dom时会将旧和新的vnode进行比较,但是两者之间的key又没有发生变化,造成了数据混乱,所以尽量不要使用index作为key<br><img src=\"/../images/9.png\"><br><img src=\"/../images/10.png\"></p>\n"},{"title":"commitlint+husky+lint-staged","_content":"\n### 为什么要使用\n\n多人开发的时候,commit message五花八门,统一规范有利于及时查找出错的提交代码,从而定位到具体的问题\n如何使用\n\n#### ●husky\n\ngit hooks工具,可以在执行git命令时,执行自定义脚本程序\n\n```js\nnpm i -D husky\nnpx husky install\nnpm set-script prepare \"husky install\"\n```\n\n//执行完上面的操作之后,项目中会多一个.husky文件夹,并且package.json中增加以下命令\n\n```js\n{\n \"scripts\": {\n \"prepare\": \"husky install\"\n }\n}\n// 现在husky已经安装好了,接下来添加对应的钩子函数,比如我需要在每次git commit提交前执行某些操作,就可以添加一个commit-msg钩子\nnpx husky add .husky/commit-msg 'npm test'\n//然后.husky目录下会增加一个commit-msg文件,每一次git commit 都会执行一词npm test(注:这一行只是测试,后面加了npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'需要把这一行注释掉,不然提交代码会报错\n//如果遇到特殊情况,要绕过git hooks,可以使用--no-verify\n```\n\n#### ●commitLint\n\n检查git commit 内容是否符合规范,只有符合规范的commit命令才能提交\n\n```js\nnpm i -D @commitlint/{config-conventional,cli}\n\n// 创建一个commitlint.config.js文件\nmodule.exports = { extends: ['@commitlint/config-conventional'] };\n\n// 上面已经引入了husky,所以修改一下commit-msg脚本,在每次git commmit时执行commitlint校验\nnpx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'\n# or\nyarn husky add .husky/commit-msg 'yarn commitlint --edit $1'\n```\n\n#### ●lint-staged\n\n对暂存区的文件执行脚本,在提交代码的时候,可以通过eslint+prettier等工具格式化代码,但是如果直接处理全部代码,首先就是可能存在性能问题,其次就是可能会修改掉其他同事的代码,这时可以引入lint-staged,它可以过滤出git 暂存区的代码,这样就不要影响到未更改的文件\n\n```js\nnpm i lint-staged -D\n```\n\n//然后在项目根目录创建.lintstagedrc,配置所需的规则\n\n```\n{\n \"*.{js,jsx,less,md,json}\": [\n \"prettier --write\"\n ],\n \"*.ts?(x)\": [\n \"prettier --parser=typescript --write\",\n \"eslint --quiet\"\n ]\n}\n```\n\n最后通过husky来执行lint-staged\n\n```js\nnpx husky add .husky/pre-commit 'npx lint-staged'\n```\n","source":"_posts/commitlint.md","raw":"---\ntitle: commitlint+husky+lint-staged\ncategories:\n - 代码规范\n---\n\n### 为什么要使用\n\n多人开发的时候,commit message五花八门,统一规范有利于及时查找出错的提交代码,从而定位到具体的问题\n如何使用\n\n#### ●husky\n\ngit hooks工具,可以在执行git命令时,执行自定义脚本程序\n\n```js\nnpm i -D husky\nnpx husky install\nnpm set-script prepare \"husky install\"\n```\n\n//执行完上面的操作之后,项目中会多一个.husky文件夹,并且package.json中增加以下命令\n\n```js\n{\n \"scripts\": {\n \"prepare\": \"husky install\"\n }\n}\n// 现在husky已经安装好了,接下来添加对应的钩子函数,比如我需要在每次git commit提交前执行某些操作,就可以添加一个commit-msg钩子\nnpx husky add .husky/commit-msg 'npm test'\n//然后.husky目录下会增加一个commit-msg文件,每一次git commit 都会执行一词npm test(注:这一行只是测试,后面加了npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'需要把这一行注释掉,不然提交代码会报错\n//如果遇到特殊情况,要绕过git hooks,可以使用--no-verify\n```\n\n#### ●commitLint\n\n检查git commit 内容是否符合规范,只有符合规范的commit命令才能提交\n\n```js\nnpm i -D @commitlint/{config-conventional,cli}\n\n// 创建一个commitlint.config.js文件\nmodule.exports = { extends: ['@commitlint/config-conventional'] };\n\n// 上面已经引入了husky,所以修改一下commit-msg脚本,在每次git commmit时执行commitlint校验\nnpx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'\n# or\nyarn husky add .husky/commit-msg 'yarn commitlint --edit $1'\n```\n\n#### ●lint-staged\n\n对暂存区的文件执行脚本,在提交代码的时候,可以通过eslint+prettier等工具格式化代码,但是如果直接处理全部代码,首先就是可能存在性能问题,其次就是可能会修改掉其他同事的代码,这时可以引入lint-staged,它可以过滤出git 暂存区的代码,这样就不要影响到未更改的文件\n\n```js\nnpm i lint-staged -D\n```\n\n//然后在项目根目录创建.lintstagedrc,配置所需的规则\n\n```\n{\n \"*.{js,jsx,less,md,json}\": [\n \"prettier --write\"\n ],\n \"*.ts?(x)\": [\n \"prettier --parser=typescript --write\",\n \"eslint --quiet\"\n ]\n}\n```\n\n最后通过husky来执行lint-staged\n\n```js\nnpx husky add .husky/pre-commit 'npx lint-staged'\n```\n","slug":"commitlint","published":1,"date":"2023-07-08T04:30:38.591Z","updated":"2023-07-08T04:30:38.591Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4qzz0003a9libcdvdhbp","content":"<h3 id=\"为什么要使用\"><a href=\"#为什么要使用\" class=\"headerlink\" title=\"为什么要使用\"></a>为什么要使用</h3><p>多人开发的时候,commit message五花八门,统一规范有利于及时查找出错的提交代码,从而定位到具体的问题<br>如何使用</p>\n<h4 id=\"●husky\"><a href=\"#●husky\" class=\"headerlink\" title=\"●husky\"></a>●husky</h4><p>git hooks工具,可以在执行git命令时,执行自定义脚本程序</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i -D husky</span><br><span class=\"line\">npx husky install</span><br><span class=\"line\">npm set-script prepare <span class=\"string\">"husky install"</span></span><br></pre></td></tr></table></figure>\n\n<p>//执行完上面的操作之后,项目中会多一个.husky文件夹,并且package.json中增加以下命令</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"string\">"scripts"</span>: {</span><br><span class=\"line\"> <span class=\"string\">"prepare"</span>: <span class=\"string\">"husky install"</span></span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"comment\">// 现在husky已经安装好了,接下来添加对应的钩子函数,比如我需要在每次git commit提交前执行某些操作,就可以添加一个commit-msg钩子</span></span><br><span class=\"line\">npx husky add .<span class=\"property\">husky</span>/commit-msg <span class=\"string\">'npm test'</span></span><br><span class=\"line\"><span class=\"comment\">//然后.husky目录下会增加一个commit-msg文件,每一次git commit 都会执行一词npm test(注:这一行只是测试,后面加了npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'需要把这一行注释掉,不然提交代码会报错</span></span><br><span class=\"line\"><span class=\"comment\">//如果遇到特殊情况,要绕过git hooks,可以使用--no-verify</span></span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●commitLint\"><a href=\"#●commitLint\" class=\"headerlink\" title=\"●commitLint\"></a>●commitLint</h4><p>检查git commit 内容是否符合规范,只有符合规范的commit命令才能提交</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i -D @commitlint/{config-conventional,cli}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 创建一个commitlint.config.js文件</span></span><br><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = { <span class=\"attr\">extends</span>: [<span class=\"string\">'@commitlint/config-conventional'</span>] };</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 上面已经引入了husky,所以修改一下commit-msg脚本,在每次git commmit时执行commitlint校验</span></span><br><span class=\"line\">npx husky add .<span class=\"property\">husky</span>/commit-msg <span class=\"string\">'npx --no -- commitlint --edit $1'</span></span><br><span class=\"line\"># or</span><br><span class=\"line\">yarn husky add .<span class=\"property\">husky</span>/commit-msg <span class=\"string\">'yarn commitlint --edit $1'</span></span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●lint-staged\"><a href=\"#●lint-staged\" class=\"headerlink\" title=\"●lint-staged\"></a>●lint-staged</h4><p>对暂存区的文件执行脚本,在提交代码的时候,可以通过eslint+prettier等工具格式化代码,但是如果直接处理全部代码,首先就是可能存在性能问题,其次就是可能会修改掉其他同事的代码,这时可以引入lint-staged,它可以过滤出git 暂存区的代码,这样就不要影响到未更改的文件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i lint-staged -D</span><br></pre></td></tr></table></figure>\n\n<p>//然后在项目根目录创建.lintstagedrc,配置所需的规则</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> "*.{js,jsx,less,md,json}": [</span><br><span class=\"line\"> "prettier --write"</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> "*.ts?(x)": [</span><br><span class=\"line\"> "prettier --parser=typescript --write",</span><br><span class=\"line\"> "eslint --quiet"</span><br><span class=\"line\"> ]</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>最后通过husky来执行lint-staged</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npx husky add .<span class=\"property\">husky</span>/pre-commit <span class=\"string\">'npx lint-staged'</span></span><br></pre></td></tr></table></figure>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"为什么要使用\"><a href=\"#为什么要使用\" class=\"headerlink\" title=\"为什么要使用\"></a>为什么要使用</h3><p>多人开发的时候,commit message五花八门,统一规范有利于及时查找出错的提交代码,从而定位到具体的问题<br>如何使用</p>\n<h4 id=\"●husky\"><a href=\"#●husky\" class=\"headerlink\" title=\"●husky\"></a>●husky</h4><p>git hooks工具,可以在执行git命令时,执行自定义脚本程序</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i -D husky</span><br><span class=\"line\">npx husky install</span><br><span class=\"line\">npm set-script prepare <span class=\"string\">"husky install"</span></span><br></pre></td></tr></table></figure>\n\n<p>//执行完上面的操作之后,项目中会多一个.husky文件夹,并且package.json中增加以下命令</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"string\">"scripts"</span>: {</span><br><span class=\"line\"> <span class=\"string\">"prepare"</span>: <span class=\"string\">"husky install"</span></span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"comment\">// 现在husky已经安装好了,接下来添加对应的钩子函数,比如我需要在每次git commit提交前执行某些操作,就可以添加一个commit-msg钩子</span></span><br><span class=\"line\">npx husky add .<span class=\"property\">husky</span>/commit-msg <span class=\"string\">'npm test'</span></span><br><span class=\"line\"><span class=\"comment\">//然后.husky目录下会增加一个commit-msg文件,每一次git commit 都会执行一词npm test(注:这一行只是测试,后面加了npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'需要把这一行注释掉,不然提交代码会报错</span></span><br><span class=\"line\"><span class=\"comment\">//如果遇到特殊情况,要绕过git hooks,可以使用--no-verify</span></span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●commitLint\"><a href=\"#●commitLint\" class=\"headerlink\" title=\"●commitLint\"></a>●commitLint</h4><p>检查git commit 内容是否符合规范,只有符合规范的commit命令才能提交</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i -D @commitlint/{config-conventional,cli}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 创建一个commitlint.config.js文件</span></span><br><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = { <span class=\"attr\">extends</span>: [<span class=\"string\">'@commitlint/config-conventional'</span>] };</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 上面已经引入了husky,所以修改一下commit-msg脚本,在每次git commmit时执行commitlint校验</span></span><br><span class=\"line\">npx husky add .<span class=\"property\">husky</span>/commit-msg <span class=\"string\">'npx --no -- commitlint --edit $1'</span></span><br><span class=\"line\"># or</span><br><span class=\"line\">yarn husky add .<span class=\"property\">husky</span>/commit-msg <span class=\"string\">'yarn commitlint --edit $1'</span></span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●lint-staged\"><a href=\"#●lint-staged\" class=\"headerlink\" title=\"●lint-staged\"></a>●lint-staged</h4><p>对暂存区的文件执行脚本,在提交代码的时候,可以通过eslint+prettier等工具格式化代码,但是如果直接处理全部代码,首先就是可能存在性能问题,其次就是可能会修改掉其他同事的代码,这时可以引入lint-staged,它可以过滤出git 暂存区的代码,这样就不要影响到未更改的文件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i lint-staged -D</span><br></pre></td></tr></table></figure>\n\n<p>//然后在项目根目录创建.lintstagedrc,配置所需的规则</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> "*.{js,jsx,less,md,json}": [</span><br><span class=\"line\"> "prettier --write"</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> "*.ts?(x)": [</span><br><span class=\"line\"> "prettier --parser=typescript --write",</span><br><span class=\"line\"> "eslint --quiet"</span><br><span class=\"line\"> ]</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>最后通过husky来执行lint-staged</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npx husky add .<span class=\"property\">husky</span>/pre-commit <span class=\"string\">'npx lint-staged'</span></span><br></pre></td></tr></table></figure>\n"},{"title":"csrf和xss","_content":"\n### csrf(跨站请求伪造)\n\n- 是什么\n 攻击者 诱导 用户在已经登录的网站上 通过点击广告链接等形式,让用户在不知情的情况下向服务器发起请求,造成用户出现损失的结果,比如说不知情的情况下发贴,甚至是转账\n\n攻击者并不能拿取到用户的身份信息(cookie),只是起到伪用户点击的情况\n\n- 怎么预防\n\n- cookie不能被获取\n\n - 设置samesite为strict,只有同一个网站发起的请求才可以访问\n - 通过请求头中的referer/origin, 服务端只处理来自同一个网站的内容,这样就能避免从其他网站中发起的请求\n\n- 请求头中带上token,token在每次会话中不变,但是不同会话中的会改变的,目的是为了不让攻击者随意猜到拿到\n\n### xss(跨脚本攻击)\n\n- 是什么\n 利用网页服务器没有对用户输入的数据进行过滤或者转义处理,导致用户输入攻击脚本对网站起到破坏或者盗取用户个人信息的结果\n- 类型\n\n - 反射型\n 只输入的内容只反射到浏览器,造成页面破坏。这种攻击方式往往需要攻击者诱使用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网址时,注入脚本进入被攻击网站,比如,点击了一个图片链接,而网站刚好就是通过执行图片链接的脚本进行页面显示这种情况。\n\n - 存储型\n 用户输入的脚本发送到服务器被存储起来,用户再次查看时,这些脚本被执行,造成页面被破坏,或者发送了请求到第三方服务器,造成用户个人信息被盗取的结果\n\n- 怎么预防\n\n - 对用户输入的数据进行转义或者过滤处理\n - 充分利用csp(内容安全策略)\n - 限制加载其他域名下的资源文件,这样即使黑客插入一个js文件,这个js也是无法被加载\n - 禁止向第三方域提交数据,这样用户数据也不会外泄\n - 禁止执行内联脚本和未授权脚本\n - 使用httpOnly属性\n 由于很多xss攻击都是用来盗用cookie的,因此还可以通过使用httpOnly属性来保护我们的cookie的安全\n\n- 对数据进行转义或者过滤处理\n","source":"_posts/csrf和xss.md","raw":"---\ntitle: csrf和xss\ntags:\n---\n\n### csrf(跨站请求伪造)\n\n- 是什么\n 攻击者 诱导 用户在已经登录的网站上 通过点击广告链接等形式,让用户在不知情的情况下向服务器发起请求,造成用户出现损失的结果,比如说不知情的情况下发贴,甚至是转账\n\n攻击者并不能拿取到用户的身份信息(cookie),只是起到伪用户点击的情况\n\n- 怎么预防\n\n- cookie不能被获取\n\n - 设置samesite为strict,只有同一个网站发起的请求才可以访问\n - 通过请求头中的referer/origin, 服务端只处理来自同一个网站的内容,这样就能避免从其他网站中发起的请求\n\n- 请求头中带上token,token在每次会话中不变,但是不同会话中的会改变的,目的是为了不让攻击者随意猜到拿到\n\n### xss(跨脚本攻击)\n\n- 是什么\n 利用网页服务器没有对用户输入的数据进行过滤或者转义处理,导致用户输入攻击脚本对网站起到破坏或者盗取用户个人信息的结果\n- 类型\n\n - 反射型\n 只输入的内容只反射到浏览器,造成页面破坏。这种攻击方式往往需要攻击者诱使用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网址时,注入脚本进入被攻击网站,比如,点击了一个图片链接,而网站刚好就是通过执行图片链接的脚本进行页面显示这种情况。\n\n - 存储型\n 用户输入的脚本发送到服务器被存储起来,用户再次查看时,这些脚本被执行,造成页面被破坏,或者发送了请求到第三方服务器,造成用户个人信息被盗取的结果\n\n- 怎么预防\n\n - 对用户输入的数据进行转义或者过滤处理\n - 充分利用csp(内容安全策略)\n - 限制加载其他域名下的资源文件,这样即使黑客插入一个js文件,这个js也是无法被加载\n - 禁止向第三方域提交数据,这样用户数据也不会外泄\n - 禁止执行内联脚本和未授权脚本\n - 使用httpOnly属性\n 由于很多xss攻击都是用来盗用cookie的,因此还可以通过使用httpOnly属性来保护我们的cookie的安全\n\n- 对数据进行转义或者过滤处理\n","slug":"csrf和xss","published":1,"date":"2024-05-09T07:42:29.898Z","updated":"2024-05-09T08:15:13.768Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r030006a9li5ohrbmo0","content":"<h3 id=\"csrf-跨站请求伪造\"><a href=\"#csrf-跨站请求伪造\" class=\"headerlink\" title=\"csrf(跨站请求伪造)\"></a>csrf(跨站请求伪造)</h3><ul>\n<li>是什么<br>攻击者 诱导 用户在已经登录的网站上 通过点击广告链接等形式,让用户在不知情的情况下向服务器发起请求,造成用户出现损失的结果,比如说不知情的情况下发贴,甚至是转账</li>\n</ul>\n<p>攻击者并不能拿取到用户的身份信息(cookie),只是起到伪用户点击的情况</p>\n<ul>\n<li><p>怎么预防</p>\n</li>\n<li><p>cookie不能被获取</p>\n<ul>\n<li>设置samesite为strict,只有同一个网站发起的请求才可以访问</li>\n<li>通过请求头中的referer/origin, 服务端只处理来自同一个网站的内容,这样就能避免从其他网站中发起的请求</li>\n</ul>\n</li>\n<li><p>请求头中带上token,token在每次会话中不变,但是不同会话中的会改变的,目的是为了不让攻击者随意猜到拿到</p>\n</li>\n</ul>\n<h3 id=\"xss(跨脚本攻击)\"><a href=\"#xss(跨脚本攻击)\" class=\"headerlink\" title=\"xss(跨脚本攻击)\"></a>xss(跨脚本攻击)</h3><ul>\n<li><p>是什么<br>利用网页服务器没有对用户输入的数据进行过滤或者转义处理,导致用户输入攻击脚本对网站起到破坏或者盗取用户个人信息的结果</p>\n</li>\n<li><p>类型</p>\n<ul>\n<li><p>反射型<br>只输入的内容只反射到浏览器,造成页面破坏。这种攻击方式往往需要攻击者诱使用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网址时,注入脚本进入被攻击网站,比如,点击了一个图片链接,而网站刚好就是通过执行图片链接的脚本进行页面显示这种情况。</p>\n</li>\n<li><p>存储型<br>用户输入的脚本发送到服务器被存储起来,用户再次查看时,这些脚本被执行,造成页面被破坏,或者发送了请求到第三方服务器,造成用户个人信息被盗取的结果</p>\n</li>\n</ul>\n</li>\n<li><p>怎么预防</p>\n<ul>\n<li>对用户输入的数据进行转义或者过滤处理</li>\n<li>充分利用csp(内容安全策略)<ul>\n<li>限制加载其他域名下的资源文件,这样即使黑客插入一个js文件,这个js也是无法被加载</li>\n<li>禁止向第三方域提交数据,这样用户数据也不会外泄</li>\n<li>禁止执行内联脚本和未授权脚本</li>\n</ul>\n</li>\n<li>使用httpOnly属性<br>由于很多xss攻击都是用来盗用cookie的,因此还可以通过使用httpOnly属性来保护我们的cookie的安全</li>\n</ul>\n</li>\n<li><p>对数据进行转义或者过滤处理</p>\n</li>\n</ul>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"csrf-跨站请求伪造\"><a href=\"#csrf-跨站请求伪造\" class=\"headerlink\" title=\"csrf(跨站请求伪造)\"></a>csrf(跨站请求伪造)</h3><ul>\n<li>是什么<br>攻击者 诱导 用户在已经登录的网站上 通过点击广告链接等形式,让用户在不知情的情况下向服务器发起请求,造成用户出现损失的结果,比如说不知情的情况下发贴,甚至是转账</li>\n</ul>\n<p>攻击者并不能拿取到用户的身份信息(cookie),只是起到伪用户点击的情况</p>\n<ul>\n<li><p>怎么预防</p>\n</li>\n<li><p>cookie不能被获取</p>\n<ul>\n<li>设置samesite为strict,只有同一个网站发起的请求才可以访问</li>\n<li>通过请求头中的referer/origin, 服务端只处理来自同一个网站的内容,这样就能避免从其他网站中发起的请求</li>\n</ul>\n</li>\n<li><p>请求头中带上token,token在每次会话中不变,但是不同会话中的会改变的,目的是为了不让攻击者随意猜到拿到</p>\n</li>\n</ul>\n<h3 id=\"xss(跨脚本攻击)\"><a href=\"#xss(跨脚本攻击)\" class=\"headerlink\" title=\"xss(跨脚本攻击)\"></a>xss(跨脚本攻击)</h3><ul>\n<li><p>是什么<br>利用网页服务器没有对用户输入的数据进行过滤或者转义处理,导致用户输入攻击脚本对网站起到破坏或者盗取用户个人信息的结果</p>\n</li>\n<li><p>类型</p>\n<ul>\n<li><p>反射型<br>只输入的内容只反射到浏览器,造成页面破坏。这种攻击方式往往需要攻击者诱使用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网址时,注入脚本进入被攻击网站,比如,点击了一个图片链接,而网站刚好就是通过执行图片链接的脚本进行页面显示这种情况。</p>\n</li>\n<li><p>存储型<br>用户输入的脚本发送到服务器被存储起来,用户再次查看时,这些脚本被执行,造成页面被破坏,或者发送了请求到第三方服务器,造成用户个人信息被盗取的结果</p>\n</li>\n</ul>\n</li>\n<li><p>怎么预防</p>\n<ul>\n<li>对用户输入的数据进行转义或者过滤处理</li>\n<li>充分利用csp(内容安全策略)<ul>\n<li>限制加载其他域名下的资源文件,这样即使黑客插入一个js文件,这个js也是无法被加载</li>\n<li>禁止向第三方域提交数据,这样用户数据也不会外泄</li>\n<li>禁止执行内联脚本和未授权脚本</li>\n</ul>\n</li>\n<li>使用httpOnly属性<br>由于很多xss攻击都是用来盗用cookie的,因此还可以通过使用httpOnly属性来保护我们的cookie的安全</li>\n</ul>\n</li>\n<li><p>对数据进行转义或者过滤处理</p>\n</li>\n</ul>\n"},{"title":"css-modules解决css样式命名冲突的问题","_content":"\n## 是什么\n\ncss modules是用于模块化和组合css的系统,通过加入局部作用域、依赖管理来避免全局污染和样式冲突,并且css module在打包的时候会自动将类名转成hash值,完全杜绝css类名冲突问题\n\n### 特性\n\n○作用域:模块中的名称默认属于本地作用域,定义在:loacal中的名称也属于本地作用域,定义在:global中的名称属于全局作用域,全局名称不用被编译成哈希字符串\n○命名:对于本地类名称,css modules建议使用camelCase方式来命名,这样会使得js文件更干净,即styles.className。但你仍然也可使用style['class-name'],不过不推荐\n○下面两点还没有体会。。。\n![](../images/2.png)\n\n```js\nimport styles from './index.moudule.scss';\n<div className={style.chat}></div>;\n```\n\n![](../images/3.png)\n","source":"_posts/css-modules.md","raw":"---\ntitle: css-modules解决css样式命名冲突的问题\ncategories:\n - 打包工具\n---\n\n## 是什么\n\ncss modules是用于模块化和组合css的系统,通过加入局部作用域、依赖管理来避免全局污染和样式冲突,并且css module在打包的时候会自动将类名转成hash值,完全杜绝css类名冲突问题\n\n### 特性\n\n○作用域:模块中的名称默认属于本地作用域,定义在:loacal中的名称也属于本地作用域,定义在:global中的名称属于全局作用域,全局名称不用被编译成哈希字符串\n○命名:对于本地类名称,css modules建议使用camelCase方式来命名,这样会使得js文件更干净,即styles.className。但你仍然也可使用style['class-name'],不过不推荐\n○下面两点还没有体会。。。\n![](../images/2.png)\n\n```js\nimport styles from './index.moudule.scss';\n<div className={style.chat}></div>;\n```\n\n![](../images/3.png)\n","slug":"css-modules","published":1,"date":"2023-07-08T04:30:38.591Z","updated":"2023-07-08T04:30:38.591Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r040007a9li5icxggd8","content":"<h2 id=\"是什么\"><a href=\"#是什么\" class=\"headerlink\" title=\"是什么\"></a>是什么</h2><p>css modules是用于模块化和组合css的系统,通过加入局部作用域、依赖管理来避免全局污染和样式冲突,并且css module在打包的时候会自动将类名转成hash值,完全杜绝css类名冲突问题</p>\n<h3 id=\"特性\"><a href=\"#特性\" class=\"headerlink\" title=\"特性\"></a>特性</h3><p>○作用域:模块中的名称默认属于本地作用域,定义在:loacal中的名称也属于本地作用域,定义在:global中的名称属于全局作用域,全局名称不用被编译成哈希字符串<br>○命名:对于本地类名称,css modules建议使用camelCase方式来命名,这样会使得js文件更干净,即styles.className。但你仍然也可使用style[‘class-name’],不过不推荐<br>○下面两点还没有体会。。。<br><img src=\"/../images/2.png\"></p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">import</span> styles <span class=\"keyword\">from</span> <span class=\"string\">'./index.moudule.scss'</span>;</span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">className</span>=<span class=\"string\">{style.chat}</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span>;</span><br></pre></td></tr></table></figure>\n\n<p><img src=\"/../images/3.png\"></p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h2 id=\"是什么\"><a href=\"#是什么\" class=\"headerlink\" title=\"是什么\"></a>是什么</h2><p>css modules是用于模块化和组合css的系统,通过加入局部作用域、依赖管理来避免全局污染和样式冲突,并且css module在打包的时候会自动将类名转成hash值,完全杜绝css类名冲突问题</p>\n<h3 id=\"特性\"><a href=\"#特性\" class=\"headerlink\" title=\"特性\"></a>特性</h3><p>○作用域:模块中的名称默认属于本地作用域,定义在:loacal中的名称也属于本地作用域,定义在:global中的名称属于全局作用域,全局名称不用被编译成哈希字符串<br>○命名:对于本地类名称,css modules建议使用camelCase方式来命名,这样会使得js文件更干净,即styles.className。但你仍然也可使用style[‘class-name’],不过不推荐<br>○下面两点还没有体会。。。<br><img src=\"/../images/2.png\"></p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">import</span> styles <span class=\"keyword\">from</span> <span class=\"string\">'./index.moudule.scss'</span>;</span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">className</span>=<span class=\"string\">{style.chat}</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span>;</span><br></pre></td></tr></table></figure>\n\n<p><img src=\"/../images/3.png\"></p>\n"},{"title":"dayjs","date":"2023-07-08T02:30:17.000Z","_content":"\n### 获取时间戳\n\n```js\n//13位时间戳,精确到毫秒\nnew Date().getTime();\n// 10位时间戳\nMath.round(new Date().getTime() / 1000).toString();\n```\n\n##### 1、ios8标准时间\n\n```js\ndayjs('2018-04-04T16:00:00.000Z');\n```\n\n##### 2、utc时间\n\n##### 3、时间戳\n\n(1)精确到毫秒的时候是13位\ndayjs(1318781876406)\n\n(2)精确到秒到时候是10位\ndayjs.unix(1318781876.721) // 可以支持小数\n\n##### 4、时间段days.duration(' ')\n\n(1)可以将时间段转化为时间错,比如01:29:20\n\n```js\ndayjs.duration('01:29:20').valueOf(); //转化为秒\ndayjs('2019-01-25').unix(); //转化为毫秒\n```\n\n##### 5、将时间戳转化为所要时间\n\n```js\ndayjs(1318781876406).format('YYYY-MM-DD HH:mm:ss');\ndayjs('1970-00-00', 'YYYY-MM-DD'); //字符串+格式\n//占位符表示\n```\n\n![](../images/4.png)\n","source":"_posts/dayjs.md","raw":"---\ntitle: dayjs\ndate: 2023-07-08 10:30:17\ntags: 'dayjs'\ncategories:\n - 插件使用\n---\n\n### 获取时间戳\n\n```js\n//13位时间戳,精确到毫秒\nnew Date().getTime();\n// 10位时间戳\nMath.round(new Date().getTime() / 1000).toString();\n```\n\n##### 1、ios8标准时间\n\n```js\ndayjs('2018-04-04T16:00:00.000Z');\n```\n\n##### 2、utc时间\n\n##### 3、时间戳\n\n(1)精确到毫秒的时候是13位\ndayjs(1318781876406)\n\n(2)精确到秒到时候是10位\ndayjs.unix(1318781876.721) // 可以支持小数\n\n##### 4、时间段days.duration(' ')\n\n(1)可以将时间段转化为时间错,比如01:29:20\n\n```js\ndayjs.duration('01:29:20').valueOf(); //转化为秒\ndayjs('2019-01-25').unix(); //转化为毫秒\n```\n\n##### 5、将时间戳转化为所要时间\n\n```js\ndayjs(1318781876406).format('YYYY-MM-DD HH:mm:ss');\ndayjs('1970-00-00', 'YYYY-MM-DD'); //字符串+格式\n//占位符表示\n```\n\n![](../images/4.png)\n","slug":"dayjs","published":1,"updated":"2023-07-08T04:30:38.592Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r050008a9liftcy45bf","content":"<h3 id=\"获取时间戳\"><a href=\"#获取时间戳\" class=\"headerlink\" title=\"获取时间戳\"></a>获取时间戳</h3><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">//13位时间戳,精确到毫秒</span></span><br><span class=\"line\"><span class=\"keyword\">new</span> <span class=\"title class_\">Date</span>().<span class=\"title function_\">getTime</span>();</span><br><span class=\"line\"><span class=\"comment\">// 10位时间戳</span></span><br><span class=\"line\"><span class=\"title class_\">Math</span>.<span class=\"title function_\">round</span>(<span class=\"keyword\">new</span> <span class=\"title class_\">Date</span>().<span class=\"title function_\">getTime</span>() / <span class=\"number\">1000</span>).<span class=\"title function_\">toString</span>();</span><br></pre></td></tr></table></figure>\n\n<h5 id=\"1、ios8标准时间\"><a href=\"#1、ios8标准时间\" class=\"headerlink\" title=\"1、ios8标准时间\"></a>1、ios8标准时间</h5><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"title function_\">dayjs</span>(<span class=\"string\">'2018-04-04T16:00:00.000Z'</span>);</span><br></pre></td></tr></table></figure>\n\n<h5 id=\"2、utc时间\"><a href=\"#2、utc时间\" class=\"headerlink\" title=\"2、utc时间\"></a>2、utc时间</h5><h5 id=\"3、时间戳\"><a href=\"#3、时间戳\" class=\"headerlink\" title=\"3、时间戳\"></a>3、时间戳</h5><p>(1)精确到毫秒的时候是13位<br>dayjs(1318781876406)</p>\n<p>(2)精确到秒到时候是10位<br>dayjs.unix(1318781876.721) // 可以支持小数</p>\n<h5 id=\"4、时间段days-duration-‘-‘\"><a href=\"#4、时间段days-duration-‘-‘\" class=\"headerlink\" title=\"4、时间段days.duration(‘ ‘)\"></a>4、时间段days.duration(‘ ‘)</h5><p>(1)可以将时间段转化为时间错,比如01:29:20</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">dayjs.<span class=\"title function_\">duration</span>(<span class=\"string\">'01:29:20'</span>).<span class=\"title function_\">valueOf</span>(); <span class=\"comment\">//转化为秒</span></span><br><span class=\"line\"><span class=\"title function_\">dayjs</span>(<span class=\"string\">'2019-01-25'</span>).<span class=\"title function_\">unix</span>(); <span class=\"comment\">//转化为毫秒</span></span><br></pre></td></tr></table></figure>\n\n<h5 id=\"5、将时间戳转化为所要时间\"><a href=\"#5、将时间戳转化为所要时间\" class=\"headerlink\" title=\"5、将时间戳转化为所要时间\"></a>5、将时间戳转化为所要时间</h5><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"title function_\">dayjs</span>(<span class=\"number\">1318781876406</span>).<span class=\"title function_\">format</span>(<span class=\"string\">'YYYY-MM-DD HH:mm:ss'</span>);</span><br><span class=\"line\"><span class=\"title function_\">dayjs</span>(<span class=\"string\">'1970-00-00'</span>, <span class=\"string\">'YYYY-MM-DD'</span>); <span class=\"comment\">//字符串+格式</span></span><br><span class=\"line\"><span class=\"comment\">//占位符表示</span></span><br></pre></td></tr></table></figure>\n\n<p><img src=\"/../images/4.png\"></p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"获取时间戳\"><a href=\"#获取时间戳\" class=\"headerlink\" title=\"获取时间戳\"></a>获取时间戳</h3><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">//13位时间戳,精确到毫秒</span></span><br><span class=\"line\"><span class=\"keyword\">new</span> <span class=\"title class_\">Date</span>().<span class=\"title function_\">getTime</span>();</span><br><span class=\"line\"><span class=\"comment\">// 10位时间戳</span></span><br><span class=\"line\"><span class=\"title class_\">Math</span>.<span class=\"title function_\">round</span>(<span class=\"keyword\">new</span> <span class=\"title class_\">Date</span>().<span class=\"title function_\">getTime</span>() / <span class=\"number\">1000</span>).<span class=\"title function_\">toString</span>();</span><br></pre></td></tr></table></figure>\n\n<h5 id=\"1、ios8标准时间\"><a href=\"#1、ios8标准时间\" class=\"headerlink\" title=\"1、ios8标准时间\"></a>1、ios8标准时间</h5><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"title function_\">dayjs</span>(<span class=\"string\">'2018-04-04T16:00:00.000Z'</span>);</span><br></pre></td></tr></table></figure>\n\n<h5 id=\"2、utc时间\"><a href=\"#2、utc时间\" class=\"headerlink\" title=\"2、utc时间\"></a>2、utc时间</h5><h5 id=\"3、时间戳\"><a href=\"#3、时间戳\" class=\"headerlink\" title=\"3、时间戳\"></a>3、时间戳</h5><p>(1)精确到毫秒的时候是13位<br>dayjs(1318781876406)</p>\n<p>(2)精确到秒到时候是10位<br>dayjs.unix(1318781876.721) // 可以支持小数</p>\n<h5 id=\"4、时间段days-duration-‘-‘\"><a href=\"#4、时间段days-duration-‘-‘\" class=\"headerlink\" title=\"4、时间段days.duration(‘ ‘)\"></a>4、时间段days.duration(‘ ‘)</h5><p>(1)可以将时间段转化为时间错,比如01:29:20</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">dayjs.<span class=\"title function_\">duration</span>(<span class=\"string\">'01:29:20'</span>).<span class=\"title function_\">valueOf</span>(); <span class=\"comment\">//转化为秒</span></span><br><span class=\"line\"><span class=\"title function_\">dayjs</span>(<span class=\"string\">'2019-01-25'</span>).<span class=\"title function_\">unix</span>(); <span class=\"comment\">//转化为毫秒</span></span><br></pre></td></tr></table></figure>\n\n<h5 id=\"5、将时间戳转化为所要时间\"><a href=\"#5、将时间戳转化为所要时间\" class=\"headerlink\" title=\"5、将时间戳转化为所要时间\"></a>5、将时间戳转化为所要时间</h5><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"title function_\">dayjs</span>(<span class=\"number\">1318781876406</span>).<span class=\"title function_\">format</span>(<span class=\"string\">'YYYY-MM-DD HH:mm:ss'</span>);</span><br><span class=\"line\"><span class=\"title function_\">dayjs</span>(<span class=\"string\">'1970-00-00'</span>, <span class=\"string\">'YYYY-MM-DD'</span>); <span class=\"comment\">//字符串+格式</span></span><br><span class=\"line\"><span class=\"comment\">//占位符表示</span></span><br></pre></td></tr></table></figure>\n\n<p><img src=\"/../images/4.png\"></p>\n"},{"title":"el-form","date":"2023-07-08T02:47:38.000Z","_content":"\n```js\nconst ruleFormRef = ref<FormInstance>()\n<el-form ref=\"ruleFormRef\">\n<el-form-item>\n <el-button type=\"primary\" @click=\"submitForm(ruleFormRef)\">\n Create\n </el-button>\n <el-button @click=\"resetForm(ruleFormRef)\">Reset</el-button>\n </el-form-item>\n</el-form>\nconst submitForm = async (formEl: FormInstance | undefined) => {\n if (!formEl) return\n await formEl.validate((valid, fields) => {\n if (valid) {\n console.log('submit!')\n } else {\n console.log('error submit!', fields)\n }\n })\n}\n\nconst resetForm = (formEl: FormInstance | undefined) => {\n if (!formEl) return\n formEl.resetFields()\n}\n```\n\nel-form-item中的prop值需要跟v-modal中的字段一样,才能进行rules,resetField等设置\n![](../images/7.png)\n![](../images/8.png)\n","source":"_posts/el-form.md","raw":"---\ntitle: el-form\ndate: 2023-07-08 10:47:38\ntags:\ncategories:\n - UI组件\n---\n\n```js\nconst ruleFormRef = ref<FormInstance>()\n<el-form ref=\"ruleFormRef\">\n<el-form-item>\n <el-button type=\"primary\" @click=\"submitForm(ruleFormRef)\">\n Create\n </el-button>\n <el-button @click=\"resetForm(ruleFormRef)\">Reset</el-button>\n </el-form-item>\n</el-form>\nconst submitForm = async (formEl: FormInstance | undefined) => {\n if (!formEl) return\n await formEl.validate((valid, fields) => {\n if (valid) {\n console.log('submit!')\n } else {\n console.log('error submit!', fields)\n }\n })\n}\n\nconst resetForm = (formEl: FormInstance | undefined) => {\n if (!formEl) return\n formEl.resetFields()\n}\n```\n\nel-form-item中的prop值需要跟v-modal中的字段一样,才能进行rules,resetField等设置\n![](../images/7.png)\n![](../images/8.png)\n","slug":"el-form","published":1,"updated":"2023-07-08T04:30:38.592Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r07000aa9ligv1hfzmq","content":"<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> ruleFormRef = ref<<span class=\"title class_\">FormInstance</span>>()</span><br><span class=\"line\"><el-form ref=<span class=\"string\">"ruleFormRef"</span>></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">el-form-item</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">el-button</span> <span class=\"attr\">type</span>=<span class=\"string\">"primary"</span> @<span class=\"attr\">click</span>=<span class=\"string\">"submitForm(ruleFormRef)"</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> Create</span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"></<span class=\"name\">el-button</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">el-button</span> @<span class=\"attr\">click</span>=<span class=\"string\">"resetForm(ruleFormRef)"</span>></span>Reset<span class=\"tag\"></<span class=\"name\">el-button</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"></<span class=\"name\">el-form-item</span>></span></span></span><br><span class=\"line\"></el-form></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title function_\">submitForm</span> = <span class=\"keyword\">async</span> (<span class=\"params\">formEl: FormInstance | <span class=\"literal\">undefined</span></span>) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (!formEl) <span class=\"keyword\">return</span></span><br><span class=\"line\"> <span class=\"keyword\">await</span> formEl.<span class=\"title function_\">validate</span>(<span class=\"function\">(<span class=\"params\">valid, fields</span>) =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (valid) {</span><br><span class=\"line\"> <span class=\"variable language_\">console</span>.<span class=\"title function_\">log</span>(<span class=\"string\">'submit!'</span>)</span><br><span class=\"line\"> } <span class=\"keyword\">else</span> {</span><br><span class=\"line\"> <span class=\"variable language_\">console</span>.<span class=\"title function_\">log</span>(<span class=\"string\">'error submit!'</span>, fields)</span><br><span class=\"line\"> }</span><br><span class=\"line\"> })</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title function_\">resetForm</span> = (<span class=\"params\">formEl: FormInstance | <span class=\"literal\">undefined</span></span>) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (!formEl) <span class=\"keyword\">return</span></span><br><span class=\"line\"> formEl.<span class=\"title function_\">resetFields</span>()</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>el-form-item中的prop值需要跟v-modal中的字段一样,才能进行rules,resetField等设置<br><img src=\"/../images/7.png\"><br><img src=\"/../images/8.png\"></p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> ruleFormRef = ref<<span class=\"title class_\">FormInstance</span>>()</span><br><span class=\"line\"><el-form ref=<span class=\"string\">"ruleFormRef"</span>></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">el-form-item</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">el-button</span> <span class=\"attr\">type</span>=<span class=\"string\">"primary"</span> @<span class=\"attr\">click</span>=<span class=\"string\">"submitForm(ruleFormRef)"</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> Create</span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"></<span class=\"name\">el-button</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">el-button</span> @<span class=\"attr\">click</span>=<span class=\"string\">"resetForm(ruleFormRef)"</span>></span>Reset<span class=\"tag\"></<span class=\"name\">el-button</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"></<span class=\"name\">el-form-item</span>></span></span></span><br><span class=\"line\"></el-form></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title function_\">submitForm</span> = <span class=\"keyword\">async</span> (<span class=\"params\">formEl: FormInstance | <span class=\"literal\">undefined</span></span>) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (!formEl) <span class=\"keyword\">return</span></span><br><span class=\"line\"> <span class=\"keyword\">await</span> formEl.<span class=\"title function_\">validate</span>(<span class=\"function\">(<span class=\"params\">valid, fields</span>) =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (valid) {</span><br><span class=\"line\"> <span class=\"variable language_\">console</span>.<span class=\"title function_\">log</span>(<span class=\"string\">'submit!'</span>)</span><br><span class=\"line\"> } <span class=\"keyword\">else</span> {</span><br><span class=\"line\"> <span class=\"variable language_\">console</span>.<span class=\"title function_\">log</span>(<span class=\"string\">'error submit!'</span>, fields)</span><br><span class=\"line\"> }</span><br><span class=\"line\"> })</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title function_\">resetForm</span> = (<span class=\"params\">formEl: FormInstance | <span class=\"literal\">undefined</span></span>) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (!formEl) <span class=\"keyword\">return</span></span><br><span class=\"line\"> formEl.<span class=\"title function_\">resetFields</span>()</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>el-form-item中的prop值需要跟v-modal中的字段一样,才能进行rules,resetField等设置<br><img src=\"/../images/7.png\"><br><img src=\"/../images/8.png\"></p>\n"},{"title":"eslint和prettier","date":"2023-05-16T10:47:23.000Z","_content":"\n#### eslint / prettier如何做到规范代码的\n\nESLint 和 Prettier 都是前端开发中常用的代码规范工具,它们可以帮助开发人员规范代码、提高代码质量,并减少代码错误。下面是它们如何规范代码的简要介绍:\n\n###### ●ESLint\n\n○语法检查: ESLint 可以检查代码中是否存在语法错误,例如未定义的变量、语法错误的表达式等\n○代码风格检查: ESLint 可以检查代码的风格是否符合规范,例如缩进、变量命名、空格等\n○安全性检查: ESLint 可以检查代码中是否存在安全漏洞,例如 XSS 攻击、SQL 注入等\n○自定义规则: ESLint 提供了丰富的规则配置,开发人员可以根据自己的需要自定义规则并进行代码检查\n\n###### ●Prettier\n\n○代码格式化: 可以自动格式化代码,使代码符合规范,并保持一致的风格\n○代码布局: 可以自动调整代码的布局,使代码易于阅读和理解\n○多语言支持: 支持多种编程语言,例如 JavaScript、TypeScript、CSS、Markdown 等\n\n#### eslint / prettier之间的关系\n\nESLint 和 Prettier 都是前端开发中常用的代码规范工具,它们可以帮助开发人员规范代码、提高代码质量,并减少代码错误。虽然它们都可以用于规范代码,但它们之间有不同的关注点和使用方式。\nESLint 主要用于检查代码风格和语法错误,可以通过配置文件来定制自己的代码风格规范,并提供了丰富的插件和扩展,可以支持各种语言和框架。ESLint 的作用是在编码过程中及时发现和解决代码问题,从而提高代码质量和可维护性。\nPrettier 主要用于代码格式化,可以对代码进行自动格式化,使代码符合统一的规范和风格。开发人员可以通过配置文件来定制自己的代码格式化规范,并支持多种语言和框架。Prettier 的作用是将已经编写好的代码快速地格式化成一个统一的格式,从而使代码更加易读、易维护、易扩展。\nESLint 和 Prettier 可以结合使用,通过使用 eslint-plugin-prettier 插件和 eslint-config-prettier 配置来将 Prettier 集成到 ESLint 中。这样可以使用 ESLint 来检查代码风格和语法错误,并使用 Prettier 来进行代码格式化。结合使用可以提高代码质量和开发效率,同时也能够使代码更加统一和规范。\n总之,ESLint 和 Prettier 都是前端开发中常用的代码规范工具,虽然它们之间有不同的关注点和使用方式,但可以结合使用来提高代码质量和开发效率。\n\n#### eslint/prettier 在react和vue项目中如何使用\n\n###### ●react项目\n\n○安装eslint/prettier相关插件\nnpm install eslint prettier eslint-plugin-react eslint-config-prettier eslint-plugin-prettier --save-dev\n\n○创建.eslintrc.json配置文件\n\n```js\n{\n \"extends\": [\n \"eslint:recommended\",\n \"plugin:react/recommended\",\n \"plugin:prettier/recommended\",\n \"prettier/react\"\n ],\n \"plugins\": [\"react\", \"prettier\"],\n \"rules\": {\n \"prettier/prettier\": [\"error\", {}, { \"usePrettierrc\": true }]\n }\n}\n```\n\n○创建.prettierrc.json配置文件\n\n```js\n{\n \"printWidth\": 80,\n \"tabWidth\": 2,\n \"useTabs\": false,\n \"semi\": true,\n \"singleQuote\": true,\n \"jsxSingleQuote\": true,\n \"trailingComma\": \"es5\",\n \"bracketSpacing\": true,\n \"jsxBracketSameLine\": false,\n \"arrowParens\": \"always\"\n}\n```\n\n○在编辑器中安装并配置eslint和prettier插件,例如 VS Code中可以安装ESLint和Prettier插件,并在setting.json文件中添加以下配置\n\n```js\n\"editor.formatOnSave\": true,\n\"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n\"editor.codeActionsOnSave\": {\n \"source.fixAll.eslint\": true\n},\n```\n\n###### ●vue项目(注:和上面react项目步骤基本一样,唯一的区别就是安装的eslint/prettier插件有区别,最下面👇再来解释一下为什么\n\n○安装eslint/prettier相关插件\n\n```js\nnpm install eslint prettier eslint-plugin-vue eslint-config-prettier eslint-plugin-prettier --save-dev\n```\n\n○创建.eslintrc.json配置文件\n\n```js\n{\n \"extends\": [\n \"eslint:recommended\",\n \"plugin:vue/recommended\",\n \"plugin:prettier/recommended\",\n \"prettier/vue\"\n ],\n \"plugins\": [\"vue\", \"prettier\"],\n \"rules\": {\n \"prettier/prettier\": [\"error\", {}, { \"usePrettierrc\": true }]\n }\n}\n```\n\n○创建.prettierrc.json配置文件\n\n```js\n{\n \"printWidth\": 80,\n \"tabWidth\": 2,\n \"useTabs\": false,\n \"semi\": true,\n \"singleQuote\": true,\n \"trailingComma\": \"es5\",\n \"bracketSpacing\": true\n}\n```\n\n○在编辑中安装eslint和prettier插件,例如VS Code中可以安装ESLint和Prettier插件,并在setting.json中添加以下配置\n\n```js\n\"editor.formatOnSave\": true,\n\"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n\"editor.codeActionsOnSave\": {\n \"source.fixAll.eslint\": true\n},\n```\n\n(vue和react存在模版语法、组件命名、状态管理等方面的差异,隐藏需要根据具体框架使用合适的插件和扩展,以确保代码可读性和可维护性,提高代码质量和开发效率\n(1)模版语法: 在vue中,模版语法是一种重要的语法结构,需要进行检查和规范,可以使用eslint-plugin-vue来检查模版语法问题;而在react中,通常使用jsx语法来定义组件,可以使用eslint-plugin-react来检查jsx相关代码\n(2)组件命名:在vue中,组件命名采用kebab-case(短横线命名法),例如my-component。而在react中,采用PascalCase(大驼峰),例如MyComponent。需要根据具体的框架选择合适的命名规范\n(3)状态管理,在vue中使用vuex,react中使用redux\\mobx等状态管理库\n(4)插件和扩展:vue和react需要使用不同的扩展工具,例如:eslint-plugin-react和eslint-plugin-vue\n\n#### 怎么自定义规范(实践)\n\n(1)使用官方生成自定义eslint规范的脚手架工具\n\n```js\n// 安装环境\nnpm i -g yo\nnpm i -g generator-eslint\n// cd 要放置项目的文件夹,创建项目\nyo eslint:plugin\n//下面是创建之后需要输入的信息\n//yo eslint:rule\n//What is your name? 随便写个你的名字\n//What is the plugin ID? 你的插件的id,推荐(eslint-plugin-xxx)的命名方式\n//Type a short description of this plugin: 描述你的插件是干啥的\n//Does this plugin contain custom ESLint rules? Yes\n//Does this plugin contain one or more processors? Yes\n```\n\n生成下面目录\n\n(2)在lib/rules/my-custom-rules1.js中写自定义的规则,下面是基本模版\n\n```js\nmodule.exports = {\n // meta里面的元数据,对于我们自定义规则,其实只关心schema就行了\n meta: {\n // 规则的类型problem|suggestion|layout\n // problem: 这条规则识别的代码可能会导致错误或让人迷惑。应该优先解决这个问题\n // suggestion: 这条规则识别的代码不会导致错误,但是建议用更好的方式\n // layout: 表示这条规则主要关心像空格、分号等这种问题\n type: 'suggestion',\n // 对于自定义规则,docs字段是非必须的\n docs: {\n description: '描述你的规则是干啥的',\n // 规则的分类,假如你把这条规则提交到eslint核心规则里,那eslint官网规则的首页会按照这个字段进行分类展示\n category: 'Possible Errors',\n // 假如你把规则提交到eslint核心规则里\n // 且像这样extends: ['eslint:recommended']继承规则的时候,这个属性是true,就会启用这条规则\n recommended: true,\n // 你的规则使用文档的url\n url: 'https://eslint.org/docs/rules/no-extra-semi',\n },\n // 标识这条规则是否可以修复,假如没有这属性,即使你在下面那个create方法里实现了fix功能,eslint也不会帮你修复\n fixable: 'code',\n // 这里定义了这条规则需要的参数\n // 比如我们是这样使用带参数的rule的时候,rules: { myRule: ['error', param1, param2....]}\n // error后面的就是参数,而参数就是在这里定义的\n schema: [],\n },\n create: function (context) {\n // 这是最重要的方法,我们对代码的校验就是在这里做的\n return {\n // callback functions\n };\n },\n};\n```\n\n接下来介绍creact方法\neslint校验代码其实是解析文件内容,通过AST(抽象语法树)生成一个对象,再检查这个对象是否符合我们的要求,如果不符合要求就报出错误\n下面举例\n\n```js\nenum myEnumText {\nfirstName = 1\n}\n```\n\n//下面是它的AST形式\n\n```js\n sourceType: module\n body: [\n EnumDeclaration: {\n id: Identifier {\n name: \"myEnumText\"\n }\n body: {\n type: EnumBooleanBody\n members: [\n EnumBooleanMember: {\n id: Identifier {\n name: \"firstName\"\n }\n init: NumericLiteral {\n value: 1\n }\n }\n ]\n }\n }\n ]\n```\n\n从上面代码可以看出,enum类型的声明变量名是EnumDeclaration,并且通过node.id.name可以获取到声明的变量名,我们通过正则可以校验这个变量名是否以E开头,如果不以E开头就报错或者警告\n![](../images/1.png)\n(3)接下来是怎么在项目中使用(这里我的插件名称是eslint-plugin-st-rules\n●将上面的项目发布成npm插件,npm login / npm publish\n\n```js\nnpm login --registry=\"具体发包地址\"\nnpm publish --registry=\"具体发包地址\"\n```\n\n●在项目中npm install eslint-plugin-rules\n\n```js\nnpm install eslint-plugin-rules --\"具体发包地址\"\n```\n\n●在.eslintrc.js中 (在这里可以省略eslint-plugin-)\n\n```js\n plugins: ['st-rules'],\n rules: {\n 'st-rules/type-prefix': 'warn', // type类型要用T开头\n 'st-rules/interface-prefix': 'warn', // interface类型要用I开头\n 'st-rules/enum-prefix': 'warn', // enum类型要用E开头\n 'st-rules/variable-name-camelcase': 'warn', // let var定义的变量需要用小驼峰\n },\n```\n\n⚠️更改了.eslintrc.js文件,需要关掉项目重新打开才会生效\n","source":"_posts/eslint-prettier.md","raw":"---\ntitle: eslint和prettier\ndate: 2023-05-16 18:47:23\ntags:\ncategories:\n - 代码规范\n---\n\n#### eslint / prettier如何做到规范代码的\n\nESLint 和 Prettier 都是前端开发中常用的代码规范工具,它们可以帮助开发人员规范代码、提高代码质量,并减少代码错误。下面是它们如何规范代码的简要介绍:\n\n###### ●ESLint\n\n○语法检查: ESLint 可以检查代码中是否存在语法错误,例如未定义的变量、语法错误的表达式等\n○代码风格检查: ESLint 可以检查代码的风格是否符合规范,例如缩进、变量命名、空格等\n○安全性检查: ESLint 可以检查代码中是否存在安全漏洞,例如 XSS 攻击、SQL 注入等\n○自定义规则: ESLint 提供了丰富的规则配置,开发人员可以根据自己的需要自定义规则并进行代码检查\n\n###### ●Prettier\n\n○代码格式化: 可以自动格式化代码,使代码符合规范,并保持一致的风格\n○代码布局: 可以自动调整代码的布局,使代码易于阅读和理解\n○多语言支持: 支持多种编程语言,例如 JavaScript、TypeScript、CSS、Markdown 等\n\n#### eslint / prettier之间的关系\n\nESLint 和 Prettier 都是前端开发中常用的代码规范工具,它们可以帮助开发人员规范代码、提高代码质量,并减少代码错误。虽然它们都可以用于规范代码,但它们之间有不同的关注点和使用方式。\nESLint 主要用于检查代码风格和语法错误,可以通过配置文件来定制自己的代码风格规范,并提供了丰富的插件和扩展,可以支持各种语言和框架。ESLint 的作用是在编码过程中及时发现和解决代码问题,从而提高代码质量和可维护性。\nPrettier 主要用于代码格式化,可以对代码进行自动格式化,使代码符合统一的规范和风格。开发人员可以通过配置文件来定制自己的代码格式化规范,并支持多种语言和框架。Prettier 的作用是将已经编写好的代码快速地格式化成一个统一的格式,从而使代码更加易读、易维护、易扩展。\nESLint 和 Prettier 可以结合使用,通过使用 eslint-plugin-prettier 插件和 eslint-config-prettier 配置来将 Prettier 集成到 ESLint 中。这样可以使用 ESLint 来检查代码风格和语法错误,并使用 Prettier 来进行代码格式化。结合使用可以提高代码质量和开发效率,同时也能够使代码更加统一和规范。\n总之,ESLint 和 Prettier 都是前端开发中常用的代码规范工具,虽然它们之间有不同的关注点和使用方式,但可以结合使用来提高代码质量和开发效率。\n\n#### eslint/prettier 在react和vue项目中如何使用\n\n###### ●react项目\n\n○安装eslint/prettier相关插件\nnpm install eslint prettier eslint-plugin-react eslint-config-prettier eslint-plugin-prettier --save-dev\n\n○创建.eslintrc.json配置文件\n\n```js\n{\n \"extends\": [\n \"eslint:recommended\",\n \"plugin:react/recommended\",\n \"plugin:prettier/recommended\",\n \"prettier/react\"\n ],\n \"plugins\": [\"react\", \"prettier\"],\n \"rules\": {\n \"prettier/prettier\": [\"error\", {}, { \"usePrettierrc\": true }]\n }\n}\n```\n\n○创建.prettierrc.json配置文件\n\n```js\n{\n \"printWidth\": 80,\n \"tabWidth\": 2,\n \"useTabs\": false,\n \"semi\": true,\n \"singleQuote\": true,\n \"jsxSingleQuote\": true,\n \"trailingComma\": \"es5\",\n \"bracketSpacing\": true,\n \"jsxBracketSameLine\": false,\n \"arrowParens\": \"always\"\n}\n```\n\n○在编辑器中安装并配置eslint和prettier插件,例如 VS Code中可以安装ESLint和Prettier插件,并在setting.json文件中添加以下配置\n\n```js\n\"editor.formatOnSave\": true,\n\"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n\"editor.codeActionsOnSave\": {\n \"source.fixAll.eslint\": true\n},\n```\n\n###### ●vue项目(注:和上面react项目步骤基本一样,唯一的区别就是安装的eslint/prettier插件有区别,最下面👇再来解释一下为什么\n\n○安装eslint/prettier相关插件\n\n```js\nnpm install eslint prettier eslint-plugin-vue eslint-config-prettier eslint-plugin-prettier --save-dev\n```\n\n○创建.eslintrc.json配置文件\n\n```js\n{\n \"extends\": [\n \"eslint:recommended\",\n \"plugin:vue/recommended\",\n \"plugin:prettier/recommended\",\n \"prettier/vue\"\n ],\n \"plugins\": [\"vue\", \"prettier\"],\n \"rules\": {\n \"prettier/prettier\": [\"error\", {}, { \"usePrettierrc\": true }]\n }\n}\n```\n\n○创建.prettierrc.json配置文件\n\n```js\n{\n \"printWidth\": 80,\n \"tabWidth\": 2,\n \"useTabs\": false,\n \"semi\": true,\n \"singleQuote\": true,\n \"trailingComma\": \"es5\",\n \"bracketSpacing\": true\n}\n```\n\n○在编辑中安装eslint和prettier插件,例如VS Code中可以安装ESLint和Prettier插件,并在setting.json中添加以下配置\n\n```js\n\"editor.formatOnSave\": true,\n\"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n\"editor.codeActionsOnSave\": {\n \"source.fixAll.eslint\": true\n},\n```\n\n(vue和react存在模版语法、组件命名、状态管理等方面的差异,隐藏需要根据具体框架使用合适的插件和扩展,以确保代码可读性和可维护性,提高代码质量和开发效率\n(1)模版语法: 在vue中,模版语法是一种重要的语法结构,需要进行检查和规范,可以使用eslint-plugin-vue来检查模版语法问题;而在react中,通常使用jsx语法来定义组件,可以使用eslint-plugin-react来检查jsx相关代码\n(2)组件命名:在vue中,组件命名采用kebab-case(短横线命名法),例如my-component。而在react中,采用PascalCase(大驼峰),例如MyComponent。需要根据具体的框架选择合适的命名规范\n(3)状态管理,在vue中使用vuex,react中使用redux\\mobx等状态管理库\n(4)插件和扩展:vue和react需要使用不同的扩展工具,例如:eslint-plugin-react和eslint-plugin-vue\n\n#### 怎么自定义规范(实践)\n\n(1)使用官方生成自定义eslint规范的脚手架工具\n\n```js\n// 安装环境\nnpm i -g yo\nnpm i -g generator-eslint\n// cd 要放置项目的文件夹,创建项目\nyo eslint:plugin\n//下面是创建之后需要输入的信息\n//yo eslint:rule\n//What is your name? 随便写个你的名字\n//What is the plugin ID? 你的插件的id,推荐(eslint-plugin-xxx)的命名方式\n//Type a short description of this plugin: 描述你的插件是干啥的\n//Does this plugin contain custom ESLint rules? Yes\n//Does this plugin contain one or more processors? Yes\n```\n\n生成下面目录\n\n(2)在lib/rules/my-custom-rules1.js中写自定义的规则,下面是基本模版\n\n```js\nmodule.exports = {\n // meta里面的元数据,对于我们自定义规则,其实只关心schema就行了\n meta: {\n // 规则的类型problem|suggestion|layout\n // problem: 这条规则识别的代码可能会导致错误或让人迷惑。应该优先解决这个问题\n // suggestion: 这条规则识别的代码不会导致错误,但是建议用更好的方式\n // layout: 表示这条规则主要关心像空格、分号等这种问题\n type: 'suggestion',\n // 对于自定义规则,docs字段是非必须的\n docs: {\n description: '描述你的规则是干啥的',\n // 规则的分类,假如你把这条规则提交到eslint核心规则里,那eslint官网规则的首页会按照这个字段进行分类展示\n category: 'Possible Errors',\n // 假如你把规则提交到eslint核心规则里\n // 且像这样extends: ['eslint:recommended']继承规则的时候,这个属性是true,就会启用这条规则\n recommended: true,\n // 你的规则使用文档的url\n url: 'https://eslint.org/docs/rules/no-extra-semi',\n },\n // 标识这条规则是否可以修复,假如没有这属性,即使你在下面那个create方法里实现了fix功能,eslint也不会帮你修复\n fixable: 'code',\n // 这里定义了这条规则需要的参数\n // 比如我们是这样使用带参数的rule的时候,rules: { myRule: ['error', param1, param2....]}\n // error后面的就是参数,而参数就是在这里定义的\n schema: [],\n },\n create: function (context) {\n // 这是最重要的方法,我们对代码的校验就是在这里做的\n return {\n // callback functions\n };\n },\n};\n```\n\n接下来介绍creact方法\neslint校验代码其实是解析文件内容,通过AST(抽象语法树)生成一个对象,再检查这个对象是否符合我们的要求,如果不符合要求就报出错误\n下面举例\n\n```js\nenum myEnumText {\nfirstName = 1\n}\n```\n\n//下面是它的AST形式\n\n```js\n sourceType: module\n body: [\n EnumDeclaration: {\n id: Identifier {\n name: \"myEnumText\"\n }\n body: {\n type: EnumBooleanBody\n members: [\n EnumBooleanMember: {\n id: Identifier {\n name: \"firstName\"\n }\n init: NumericLiteral {\n value: 1\n }\n }\n ]\n }\n }\n ]\n```\n\n从上面代码可以看出,enum类型的声明变量名是EnumDeclaration,并且通过node.id.name可以获取到声明的变量名,我们通过正则可以校验这个变量名是否以E开头,如果不以E开头就报错或者警告\n![](../images/1.png)\n(3)接下来是怎么在项目中使用(这里我的插件名称是eslint-plugin-st-rules\n●将上面的项目发布成npm插件,npm login / npm publish\n\n```js\nnpm login --registry=\"具体发包地址\"\nnpm publish --registry=\"具体发包地址\"\n```\n\n●在项目中npm install eslint-plugin-rules\n\n```js\nnpm install eslint-plugin-rules --\"具体发包地址\"\n```\n\n●在.eslintrc.js中 (在这里可以省略eslint-plugin-)\n\n```js\n plugins: ['st-rules'],\n rules: {\n 'st-rules/type-prefix': 'warn', // type类型要用T开头\n 'st-rules/interface-prefix': 'warn', // interface类型要用I开头\n 'st-rules/enum-prefix': 'warn', // enum类型要用E开头\n 'st-rules/variable-name-camelcase': 'warn', // let var定义的变量需要用小驼峰\n },\n```\n\n⚠️更改了.eslintrc.js文件,需要关掉项目重新打开才会生效\n","slug":"eslint-prettier","published":1,"updated":"2023-07-08T04:30:38.592Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r09000ca9li4zvd4cao","content":"<h4 id=\"eslint-x2F-prettier如何做到规范代码的\"><a href=\"#eslint-x2F-prettier如何做到规范代码的\" class=\"headerlink\" title=\"eslint / prettier如何做到规范代码的\"></a>eslint / prettier如何做到规范代码的</h4><p>ESLint 和 Prettier 都是前端开发中常用的代码规范工具,它们可以帮助开发人员规范代码、提高代码质量,并减少代码错误。下面是它们如何规范代码的简要介绍:</p>\n<h6 id=\"●ESLint\"><a href=\"#●ESLint\" class=\"headerlink\" title=\"●ESLint\"></a>●ESLint</h6><p>○语法检查: ESLint 可以检查代码中是否存在语法错误,例如未定义的变量、语法错误的表达式等<br>○代码风格检查: ESLint 可以检查代码的风格是否符合规范,例如缩进、变量命名、空格等<br>○安全性检查: ESLint 可以检查代码中是否存在安全漏洞,例如 XSS 攻击、SQL 注入等<br>○自定义规则: ESLint 提供了丰富的规则配置,开发人员可以根据自己的需要自定义规则并进行代码检查</p>\n<h6 id=\"●Prettier\"><a href=\"#●Prettier\" class=\"headerlink\" title=\"●Prettier\"></a>●Prettier</h6><p>○代码格式化: 可以自动格式化代码,使代码符合规范,并保持一致的风格<br>○代码布局: 可以自动调整代码的布局,使代码易于阅读和理解<br>○多语言支持: 支持多种编程语言,例如 JavaScript、TypeScript、CSS、Markdown 等</p>\n<h4 id=\"eslint-x2F-prettier之间的关系\"><a href=\"#eslint-x2F-prettier之间的关系\" class=\"headerlink\" title=\"eslint / prettier之间的关系\"></a>eslint / prettier之间的关系</h4><p>ESLint 和 Prettier 都是前端开发中常用的代码规范工具,它们可以帮助开发人员规范代码、提高代码质量,并减少代码错误。虽然它们都可以用于规范代码,但它们之间有不同的关注点和使用方式。<br>ESLint 主要用于检查代码风格和语法错误,可以通过配置文件来定制自己的代码风格规范,并提供了丰富的插件和扩展,可以支持各种语言和框架。ESLint 的作用是在编码过程中及时发现和解决代码问题,从而提高代码质量和可维护性。<br>Prettier 主要用于代码格式化,可以对代码进行自动格式化,使代码符合统一的规范和风格。开发人员可以通过配置文件来定制自己的代码格式化规范,并支持多种语言和框架。Prettier 的作用是将已经编写好的代码快速地格式化成一个统一的格式,从而使代码更加易读、易维护、易扩展。<br>ESLint 和 Prettier 可以结合使用,通过使用 eslint-plugin-prettier 插件和 eslint-config-prettier 配置来将 Prettier 集成到 ESLint 中。这样可以使用 ESLint 来检查代码风格和语法错误,并使用 Prettier 来进行代码格式化。结合使用可以提高代码质量和开发效率,同时也能够使代码更加统一和规范。<br>总之,ESLint 和 Prettier 都是前端开发中常用的代码规范工具,虽然它们之间有不同的关注点和使用方式,但可以结合使用来提高代码质量和开发效率。</p>\n<h4 id=\"eslint-x2F-prettier-在react和vue项目中如何使用\"><a href=\"#eslint-x2F-prettier-在react和vue项目中如何使用\" class=\"headerlink\" title=\"eslint/prettier 在react和vue项目中如何使用\"></a>eslint/prettier 在react和vue项目中如何使用</h4><h6 id=\"●react项目\"><a href=\"#●react项目\" class=\"headerlink\" title=\"●react项目\"></a>●react项目</h6><p>○安装eslint/prettier相关插件<br>npm install eslint prettier eslint-plugin-react eslint-config-prettier eslint-plugin-prettier –save-dev</p>\n<p>○创建.eslintrc.json配置文件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"string\">"extends"</span>: [</span><br><span class=\"line\"> <span class=\"string\">"eslint:recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"plugin:react/recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"plugin:prettier/recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"prettier/react"</span></span><br><span class=\"line\"> ],</span><br><span class=\"line\"> <span class=\"string\">"plugins"</span>: [<span class=\"string\">"react"</span>, <span class=\"string\">"prettier"</span>],</span><br><span class=\"line\"> <span class=\"string\">"rules"</span>: {</span><br><span class=\"line\"> <span class=\"string\">"prettier/prettier"</span>: [<span class=\"string\">"error"</span>, {}, { <span class=\"string\">"usePrettierrc"</span>: <span class=\"literal\">true</span> }]</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>○创建.prettierrc.json配置文件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"string\">"printWidth"</span>: <span class=\"number\">80</span>,</span><br><span class=\"line\"> <span class=\"string\">"tabWidth"</span>: <span class=\"number\">2</span>,</span><br><span class=\"line\"> <span class=\"string\">"useTabs"</span>: <span class=\"literal\">false</span>,</span><br><span class=\"line\"> <span class=\"string\">"semi"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"singleQuote"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"jsxSingleQuote"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"trailingComma"</span>: <span class=\"string\">"es5"</span>,</span><br><span class=\"line\"> <span class=\"string\">"bracketSpacing"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"jsxBracketSameLine"</span>: <span class=\"literal\">false</span>,</span><br><span class=\"line\"> <span class=\"string\">"arrowParens"</span>: <span class=\"string\">"always"</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>○在编辑器中安装并配置eslint和prettier插件,例如 VS Code中可以安装ESLint和Prettier插件,并在setting.json文件中添加以下配置</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"string\">"editor.formatOnSave"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"><span class=\"string\">"editor.defaultFormatter"</span>: <span class=\"string\">"esbenp.prettier-vscode"</span>,</span><br><span class=\"line\"><span class=\"string\">"editor.codeActionsOnSave"</span>: {</span><br><span class=\"line\"> <span class=\"string\">"source.fixAll.eslint"</span>: <span class=\"literal\">true</span></span><br><span class=\"line\">},</span><br></pre></td></tr></table></figure>\n\n<h6 id=\"●vue项目(注:和上面react项目步骤基本一样,唯一的区别就是安装的eslint-x2F-prettier插件有区别,最下面👇再来解释一下为什么\"><a href=\"#●vue项目(注:和上面react项目步骤基本一样,唯一的区别就是安装的eslint-x2F-prettier插件有区别,最下面👇再来解释一下为什么\" class=\"headerlink\" title=\"●vue项目(注:和上面react项目步骤基本一样,唯一的区别就是安装的eslint/prettier插件有区别,最下面👇再来解释一下为什么\"></a>●vue项目(注:和上面react项目步骤基本一样,唯一的区别就是安装的eslint/prettier插件有区别,最下面👇再来解释一下为什么</h6><p>○安装eslint/prettier相关插件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm install eslint prettier eslint-plugin-vue eslint-config-prettier eslint-plugin-prettier --save-dev</span><br></pre></td></tr></table></figure>\n\n<p>○创建.eslintrc.json配置文件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"string\">"extends"</span>: [</span><br><span class=\"line\"> <span class=\"string\">"eslint:recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"plugin:vue/recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"plugin:prettier/recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"prettier/vue"</span></span><br><span class=\"line\"> ],</span><br><span class=\"line\"> <span class=\"string\">"plugins"</span>: [<span class=\"string\">"vue"</span>, <span class=\"string\">"prettier"</span>],</span><br><span class=\"line\"> <span class=\"string\">"rules"</span>: {</span><br><span class=\"line\"> <span class=\"string\">"prettier/prettier"</span>: [<span class=\"string\">"error"</span>, {}, { <span class=\"string\">"usePrettierrc"</span>: <span class=\"literal\">true</span> }]</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>○创建.prettierrc.json配置文件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"string\">"printWidth"</span>: <span class=\"number\">80</span>,</span><br><span class=\"line\"> <span class=\"string\">"tabWidth"</span>: <span class=\"number\">2</span>,</span><br><span class=\"line\"> <span class=\"string\">"useTabs"</span>: <span class=\"literal\">false</span>,</span><br><span class=\"line\"> <span class=\"string\">"semi"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"singleQuote"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"trailingComma"</span>: <span class=\"string\">"es5"</span>,</span><br><span class=\"line\"> <span class=\"string\">"bracketSpacing"</span>: <span class=\"literal\">true</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>○在编辑中安装eslint和prettier插件,例如VS Code中可以安装ESLint和Prettier插件,并在setting.json中添加以下配置</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"string\">"editor.formatOnSave"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"><span class=\"string\">"editor.defaultFormatter"</span>: <span class=\"string\">"esbenp.prettier-vscode"</span>,</span><br><span class=\"line\"><span class=\"string\">"editor.codeActionsOnSave"</span>: {</span><br><span class=\"line\"> <span class=\"string\">"source.fixAll.eslint"</span>: <span class=\"literal\">true</span></span><br><span class=\"line\">},</span><br></pre></td></tr></table></figure>\n\n<p>(vue和react存在模版语法、组件命名、状态管理等方面的差异,隐藏需要根据具体框架使用合适的插件和扩展,以确保代码可读性和可维护性,提高代码质量和开发效率<br>(1)模版语法: 在vue中,模版语法是一种重要的语法结构,需要进行检查和规范,可以使用eslint-plugin-vue来检查模版语法问题;而在react中,通常使用jsx语法来定义组件,可以使用eslint-plugin-react来检查jsx相关代码<br>(2)组件命名:在vue中,组件命名采用kebab-case(短横线命名法),例如my-component。而在react中,采用PascalCase(大驼峰),例如MyComponent。需要根据具体的框架选择合适的命名规范<br>(3)状态管理,在vue中使用vuex,react中使用redux\\mobx等状态管理库<br>(4)插件和扩展:vue和react需要使用不同的扩展工具,例如:eslint-plugin-react和eslint-plugin-vue</p>\n<h4 id=\"怎么自定义规范(实践)\"><a href=\"#怎么自定义规范(实践)\" class=\"headerlink\" title=\"怎么自定义规范(实践)\"></a>怎么自定义规范(实践)</h4><p>(1)使用官方生成自定义eslint规范的脚手架工具</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 安装环境</span></span><br><span class=\"line\">npm i -g yo</span><br><span class=\"line\">npm i -g generator-eslint</span><br><span class=\"line\"><span class=\"comment\">// cd 要放置项目的文件夹,创建项目</span></span><br><span class=\"line\">yo <span class=\"attr\">eslint</span>:plugin</span><br><span class=\"line\"><span class=\"comment\">//下面是创建之后需要输入的信息</span></span><br><span class=\"line\"><span class=\"comment\">//yo eslint:rule</span></span><br><span class=\"line\"><span class=\"comment\">//What is your name? 随便写个你的名字</span></span><br><span class=\"line\"><span class=\"comment\">//What is the plugin ID? 你的插件的id,推荐(eslint-plugin-xxx)的命名方式</span></span><br><span class=\"line\"><span class=\"comment\">//Type a short description of this plugin: 描述你的插件是干啥的</span></span><br><span class=\"line\"><span class=\"comment\">//Does this plugin contain custom ESLint rules? Yes</span></span><br><span class=\"line\"><span class=\"comment\">//Does this plugin contain one or more processors? Yes</span></span><br></pre></td></tr></table></figure>\n\n<p>生成下面目录</p>\n<p>(2)在lib/rules/my-custom-rules1.js中写自定义的规则,下面是基本模版</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"comment\">// meta里面的元数据,对于我们自定义规则,其实只关心schema就行了</span></span><br><span class=\"line\"> <span class=\"attr\">meta</span>: {</span><br><span class=\"line\"> <span class=\"comment\">// 规则的类型problem|suggestion|layout</span></span><br><span class=\"line\"> <span class=\"comment\">// problem: 这条规则识别的代码可能会导致错误或让人迷惑。应该优先解决这个问题</span></span><br><span class=\"line\"> <span class=\"comment\">// suggestion: 这条规则识别的代码不会导致错误,但是建议用更好的方式</span></span><br><span class=\"line\"> <span class=\"comment\">// layout: 表示这条规则主要关心像空格、分号等这种问题</span></span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'suggestion'</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 对于自定义规则,docs字段是非必须的</span></span><br><span class=\"line\"> <span class=\"attr\">docs</span>: {</span><br><span class=\"line\"> <span class=\"attr\">description</span>: <span class=\"string\">'描述你的规则是干啥的'</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 规则的分类,假如你把这条规则提交到eslint核心规则里,那eslint官网规则的首页会按照这个字段进行分类展示</span></span><br><span class=\"line\"> <span class=\"attr\">category</span>: <span class=\"string\">'Possible Errors'</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 假如你把规则提交到eslint核心规则里</span></span><br><span class=\"line\"> <span class=\"comment\">// 且像这样extends: ['eslint:recommended']继承规则的时候,这个属性是true,就会启用这条规则</span></span><br><span class=\"line\"> <span class=\"attr\">recommended</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 你的规则使用文档的url</span></span><br><span class=\"line\"> <span class=\"attr\">url</span>: <span class=\"string\">'https://eslint.org/docs/rules/no-extra-semi'</span>,</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"comment\">// 标识这条规则是否可以修复,假如没有这属性,即使你在下面那个create方法里实现了fix功能,eslint也不会帮你修复</span></span><br><span class=\"line\"> <span class=\"attr\">fixable</span>: <span class=\"string\">'code'</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 这里定义了这条规则需要的参数</span></span><br><span class=\"line\"> <span class=\"comment\">// 比如我们是这样使用带参数的rule的时候,rules: { myRule: ['error', param1, param2....]}</span></span><br><span class=\"line\"> <span class=\"comment\">// error后面的就是参数,而参数就是在这里定义的</span></span><br><span class=\"line\"> <span class=\"attr\">schema</span>: [],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">create</span>: <span class=\"keyword\">function</span> (<span class=\"params\">context</span>) {</span><br><span class=\"line\"> <span class=\"comment\">// 这是最重要的方法,我们对代码的校验就是在这里做的</span></span><br><span class=\"line\"> <span class=\"keyword\">return</span> {</span><br><span class=\"line\"> <span class=\"comment\">// callback functions</span></span><br><span class=\"line\"> };</span><br><span class=\"line\"> },</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p>接下来介绍creact方法<br>eslint校验代码其实是解析文件内容,通过AST(抽象语法树)生成一个对象,再检查这个对象是否符合我们的要求,如果不符合要求就报出错误<br>下面举例</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">enum myEnumText {</span><br><span class=\"line\">firstName = <span class=\"number\">1</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>//下面是它的AST形式</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">sourceType</span>: <span class=\"variable language_\">module</span></span><br><span class=\"line\"><span class=\"attr\">body</span>: [</span><br><span class=\"line\"> <span class=\"title class_\">EnumDeclaration</span>: {</span><br><span class=\"line\"> <span class=\"attr\">id</span>: <span class=\"title class_\">Identifier</span> {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">"myEnumText"</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"attr\">body</span>: {</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"title class_\">EnumBooleanBody</span></span><br><span class=\"line\"> <span class=\"attr\">members</span>: [</span><br><span class=\"line\"> <span class=\"title class_\">EnumBooleanMember</span>: {</span><br><span class=\"line\"> <span class=\"attr\">id</span>: <span class=\"title class_\">Identifier</span> {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">"firstName"</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"attr\">init</span>: <span class=\"title class_\">NumericLiteral</span> {</span><br><span class=\"line\"> <span class=\"attr\">value</span>: <span class=\"number\">1</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> ]</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\">]</span><br></pre></td></tr></table></figure>\n\n<p>从上面代码可以看出,enum类型的声明变量名是EnumDeclaration,并且通过node.id.name可以获取到声明的变量名,我们通过正则可以校验这个变量名是否以E开头,如果不以E开头就报错或者警告<br><img src=\"/../images/1.png\"><br>(3)接下来是怎么在项目中使用(这里我的插件名称是eslint-plugin-st-rules<br>●将上面的项目发布成npm插件,npm login / npm publish</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm login --registry=<span class=\"string\">"具体发包地址"</span></span><br><span class=\"line\">npm publish --registry=<span class=\"string\">"具体发包地址"</span></span><br></pre></td></tr></table></figure>\n\n<p>●在项目中npm install eslint-plugin-rules</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm install eslint-plugin-rules --<span class=\"string\">"具体发包地址"</span></span><br></pre></td></tr></table></figure>\n\n<p>●在.eslintrc.js中 (在这里可以省略eslint-plugin-)</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">plugins</span>: [<span class=\"string\">'st-rules'</span>],</span><br><span class=\"line\"> <span class=\"attr\">rules</span>: {</span><br><span class=\"line\"> <span class=\"string\">'st-rules/type-prefix'</span>: <span class=\"string\">'warn'</span>, <span class=\"comment\">// type类型要用T开头</span></span><br><span class=\"line\"> <span class=\"string\">'st-rules/interface-prefix'</span>: <span class=\"string\">'warn'</span>, <span class=\"comment\">// interface类型要用I开头</span></span><br><span class=\"line\"> <span class=\"string\">'st-rules/enum-prefix'</span>: <span class=\"string\">'warn'</span>, <span class=\"comment\">// enum类型要用E开头</span></span><br><span class=\"line\"> <span class=\"string\">'st-rules/variable-name-camelcase'</span>: <span class=\"string\">'warn'</span>, <span class=\"comment\">// let var定义的变量需要用小驼峰</span></span><br><span class=\"line\"> },</span><br></pre></td></tr></table></figure>\n\n<p>⚠️更改了.eslintrc.js文件,需要关掉项目重新打开才会生效</p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h4 id=\"eslint-x2F-prettier如何做到规范代码的\"><a href=\"#eslint-x2F-prettier如何做到规范代码的\" class=\"headerlink\" title=\"eslint / prettier如何做到规范代码的\"></a>eslint / prettier如何做到规范代码的</h4><p>ESLint 和 Prettier 都是前端开发中常用的代码规范工具,它们可以帮助开发人员规范代码、提高代码质量,并减少代码错误。下面是它们如何规范代码的简要介绍:</p>\n<h6 id=\"●ESLint\"><a href=\"#●ESLint\" class=\"headerlink\" title=\"●ESLint\"></a>●ESLint</h6><p>○语法检查: ESLint 可以检查代码中是否存在语法错误,例如未定义的变量、语法错误的表达式等<br>○代码风格检查: ESLint 可以检查代码的风格是否符合规范,例如缩进、变量命名、空格等<br>○安全性检查: ESLint 可以检查代码中是否存在安全漏洞,例如 XSS 攻击、SQL 注入等<br>○自定义规则: ESLint 提供了丰富的规则配置,开发人员可以根据自己的需要自定义规则并进行代码检查</p>\n<h6 id=\"●Prettier\"><a href=\"#●Prettier\" class=\"headerlink\" title=\"●Prettier\"></a>●Prettier</h6><p>○代码格式化: 可以自动格式化代码,使代码符合规范,并保持一致的风格<br>○代码布局: 可以自动调整代码的布局,使代码易于阅读和理解<br>○多语言支持: 支持多种编程语言,例如 JavaScript、TypeScript、CSS、Markdown 等</p>\n<h4 id=\"eslint-x2F-prettier之间的关系\"><a href=\"#eslint-x2F-prettier之间的关系\" class=\"headerlink\" title=\"eslint / prettier之间的关系\"></a>eslint / prettier之间的关系</h4><p>ESLint 和 Prettier 都是前端开发中常用的代码规范工具,它们可以帮助开发人员规范代码、提高代码质量,并减少代码错误。虽然它们都可以用于规范代码,但它们之间有不同的关注点和使用方式。<br>ESLint 主要用于检查代码风格和语法错误,可以通过配置文件来定制自己的代码风格规范,并提供了丰富的插件和扩展,可以支持各种语言和框架。ESLint 的作用是在编码过程中及时发现和解决代码问题,从而提高代码质量和可维护性。<br>Prettier 主要用于代码格式化,可以对代码进行自动格式化,使代码符合统一的规范和风格。开发人员可以通过配置文件来定制自己的代码格式化规范,并支持多种语言和框架。Prettier 的作用是将已经编写好的代码快速地格式化成一个统一的格式,从而使代码更加易读、易维护、易扩展。<br>ESLint 和 Prettier 可以结合使用,通过使用 eslint-plugin-prettier 插件和 eslint-config-prettier 配置来将 Prettier 集成到 ESLint 中。这样可以使用 ESLint 来检查代码风格和语法错误,并使用 Prettier 来进行代码格式化。结合使用可以提高代码质量和开发效率,同时也能够使代码更加统一和规范。<br>总之,ESLint 和 Prettier 都是前端开发中常用的代码规范工具,虽然它们之间有不同的关注点和使用方式,但可以结合使用来提高代码质量和开发效率。</p>\n<h4 id=\"eslint-x2F-prettier-在react和vue项目中如何使用\"><a href=\"#eslint-x2F-prettier-在react和vue项目中如何使用\" class=\"headerlink\" title=\"eslint/prettier 在react和vue项目中如何使用\"></a>eslint/prettier 在react和vue项目中如何使用</h4><h6 id=\"●react项目\"><a href=\"#●react项目\" class=\"headerlink\" title=\"●react项目\"></a>●react项目</h6><p>○安装eslint/prettier相关插件<br>npm install eslint prettier eslint-plugin-react eslint-config-prettier eslint-plugin-prettier –save-dev</p>\n<p>○创建.eslintrc.json配置文件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"string\">"extends"</span>: [</span><br><span class=\"line\"> <span class=\"string\">"eslint:recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"plugin:react/recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"plugin:prettier/recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"prettier/react"</span></span><br><span class=\"line\"> ],</span><br><span class=\"line\"> <span class=\"string\">"plugins"</span>: [<span class=\"string\">"react"</span>, <span class=\"string\">"prettier"</span>],</span><br><span class=\"line\"> <span class=\"string\">"rules"</span>: {</span><br><span class=\"line\"> <span class=\"string\">"prettier/prettier"</span>: [<span class=\"string\">"error"</span>, {}, { <span class=\"string\">"usePrettierrc"</span>: <span class=\"literal\">true</span> }]</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>○创建.prettierrc.json配置文件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"string\">"printWidth"</span>: <span class=\"number\">80</span>,</span><br><span class=\"line\"> <span class=\"string\">"tabWidth"</span>: <span class=\"number\">2</span>,</span><br><span class=\"line\"> <span class=\"string\">"useTabs"</span>: <span class=\"literal\">false</span>,</span><br><span class=\"line\"> <span class=\"string\">"semi"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"singleQuote"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"jsxSingleQuote"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"trailingComma"</span>: <span class=\"string\">"es5"</span>,</span><br><span class=\"line\"> <span class=\"string\">"bracketSpacing"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"jsxBracketSameLine"</span>: <span class=\"literal\">false</span>,</span><br><span class=\"line\"> <span class=\"string\">"arrowParens"</span>: <span class=\"string\">"always"</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>○在编辑器中安装并配置eslint和prettier插件,例如 VS Code中可以安装ESLint和Prettier插件,并在setting.json文件中添加以下配置</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"string\">"editor.formatOnSave"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"><span class=\"string\">"editor.defaultFormatter"</span>: <span class=\"string\">"esbenp.prettier-vscode"</span>,</span><br><span class=\"line\"><span class=\"string\">"editor.codeActionsOnSave"</span>: {</span><br><span class=\"line\"> <span class=\"string\">"source.fixAll.eslint"</span>: <span class=\"literal\">true</span></span><br><span class=\"line\">},</span><br></pre></td></tr></table></figure>\n\n<h6 id=\"●vue项目(注:和上面react项目步骤基本一样,唯一的区别就是安装的eslint-x2F-prettier插件有区别,最下面👇再来解释一下为什么\"><a href=\"#●vue项目(注:和上面react项目步骤基本一样,唯一的区别就是安装的eslint-x2F-prettier插件有区别,最下面👇再来解释一下为什么\" class=\"headerlink\" title=\"●vue项目(注:和上面react项目步骤基本一样,唯一的区别就是安装的eslint/prettier插件有区别,最下面👇再来解释一下为什么\"></a>●vue项目(注:和上面react项目步骤基本一样,唯一的区别就是安装的eslint/prettier插件有区别,最下面👇再来解释一下为什么</h6><p>○安装eslint/prettier相关插件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm install eslint prettier eslint-plugin-vue eslint-config-prettier eslint-plugin-prettier --save-dev</span><br></pre></td></tr></table></figure>\n\n<p>○创建.eslintrc.json配置文件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"string\">"extends"</span>: [</span><br><span class=\"line\"> <span class=\"string\">"eslint:recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"plugin:vue/recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"plugin:prettier/recommended"</span>,</span><br><span class=\"line\"> <span class=\"string\">"prettier/vue"</span></span><br><span class=\"line\"> ],</span><br><span class=\"line\"> <span class=\"string\">"plugins"</span>: [<span class=\"string\">"vue"</span>, <span class=\"string\">"prettier"</span>],</span><br><span class=\"line\"> <span class=\"string\">"rules"</span>: {</span><br><span class=\"line\"> <span class=\"string\">"prettier/prettier"</span>: [<span class=\"string\">"error"</span>, {}, { <span class=\"string\">"usePrettierrc"</span>: <span class=\"literal\">true</span> }]</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>○创建.prettierrc.json配置文件</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"string\">"printWidth"</span>: <span class=\"number\">80</span>,</span><br><span class=\"line\"> <span class=\"string\">"tabWidth"</span>: <span class=\"number\">2</span>,</span><br><span class=\"line\"> <span class=\"string\">"useTabs"</span>: <span class=\"literal\">false</span>,</span><br><span class=\"line\"> <span class=\"string\">"semi"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"singleQuote"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"string\">"trailingComma"</span>: <span class=\"string\">"es5"</span>,</span><br><span class=\"line\"> <span class=\"string\">"bracketSpacing"</span>: <span class=\"literal\">true</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>○在编辑中安装eslint和prettier插件,例如VS Code中可以安装ESLint和Prettier插件,并在setting.json中添加以下配置</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"string\">"editor.formatOnSave"</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"><span class=\"string\">"editor.defaultFormatter"</span>: <span class=\"string\">"esbenp.prettier-vscode"</span>,</span><br><span class=\"line\"><span class=\"string\">"editor.codeActionsOnSave"</span>: {</span><br><span class=\"line\"> <span class=\"string\">"source.fixAll.eslint"</span>: <span class=\"literal\">true</span></span><br><span class=\"line\">},</span><br></pre></td></tr></table></figure>\n\n<p>(vue和react存在模版语法、组件命名、状态管理等方面的差异,隐藏需要根据具体框架使用合适的插件和扩展,以确保代码可读性和可维护性,提高代码质量和开发效率<br>(1)模版语法: 在vue中,模版语法是一种重要的语法结构,需要进行检查和规范,可以使用eslint-plugin-vue来检查模版语法问题;而在react中,通常使用jsx语法来定义组件,可以使用eslint-plugin-react来检查jsx相关代码<br>(2)组件命名:在vue中,组件命名采用kebab-case(短横线命名法),例如my-component。而在react中,采用PascalCase(大驼峰),例如MyComponent。需要根据具体的框架选择合适的命名规范<br>(3)状态管理,在vue中使用vuex,react中使用redux\\mobx等状态管理库<br>(4)插件和扩展:vue和react需要使用不同的扩展工具,例如:eslint-plugin-react和eslint-plugin-vue</p>\n<h4 id=\"怎么自定义规范(实践)\"><a href=\"#怎么自定义规范(实践)\" class=\"headerlink\" title=\"怎么自定义规范(实践)\"></a>怎么自定义规范(实践)</h4><p>(1)使用官方生成自定义eslint规范的脚手架工具</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 安装环境</span></span><br><span class=\"line\">npm i -g yo</span><br><span class=\"line\">npm i -g generator-eslint</span><br><span class=\"line\"><span class=\"comment\">// cd 要放置项目的文件夹,创建项目</span></span><br><span class=\"line\">yo <span class=\"attr\">eslint</span>:plugin</span><br><span class=\"line\"><span class=\"comment\">//下面是创建之后需要输入的信息</span></span><br><span class=\"line\"><span class=\"comment\">//yo eslint:rule</span></span><br><span class=\"line\"><span class=\"comment\">//What is your name? 随便写个你的名字</span></span><br><span class=\"line\"><span class=\"comment\">//What is the plugin ID? 你的插件的id,推荐(eslint-plugin-xxx)的命名方式</span></span><br><span class=\"line\"><span class=\"comment\">//Type a short description of this plugin: 描述你的插件是干啥的</span></span><br><span class=\"line\"><span class=\"comment\">//Does this plugin contain custom ESLint rules? Yes</span></span><br><span class=\"line\"><span class=\"comment\">//Does this plugin contain one or more processors? Yes</span></span><br></pre></td></tr></table></figure>\n\n<p>生成下面目录</p>\n<p>(2)在lib/rules/my-custom-rules1.js中写自定义的规则,下面是基本模版</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"comment\">// meta里面的元数据,对于我们自定义规则,其实只关心schema就行了</span></span><br><span class=\"line\"> <span class=\"attr\">meta</span>: {</span><br><span class=\"line\"> <span class=\"comment\">// 规则的类型problem|suggestion|layout</span></span><br><span class=\"line\"> <span class=\"comment\">// problem: 这条规则识别的代码可能会导致错误或让人迷惑。应该优先解决这个问题</span></span><br><span class=\"line\"> <span class=\"comment\">// suggestion: 这条规则识别的代码不会导致错误,但是建议用更好的方式</span></span><br><span class=\"line\"> <span class=\"comment\">// layout: 表示这条规则主要关心像空格、分号等这种问题</span></span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'suggestion'</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 对于自定义规则,docs字段是非必须的</span></span><br><span class=\"line\"> <span class=\"attr\">docs</span>: {</span><br><span class=\"line\"> <span class=\"attr\">description</span>: <span class=\"string\">'描述你的规则是干啥的'</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 规则的分类,假如你把这条规则提交到eslint核心规则里,那eslint官网规则的首页会按照这个字段进行分类展示</span></span><br><span class=\"line\"> <span class=\"attr\">category</span>: <span class=\"string\">'Possible Errors'</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 假如你把规则提交到eslint核心规则里</span></span><br><span class=\"line\"> <span class=\"comment\">// 且像这样extends: ['eslint:recommended']继承规则的时候,这个属性是true,就会启用这条规则</span></span><br><span class=\"line\"> <span class=\"attr\">recommended</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 你的规则使用文档的url</span></span><br><span class=\"line\"> <span class=\"attr\">url</span>: <span class=\"string\">'https://eslint.org/docs/rules/no-extra-semi'</span>,</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"comment\">// 标识这条规则是否可以修复,假如没有这属性,即使你在下面那个create方法里实现了fix功能,eslint也不会帮你修复</span></span><br><span class=\"line\"> <span class=\"attr\">fixable</span>: <span class=\"string\">'code'</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 这里定义了这条规则需要的参数</span></span><br><span class=\"line\"> <span class=\"comment\">// 比如我们是这样使用带参数的rule的时候,rules: { myRule: ['error', param1, param2....]}</span></span><br><span class=\"line\"> <span class=\"comment\">// error后面的就是参数,而参数就是在这里定义的</span></span><br><span class=\"line\"> <span class=\"attr\">schema</span>: [],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">create</span>: <span class=\"keyword\">function</span> (<span class=\"params\">context</span>) {</span><br><span class=\"line\"> <span class=\"comment\">// 这是最重要的方法,我们对代码的校验就是在这里做的</span></span><br><span class=\"line\"> <span class=\"keyword\">return</span> {</span><br><span class=\"line\"> <span class=\"comment\">// callback functions</span></span><br><span class=\"line\"> };</span><br><span class=\"line\"> },</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p>接下来介绍creact方法<br>eslint校验代码其实是解析文件内容,通过AST(抽象语法树)生成一个对象,再检查这个对象是否符合我们的要求,如果不符合要求就报出错误<br>下面举例</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">enum myEnumText {</span><br><span class=\"line\">firstName = <span class=\"number\">1</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>//下面是它的AST形式</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">sourceType</span>: <span class=\"variable language_\">module</span></span><br><span class=\"line\"><span class=\"attr\">body</span>: [</span><br><span class=\"line\"> <span class=\"title class_\">EnumDeclaration</span>: {</span><br><span class=\"line\"> <span class=\"attr\">id</span>: <span class=\"title class_\">Identifier</span> {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">"myEnumText"</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"attr\">body</span>: {</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"title class_\">EnumBooleanBody</span></span><br><span class=\"line\"> <span class=\"attr\">members</span>: [</span><br><span class=\"line\"> <span class=\"title class_\">EnumBooleanMember</span>: {</span><br><span class=\"line\"> <span class=\"attr\">id</span>: <span class=\"title class_\">Identifier</span> {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">"firstName"</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"attr\">init</span>: <span class=\"title class_\">NumericLiteral</span> {</span><br><span class=\"line\"> <span class=\"attr\">value</span>: <span class=\"number\">1</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> ]</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\">]</span><br></pre></td></tr></table></figure>\n\n<p>从上面代码可以看出,enum类型的声明变量名是EnumDeclaration,并且通过node.id.name可以获取到声明的变量名,我们通过正则可以校验这个变量名是否以E开头,如果不以E开头就报错或者警告<br><img src=\"/../images/1.png\"><br>(3)接下来是怎么在项目中使用(这里我的插件名称是eslint-plugin-st-rules<br>●将上面的项目发布成npm插件,npm login / npm publish</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm login --registry=<span class=\"string\">"具体发包地址"</span></span><br><span class=\"line\">npm publish --registry=<span class=\"string\">"具体发包地址"</span></span><br></pre></td></tr></table></figure>\n\n<p>●在项目中npm install eslint-plugin-rules</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm install eslint-plugin-rules --<span class=\"string\">"具体发包地址"</span></span><br></pre></td></tr></table></figure>\n\n<p>●在.eslintrc.js中 (在这里可以省略eslint-plugin-)</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">plugins</span>: [<span class=\"string\">'st-rules'</span>],</span><br><span class=\"line\"> <span class=\"attr\">rules</span>: {</span><br><span class=\"line\"> <span class=\"string\">'st-rules/type-prefix'</span>: <span class=\"string\">'warn'</span>, <span class=\"comment\">// type类型要用T开头</span></span><br><span class=\"line\"> <span class=\"string\">'st-rules/interface-prefix'</span>: <span class=\"string\">'warn'</span>, <span class=\"comment\">// interface类型要用I开头</span></span><br><span class=\"line\"> <span class=\"string\">'st-rules/enum-prefix'</span>: <span class=\"string\">'warn'</span>, <span class=\"comment\">// enum类型要用E开头</span></span><br><span class=\"line\"> <span class=\"string\">'st-rules/variable-name-camelcase'</span>: <span class=\"string\">'warn'</span>, <span class=\"comment\">// let var定义的变量需要用小驼峰</span></span><br><span class=\"line\"> },</span><br></pre></td></tr></table></figure>\n\n<p>⚠️更改了.eslintrc.js文件,需要关掉项目重新打开才会生效</p>\n"},{"title":"flex","date":"2023-07-08T02:43:39.000Z","_content":"\n#### align-content、align-items、align-self区别\n\n●align-content(flex-start/flex-end/center/stretch/space-between/space-around\n![](../images/5.png)\n●align-items\n![](../images/6.png)\n●align-self\nalign-self属性规定的是flex容器规定的align-items属性,同样也只能规定在交叉轴上的对齐方式,默认align-self:auto,所以会继承align-items属性\n","source":"_posts/flex.md","raw":"---\ntitle: flex\ndate: 2023-07-08 10:43:39\ntags:\ncategories:\n - css\n---\n\n#### align-content、align-items、align-self区别\n\n●align-content(flex-start/flex-end/center/stretch/space-between/space-around\n![](../images/5.png)\n●align-items\n![](../images/6.png)\n●align-self\nalign-self属性规定的是flex容器规定的align-items属性,同样也只能规定在交叉轴上的对齐方式,默认align-self:auto,所以会继承align-items属性\n","slug":"flex","published":1,"updated":"2023-07-08T04:30:38.593Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0a000fa9li0awy675h","content":"<h4 id=\"align-content、align-items、align-self区别\"><a href=\"#align-content、align-items、align-self区别\" class=\"headerlink\" title=\"align-content、align-items、align-self区别\"></a>align-content、align-items、align-self区别</h4><p>●align-content(flex-start/flex-end/center/stretch/space-between/space-around<br><img src=\"/../images/5.png\"><br>●align-items<br><img src=\"/../images/6.png\"><br>●align-self<br>align-self属性规定的是flex容器规定的align-items属性,同样也只能规定在交叉轴上的对齐方式,默认align-self:auto,所以会继承align-items属性</p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h4 id=\"align-content、align-items、align-self区别\"><a href=\"#align-content、align-items、align-self区别\" class=\"headerlink\" title=\"align-content、align-items、align-self区别\"></a>align-content、align-items、align-self区别</h4><p>●align-content(flex-start/flex-end/center/stretch/space-between/space-around<br><img src=\"/../images/5.png\"><br>●align-items<br><img src=\"/../images/6.png\"><br>●align-self<br>align-self属性规定的是flex容器规定的align-items属性,同样也只能规定在交叉轴上的对齐方式,默认align-self:auto,所以会继承align-items属性</p>\n"},{"title":"Hello World","_content":"Welcome to [Hexo](https://hexo.io/)! This is your very first post. Check [documentation](https://hexo.io/docs/) for more info. If you get any problems when using Hexo, you can find the answer in [troubleshooting](https://hexo.io/docs/troubleshooting.html) or you can ask me on [GitHub](https://github.com/hexojs/hexo/issues).\n\n## Quick Start\n\n### Create a new post\n\n``` bash\nhexo new \"My New Post\"\n```\n\nMore info: [Writing](https://hexo.io/docs/writing.html)\n\n### Run server\n\n``` bash\nhexo server\n```\n\nMore info: [Server](https://hexo.io/docs/server.html)\n\n### Generate static files\n\n``` bash\nhexo generate\n```\n\nMore info: [Generating](https://hexo.io/docs/generating.html)\n\n### Deploy to remote sites\n\n``` bash\nhexo deploy\n```\n\nMore info: [Deployment](https://hexo.io/docs/one-command-deployment.html)\n","source":"_posts/hello-world.md","raw":"---\ntitle: Hello World\n---\nWelcome to [Hexo](https://hexo.io/)! This is your very first post. Check [documentation](https://hexo.io/docs/) for more info. If you get any problems when using Hexo, you can find the answer in [troubleshooting](https://hexo.io/docs/troubleshooting.html) or you can ask me on [GitHub](https://github.com/hexojs/hexo/issues).\n\n## Quick Start\n\n### Create a new post\n\n``` bash\nhexo new \"My New Post\"\n```\n\nMore info: [Writing](https://hexo.io/docs/writing.html)\n\n### Run server\n\n``` bash\nhexo server\n```\n\nMore info: [Server](https://hexo.io/docs/server.html)\n\n### Generate static files\n\n``` bash\nhexo generate\n```\n\nMore info: [Generating](https://hexo.io/docs/generating.html)\n\n### Deploy to remote sites\n\n``` bash\nhexo deploy\n```\n\nMore info: [Deployment](https://hexo.io/docs/one-command-deployment.html)\n","slug":"hello-world","published":1,"date":"2023-07-08T04:30:38.593Z","updated":"2023-07-08T04:30:38.593Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0b000ga9li7ug98k11","content":"<p>Welcome to <a href=\"https://hexo.io/\">Hexo</a>! This is your very first post. Check <a href=\"https://hexo.io/docs/\">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href=\"https://hexo.io/docs/troubleshooting.html\">troubleshooting</a> or you can ask me on <a href=\"https://github.com/hexojs/hexo/issues\">GitHub</a>.</p>\n<h2 id=\"Quick-Start\"><a href=\"#Quick-Start\" class=\"headerlink\" title=\"Quick Start\"></a>Quick Start</h2><h3 id=\"Create-a-new-post\"><a href=\"#Create-a-new-post\" class=\"headerlink\" title=\"Create a new post\"></a>Create a new post</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">hexo new <span class=\"string\">"My New Post"</span></span><br></pre></td></tr></table></figure>\n\n<p>More info: <a href=\"https://hexo.io/docs/writing.html\">Writing</a></p>\n<h3 id=\"Run-server\"><a href=\"#Run-server\" class=\"headerlink\" title=\"Run server\"></a>Run server</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">hexo server</span><br></pre></td></tr></table></figure>\n\n<p>More info: <a href=\"https://hexo.io/docs/server.html\">Server</a></p>\n<h3 id=\"Generate-static-files\"><a href=\"#Generate-static-files\" class=\"headerlink\" title=\"Generate static files\"></a>Generate static files</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">hexo generate</span><br></pre></td></tr></table></figure>\n\n<p>More info: <a href=\"https://hexo.io/docs/generating.html\">Generating</a></p>\n<h3 id=\"Deploy-to-remote-sites\"><a href=\"#Deploy-to-remote-sites\" class=\"headerlink\" title=\"Deploy to remote sites\"></a>Deploy to remote sites</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">hexo deploy</span><br></pre></td></tr></table></figure>\n\n<p>More info: <a href=\"https://hexo.io/docs/one-command-deployment.html\">Deployment</a></p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<p>Welcome to <a href=\"https://hexo.io/\">Hexo</a>! This is your very first post. Check <a href=\"https://hexo.io/docs/\">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href=\"https://hexo.io/docs/troubleshooting.html\">troubleshooting</a> or you can ask me on <a href=\"https://github.com/hexojs/hexo/issues\">GitHub</a>.</p>\n<h2 id=\"Quick-Start\"><a href=\"#Quick-Start\" class=\"headerlink\" title=\"Quick Start\"></a>Quick Start</h2><h3 id=\"Create-a-new-post\"><a href=\"#Create-a-new-post\" class=\"headerlink\" title=\"Create a new post\"></a>Create a new post</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">hexo new <span class=\"string\">"My New Post"</span></span><br></pre></td></tr></table></figure>\n\n<p>More info: <a href=\"https://hexo.io/docs/writing.html\">Writing</a></p>\n<h3 id=\"Run-server\"><a href=\"#Run-server\" class=\"headerlink\" title=\"Run server\"></a>Run server</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">hexo server</span><br></pre></td></tr></table></figure>\n\n<p>More info: <a href=\"https://hexo.io/docs/server.html\">Server</a></p>\n<h3 id=\"Generate-static-files\"><a href=\"#Generate-static-files\" class=\"headerlink\" title=\"Generate static files\"></a>Generate static files</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">hexo generate</span><br></pre></td></tr></table></figure>\n\n<p>More info: <a href=\"https://hexo.io/docs/generating.html\">Generating</a></p>\n<h3 id=\"Deploy-to-remote-sites\"><a href=\"#Deploy-to-remote-sites\" class=\"headerlink\" title=\"Deploy to remote sites\"></a>Deploy to remote sites</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">hexo deploy</span><br></pre></td></tr></table></figure>\n\n<p>More info: <a href=\"https://hexo.io/docs/one-command-deployment.html\">Deployment</a></p>\n"},{"title":"loading组件","date":"2023-08-19T16:00:00.000Z","_content":"\n```html\n<div class=\"loading\"></div>\n\n<style>\n .loading {\n width: 30px;\n height: 30px;\n border: 2px solid #000;\n border-top-color: transparent;\n border-radius: 100%;\n\n animation: circle infinite 0.75s linear;\n }\n\n /* 转转转动画 */\n @keyframes circle {\n 0% {\n transform: rotate(0);\n }\n 100% {\n transform: rotate(360deg);\n }\n }\n</style>\n```\n\n```html\n<div class=\"loading\">\n <div></div>\n <div></div>\n <div></div>\n</div>\n<style>\n .loading {\n width: 1.5625rem;\n height: 1.5625rem;\n display: block;\n font-size: 0;\n color: #000;\n position: relative;\n }\n\n .loading > div {\n display: inline-block;\n float: none;\n background-color: currentColor;\n border: 0 solid currentColor;\n position: absolute;\n top: 0;\n left: 0;\n width: 0.5rem;\n height: 0.5rem;\n border-radius: 100%;\n }\n\n .loading > div:nth-child(1) {\n animation: ball-triangle-path-ball-one 3s 0s ease-in-out infinite;\n }\n\n .loading > div:nth-child(2) {\n animation: ball-triangle-path-ball-two 3s 0s ease-in-out infinite;\n background: rgba(179, 179, 180, 1);\n }\n\n .loading > div:nth-child(3) {\n animation: ball-triangle-path-ball-tree 3s 0s ease-in-out infinite;\n background: rgba(114, 113, 115, 1);\n }\n\n @keyframes ball-triangle-path-ball-one {\n 0% {\n transform: translate(0, 220%);\n }\n\n 17% {\n opacity: 0.5;\n }\n\n 33% {\n opacity: 1;\n transform: translate(110%, 0);\n }\n\n 50% {\n opacity: 0.5;\n }\n\n 66% {\n opacity: 1;\n transform: translate(220%, 220%);\n }\n\n 83% {\n opacity: 0.5;\n }\n\n 100% {\n opacity: 1;\n transform: translate(0, 220%);\n }\n }\n\n @keyframes ball-triangle-path-ball-two {\n 0% {\n transform: translate(110%, 0);\n }\n\n 17% {\n opacity: 0.5;\n }\n\n 33% {\n opacity: 1;\n transform: translate(220%, 220%);\n }\n\n 50% {\n opacity: 0.5;\n }\n\n 66% {\n opacity: 1;\n transform: translate(0, 220%);\n }\n\n 83% {\n opacity: 0.5;\n }\n\n 100% {\n opacity: 1;\n transform: translate(110%, 0);\n }\n }\n\n @keyframes ball-triangle-path-ball-tree {\n 0% {\n transform: translate(220%, 220%);\n }\n\n 17% {\n opacity: 0.5;\n }\n\n 33% {\n opacity: 1;\n transform: translate(0, 220%);\n }\n\n 50% {\n opacity: 0.5;\n }\n\n 66% {\n opacity: 1;\n transform: translate(110%, 0);\n }\n\n 83% {\n opacity: 0.5;\n }\n\n 100% {\n opacity: 1;\n transform: translate(220%, 220%);\n }\n }\n</style>\n```\n\n#### 主要是使用了css中关键帧动画\n\n- @keyframes keyName {\n 0%:{\n transform: rotate/ translate\n }\n 100%: {\n\n }\n }\n\n- animation: keyName(关键帧名称) time(周期) infinate(循环) linear(线性变化)\n- animation-delay: time(时间\n- transform: rotate(旋转) translate(位移)\n\n注:引用文章链接\n<https://juejin.cn/post/7037036742985121800#heading-1>\n","source":"_posts/loading.md","raw":"---\ntitle: loading组件\ndate: 2023-08-20\ntags:\ncategories:\n - UI组件\n---\n\n```html\n<div class=\"loading\"></div>\n\n<style>\n .loading {\n width: 30px;\n height: 30px;\n border: 2px solid #000;\n border-top-color: transparent;\n border-radius: 100%;\n\n animation: circle infinite 0.75s linear;\n }\n\n /* 转转转动画 */\n @keyframes circle {\n 0% {\n transform: rotate(0);\n }\n 100% {\n transform: rotate(360deg);\n }\n }\n</style>\n```\n\n```html\n<div class=\"loading\">\n <div></div>\n <div></div>\n <div></div>\n</div>\n<style>\n .loading {\n width: 1.5625rem;\n height: 1.5625rem;\n display: block;\n font-size: 0;\n color: #000;\n position: relative;\n }\n\n .loading > div {\n display: inline-block;\n float: none;\n background-color: currentColor;\n border: 0 solid currentColor;\n position: absolute;\n top: 0;\n left: 0;\n width: 0.5rem;\n height: 0.5rem;\n border-radius: 100%;\n }\n\n .loading > div:nth-child(1) {\n animation: ball-triangle-path-ball-one 3s 0s ease-in-out infinite;\n }\n\n .loading > div:nth-child(2) {\n animation: ball-triangle-path-ball-two 3s 0s ease-in-out infinite;\n background: rgba(179, 179, 180, 1);\n }\n\n .loading > div:nth-child(3) {\n animation: ball-triangle-path-ball-tree 3s 0s ease-in-out infinite;\n background: rgba(114, 113, 115, 1);\n }\n\n @keyframes ball-triangle-path-ball-one {\n 0% {\n transform: translate(0, 220%);\n }\n\n 17% {\n opacity: 0.5;\n }\n\n 33% {\n opacity: 1;\n transform: translate(110%, 0);\n }\n\n 50% {\n opacity: 0.5;\n }\n\n 66% {\n opacity: 1;\n transform: translate(220%, 220%);\n }\n\n 83% {\n opacity: 0.5;\n }\n\n 100% {\n opacity: 1;\n transform: translate(0, 220%);\n }\n }\n\n @keyframes ball-triangle-path-ball-two {\n 0% {\n transform: translate(110%, 0);\n }\n\n 17% {\n opacity: 0.5;\n }\n\n 33% {\n opacity: 1;\n transform: translate(220%, 220%);\n }\n\n 50% {\n opacity: 0.5;\n }\n\n 66% {\n opacity: 1;\n transform: translate(0, 220%);\n }\n\n 83% {\n opacity: 0.5;\n }\n\n 100% {\n opacity: 1;\n transform: translate(110%, 0);\n }\n }\n\n @keyframes ball-triangle-path-ball-tree {\n 0% {\n transform: translate(220%, 220%);\n }\n\n 17% {\n opacity: 0.5;\n }\n\n 33% {\n opacity: 1;\n transform: translate(0, 220%);\n }\n\n 50% {\n opacity: 0.5;\n }\n\n 66% {\n opacity: 1;\n transform: translate(110%, 0);\n }\n\n 83% {\n opacity: 0.5;\n }\n\n 100% {\n opacity: 1;\n transform: translate(220%, 220%);\n }\n }\n</style>\n```\n\n#### 主要是使用了css中关键帧动画\n\n- @keyframes keyName {\n 0%:{\n transform: rotate/ translate\n }\n 100%: {\n\n }\n }\n\n- animation: keyName(关键帧名称) time(周期) infinate(循环) linear(线性变化)\n- animation-delay: time(时间\n- transform: rotate(旋转) translate(位移)\n\n注:引用文章链接\n<https://juejin.cn/post/7037036742985121800#heading-1>\n","slug":"loading","published":1,"updated":"2023-08-20T04:38:32.793Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0d000ka9libl3u9k9v","content":"<figure class=\"highlight html\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"loading"</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">style</span>></span><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">width</span>: <span class=\"number\">30px</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">height</span>: <span class=\"number\">30px</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">border</span>: <span class=\"number\">2px</span> solid <span class=\"number\">#000</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">border-top-color</span>: transparent;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">border-radius</span>: <span class=\"number\">100%</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">animation</span>: circle infinite <span class=\"number\">0.75s</span> linear;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"comment\">/* 转转转动画 */</span></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"keyword\">@keyframes</span> circle {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">0%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">rotate</span>(<span class=\"number\">0</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">100%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">rotate</span>(<span class=\"number\">360deg</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span><span class=\"tag\"></<span class=\"name\">style</span>></span></span><br></pre></td></tr></table></figure>\n\n<figure class=\"highlight html\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br><span class=\"line\">60</span><br><span class=\"line\">61</span><br><span class=\"line\">62</span><br><span class=\"line\">63</span><br><span class=\"line\">64</span><br><span class=\"line\">65</span><br><span class=\"line\">66</span><br><span class=\"line\">67</span><br><span class=\"line\">68</span><br><span class=\"line\">69</span><br><span class=\"line\">70</span><br><span class=\"line\">71</span><br><span class=\"line\">72</span><br><span class=\"line\">73</span><br><span class=\"line\">74</span><br><span class=\"line\">75</span><br><span class=\"line\">76</span><br><span class=\"line\">77</span><br><span class=\"line\">78</span><br><span class=\"line\">79</span><br><span class=\"line\">80</span><br><span class=\"line\">81</span><br><span class=\"line\">82</span><br><span class=\"line\">83</span><br><span class=\"line\">84</span><br><span class=\"line\">85</span><br><span class=\"line\">86</span><br><span class=\"line\">87</span><br><span class=\"line\">88</span><br><span class=\"line\">89</span><br><span class=\"line\">90</span><br><span class=\"line\">91</span><br><span class=\"line\">92</span><br><span class=\"line\">93</span><br><span class=\"line\">94</span><br><span class=\"line\">95</span><br><span class=\"line\">96</span><br><span class=\"line\">97</span><br><span class=\"line\">98</span><br><span class=\"line\">99</span><br><span class=\"line\">100</span><br><span class=\"line\">101</span><br><span class=\"line\">102</span><br><span class=\"line\">103</span><br><span class=\"line\">104</span><br><span class=\"line\">105</span><br><span class=\"line\">106</span><br><span class=\"line\">107</span><br><span class=\"line\">108</span><br><span class=\"line\">109</span><br><span class=\"line\">110</span><br><span class=\"line\">111</span><br><span class=\"line\">112</span><br><span class=\"line\">113</span><br><span class=\"line\">114</span><br><span class=\"line\">115</span><br><span class=\"line\">116</span><br><span class=\"line\">117</span><br><span class=\"line\">118</span><br><span class=\"line\">119</span><br><span class=\"line\">120</span><br><span class=\"line\">121</span><br><span class=\"line\">122</span><br><span class=\"line\">123</span><br><span class=\"line\">124</span><br><span class=\"line\">125</span><br><span class=\"line\">126</span><br><span class=\"line\">127</span><br><span class=\"line\">128</span><br><span class=\"line\">129</span><br><span class=\"line\">130</span><br><span class=\"line\">131</span><br><span class=\"line\">132</span><br><span class=\"line\">133</span><br><span class=\"line\">134</span><br><span class=\"line\">135</span><br><span class=\"line\">136</span><br><span class=\"line\">137</span><br><span class=\"line\">138</span><br><span class=\"line\">139</span><br><span class=\"line\">140</span><br><span class=\"line\">141</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"loading"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">style</span>></span><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">width</span>: <span class=\"number\">1.5625rem</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">height</span>: <span class=\"number\">1.5625rem</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">display</span>: block;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">font-size</span>: <span class=\"number\">0</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">color</span>: <span class=\"number\">#000</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">position</span>: relative;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> > <span class=\"selector-tag\">div</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">display</span>: inline-block;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">float</span>: none;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">background-color</span>: currentColor;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">border</span>: <span class=\"number\">0</span> solid currentColor;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">position</span>: absolute;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">top</span>: <span class=\"number\">0</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">left</span>: <span class=\"number\">0</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">width</span>: <span class=\"number\">0.5rem</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">height</span>: <span class=\"number\">0.5rem</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">border-radius</span>: <span class=\"number\">100%</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> > <span class=\"selector-tag\">div</span><span class=\"selector-pseudo\">:nth-child</span>(<span class=\"number\">1</span>) {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">animation</span>: ball-triangle-path-ball-one <span class=\"number\">3s</span> <span class=\"number\">0s</span> ease-in-out infinite;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> > <span class=\"selector-tag\">div</span><span class=\"selector-pseudo\">:nth-child</span>(<span class=\"number\">2</span>) {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">animation</span>: ball-triangle-path-ball-two <span class=\"number\">3s</span> <span class=\"number\">0s</span> ease-in-out infinite;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">background</span>: <span class=\"built_in\">rgba</span>(<span class=\"number\">179</span>, <span class=\"number\">179</span>, <span class=\"number\">180</span>, <span class=\"number\">1</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> > <span class=\"selector-tag\">div</span><span class=\"selector-pseudo\">:nth-child</span>(<span class=\"number\">3</span>) {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">animation</span>: ball-triangle-path-ball-tree <span class=\"number\">3s</span> <span class=\"number\">0s</span> ease-in-out infinite;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">background</span>: <span class=\"built_in\">rgba</span>(<span class=\"number\">114</span>, <span class=\"number\">113</span>, <span class=\"number\">115</span>, <span class=\"number\">1</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"keyword\">@keyframes</span> ball-triangle-path-ball-one {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">0%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">0</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">17%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">33%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">110%</span>, <span class=\"number\">0</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">50%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">66%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">220%</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">83%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">100%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">0</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"keyword\">@keyframes</span> ball-triangle-path-ball-two {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">0%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">110%</span>, <span class=\"number\">0</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">17%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">33%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">220%</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">50%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">66%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">0</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">83%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">100%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">110%</span>, <span class=\"number\">0</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"keyword\">@keyframes</span> ball-triangle-path-ball-tree {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">0%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">220%</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">17%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">33%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">0</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">50%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">66%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">110%</span>, <span class=\"number\">0</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">83%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">100%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">220%</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span><span class=\"tag\"></<span class=\"name\">style</span>></span></span><br></pre></td></tr></table></figure>\n\n<h4 id=\"主要是使用了css中关键帧动画\"><a href=\"#主要是使用了css中关键帧动画\" class=\"headerlink\" title=\"主要是使用了css中关键帧动画\"></a>主要是使用了css中关键帧动画</h4><ul>\n<li><p>@keyframes keyName {<br>0%:{<br>transform: rotate/ translate<br>}<br>100%: {</p>\n<p>}<br>}</p>\n</li>\n<li><p>animation: keyName(关键帧名称) time(周期) infinate(循环) linear(线性变化)</p>\n</li>\n<li><p>animation-delay: time(时间</p>\n</li>\n<li><p>transform: rotate(旋转) translate(位移)</p>\n</li>\n</ul>\n<p>注:引用文章链接<br><a href=\"https://juejin.cn/post/7037036742985121800#heading-1\">https://juejin.cn/post/7037036742985121800#heading-1</a></p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<figure class=\"highlight html\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"loading"</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">style</span>></span><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">width</span>: <span class=\"number\">30px</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">height</span>: <span class=\"number\">30px</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">border</span>: <span class=\"number\">2px</span> solid <span class=\"number\">#000</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">border-top-color</span>: transparent;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">border-radius</span>: <span class=\"number\">100%</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">animation</span>: circle infinite <span class=\"number\">0.75s</span> linear;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"comment\">/* 转转转动画 */</span></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"keyword\">@keyframes</span> circle {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">0%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">rotate</span>(<span class=\"number\">0</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">100%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">rotate</span>(<span class=\"number\">360deg</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span><span class=\"tag\"></<span class=\"name\">style</span>></span></span><br></pre></td></tr></table></figure>\n\n<figure class=\"highlight html\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br><span class=\"line\">60</span><br><span class=\"line\">61</span><br><span class=\"line\">62</span><br><span class=\"line\">63</span><br><span class=\"line\">64</span><br><span class=\"line\">65</span><br><span class=\"line\">66</span><br><span class=\"line\">67</span><br><span class=\"line\">68</span><br><span class=\"line\">69</span><br><span class=\"line\">70</span><br><span class=\"line\">71</span><br><span class=\"line\">72</span><br><span class=\"line\">73</span><br><span class=\"line\">74</span><br><span class=\"line\">75</span><br><span class=\"line\">76</span><br><span class=\"line\">77</span><br><span class=\"line\">78</span><br><span class=\"line\">79</span><br><span class=\"line\">80</span><br><span class=\"line\">81</span><br><span class=\"line\">82</span><br><span class=\"line\">83</span><br><span class=\"line\">84</span><br><span class=\"line\">85</span><br><span class=\"line\">86</span><br><span class=\"line\">87</span><br><span class=\"line\">88</span><br><span class=\"line\">89</span><br><span class=\"line\">90</span><br><span class=\"line\">91</span><br><span class=\"line\">92</span><br><span class=\"line\">93</span><br><span class=\"line\">94</span><br><span class=\"line\">95</span><br><span class=\"line\">96</span><br><span class=\"line\">97</span><br><span class=\"line\">98</span><br><span class=\"line\">99</span><br><span class=\"line\">100</span><br><span class=\"line\">101</span><br><span class=\"line\">102</span><br><span class=\"line\">103</span><br><span class=\"line\">104</span><br><span class=\"line\">105</span><br><span class=\"line\">106</span><br><span class=\"line\">107</span><br><span class=\"line\">108</span><br><span class=\"line\">109</span><br><span class=\"line\">110</span><br><span class=\"line\">111</span><br><span class=\"line\">112</span><br><span class=\"line\">113</span><br><span class=\"line\">114</span><br><span class=\"line\">115</span><br><span class=\"line\">116</span><br><span class=\"line\">117</span><br><span class=\"line\">118</span><br><span class=\"line\">119</span><br><span class=\"line\">120</span><br><span class=\"line\">121</span><br><span class=\"line\">122</span><br><span class=\"line\">123</span><br><span class=\"line\">124</span><br><span class=\"line\">125</span><br><span class=\"line\">126</span><br><span class=\"line\">127</span><br><span class=\"line\">128</span><br><span class=\"line\">129</span><br><span class=\"line\">130</span><br><span class=\"line\">131</span><br><span class=\"line\">132</span><br><span class=\"line\">133</span><br><span class=\"line\">134</span><br><span class=\"line\">135</span><br><span class=\"line\">136</span><br><span class=\"line\">137</span><br><span class=\"line\">138</span><br><span class=\"line\">139</span><br><span class=\"line\">140</span><br><span class=\"line\">141</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"loading"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">style</span>></span><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">width</span>: <span class=\"number\">1.5625rem</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">height</span>: <span class=\"number\">1.5625rem</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">display</span>: block;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">font-size</span>: <span class=\"number\">0</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">color</span>: <span class=\"number\">#000</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">position</span>: relative;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> > <span class=\"selector-tag\">div</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">display</span>: inline-block;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">float</span>: none;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">background-color</span>: currentColor;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">border</span>: <span class=\"number\">0</span> solid currentColor;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">position</span>: absolute;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">top</span>: <span class=\"number\">0</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">left</span>: <span class=\"number\">0</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">width</span>: <span class=\"number\">0.5rem</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">height</span>: <span class=\"number\">0.5rem</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">border-radius</span>: <span class=\"number\">100%</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> > <span class=\"selector-tag\">div</span><span class=\"selector-pseudo\">:nth-child</span>(<span class=\"number\">1</span>) {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">animation</span>: ball-triangle-path-ball-one <span class=\"number\">3s</span> <span class=\"number\">0s</span> ease-in-out infinite;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> > <span class=\"selector-tag\">div</span><span class=\"selector-pseudo\">:nth-child</span>(<span class=\"number\">2</span>) {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">animation</span>: ball-triangle-path-ball-two <span class=\"number\">3s</span> <span class=\"number\">0s</span> ease-in-out infinite;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">background</span>: <span class=\"built_in\">rgba</span>(<span class=\"number\">179</span>, <span class=\"number\">179</span>, <span class=\"number\">180</span>, <span class=\"number\">1</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"selector-class\">.loading</span> > <span class=\"selector-tag\">div</span><span class=\"selector-pseudo\">:nth-child</span>(<span class=\"number\">3</span>) {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">animation</span>: ball-triangle-path-ball-tree <span class=\"number\">3s</span> <span class=\"number\">0s</span> ease-in-out infinite;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">background</span>: <span class=\"built_in\">rgba</span>(<span class=\"number\">114</span>, <span class=\"number\">113</span>, <span class=\"number\">115</span>, <span class=\"number\">1</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"keyword\">@keyframes</span> ball-triangle-path-ball-one {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">0%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">0</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">17%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">33%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">110%</span>, <span class=\"number\">0</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">50%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">66%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">220%</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">83%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">100%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">0</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"keyword\">@keyframes</span> ball-triangle-path-ball-two {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">0%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">110%</span>, <span class=\"number\">0</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">17%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">33%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">220%</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">50%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">66%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">0</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">83%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">100%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">110%</span>, <span class=\"number\">0</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"keyword\">@keyframes</span> ball-triangle-path-ball-tree {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">0%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">220%</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">17%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">33%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">0</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">50%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">66%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">110%</span>, <span class=\"number\">0</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">83%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">0.5</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"number\">100%</span> {</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">opacity</span>: <span class=\"number\">1</span>;</span></span><br><span class=\"line\"><span class=\"language-css\"> <span class=\"attribute\">transform</span>: <span class=\"built_in\">translate</span>(<span class=\"number\">220%</span>, <span class=\"number\">220%</span>);</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"> }</span></span><br><span class=\"line\"><span class=\"language-css\"></span><span class=\"tag\"></<span class=\"name\">style</span>></span></span><br></pre></td></tr></table></figure>\n\n<h4 id=\"主要是使用了css中关键帧动画\"><a href=\"#主要是使用了css中关键帧动画\" class=\"headerlink\" title=\"主要是使用了css中关键帧动画\"></a>主要是使用了css中关键帧动画</h4><ul>\n<li><p>@keyframes keyName {<br>0%:{<br>transform: rotate/ translate<br>}<br>100%: {</p>\n<p>}<br>}</p>\n</li>\n<li><p>animation: keyName(关键帧名称) time(周期) infinate(循环) linear(线性变化)</p>\n</li>\n<li><p>animation-delay: time(时间</p>\n</li>\n<li><p>transform: rotate(旋转) translate(位移)</p>\n</li>\n</ul>\n<p>注:引用文章链接<br><a href=\"https://juejin.cn/post/7037036742985121800#heading-1\">https://juejin.cn/post/7037036742985121800#heading-1</a></p>\n"},{"title":"nextjs遇到的问题","_content":"\n## Hydration(水合)错误\n\n- 是什么: 在渲染你的应用程序时,预渲染的react树(ssr或ssg) 和在浏览器中第一次渲染时渲染的react树之间存在差异。这一次渲染被称为hydration,这是react的一个特性\n\n- 不规范的html标签\n\n ```html\n <P>\n <div></div>\n </p>\n ```\n\n- 数据问题,数据在服务端和首次客户端渲染展示的数据不一致\n 例如我在代码中使用了import { isMobile } from 'react-device-detect';\n 但是因为isMobile默认是false,但是如果在移动端设置中,首次渲染时是true,这就造成了hydration问题\n 解决方法就是在useEffect中执行判断,使得判断的变量始终在浏览器端才执行,下面代码是我自己为了解决这个isMobile问题封装的简单钩子\n\n ```js\n import { useEffect, useState } from 'react';\n import { isMobile } from 'react-device-detect';\n\n const useIsMobile = () => {\n const [mobile, setMobile] = useState(true);\n useEffect(() => {\n setMobile(isMobile);\n }, [isMobile]);\n return mobile;\n };\n\n export default useIsMobile;\n ```\n","source":"_posts/nextjs.md","raw":"---\ntitle: nextjs遇到的问题\n---\n\n## Hydration(水合)错误\n\n- 是什么: 在渲染你的应用程序时,预渲染的react树(ssr或ssg) 和在浏览器中第一次渲染时渲染的react树之间存在差异。这一次渲染被称为hydration,这是react的一个特性\n\n- 不规范的html标签\n\n ```html\n <P>\n <div></div>\n </p>\n ```\n\n- 数据问题,数据在服务端和首次客户端渲染展示的数据不一致\n 例如我在代码中使用了import { isMobile } from 'react-device-detect';\n 但是因为isMobile默认是false,但是如果在移动端设置中,首次渲染时是true,这就造成了hydration问题\n 解决方法就是在useEffect中执行判断,使得判断的变量始终在浏览器端才执行,下面代码是我自己为了解决这个isMobile问题封装的简单钩子\n\n ```js\n import { useEffect, useState } from 'react';\n import { isMobile } from 'react-device-detect';\n\n const useIsMobile = () => {\n const [mobile, setMobile] = useState(true);\n useEffect(() => {\n setMobile(isMobile);\n }, [isMobile]);\n return mobile;\n };\n\n export default useIsMobile;\n ```\n","slug":"nextjs","published":1,"date":"2023-12-26T08:49:12.264Z","updated":"2023-12-26T08:59:36.102Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0e000ma9li34v9dbyz","content":"<h2 id=\"Hydration-水合-错误\"><a href=\"#Hydration-水合-错误\" class=\"headerlink\" title=\"Hydration(水合)错误\"></a>Hydration(水合)错误</h2><ul>\n<li><p>是什么: 在渲染你的应用程序时,预渲染的react树(ssr或ssg) 和在浏览器中第一次渲染时渲染的react树之间存在差异。这一次渲染被称为hydration,这是react的一个特性</p>\n</li>\n<li><p>不规范的html标签</p>\n<figure class=\"highlight html\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"tag\"><<span class=\"name\">P</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"><span class=\"tag\"></<span class=\"name\">p</span>></span></span><br></pre></td></tr></table></figure>\n</li>\n<li><p>数据问题,数据在服务端和首次客户端渲染展示的数据不一致<br>例如我在代码中使用了import { isMobile } from ‘react-device-detect’;<br>但是因为isMobile默认是false,但是如果在移动端设置中,首次渲染时是true,这就造成了hydration问题<br>解决方法就是在useEffect中执行判断,使得判断的变量始终在浏览器端才执行,下面代码是我自己为了解决这个isMobile问题封装的简单钩子</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">import</span> { useEffect, useState } <span class=\"keyword\">from</span> <span class=\"string\">'react'</span>;</span><br><span class=\"line\"><span class=\"keyword\">import</span> { isMobile } <span class=\"keyword\">from</span> <span class=\"string\">'react-device-detect'</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title function_\">useIsMobile</span> = (<span class=\"params\"></span>) => {</span><br><span class=\"line\"> <span class=\"keyword\">const</span> [mobile, setMobile] = <span class=\"title function_\">useState</span>(<span class=\"literal\">true</span>);</span><br><span class=\"line\"> <span class=\"title function_\">useEffect</span>(<span class=\"function\">() =></span> {</span><br><span class=\"line\"> <span class=\"title function_\">setMobile</span>(isMobile);</span><br><span class=\"line\"> }, [isMobile]);</span><br><span class=\"line\"> <span class=\"keyword\">return</span> mobile;</span><br><span class=\"line\">};</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">export</span> <span class=\"keyword\">default</span> useIsMobile;</span><br></pre></td></tr></table></figure></li>\n</ul>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h2 id=\"Hydration-水合-错误\"><a href=\"#Hydration-水合-错误\" class=\"headerlink\" title=\"Hydration(水合)错误\"></a>Hydration(水合)错误</h2><ul>\n<li><p>是什么: 在渲染你的应用程序时,预渲染的react树(ssr或ssg) 和在浏览器中第一次渲染时渲染的react树之间存在差异。这一次渲染被称为hydration,这是react的一个特性</p>\n</li>\n<li><p>不规范的html标签</p>\n<figure class=\"highlight html\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"tag\"><<span class=\"name\">P</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"><span class=\"tag\"></<span class=\"name\">p</span>></span></span><br></pre></td></tr></table></figure>\n</li>\n<li><p>数据问题,数据在服务端和首次客户端渲染展示的数据不一致<br>例如我在代码中使用了import { isMobile } from ‘react-device-detect’;<br>但是因为isMobile默认是false,但是如果在移动端设置中,首次渲染时是true,这就造成了hydration问题<br>解决方法就是在useEffect中执行判断,使得判断的变量始终在浏览器端才执行,下面代码是我自己为了解决这个isMobile问题封装的简单钩子</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">import</span> { useEffect, useState } <span class=\"keyword\">from</span> <span class=\"string\">'react'</span>;</span><br><span class=\"line\"><span class=\"keyword\">import</span> { isMobile } <span class=\"keyword\">from</span> <span class=\"string\">'react-device-detect'</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title function_\">useIsMobile</span> = (<span class=\"params\"></span>) => {</span><br><span class=\"line\"> <span class=\"keyword\">const</span> [mobile, setMobile] = <span class=\"title function_\">useState</span>(<span class=\"literal\">true</span>);</span><br><span class=\"line\"> <span class=\"title function_\">useEffect</span>(<span class=\"function\">() =></span> {</span><br><span class=\"line\"> <span class=\"title function_\">setMobile</span>(isMobile);</span><br><span class=\"line\"> }, [isMobile]);</span><br><span class=\"line\"> <span class=\"keyword\">return</span> mobile;</span><br><span class=\"line\">};</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">export</span> <span class=\"keyword\">default</span> useIsMobile;</span><br></pre></td></tr></table></figure></li>\n</ul>\n"},{"title":"h5中的video","_content":"\n### 视频分辨率\n\n指视频的宽度✖️视频高度,衡量分辨率的单位是像素\n4K/2K/1080P/720P, 720P成为标准高清,低于720P的就不属于高清范围\n\n### 视频码率\n\n视频每秒传输的比特数(kbps mbps)c, 码率多大视频质量越好,但随着视频也越大\n\n### 视频编码格式\n\n标准格式的h264, 其它格式有MOV、 mpeg4等\n\n### 在h5中使用\n\n```js\n<video\n id=''\n class=''\n poster='XX.jpg'\n src='XX.mp4'\n controls\n muted\n autoplay\n webkit-playsinline\n playsinline\n></video>\n\n// controls 显示进度条等控件\n// autoplay 自动播放,这个属性需要和muted静音一起使用才会生效\n// playsinline 和 webkit-playsinline 在ios系统中不设置该属性会导致视频直接弹出页面\n```\n","source":"_posts/video.md","raw":"---\ntitle: h5中的video\n---\n\n### 视频分辨率\n\n指视频的宽度✖️视频高度,衡量分辨率的单位是像素\n4K/2K/1080P/720P, 720P成为标准高清,低于720P的就不属于高清范围\n\n### 视频码率\n\n视频每秒传输的比特数(kbps mbps)c, 码率多大视频质量越好,但随着视频也越大\n\n### 视频编码格式\n\n标准格式的h264, 其它格式有MOV、 mpeg4等\n\n### 在h5中使用\n\n```js\n<video\n id=''\n class=''\n poster='XX.jpg'\n src='XX.mp4'\n controls\n muted\n autoplay\n webkit-playsinline\n playsinline\n></video>\n\n// controls 显示进度条等控件\n// autoplay 自动播放,这个属性需要和muted静音一起使用才会生效\n// playsinline 和 webkit-playsinline 在ios系统中不设置该属性会导致视频直接弹出页面\n```\n","slug":"video","published":1,"date":"2023-12-21T08:20:55.406Z","updated":"2023-12-21T08:56:27.984Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0g000pa9li7k09do4c","content":"<h3 id=\"视频分辨率\"><a href=\"#视频分辨率\" class=\"headerlink\" title=\"视频分辨率\"></a>视频分辨率</h3><p>指视频的宽度✖️视频高度,衡量分辨率的单位是像素<br>4K/2K/1080P/720P, 720P成为标准高清,低于720P的就不属于高清范围</p>\n<h3 id=\"视频码率\"><a href=\"#视频码率\" class=\"headerlink\" title=\"视频码率\"></a>视频码率</h3><p>视频每秒传输的比特数(kbps mbps)c, 码率多大视频质量越好,但随着视频也越大</p>\n<h3 id=\"视频编码格式\"><a href=\"#视频编码格式\" class=\"headerlink\" title=\"视频编码格式\"></a>视频编码格式</h3><p>标准格式的h264, 其它格式有MOV、 mpeg4等</p>\n<h3 id=\"在h5中使用\"><a href=\"#在h5中使用\" class=\"headerlink\" title=\"在h5中使用\"></a>在h5中使用</h3><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><video</span><br><span class=\"line\"> id=<span class=\"string\">''</span></span><br><span class=\"line\"> <span class=\"keyword\">class</span>=<span class=\"string\">''</span></span><br><span class=\"line\"> poster=<span class=\"string\">'XX.jpg'</span></span><br><span class=\"line\"> src=<span class=\"string\">'XX.mp4'</span></span><br><span class=\"line\"> controls</span><br><span class=\"line\"> muted</span><br><span class=\"line\"> autoplay</span><br><span class=\"line\"> webkit-playsinline</span><br><span class=\"line\"> playsinline</span><br><span class=\"line\">></video></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// controls 显示进度条等控件</span></span><br><span class=\"line\"><span class=\"comment\">// autoplay 自动播放,这个属性需要和muted静音一起使用才会生效</span></span><br><span class=\"line\"><span class=\"comment\">// playsinline 和 webkit-playsinline 在ios系统中不设置该属性会导致视频直接弹出页面</span></span><br></pre></td></tr></table></figure>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"视频分辨率\"><a href=\"#视频分辨率\" class=\"headerlink\" title=\"视频分辨率\"></a>视频分辨率</h3><p>指视频的宽度✖️视频高度,衡量分辨率的单位是像素<br>4K/2K/1080P/720P, 720P成为标准高清,低于720P的就不属于高清范围</p>\n<h3 id=\"视频码率\"><a href=\"#视频码率\" class=\"headerlink\" title=\"视频码率\"></a>视频码率</h3><p>视频每秒传输的比特数(kbps mbps)c, 码率多大视频质量越好,但随着视频也越大</p>\n<h3 id=\"视频编码格式\"><a href=\"#视频编码格式\" class=\"headerlink\" title=\"视频编码格式\"></a>视频编码格式</h3><p>标准格式的h264, 其它格式有MOV、 mpeg4等</p>\n<h3 id=\"在h5中使用\"><a href=\"#在h5中使用\" class=\"headerlink\" title=\"在h5中使用\"></a>在h5中使用</h3><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><video</span><br><span class=\"line\"> id=<span class=\"string\">''</span></span><br><span class=\"line\"> <span class=\"keyword\">class</span>=<span class=\"string\">''</span></span><br><span class=\"line\"> poster=<span class=\"string\">'XX.jpg'</span></span><br><span class=\"line\"> src=<span class=\"string\">'XX.mp4'</span></span><br><span class=\"line\"> controls</span><br><span class=\"line\"> muted</span><br><span class=\"line\"> autoplay</span><br><span class=\"line\"> webkit-playsinline</span><br><span class=\"line\"> playsinline</span><br><span class=\"line\">></video></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// controls 显示进度条等控件</span></span><br><span class=\"line\"><span class=\"comment\">// autoplay 自动播放,这个属性需要和muted静音一起使用才会生效</span></span><br><span class=\"line\"><span class=\"comment\">// playsinline 和 webkit-playsinline 在ios系统中不设置该属性会导致视频直接弹出页面</span></span><br></pre></td></tr></table></figure>\n"},{"title":"protable|proform","date":"2023-07-08T02:53:12.000Z","_content":"\n### ●protable用于数据展示,const ref = useRef<actionType>()\n\n用于多选框清楚、表单重新加载(重置,筛选\n\n### ●proform用于数据录入 , const ref = useRef<formInstance>()\n\n表单内容清空\n\n#### ●search选择框中\n\n```js\n// 是一个枚举对象map或者object\nfieldProps: {\n multiple: true\u000b}\nvalueEnum: {\n '': {text: ''}\n}\n\n//\nvalueType: 'select',\nfieldProps: {\n multiple: true,\n options: [{label:'', value:''}]\n}\n```\n\n1、valueEnum是枚举类型,可以将数值转化成你想要的值,如果hideInSearch也会是选择框\n2、fieldProps:{\n","source":"_posts/protable|proform.md","raw":"---\ntitle: protable|proform\ndate: 2023-07-08 10:53:12\ntags:\ncategories:\n - UI组件\n---\n\n### ●protable用于数据展示,const ref = useRef<actionType>()\n\n用于多选框清楚、表单重新加载(重置,筛选\n\n### ●proform用于数据录入 , const ref = useRef<formInstance>()\n\n表单内容清空\n\n#### ●search选择框中\n\n```js\n// 是一个枚举对象map或者object\nfieldProps: {\n multiple: true\u000b}\nvalueEnum: {\n '': {text: ''}\n}\n\n//\nvalueType: 'select',\nfieldProps: {\n multiple: true,\n options: [{label:'', value:''}]\n}\n```\n\n1、valueEnum是枚举类型,可以将数值转化成你想要的值,如果hideInSearch也会是选择框\n2、fieldProps:{\n","slug":"protable|proform","published":1,"updated":"2023-07-08T04:30:38.594Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0h000qa9li304m2oqx","content":"<h3 id=\"●protable用于数据展示,const-ref-x3D-useRef\"><a href=\"#●protable用于数据展示,const-ref-x3D-useRef\" class=\"headerlink\" title=\"●protable用于数据展示,const ref = useRef()\"></a>●protable用于数据展示,const ref = useRef<actionType>()</h3><p>用于多选框清楚、表单重新加载(重置,筛选</p>\n<h3 id=\"●proform用于数据录入-const-ref-x3D-useRef\"><a href=\"#●proform用于数据录入-const-ref-x3D-useRef\" class=\"headerlink\" title=\"●proform用于数据录入 , const ref = useRef()\"></a>●proform用于数据录入 , const ref = useRef<formInstance>()</h3><p>表单内容清空</p>\n<h4 id=\"●search选择框中\"><a href=\"#●search选择框中\" class=\"headerlink\" title=\"●search选择框中\"></a>●search选择框中</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 是一个枚举对象map或者object</span></span><br><span class=\"line\"><span class=\"attr\">fieldProps</span>: {</span><br><span class=\"line\"> <span class=\"attr\">multiple</span>: <span class=\"literal\">true</span>\u000b}</span><br><span class=\"line\"><span class=\"attr\">valueEnum</span>: {</span><br><span class=\"line\"> <span class=\"string\">''</span>: {<span class=\"attr\">text</span>: <span class=\"string\">''</span>}</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">//</span></span><br><span class=\"line\"><span class=\"attr\">valueType</span>: <span class=\"string\">'select'</span>,</span><br><span class=\"line\"><span class=\"attr\">fieldProps</span>: {</span><br><span class=\"line\"> <span class=\"attr\">multiple</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">options</span>: [{<span class=\"attr\">label</span>:<span class=\"string\">''</span>, <span class=\"attr\">value</span>:<span class=\"string\">''</span>}]</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>1、valueEnum是枚举类型,可以将数值转化成你想要的值,如果hideInSearch也会是选择框<br>2、fieldProps:{</p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"●protable用于数据展示,const-ref-x3D-useRef\"><a href=\"#●protable用于数据展示,const-ref-x3D-useRef\" class=\"headerlink\" title=\"●protable用于数据展示,const ref = useRef()\"></a>●protable用于数据展示,const ref = useRef<actionType>()</h3><p>用于多选框清楚、表单重新加载(重置,筛选</p>\n<h3 id=\"●proform用于数据录入-const-ref-x3D-useRef\"><a href=\"#●proform用于数据录入-const-ref-x3D-useRef\" class=\"headerlink\" title=\"●proform用于数据录入 , const ref = useRef()\"></a>●proform用于数据录入 , const ref = useRef<formInstance>()</h3><p>表单内容清空</p>\n<h4 id=\"●search选择框中\"><a href=\"#●search选择框中\" class=\"headerlink\" title=\"●search选择框中\"></a>●search选择框中</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 是一个枚举对象map或者object</span></span><br><span class=\"line\"><span class=\"attr\">fieldProps</span>: {</span><br><span class=\"line\"> <span class=\"attr\">multiple</span>: <span class=\"literal\">true</span>\u000b}</span><br><span class=\"line\"><span class=\"attr\">valueEnum</span>: {</span><br><span class=\"line\"> <span class=\"string\">''</span>: {<span class=\"attr\">text</span>: <span class=\"string\">''</span>}</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">//</span></span><br><span class=\"line\"><span class=\"attr\">valueType</span>: <span class=\"string\">'select'</span>,</span><br><span class=\"line\"><span class=\"attr\">fieldProps</span>: {</span><br><span class=\"line\"> <span class=\"attr\">multiple</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">options</span>: [{<span class=\"attr\">label</span>:<span class=\"string\">''</span>, <span class=\"attr\">value</span>:<span class=\"string\">''</span>}]</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>1、valueEnum是枚举类型,可以将数值转化成你想要的值,如果hideInSearch也会是选择框<br>2、fieldProps:{</p>\n"},{"title":"vue响应式","date":"2023-07-08T02:39:39.000Z","_content":"\n### 一、vue3和vue2区别\n\n#### (1)vue2 中object.defineProperty缺点\n\n●只能监听对象中的某个属性\n\n```js\nconst person = {age: 3, name: 'hh'}\nObject.defineProperty(person, 'age', handles)\nhandles = {\nget(){}\nset(newValue){}\n}\n```\n\n●对对象的添加删除操作,无法劫持,新增set delete\n\n```js\n// 当对象person中新增属性时,会没法监听\nperson.newProperty = '1' ,//不能监听newPorperty属性\n```\n\n●对数组中的api无法劫持,重新数组api\n\n```js\narr.push('1');\n```\n\n●存在深层嵌套关系,性能问题\n\n#### (2)vue3基于ES6新增的proxy对象实现数据代理以及通过reflect对数据源进行操作\n\n●proxy可以监听整个对象\n●proxy(代理)拦截对象中任意属性的变化\n●reflect(反射)对源对象的属性进行操作 (Reflect的特性和Object相似)\n\n```js\nconst person = {age: 3, name: 'hh'}\n// 此处只是简写用法,没有定义key,key可以为age或name\nnew Proxy(person, {\nget(){\nReflect.get(person, key)\n}\nset(newValue){\nReflect.set(person, key, newValue)\n}\n})\n```\n\n### 二、vue3中属性\n\n#### (1)reactive:基于proxy和reflect实现\n\n// 基本使用, 只对对象有用,对其他类型数据不起作用\n\n```js\nconst state = reactive({ count: 0 })\n\n<div>{{ state.count }}</div>\n// 缺点, 解构或者单独赋值后不再具有响应式\nconst { count } = state\nconst n = state.count\n```\n\n总结:存在2个api缺陷\n●只对对象类型有效,而对string,number, boolean无效\n●因为vue的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该对响应式对象的相同引用,这意味着我们不可以随意替换一个响应式对象,这会导致对初始引用失效(JavaScript 没有可以作用于所有值类型的 “引用” 机制)\n\n```js\nlet state = reactive({ count: 0 });\n// 上面的引用 ({ count: 0 }) 将不再被追踪(响应性连接已丢失!)\nstate = reactive({ count: 1 });\n```\n\n#### (2)ref:原理和Object.defineProperty一样,当传入为对象时,这用reactive再包裹一层\n\n```js\nconst objectRef = ref({ count: 0 });\n\n// 这是响应式的替换\nobjectRef.value = { count: 1 };\n```\n\n总结:ref() 让我们能创造一种对任意值的 “引用”,并能够在不丢失响应性的前提下传递这些引用\n(3)toRef, toRefs\n\n```js\nconst state = reactive({\nfoo: 1,\nbar: 2\n})\nconst stateAsRefs = toRefs(state)\n//想要使用toRef也可以\nconst foo = toRef(state, 'foo')\n/_\nstateAsRefs 的类型:{\nfoo: Ref<number>,\nbar: Ref<number>\n}\n_/\n\n// 这个 ref 和源属性已经“链接上了”\nstate.foo++\nconsole.log(stateAsRefs.foo.value) // 2\n\nstateAsRefs.foo.value++\nconsole.log(state.foo) //\n```\n","source":"_posts/vue响应式.md","raw":"---\ntitle: vue响应式\ndate: 2023-07-08 10:39:39\ntags:\ncategories:\n - vue\n---\n\n### 一、vue3和vue2区别\n\n#### (1)vue2 中object.defineProperty缺点\n\n●只能监听对象中的某个属性\n\n```js\nconst person = {age: 3, name: 'hh'}\nObject.defineProperty(person, 'age', handles)\nhandles = {\nget(){}\nset(newValue){}\n}\n```\n\n●对对象的添加删除操作,无法劫持,新增set delete\n\n```js\n// 当对象person中新增属性时,会没法监听\nperson.newProperty = '1' ,//不能监听newPorperty属性\n```\n\n●对数组中的api无法劫持,重新数组api\n\n```js\narr.push('1');\n```\n\n●存在深层嵌套关系,性能问题\n\n#### (2)vue3基于ES6新增的proxy对象实现数据代理以及通过reflect对数据源进行操作\n\n●proxy可以监听整个对象\n●proxy(代理)拦截对象中任意属性的变化\n●reflect(反射)对源对象的属性进行操作 (Reflect的特性和Object相似)\n\n```js\nconst person = {age: 3, name: 'hh'}\n// 此处只是简写用法,没有定义key,key可以为age或name\nnew Proxy(person, {\nget(){\nReflect.get(person, key)\n}\nset(newValue){\nReflect.set(person, key, newValue)\n}\n})\n```\n\n### 二、vue3中属性\n\n#### (1)reactive:基于proxy和reflect实现\n\n// 基本使用, 只对对象有用,对其他类型数据不起作用\n\n```js\nconst state = reactive({ count: 0 })\n\n<div>{{ state.count }}</div>\n// 缺点, 解构或者单独赋值后不再具有响应式\nconst { count } = state\nconst n = state.count\n```\n\n总结:存在2个api缺陷\n●只对对象类型有效,而对string,number, boolean无效\n●因为vue的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该对响应式对象的相同引用,这意味着我们不可以随意替换一个响应式对象,这会导致对初始引用失效(JavaScript 没有可以作用于所有值类型的 “引用” 机制)\n\n```js\nlet state = reactive({ count: 0 });\n// 上面的引用 ({ count: 0 }) 将不再被追踪(响应性连接已丢失!)\nstate = reactive({ count: 1 });\n```\n\n#### (2)ref:原理和Object.defineProperty一样,当传入为对象时,这用reactive再包裹一层\n\n```js\nconst objectRef = ref({ count: 0 });\n\n// 这是响应式的替换\nobjectRef.value = { count: 1 };\n```\n\n总结:ref() 让我们能创造一种对任意值的 “引用”,并能够在不丢失响应性的前提下传递这些引用\n(3)toRef, toRefs\n\n```js\nconst state = reactive({\nfoo: 1,\nbar: 2\n})\nconst stateAsRefs = toRefs(state)\n//想要使用toRef也可以\nconst foo = toRef(state, 'foo')\n/_\nstateAsRefs 的类型:{\nfoo: Ref<number>,\nbar: Ref<number>\n}\n_/\n\n// 这个 ref 和源属性已经“链接上了”\nstate.foo++\nconsole.log(stateAsRefs.foo.value) // 2\n\nstateAsRefs.foo.value++\nconsole.log(state.foo) //\n```\n","slug":"vue响应式","published":1,"updated":"2023-07-08T04:30:38.594Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0i000sa9liegol40bx","content":"<h3 id=\"一、vue3和vue2区别\"><a href=\"#一、vue3和vue2区别\" class=\"headerlink\" title=\"一、vue3和vue2区别\"></a>一、vue3和vue2区别</h3><h4 id=\"(1)vue2-中object-defineProperty缺点\"><a href=\"#(1)vue2-中object-defineProperty缺点\" class=\"headerlink\" title=\"(1)vue2 中object.defineProperty缺点\"></a>(1)vue2 中object.defineProperty缺点</h4><p>●只能监听对象中的某个属性</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> person = {<span class=\"attr\">age</span>: <span class=\"number\">3</span>, <span class=\"attr\">name</span>: <span class=\"string\">'hh'</span>}</span><br><span class=\"line\"><span class=\"title class_\">Object</span>.<span class=\"title function_\">defineProperty</span>(person, <span class=\"string\">'age'</span>, handles)</span><br><span class=\"line\">handles = {</span><br><span class=\"line\"><span class=\"title function_\">get</span>(<span class=\"params\"></span>){}</span><br><span class=\"line\"><span class=\"title function_\">set</span>(<span class=\"params\">newValue</span>){}</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>●对对象的添加删除操作,无法劫持,新增set delete</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 当对象person中新增属性时,会没法监听</span></span><br><span class=\"line\">person.<span class=\"property\">newProperty</span> = <span class=\"string\">'1'</span> ,<span class=\"comment\">//不能监听newPorperty属性</span></span><br></pre></td></tr></table></figure>\n\n<p>●对数组中的api无法劫持,重新数组api</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">arr.<span class=\"title function_\">push</span>(<span class=\"string\">'1'</span>);</span><br></pre></td></tr></table></figure>\n\n<p>●存在深层嵌套关系,性能问题</p>\n<h4 id=\"(2)vue3基于ES6新增的proxy对象实现数据代理以及通过reflect对数据源进行操作\"><a href=\"#(2)vue3基于ES6新增的proxy对象实现数据代理以及通过reflect对数据源进行操作\" class=\"headerlink\" title=\"(2)vue3基于ES6新增的proxy对象实现数据代理以及通过reflect对数据源进行操作\"></a>(2)vue3基于ES6新增的proxy对象实现数据代理以及通过reflect对数据源进行操作</h4><p>●proxy可以监听整个对象<br>●proxy(代理)拦截对象中任意属性的变化<br>●reflect(反射)对源对象的属性进行操作 (Reflect的特性和Object相似)</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> person = {<span class=\"attr\">age</span>: <span class=\"number\">3</span>, <span class=\"attr\">name</span>: <span class=\"string\">'hh'</span>}</span><br><span class=\"line\"><span class=\"comment\">// 此处只是简写用法,没有定义key,key可以为age或name</span></span><br><span class=\"line\"><span class=\"keyword\">new</span> <span class=\"title class_\">Proxy</span>(person, {</span><br><span class=\"line\"><span class=\"title function_\">get</span>(<span class=\"params\"></span>){</span><br><span class=\"line\"><span class=\"title class_\">Reflect</span>.<span class=\"title function_\">get</span>(person, key)</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"title function_\">set</span>(<span class=\"params\">newValue</span>){</span><br><span class=\"line\"><span class=\"title class_\">Reflect</span>.<span class=\"title function_\">set</span>(person, key, newValue)</span><br><span class=\"line\">}</span><br><span class=\"line\">})</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"二、vue3中属性\"><a href=\"#二、vue3中属性\" class=\"headerlink\" title=\"二、vue3中属性\"></a>二、vue3中属性</h3><h4 id=\"(1)reactive:基于proxy和reflect实现\"><a href=\"#(1)reactive:基于proxy和reflect实现\" class=\"headerlink\" title=\"(1)reactive:基于proxy和reflect实现\"></a>(1)reactive:基于proxy和reflect实现</h4><p>// 基本使用, 只对对象有用,对其他类型数据不起作用</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> state = <span class=\"title function_\">reactive</span>({ <span class=\"attr\">count</span>: <span class=\"number\">0</span> })</span><br><span class=\"line\"></span><br><span class=\"line\"><div>{{ state.<span class=\"property\">count</span> }}</div></span><br><span class=\"line\"><span class=\"comment\">// 缺点, 解构或者单独赋值后不再具有响应式</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> { count } = state</span><br><span class=\"line\"><span class=\"keyword\">const</span> n = state.<span class=\"property\">count</span></span><br></pre></td></tr></table></figure>\n\n<p>总结:存在2个api缺陷<br>●只对对象类型有效,而对string,number, boolean无效<br>●因为vue的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该对响应式对象的相同引用,这意味着我们不可以随意替换一个响应式对象,这会导致对初始引用失效(JavaScript 没有可以作用于所有值类型的 “引用” 机制)</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">let</span> state = <span class=\"title function_\">reactive</span>({ <span class=\"attr\">count</span>: <span class=\"number\">0</span> });</span><br><span class=\"line\"><span class=\"comment\">// 上面的引用 ({ count: 0 }) 将不再被追踪(响应性连接已丢失!)</span></span><br><span class=\"line\">state = <span class=\"title function_\">reactive</span>({ <span class=\"attr\">count</span>: <span class=\"number\">1</span> });</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"2-ref:原理和Object-defineProperty一样,当传入为对象时,这用reactive再包裹一层\"><a href=\"#2-ref:原理和Object-defineProperty一样,当传入为对象时,这用reactive再包裹一层\" class=\"headerlink\" title=\"(2)ref:原理和Object.defineProperty一样,当传入为对象时,这用reactive再包裹一层\"></a>(2)ref:原理和Object.defineProperty一样,当传入为对象时,这用reactive再包裹一层</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> objectRef = <span class=\"title function_\">ref</span>({ <span class=\"attr\">count</span>: <span class=\"number\">0</span> });</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 这是响应式的替换</span></span><br><span class=\"line\">objectRef.<span class=\"property\">value</span> = { <span class=\"attr\">count</span>: <span class=\"number\">1</span> };</span><br></pre></td></tr></table></figure>\n\n<p>总结:ref() 让我们能创造一种对任意值的 “引用”,并能够在不丢失响应性的前提下传递这些引用<br>(3)toRef, toRefs</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> state = <span class=\"title function_\">reactive</span>({</span><br><span class=\"line\"><span class=\"attr\">foo</span>: <span class=\"number\">1</span>,</span><br><span class=\"line\"><span class=\"attr\">bar</span>: <span class=\"number\">2</span></span><br><span class=\"line\">})</span><br><span class=\"line\"><span class=\"keyword\">const</span> stateAsRefs = <span class=\"title function_\">toRefs</span>(state)</span><br><span class=\"line\"><span class=\"comment\">//想要使用toRef也可以</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> foo = <span class=\"title function_\">toRef</span>(state, <span class=\"string\">'foo'</span>)</span><br><span class=\"line\">/_</span><br><span class=\"line\">stateAsRefs 的类型:{</span><br><span class=\"line\"><span class=\"attr\">foo</span>: <span class=\"title class_\">Ref</span><number>,</span><br><span class=\"line\"><span class=\"attr\">bar</span>: <span class=\"title class_\">Ref</span><number></span><br><span class=\"line\">}</span><br><span class=\"line\">_/</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 这个 ref 和源属性已经“链接上了”</span></span><br><span class=\"line\">state.<span class=\"property\">foo</span>++</span><br><span class=\"line\"><span class=\"variable language_\">console</span>.<span class=\"title function_\">log</span>(stateAsRefs.<span class=\"property\">foo</span>.<span class=\"property\">value</span>) <span class=\"comment\">// 2</span></span><br><span class=\"line\"></span><br><span class=\"line\">stateAsRefs.<span class=\"property\">foo</span>.<span class=\"property\">value</span>++</span><br><span class=\"line\"><span class=\"variable language_\">console</span>.<span class=\"title function_\">log</span>(state.<span class=\"property\">foo</span>) <span class=\"comment\">//</span></span><br></pre></td></tr></table></figure>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"一、vue3和vue2区别\"><a href=\"#一、vue3和vue2区别\" class=\"headerlink\" title=\"一、vue3和vue2区别\"></a>一、vue3和vue2区别</h3><h4 id=\"(1)vue2-中object-defineProperty缺点\"><a href=\"#(1)vue2-中object-defineProperty缺点\" class=\"headerlink\" title=\"(1)vue2 中object.defineProperty缺点\"></a>(1)vue2 中object.defineProperty缺点</h4><p>●只能监听对象中的某个属性</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> person = {<span class=\"attr\">age</span>: <span class=\"number\">3</span>, <span class=\"attr\">name</span>: <span class=\"string\">'hh'</span>}</span><br><span class=\"line\"><span class=\"title class_\">Object</span>.<span class=\"title function_\">defineProperty</span>(person, <span class=\"string\">'age'</span>, handles)</span><br><span class=\"line\">handles = {</span><br><span class=\"line\"><span class=\"title function_\">get</span>(<span class=\"params\"></span>){}</span><br><span class=\"line\"><span class=\"title function_\">set</span>(<span class=\"params\">newValue</span>){}</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>●对对象的添加删除操作,无法劫持,新增set delete</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 当对象person中新增属性时,会没法监听</span></span><br><span class=\"line\">person.<span class=\"property\">newProperty</span> = <span class=\"string\">'1'</span> ,<span class=\"comment\">//不能监听newPorperty属性</span></span><br></pre></td></tr></table></figure>\n\n<p>●对数组中的api无法劫持,重新数组api</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">arr.<span class=\"title function_\">push</span>(<span class=\"string\">'1'</span>);</span><br></pre></td></tr></table></figure>\n\n<p>●存在深层嵌套关系,性能问题</p>\n<h4 id=\"(2)vue3基于ES6新增的proxy对象实现数据代理以及通过reflect对数据源进行操作\"><a href=\"#(2)vue3基于ES6新增的proxy对象实现数据代理以及通过reflect对数据源进行操作\" class=\"headerlink\" title=\"(2)vue3基于ES6新增的proxy对象实现数据代理以及通过reflect对数据源进行操作\"></a>(2)vue3基于ES6新增的proxy对象实现数据代理以及通过reflect对数据源进行操作</h4><p>●proxy可以监听整个对象<br>●proxy(代理)拦截对象中任意属性的变化<br>●reflect(反射)对源对象的属性进行操作 (Reflect的特性和Object相似)</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> person = {<span class=\"attr\">age</span>: <span class=\"number\">3</span>, <span class=\"attr\">name</span>: <span class=\"string\">'hh'</span>}</span><br><span class=\"line\"><span class=\"comment\">// 此处只是简写用法,没有定义key,key可以为age或name</span></span><br><span class=\"line\"><span class=\"keyword\">new</span> <span class=\"title class_\">Proxy</span>(person, {</span><br><span class=\"line\"><span class=\"title function_\">get</span>(<span class=\"params\"></span>){</span><br><span class=\"line\"><span class=\"title class_\">Reflect</span>.<span class=\"title function_\">get</span>(person, key)</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"title function_\">set</span>(<span class=\"params\">newValue</span>){</span><br><span class=\"line\"><span class=\"title class_\">Reflect</span>.<span class=\"title function_\">set</span>(person, key, newValue)</span><br><span class=\"line\">}</span><br><span class=\"line\">})</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"二、vue3中属性\"><a href=\"#二、vue3中属性\" class=\"headerlink\" title=\"二、vue3中属性\"></a>二、vue3中属性</h3><h4 id=\"(1)reactive:基于proxy和reflect实现\"><a href=\"#(1)reactive:基于proxy和reflect实现\" class=\"headerlink\" title=\"(1)reactive:基于proxy和reflect实现\"></a>(1)reactive:基于proxy和reflect实现</h4><p>// 基本使用, 只对对象有用,对其他类型数据不起作用</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> state = <span class=\"title function_\">reactive</span>({ <span class=\"attr\">count</span>: <span class=\"number\">0</span> })</span><br><span class=\"line\"></span><br><span class=\"line\"><div>{{ state.<span class=\"property\">count</span> }}</div></span><br><span class=\"line\"><span class=\"comment\">// 缺点, 解构或者单独赋值后不再具有响应式</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> { count } = state</span><br><span class=\"line\"><span class=\"keyword\">const</span> n = state.<span class=\"property\">count</span></span><br></pre></td></tr></table></figure>\n\n<p>总结:存在2个api缺陷<br>●只对对象类型有效,而对string,number, boolean无效<br>●因为vue的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该对响应式对象的相同引用,这意味着我们不可以随意替换一个响应式对象,这会导致对初始引用失效(JavaScript 没有可以作用于所有值类型的 “引用” 机制)</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">let</span> state = <span class=\"title function_\">reactive</span>({ <span class=\"attr\">count</span>: <span class=\"number\">0</span> });</span><br><span class=\"line\"><span class=\"comment\">// 上面的引用 ({ count: 0 }) 将不再被追踪(响应性连接已丢失!)</span></span><br><span class=\"line\">state = <span class=\"title function_\">reactive</span>({ <span class=\"attr\">count</span>: <span class=\"number\">1</span> });</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"2-ref:原理和Object-defineProperty一样,当传入为对象时,这用reactive再包裹一层\"><a href=\"#2-ref:原理和Object-defineProperty一样,当传入为对象时,这用reactive再包裹一层\" class=\"headerlink\" title=\"(2)ref:原理和Object.defineProperty一样,当传入为对象时,这用reactive再包裹一层\"></a>(2)ref:原理和Object.defineProperty一样,当传入为对象时,这用reactive再包裹一层</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> objectRef = <span class=\"title function_\">ref</span>({ <span class=\"attr\">count</span>: <span class=\"number\">0</span> });</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 这是响应式的替换</span></span><br><span class=\"line\">objectRef.<span class=\"property\">value</span> = { <span class=\"attr\">count</span>: <span class=\"number\">1</span> };</span><br></pre></td></tr></table></figure>\n\n<p>总结:ref() 让我们能创造一种对任意值的 “引用”,并能够在不丢失响应性的前提下传递这些引用<br>(3)toRef, toRefs</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> state = <span class=\"title function_\">reactive</span>({</span><br><span class=\"line\"><span class=\"attr\">foo</span>: <span class=\"number\">1</span>,</span><br><span class=\"line\"><span class=\"attr\">bar</span>: <span class=\"number\">2</span></span><br><span class=\"line\">})</span><br><span class=\"line\"><span class=\"keyword\">const</span> stateAsRefs = <span class=\"title function_\">toRefs</span>(state)</span><br><span class=\"line\"><span class=\"comment\">//想要使用toRef也可以</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> foo = <span class=\"title function_\">toRef</span>(state, <span class=\"string\">'foo'</span>)</span><br><span class=\"line\">/_</span><br><span class=\"line\">stateAsRefs 的类型:{</span><br><span class=\"line\"><span class=\"attr\">foo</span>: <span class=\"title class_\">Ref</span><number>,</span><br><span class=\"line\"><span class=\"attr\">bar</span>: <span class=\"title class_\">Ref</span><number></span><br><span class=\"line\">}</span><br><span class=\"line\">_/</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 这个 ref 和源属性已经“链接上了”</span></span><br><span class=\"line\">state.<span class=\"property\">foo</span>++</span><br><span class=\"line\"><span class=\"variable language_\">console</span>.<span class=\"title function_\">log</span>(stateAsRefs.<span class=\"property\">foo</span>.<span class=\"property\">value</span>) <span class=\"comment\">// 2</span></span><br><span class=\"line\"></span><br><span class=\"line\">stateAsRefs.<span class=\"property\">foo</span>.<span class=\"property\">value</span>++</span><br><span class=\"line\"><span class=\"variable language_\">console</span>.<span class=\"title function_\">log</span>(state.<span class=\"property\">foo</span>) <span class=\"comment\">//</span></span><br></pre></td></tr></table></figure>\n"},{"title":"webpack","_content":"\n### 一、主要概念\n\n#### ●5大核心概念\n\n```js\nmodule.exports = {\n // 入口\n entry: '',\n // 输出\n output: {},\n // 加载器loader\n module: {\n rules: [],\n },\n // 插件\n plugins: [],\n // 模式\n mode: '', // development|production\n};\n```\n\n#### ●生产模式和开发模式\n\n○开发模式\n(1)编译代码,使浏览器能识别运行\n开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源\n(2)代码质量检查,树立代码规范\n提前检查代码的一些隐患,让代码运行时能更加健壮。提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。\n\n○生产模式\n生产模式是开发完成代码后,我们需要得到代码将来部署上线。这个模式下我们主要 对代码进行优化,让其运行性能更好。优化主要从两个角度出发:\n1)优化代码运行性能(2)优化代码打包速度\n\n#### ●处理样式资源\n\n1)Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源\n\n```js\n// css-loader: 负责将css文件编译成webpack能识别的模块\n// style-loader: 会动态创建一个style标签,里面放置webpack中css模块内容\nconst path = require('path');\n\nmodule.exports = {\n entry: '',\n output: {},\n module: {\n rules: [\n {\n // 用来匹配 .css 结尾的文件\n test: /\\.css$/,\n // use 数组里面 Loader 执行顺序是从右到左\n use: ['style-loader', 'css-loader'],\n },\n {\n test: /\\.less$/,\n use: ['style-loader', 'css-loader', 'less-loader'],\n },\n {\n test: /\\.s[ac]ss$/,\n use: ['style-loader', 'css-loader', 'sass-loader'],\n },\n {\n test: /\\.styl$/,\n use: ['style-loader', 'css-loader', 'stylus-loader'],\n },\n ],\n },\n plugins: [],\n mode: 'development',\n};\n```\n\n2)提取css成单独的文件\ncss文件目前被打包到js文件中,当js文件加载时,会创建一个style标签来生成样式,这对于网站来说,会造成闪屏现象,用户体验不好,我们应该是单独的css文件,通过link标签加载性能才好\n\n```js\nnpm i mini-css-extract-plugin -D\nconst MiniCssExtractPlugin =require(\"mini-css-extract-plugin\");\n// 将style-loader替换成 MiniCssExtractPlugin.loader\nrules: [\n {\n // 用来匹配 .css 结尾的文件\n test: /\\.css$/,\n // use 数组里面 Loader 执行顺序是从右到左\n use: [MiniCssExtractPlugin.loader, \"css-loader\"],\n }]\n\n3)css兼容性处理\nnpm i postcss-loader postcss postcss-preset-env -D\nrules: [\n {\n // 用来匹配 .css 结尾的文件\n test: /\\.css$/,\n // use 数组里面 Loader 执行顺序是从右到左\n use: [\n MiniCssExtractPlugin.loader,\n \"css-loader\",\n {\n loader: \"postcss-loader\",\n options: {\n postcssOptions: {\n plugins: [\n \"postcss-preset-env\", // 能解决大多数样式兼容性问题\n ],\n },\n },\n },\n ],\n\n 在package.json中可以更改兼容性\n{\n // 其他省略\n \"browserslist\": [\"ie >= 8\"]\n}\n```\n\n4)压缩css\n\n```js\nnpm i css-minimizer-webpack-plugin -D\nconst CssMinimizerPlugin = require(\"css-minimizer-webpack-plugin\");\nplugins: [\n // css压缩\n new CssMinimizerPlugin(),\n ],\n```\n\n5)合并配置处理\n\n```js\nconst getStyleLoaders = (preProcessor) => {\n return [\n MiniCssExtractPlugin.loader,\n 'css-loader',\n {\n loader: 'postcss-loader',\n options: {\n postcssOptions: {\n plugins: [\n 'postcss-preset-env', // 能解决大多数样式兼容性问题\n ],\n },\n },\n },\n preProcessor,\n ].filter(Boolean);\n};\n// 下面是用法\nrules: [\n {\n // 用来匹配 .css 结尾的文件\n test: /\\.css$/,\n // use 数组里面 Loader 执行顺序是从右到左\n use: getStyleLoaders(),\n },\n {\n test: /\\.less$/,\n use: getStyleLoaders('less-loader'),\n },\n];\n```\n\n#### ●处理图片资源\n\n```js\n// webpack4中,处理图片要通过file-loader和url-loader进行处理,但是webpack5已经将两个loader功能内置到webpack里了,我们只需要简单配置即可处理图片资源\nrules: [\n{\n test: /\\.(png|jpe?g|gif|webp)$/,\n type: \"asset\",\n}],\n\n// 优化\n{\n test: /\\.(png|jpe?g|gif|webp)$/,\n type: \"asset\",\n //将小于某个大小的图片转化成 data URI 形式(Base64 格式, 优点是能减 少请求次数,缺点是会导致体积变大\n parser: {\n dataUrlCondition: {\n maxSize: 10 * 1024, // 小于10kb的图片会被base64处理\n },\n },\n// 修改资源输入路径\ngenerator: {\n // 将图片文件输出到 static/imgs 目录中\n // 将图片文件命名 [hash:8][ext][query]\n // [hash:8]: hash值取8位\n // [ext]: 使用之前的文件扩展名\n // [query]: 添加之前的query参数\n filename: \"static/imgs/[hash:8][ext][query]\",\n}},\n```\n\n#### ●处理js资源\n\n```js\n1)针对 js 兼容性处理,我们使用 Babel 来完成\n// 此处eslint具体配置省略,只写webpack配置\nconst ESLintWebpackPlugin = require(\"eslint-webpack-plugin\");\n plugins: [\n new ESLintWebpackPlugin({\n // 指定检查文件的根目录\n context: path.resolve(__dirname, \"src\"),\n }),\n ],\n```\n\n2)针对代码格式,我们使用 Eslint 来完成\n\n```js\nnpm i babel-loader @babel/core @babel/preset-env -D\n// babel.config.js\nmodule.exports = {\n presets: [\"@babel/preset-env\"],\n};\n```\n\n#### ●处理html资源\n\n```js\nnpm i html-webpack-plugin -D\nconst HtmlWebpackPlugin = require(\"html-webpack-plugin\");\n plugins: [\n new HtmlWebpackPlugin({\n // 以 public/index.html 为模板创建文件\n // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源\n template: path.resolve(__dirname, \"public/index.html\"),\n }),\n ],\n```\n\n### 二、优化\n\n#### ●提升开发体验\n\n(1)sourceMap方便出现问题时定位到具体代码\n\n```js\nmodule.exports = {\n // 其他省略\n mode: 'production',\n devtool: 'source-map',\n};\n\nmodule.exports = {\n // 其他省略\n mode: 'development',\n devtool: 'cheap-module-source-map',\n};\n```\n\n#### ●提升打包构建速度\n\n(1)oneOf\n\n```js\nmodule: {\n rules: [\n {\n oneOf: [\n {\n // 用来匹配 .css 结尾的文件\n test: /\\.css$/,\n include: XXXX,\n // use 数组里面 Loader 执行顺序是从右到左\n use: [\"style-loader\", \"css-loader\"],\n }]\n```\n\n(2) include exclude\n(3)hotMdouleReplacement(HMR)\n(4)cache\n\n```js\n// 每次js打包都要经过eslint和babel编译,速度比较慢,可以缓存之前的eslint检查和babel编译结果,这样二次打包速度会快很多\nplugins: [\n new ESLintWebpackPlugin({\n // 指定检查文件的根目录\n context: path.resolve(__dirname, '../src'),\n exclude: 'node_modules', // 默认值\n cache: true, // 开启缓存\n // 缓存目录\n cacheLocation: path.resolve(\n __dirname,\n '../node_modules/.cache/.eslintcache'\n ),\n }),\n];\n```\n\n(5)Thead多核,多进程\n\n#### ●减少代码体积\n\n(1)tree shaking\n(2)Image Minimizer\n当项目中引入图片过多时(针对本地文件)可以进行压缩\n\n```js\nnpm i image-minimizer-webpack-plugin imagemin -D\n// 无损压缩\nnpm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D\n// 有损压缩\nnpm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D\n\nconst ImageMinimizerPlugin = require(\"image-minimizer-webpack-plugin\");\noptimization: {\n minimizer: [\n // css压缩也可以写到optimization.minimizer里面,效果一样的\n new CssMinimizerPlugin(),\n // 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了\n new TerserPlugin({\n parallel: threads, // 开启多进程\n }),\n // 压缩图片\n new ImageMinimizerPlugin({\n minimizer: {\n implementation: ImageMinimizerPlugin.imageminGenerate,\n options: {\n plugins: [\n [\"gifsicle\", { interlaced: true }],\n [\"jpegtran\", { progressive: true }],\n [\"optipng\", { optimizationLevel: 5 }],\n [\n \"svgo\",\n {\n plugins: [\n \"preset-default\",\n \"prefixIds\",\n {\n name: \"sortAttrs\",\n params: {\n xmlnsOrder: \"alphabetical\",\n },\n },\n ],\n },\n ],\n ],\n },\n },\n }),\n ],\n },\n```\n\n#### ●优化代码运行性能\n\n(1)code split\n●分割文件:将打包生成的文件进行分割,生产多个js文件\n●按需加载,需要哪个文件就加载哪个\n\n```js\noptimization: {\n // 代码分割配置\n splitChunks: {\n chunks: \"all\", // 对所有模块都进行分割\n }\n}\n```\n","source":"_posts/webpack.md","raw":"---\ntitle: webpack\ncategories:\n - 打包工具\n---\n\n### 一、主要概念\n\n#### ●5大核心概念\n\n```js\nmodule.exports = {\n // 入口\n entry: '',\n // 输出\n output: {},\n // 加载器loader\n module: {\n rules: [],\n },\n // 插件\n plugins: [],\n // 模式\n mode: '', // development|production\n};\n```\n\n#### ●生产模式和开发模式\n\n○开发模式\n(1)编译代码,使浏览器能识别运行\n开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源\n(2)代码质量检查,树立代码规范\n提前检查代码的一些隐患,让代码运行时能更加健壮。提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。\n\n○生产模式\n生产模式是开发完成代码后,我们需要得到代码将来部署上线。这个模式下我们主要 对代码进行优化,让其运行性能更好。优化主要从两个角度出发:\n1)优化代码运行性能(2)优化代码打包速度\n\n#### ●处理样式资源\n\n1)Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源\n\n```js\n// css-loader: 负责将css文件编译成webpack能识别的模块\n// style-loader: 会动态创建一个style标签,里面放置webpack中css模块内容\nconst path = require('path');\n\nmodule.exports = {\n entry: '',\n output: {},\n module: {\n rules: [\n {\n // 用来匹配 .css 结尾的文件\n test: /\\.css$/,\n // use 数组里面 Loader 执行顺序是从右到左\n use: ['style-loader', 'css-loader'],\n },\n {\n test: /\\.less$/,\n use: ['style-loader', 'css-loader', 'less-loader'],\n },\n {\n test: /\\.s[ac]ss$/,\n use: ['style-loader', 'css-loader', 'sass-loader'],\n },\n {\n test: /\\.styl$/,\n use: ['style-loader', 'css-loader', 'stylus-loader'],\n },\n ],\n },\n plugins: [],\n mode: 'development',\n};\n```\n\n2)提取css成单独的文件\ncss文件目前被打包到js文件中,当js文件加载时,会创建一个style标签来生成样式,这对于网站来说,会造成闪屏现象,用户体验不好,我们应该是单独的css文件,通过link标签加载性能才好\n\n```js\nnpm i mini-css-extract-plugin -D\nconst MiniCssExtractPlugin =require(\"mini-css-extract-plugin\");\n// 将style-loader替换成 MiniCssExtractPlugin.loader\nrules: [\n {\n // 用来匹配 .css 结尾的文件\n test: /\\.css$/,\n // use 数组里面 Loader 执行顺序是从右到左\n use: [MiniCssExtractPlugin.loader, \"css-loader\"],\n }]\n\n3)css兼容性处理\nnpm i postcss-loader postcss postcss-preset-env -D\nrules: [\n {\n // 用来匹配 .css 结尾的文件\n test: /\\.css$/,\n // use 数组里面 Loader 执行顺序是从右到左\n use: [\n MiniCssExtractPlugin.loader,\n \"css-loader\",\n {\n loader: \"postcss-loader\",\n options: {\n postcssOptions: {\n plugins: [\n \"postcss-preset-env\", // 能解决大多数样式兼容性问题\n ],\n },\n },\n },\n ],\n\n 在package.json中可以更改兼容性\n{\n // 其他省略\n \"browserslist\": [\"ie >= 8\"]\n}\n```\n\n4)压缩css\n\n```js\nnpm i css-minimizer-webpack-plugin -D\nconst CssMinimizerPlugin = require(\"css-minimizer-webpack-plugin\");\nplugins: [\n // css压缩\n new CssMinimizerPlugin(),\n ],\n```\n\n5)合并配置处理\n\n```js\nconst getStyleLoaders = (preProcessor) => {\n return [\n MiniCssExtractPlugin.loader,\n 'css-loader',\n {\n loader: 'postcss-loader',\n options: {\n postcssOptions: {\n plugins: [\n 'postcss-preset-env', // 能解决大多数样式兼容性问题\n ],\n },\n },\n },\n preProcessor,\n ].filter(Boolean);\n};\n// 下面是用法\nrules: [\n {\n // 用来匹配 .css 结尾的文件\n test: /\\.css$/,\n // use 数组里面 Loader 执行顺序是从右到左\n use: getStyleLoaders(),\n },\n {\n test: /\\.less$/,\n use: getStyleLoaders('less-loader'),\n },\n];\n```\n\n#### ●处理图片资源\n\n```js\n// webpack4中,处理图片要通过file-loader和url-loader进行处理,但是webpack5已经将两个loader功能内置到webpack里了,我们只需要简单配置即可处理图片资源\nrules: [\n{\n test: /\\.(png|jpe?g|gif|webp)$/,\n type: \"asset\",\n}],\n\n// 优化\n{\n test: /\\.(png|jpe?g|gif|webp)$/,\n type: \"asset\",\n //将小于某个大小的图片转化成 data URI 形式(Base64 格式, 优点是能减 少请求次数,缺点是会导致体积变大\n parser: {\n dataUrlCondition: {\n maxSize: 10 * 1024, // 小于10kb的图片会被base64处理\n },\n },\n// 修改资源输入路径\ngenerator: {\n // 将图片文件输出到 static/imgs 目录中\n // 将图片文件命名 [hash:8][ext][query]\n // [hash:8]: hash值取8位\n // [ext]: 使用之前的文件扩展名\n // [query]: 添加之前的query参数\n filename: \"static/imgs/[hash:8][ext][query]\",\n}},\n```\n\n#### ●处理js资源\n\n```js\n1)针对 js 兼容性处理,我们使用 Babel 来完成\n// 此处eslint具体配置省略,只写webpack配置\nconst ESLintWebpackPlugin = require(\"eslint-webpack-plugin\");\n plugins: [\n new ESLintWebpackPlugin({\n // 指定检查文件的根目录\n context: path.resolve(__dirname, \"src\"),\n }),\n ],\n```\n\n2)针对代码格式,我们使用 Eslint 来完成\n\n```js\nnpm i babel-loader @babel/core @babel/preset-env -D\n// babel.config.js\nmodule.exports = {\n presets: [\"@babel/preset-env\"],\n};\n```\n\n#### ●处理html资源\n\n```js\nnpm i html-webpack-plugin -D\nconst HtmlWebpackPlugin = require(\"html-webpack-plugin\");\n plugins: [\n new HtmlWebpackPlugin({\n // 以 public/index.html 为模板创建文件\n // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源\n template: path.resolve(__dirname, \"public/index.html\"),\n }),\n ],\n```\n\n### 二、优化\n\n#### ●提升开发体验\n\n(1)sourceMap方便出现问题时定位到具体代码\n\n```js\nmodule.exports = {\n // 其他省略\n mode: 'production',\n devtool: 'source-map',\n};\n\nmodule.exports = {\n // 其他省略\n mode: 'development',\n devtool: 'cheap-module-source-map',\n};\n```\n\n#### ●提升打包构建速度\n\n(1)oneOf\n\n```js\nmodule: {\n rules: [\n {\n oneOf: [\n {\n // 用来匹配 .css 结尾的文件\n test: /\\.css$/,\n include: XXXX,\n // use 数组里面 Loader 执行顺序是从右到左\n use: [\"style-loader\", \"css-loader\"],\n }]\n```\n\n(2) include exclude\n(3)hotMdouleReplacement(HMR)\n(4)cache\n\n```js\n// 每次js打包都要经过eslint和babel编译,速度比较慢,可以缓存之前的eslint检查和babel编译结果,这样二次打包速度会快很多\nplugins: [\n new ESLintWebpackPlugin({\n // 指定检查文件的根目录\n context: path.resolve(__dirname, '../src'),\n exclude: 'node_modules', // 默认值\n cache: true, // 开启缓存\n // 缓存目录\n cacheLocation: path.resolve(\n __dirname,\n '../node_modules/.cache/.eslintcache'\n ),\n }),\n];\n```\n\n(5)Thead多核,多进程\n\n#### ●减少代码体积\n\n(1)tree shaking\n(2)Image Minimizer\n当项目中引入图片过多时(针对本地文件)可以进行压缩\n\n```js\nnpm i image-minimizer-webpack-plugin imagemin -D\n// 无损压缩\nnpm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D\n// 有损压缩\nnpm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D\n\nconst ImageMinimizerPlugin = require(\"image-minimizer-webpack-plugin\");\noptimization: {\n minimizer: [\n // css压缩也可以写到optimization.minimizer里面,效果一样的\n new CssMinimizerPlugin(),\n // 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了\n new TerserPlugin({\n parallel: threads, // 开启多进程\n }),\n // 压缩图片\n new ImageMinimizerPlugin({\n minimizer: {\n implementation: ImageMinimizerPlugin.imageminGenerate,\n options: {\n plugins: [\n [\"gifsicle\", { interlaced: true }],\n [\"jpegtran\", { progressive: true }],\n [\"optipng\", { optimizationLevel: 5 }],\n [\n \"svgo\",\n {\n plugins: [\n \"preset-default\",\n \"prefixIds\",\n {\n name: \"sortAttrs\",\n params: {\n xmlnsOrder: \"alphabetical\",\n },\n },\n ],\n },\n ],\n ],\n },\n },\n }),\n ],\n },\n```\n\n#### ●优化代码运行性能\n\n(1)code split\n●分割文件:将打包生成的文件进行分割,生产多个js文件\n●按需加载,需要哪个文件就加载哪个\n\n```js\noptimization: {\n // 代码分割配置\n splitChunks: {\n chunks: \"all\", // 对所有模块都进行分割\n }\n}\n```\n","slug":"webpack","published":1,"date":"2023-07-08T04:30:38.594Z","updated":"2023-07-08T04:30:38.595Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0j000ua9libl6balyo","content":"<h3 id=\"一、主要概念\"><a href=\"#一、主要概念\" class=\"headerlink\" title=\"一、主要概念\"></a>一、主要概念</h3><h4 id=\"●5大核心概念\"><a href=\"#●5大核心概念\" class=\"headerlink\" title=\"●5大核心概念\"></a>●5大核心概念</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"comment\">// 入口</span></span><br><span class=\"line\"> <span class=\"attr\">entry</span>: <span class=\"string\">''</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 输出</span></span><br><span class=\"line\"> <span class=\"attr\">output</span>: {},</span><br><span class=\"line\"> <span class=\"comment\">// 加载器loader</span></span><br><span class=\"line\"> <span class=\"attr\">module</span>: {</span><br><span class=\"line\"> <span class=\"attr\">rules</span>: [],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"comment\">// 插件</span></span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [],</span><br><span class=\"line\"> <span class=\"comment\">// 模式</span></span><br><span class=\"line\"> <span class=\"attr\">mode</span>: <span class=\"string\">''</span>, <span class=\"comment\">// development|production</span></span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●生产模式和开发模式\"><a href=\"#●生产模式和开发模式\" class=\"headerlink\" title=\"●生产模式和开发模式\"></a>●生产模式和开发模式</h4><p>○开发模式<br>(1)编译代码,使浏览器能识别运行<br>开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源<br>(2)代码质量检查,树立代码规范<br>提前检查代码的一些隐患,让代码运行时能更加健壮。提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。</p>\n<p>○生产模式<br>生产模式是开发完成代码后,我们需要得到代码将来部署上线。这个模式下我们主要 对代码进行优化,让其运行性能更好。优化主要从两个角度出发:<br>1)优化代码运行性能(2)优化代码打包速度</p>\n<h4 id=\"●处理样式资源\"><a href=\"#●处理样式资源\" class=\"headerlink\" title=\"●处理样式资源\"></a>●处理样式资源</h4><p>1)Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// css-loader: 负责将css文件编译成webpack能识别的模块</span></span><br><span class=\"line\"><span class=\"comment\">// style-loader: 会动态创建一个style标签,里面放置webpack中css模块内容</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> path = <span class=\"built_in\">require</span>(<span class=\"string\">'path'</span>);</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"attr\">entry</span>: <span class=\"string\">''</span>,</span><br><span class=\"line\"> <span class=\"attr\">output</span>: {},</span><br><span class=\"line\"> <span class=\"attr\">module</span>: {</span><br><span class=\"line\"> <span class=\"attr\">rules</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"comment\">// 用来匹配 .css 结尾的文件</span></span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.css$/</span>,</span><br><span class=\"line\"> <span class=\"comment\">// use 数组里面 Loader 执行顺序是从右到左</span></span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"string\">'style-loader'</span>, <span class=\"string\">'css-loader'</span>],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.less$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"string\">'style-loader'</span>, <span class=\"string\">'css-loader'</span>, <span class=\"string\">'less-loader'</span>],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.s[ac]ss$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"string\">'style-loader'</span>, <span class=\"string\">'css-loader'</span>, <span class=\"string\">'sass-loader'</span>],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.styl$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"string\">'style-loader'</span>, <span class=\"string\">'css-loader'</span>, <span class=\"string\">'stylus-loader'</span>],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [],</span><br><span class=\"line\"> <span class=\"attr\">mode</span>: <span class=\"string\">'development'</span>,</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p>2)提取css成单独的文件<br>css文件目前被打包到js文件中,当js文件加载时,会创建一个style标签来生成样式,这对于网站来说,会造成闪屏现象,用户体验不好,我们应该是单独的css文件,通过link标签加载性能才好</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i mini-css-extract-plugin -D</span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title class_\">MiniCssExtractPlugin</span> =<span class=\"built_in\">require</span>(<span class=\"string\">"mini-css-extract-plugin"</span>);</span><br><span class=\"line\"><span class=\"comment\">// 将style-loader替换成 MiniCssExtractPlugin.loader</span></span><br><span class=\"line\"><span class=\"attr\">rules</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"comment\">// 用来匹配 .css 结尾的文件</span></span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.css$/</span>,</span><br><span class=\"line\"> <span class=\"comment\">// use 数组里面 Loader 执行顺序是从右到左</span></span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"title class_\">MiniCssExtractPlugin</span>.<span class=\"property\">loader</span>, <span class=\"string\">"css-loader"</span>],</span><br><span class=\"line\"> }]</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"number\">3</span>)css兼容性处理</span><br><span class=\"line\">npm i postcss-loader postcss postcss-preset-env -D</span><br><span class=\"line\"><span class=\"attr\">rules</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"comment\">// 用来匹配 .css 结尾的文件</span></span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.css$/</span>,</span><br><span class=\"line\"> <span class=\"comment\">// use 数组里面 Loader 执行顺序是从右到左</span></span><br><span class=\"line\"> <span class=\"attr\">use</span>: [</span><br><span class=\"line\"> <span class=\"title class_\">MiniCssExtractPlugin</span>.<span class=\"property\">loader</span>,</span><br><span class=\"line\"> <span class=\"string\">"css-loader"</span>,</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">loader</span>: <span class=\"string\">"postcss-loader"</span>,</span><br><span class=\"line\"> <span class=\"attr\">options</span>: {</span><br><span class=\"line\"> <span class=\"attr\">postcssOptions</span>: {</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"string\">"postcss-preset-env"</span>, <span class=\"comment\">// 能解决大多数样式兼容性问题</span></span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> ],</span><br><span class=\"line\"></span><br><span class=\"line\"> 在package.<span class=\"property\">json</span>中可以更改兼容性</span><br><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"comment\">// 其他省略</span></span><br><span class=\"line\"> <span class=\"string\">"browserslist"</span>: [<span class=\"string\">"ie >= 8"</span>]</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>4)压缩css</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i css-minimizer-webpack-plugin -D</span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title class_\">CssMinimizerPlugin</span> = <span class=\"built_in\">require</span>(<span class=\"string\">"css-minimizer-webpack-plugin"</span>);</span><br><span class=\"line\"><span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"comment\">// css压缩</span></span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">CssMinimizerPlugin</span>(),</span><br><span class=\"line\"> ],</span><br></pre></td></tr></table></figure>\n\n<p>5)合并配置处理</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title function_\">getStyleLoaders</span> = (<span class=\"params\">preProcessor</span>) => {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> [</span><br><span class=\"line\"> <span class=\"title class_\">MiniCssExtractPlugin</span>.<span class=\"property\">loader</span>,</span><br><span class=\"line\"> <span class=\"string\">'css-loader'</span>,</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">loader</span>: <span class=\"string\">'postcss-loader'</span>,</span><br><span class=\"line\"> <span class=\"attr\">options</span>: {</span><br><span class=\"line\"> <span class=\"attr\">postcssOptions</span>: {</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"string\">'postcss-preset-env'</span>, <span class=\"comment\">// 能解决大多数样式兼容性问题</span></span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> preProcessor,</span><br><span class=\"line\"> ].<span class=\"title function_\">filter</span>(<span class=\"title class_\">Boolean</span>);</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"comment\">// 下面是用法</span></span><br><span class=\"line\"><span class=\"attr\">rules</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"comment\">// 用来匹配 .css 结尾的文件</span></span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.css$/</span>,</span><br><span class=\"line\"> <span class=\"comment\">// use 数组里面 Loader 执行顺序是从右到左</span></span><br><span class=\"line\"> <span class=\"attr\">use</span>: <span class=\"title function_\">getStyleLoaders</span>(),</span><br><span class=\"line\"> },</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.less$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">use</span>: <span class=\"title function_\">getStyleLoaders</span>(<span class=\"string\">'less-loader'</span>),</span><br><span class=\"line\"> },</span><br><span class=\"line\">];</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●处理图片资源\"><a href=\"#●处理图片资源\" class=\"headerlink\" title=\"●处理图片资源\"></a>●处理图片资源</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// webpack4中,处理图片要通过file-loader和url-loader进行处理,但是webpack5已经将两个loader功能内置到webpack里了,我们只需要简单配置即可处理图片资源</span></span><br><span class=\"line\"><span class=\"attr\">rules</span>: [</span><br><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.(png|jpe?g|gif|webp)$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">"asset"</span>,</span><br><span class=\"line\">}],</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 优化</span></span><br><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.(png|jpe?g|gif|webp)$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">"asset"</span>,</span><br><span class=\"line\"> <span class=\"comment\">//将小于某个大小的图片转化成 data URI 形式(Base64 格式, 优点是能减 少请求次数,缺点是会导致体积变大</span></span><br><span class=\"line\"> <span class=\"attr\">parser</span>: {</span><br><span class=\"line\"> <span class=\"attr\">dataUrlCondition</span>: {</span><br><span class=\"line\"> <span class=\"attr\">maxSize</span>: <span class=\"number\">10</span> * <span class=\"number\">1024</span>, <span class=\"comment\">// 小于10kb的图片会被base64处理</span></span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"><span class=\"comment\">// 修改资源输入路径</span></span><br><span class=\"line\"><span class=\"attr\">generator</span>: {</span><br><span class=\"line\"> <span class=\"comment\">// 将图片文件输出到 static/imgs 目录中</span></span><br><span class=\"line\"> <span class=\"comment\">// 将图片文件命名 [hash:8][ext][query]</span></span><br><span class=\"line\"> <span class=\"comment\">// [hash:8]: hash值取8位</span></span><br><span class=\"line\"> <span class=\"comment\">// [ext]: 使用之前的文件扩展名</span></span><br><span class=\"line\"> <span class=\"comment\">// [query]: 添加之前的query参数</span></span><br><span class=\"line\"> <span class=\"attr\">filename</span>: <span class=\"string\">"static/imgs/[hash:8][ext][query]"</span>,</span><br><span class=\"line\">}},</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●处理js资源\"><a href=\"#●处理js资源\" class=\"headerlink\" title=\"●处理js资源\"></a>●处理js资源</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"number\">1</span>)针对 js 兼容性处理,我们使用 <span class=\"title class_\">Babel</span> 来完成</span><br><span class=\"line\"><span class=\"comment\">// 此处eslint具体配置省略,只写webpack配置</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title class_\">ESLintWebpackPlugin</span> = <span class=\"built_in\">require</span>(<span class=\"string\">"eslint-webpack-plugin"</span>);</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">ESLintWebpackPlugin</span>({</span><br><span class=\"line\"> <span class=\"comment\">// 指定检查文件的根目录</span></span><br><span class=\"line\"> <span class=\"attr\">context</span>: path.<span class=\"title function_\">resolve</span>(__dirname, <span class=\"string\">"src"</span>),</span><br><span class=\"line\"> }),</span><br><span class=\"line\"> ],</span><br></pre></td></tr></table></figure>\n\n<p>2)针对代码格式,我们使用 Eslint 来完成</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i babel-loader @babel/core @babel/preset-env -D</span><br><span class=\"line\"><span class=\"comment\">// babel.config.js</span></span><br><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"attr\">presets</span>: [<span class=\"string\">"@babel/preset-env"</span>],</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●处理html资源\"><a href=\"#●处理html资源\" class=\"headerlink\" title=\"●处理html资源\"></a>●处理html资源</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i html-webpack-plugin -D</span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title class_\">HtmlWebpackPlugin</span> = <span class=\"built_in\">require</span>(<span class=\"string\">"html-webpack-plugin"</span>);</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">HtmlWebpackPlugin</span>({</span><br><span class=\"line\"> <span class=\"comment\">// 以 public/index.html 为模板创建文件</span></span><br><span class=\"line\"> <span class=\"comment\">// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源</span></span><br><span class=\"line\"> <span class=\"attr\">template</span>: path.<span class=\"title function_\">resolve</span>(__dirname, <span class=\"string\">"public/index.html"</span>),</span><br><span class=\"line\"> }),</span><br><span class=\"line\"> ],</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"二、优化\"><a href=\"#二、优化\" class=\"headerlink\" title=\"二、优化\"></a>二、优化</h3><h4 id=\"●提升开发体验\"><a href=\"#●提升开发体验\" class=\"headerlink\" title=\"●提升开发体验\"></a>●提升开发体验</h4><p>(1)sourceMap方便出现问题时定位到具体代码</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"comment\">// 其他省略</span></span><br><span class=\"line\"> <span class=\"attr\">mode</span>: <span class=\"string\">'production'</span>,</span><br><span class=\"line\"> <span class=\"attr\">devtool</span>: <span class=\"string\">'source-map'</span>,</span><br><span class=\"line\">};</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"comment\">// 其他省略</span></span><br><span class=\"line\"> <span class=\"attr\">mode</span>: <span class=\"string\">'development'</span>,</span><br><span class=\"line\"> <span class=\"attr\">devtool</span>: <span class=\"string\">'cheap-module-source-map'</span>,</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●提升打包构建速度\"><a href=\"#●提升打包构建速度\" class=\"headerlink\" title=\"●提升打包构建速度\"></a>●提升打包构建速度</h4><p>(1)oneOf</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">module</span>: {</span><br><span class=\"line\"> <span class=\"attr\">rules</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">oneOf</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"comment\">// 用来匹配 .css 结尾的文件</span></span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.css$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">include</span>: <span class=\"variable constant_\">XXXX</span>,</span><br><span class=\"line\"> <span class=\"comment\">// use 数组里面 Loader 执行顺序是从右到左</span></span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"string\">"style-loader"</span>, <span class=\"string\">"css-loader"</span>],</span><br><span class=\"line\"> }]</span><br></pre></td></tr></table></figure>\n\n<p>(2) include exclude<br>(3)hotMdouleReplacement(HMR)<br>(4)cache</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 每次js打包都要经过eslint和babel编译,速度比较慢,可以缓存之前的eslint检查和babel编译结果,这样二次打包速度会快很多</span></span><br><span class=\"line\"><span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">ESLintWebpackPlugin</span>({</span><br><span class=\"line\"> <span class=\"comment\">// 指定检查文件的根目录</span></span><br><span class=\"line\"> <span class=\"attr\">context</span>: path.<span class=\"title function_\">resolve</span>(__dirname, <span class=\"string\">'../src'</span>),</span><br><span class=\"line\"> <span class=\"attr\">exclude</span>: <span class=\"string\">'node_modules'</span>, <span class=\"comment\">// 默认值</span></span><br><span class=\"line\"> <span class=\"attr\">cache</span>: <span class=\"literal\">true</span>, <span class=\"comment\">// 开启缓存</span></span><br><span class=\"line\"> <span class=\"comment\">// 缓存目录</span></span><br><span class=\"line\"> <span class=\"attr\">cacheLocation</span>: path.<span class=\"title function_\">resolve</span>(</span><br><span class=\"line\"> __dirname,</span><br><span class=\"line\"> <span class=\"string\">'../node_modules/.cache/.eslintcache'</span></span><br><span class=\"line\"> ),</span><br><span class=\"line\"> }),</span><br><span class=\"line\">];</span><br></pre></td></tr></table></figure>\n\n<p>(5)Thead多核,多进程</p>\n<h4 id=\"●减少代码体积\"><a href=\"#●减少代码体积\" class=\"headerlink\" title=\"●减少代码体积\"></a>●减少代码体积</h4><p>(1)tree shaking<br>(2)Image Minimizer<br>当项目中引入图片过多时(针对本地文件)可以进行压缩</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i image-minimizer-webpack-plugin imagemin -D</span><br><span class=\"line\"><span class=\"comment\">// 无损压缩</span></span><br><span class=\"line\">npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D</span><br><span class=\"line\"><span class=\"comment\">// 有损压缩</span></span><br><span class=\"line\">npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title class_\">ImageMinimizerPlugin</span> = <span class=\"built_in\">require</span>(<span class=\"string\">"image-minimizer-webpack-plugin"</span>);</span><br><span class=\"line\"><span class=\"attr\">optimization</span>: {</span><br><span class=\"line\"> <span class=\"attr\">minimizer</span>: [</span><br><span class=\"line\"> <span class=\"comment\">// css压缩也可以写到optimization.minimizer里面,效果一样的</span></span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">CssMinimizerPlugin</span>(),</span><br><span class=\"line\"> <span class=\"comment\">// 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了</span></span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">TerserPlugin</span>({</span><br><span class=\"line\"> <span class=\"attr\">parallel</span>: threads, <span class=\"comment\">// 开启多进程</span></span><br><span class=\"line\"> }),</span><br><span class=\"line\"> <span class=\"comment\">// 压缩图片</span></span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">ImageMinimizerPlugin</span>({</span><br><span class=\"line\"> <span class=\"attr\">minimizer</span>: {</span><br><span class=\"line\"> <span class=\"attr\">implementation</span>: <span class=\"title class_\">ImageMinimizerPlugin</span>.<span class=\"property\">imageminGenerate</span>,</span><br><span class=\"line\"> <span class=\"attr\">options</span>: {</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> [<span class=\"string\">"gifsicle"</span>, { <span class=\"attr\">interlaced</span>: <span class=\"literal\">true</span> }],</span><br><span class=\"line\"> [<span class=\"string\">"jpegtran"</span>, { <span class=\"attr\">progressive</span>: <span class=\"literal\">true</span> }],</span><br><span class=\"line\"> [<span class=\"string\">"optipng"</span>, { <span class=\"attr\">optimizationLevel</span>: <span class=\"number\">5</span> }],</span><br><span class=\"line\"> [</span><br><span class=\"line\"> <span class=\"string\">"svgo"</span>,</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"string\">"preset-default"</span>,</span><br><span class=\"line\"> <span class=\"string\">"prefixIds"</span>,</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">"sortAttrs"</span>,</span><br><span class=\"line\"> <span class=\"attr\">params</span>: {</span><br><span class=\"line\"> <span class=\"attr\">xmlnsOrder</span>: <span class=\"string\">"alphabetical"</span>,</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> }),</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●优化代码运行性能\"><a href=\"#●优化代码运行性能\" class=\"headerlink\" title=\"●优化代码运行性能\"></a>●优化代码运行性能</h4><p>(1)code split<br>●分割文件:将打包生成的文件进行分割,生产多个js文件<br>●按需加载,需要哪个文件就加载哪个</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">optimization</span>: {</span><br><span class=\"line\"> <span class=\"comment\">// 代码分割配置</span></span><br><span class=\"line\"> <span class=\"attr\">splitChunks</span>: {</span><br><span class=\"line\"> <span class=\"attr\">chunks</span>: <span class=\"string\">"all"</span>, <span class=\"comment\">// 对所有模块都进行分割</span></span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"一、主要概念\"><a href=\"#一、主要概念\" class=\"headerlink\" title=\"一、主要概念\"></a>一、主要概念</h3><h4 id=\"●5大核心概念\"><a href=\"#●5大核心概念\" class=\"headerlink\" title=\"●5大核心概念\"></a>●5大核心概念</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"comment\">// 入口</span></span><br><span class=\"line\"> <span class=\"attr\">entry</span>: <span class=\"string\">''</span>,</span><br><span class=\"line\"> <span class=\"comment\">// 输出</span></span><br><span class=\"line\"> <span class=\"attr\">output</span>: {},</span><br><span class=\"line\"> <span class=\"comment\">// 加载器loader</span></span><br><span class=\"line\"> <span class=\"attr\">module</span>: {</span><br><span class=\"line\"> <span class=\"attr\">rules</span>: [],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"comment\">// 插件</span></span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [],</span><br><span class=\"line\"> <span class=\"comment\">// 模式</span></span><br><span class=\"line\"> <span class=\"attr\">mode</span>: <span class=\"string\">''</span>, <span class=\"comment\">// development|production</span></span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●生产模式和开发模式\"><a href=\"#●生产模式和开发模式\" class=\"headerlink\" title=\"●生产模式和开发模式\"></a>●生产模式和开发模式</h4><p>○开发模式<br>(1)编译代码,使浏览器能识别运行<br>开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源<br>(2)代码质量检查,树立代码规范<br>提前检查代码的一些隐患,让代码运行时能更加健壮。提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。</p>\n<p>○生产模式<br>生产模式是开发完成代码后,我们需要得到代码将来部署上线。这个模式下我们主要 对代码进行优化,让其运行性能更好。优化主要从两个角度出发:<br>1)优化代码运行性能(2)优化代码打包速度</p>\n<h4 id=\"●处理样式资源\"><a href=\"#●处理样式资源\" class=\"headerlink\" title=\"●处理样式资源\"></a>●处理样式资源</h4><p>1)Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// css-loader: 负责将css文件编译成webpack能识别的模块</span></span><br><span class=\"line\"><span class=\"comment\">// style-loader: 会动态创建一个style标签,里面放置webpack中css模块内容</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> path = <span class=\"built_in\">require</span>(<span class=\"string\">'path'</span>);</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"attr\">entry</span>: <span class=\"string\">''</span>,</span><br><span class=\"line\"> <span class=\"attr\">output</span>: {},</span><br><span class=\"line\"> <span class=\"attr\">module</span>: {</span><br><span class=\"line\"> <span class=\"attr\">rules</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"comment\">// 用来匹配 .css 结尾的文件</span></span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.css$/</span>,</span><br><span class=\"line\"> <span class=\"comment\">// use 数组里面 Loader 执行顺序是从右到左</span></span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"string\">'style-loader'</span>, <span class=\"string\">'css-loader'</span>],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.less$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"string\">'style-loader'</span>, <span class=\"string\">'css-loader'</span>, <span class=\"string\">'less-loader'</span>],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.s[ac]ss$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"string\">'style-loader'</span>, <span class=\"string\">'css-loader'</span>, <span class=\"string\">'sass-loader'</span>],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.styl$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"string\">'style-loader'</span>, <span class=\"string\">'css-loader'</span>, <span class=\"string\">'stylus-loader'</span>],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [],</span><br><span class=\"line\"> <span class=\"attr\">mode</span>: <span class=\"string\">'development'</span>,</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p>2)提取css成单独的文件<br>css文件目前被打包到js文件中,当js文件加载时,会创建一个style标签来生成样式,这对于网站来说,会造成闪屏现象,用户体验不好,我们应该是单独的css文件,通过link标签加载性能才好</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i mini-css-extract-plugin -D</span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title class_\">MiniCssExtractPlugin</span> =<span class=\"built_in\">require</span>(<span class=\"string\">"mini-css-extract-plugin"</span>);</span><br><span class=\"line\"><span class=\"comment\">// 将style-loader替换成 MiniCssExtractPlugin.loader</span></span><br><span class=\"line\"><span class=\"attr\">rules</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"comment\">// 用来匹配 .css 结尾的文件</span></span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.css$/</span>,</span><br><span class=\"line\"> <span class=\"comment\">// use 数组里面 Loader 执行顺序是从右到左</span></span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"title class_\">MiniCssExtractPlugin</span>.<span class=\"property\">loader</span>, <span class=\"string\">"css-loader"</span>],</span><br><span class=\"line\"> }]</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"number\">3</span>)css兼容性处理</span><br><span class=\"line\">npm i postcss-loader postcss postcss-preset-env -D</span><br><span class=\"line\"><span class=\"attr\">rules</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"comment\">// 用来匹配 .css 结尾的文件</span></span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.css$/</span>,</span><br><span class=\"line\"> <span class=\"comment\">// use 数组里面 Loader 执行顺序是从右到左</span></span><br><span class=\"line\"> <span class=\"attr\">use</span>: [</span><br><span class=\"line\"> <span class=\"title class_\">MiniCssExtractPlugin</span>.<span class=\"property\">loader</span>,</span><br><span class=\"line\"> <span class=\"string\">"css-loader"</span>,</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">loader</span>: <span class=\"string\">"postcss-loader"</span>,</span><br><span class=\"line\"> <span class=\"attr\">options</span>: {</span><br><span class=\"line\"> <span class=\"attr\">postcssOptions</span>: {</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"string\">"postcss-preset-env"</span>, <span class=\"comment\">// 能解决大多数样式兼容性问题</span></span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> ],</span><br><span class=\"line\"></span><br><span class=\"line\"> 在package.<span class=\"property\">json</span>中可以更改兼容性</span><br><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"comment\">// 其他省略</span></span><br><span class=\"line\"> <span class=\"string\">"browserslist"</span>: [<span class=\"string\">"ie >= 8"</span>]</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>4)压缩css</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i css-minimizer-webpack-plugin -D</span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title class_\">CssMinimizerPlugin</span> = <span class=\"built_in\">require</span>(<span class=\"string\">"css-minimizer-webpack-plugin"</span>);</span><br><span class=\"line\"><span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"comment\">// css压缩</span></span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">CssMinimizerPlugin</span>(),</span><br><span class=\"line\"> ],</span><br></pre></td></tr></table></figure>\n\n<p>5)合并配置处理</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title function_\">getStyleLoaders</span> = (<span class=\"params\">preProcessor</span>) => {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> [</span><br><span class=\"line\"> <span class=\"title class_\">MiniCssExtractPlugin</span>.<span class=\"property\">loader</span>,</span><br><span class=\"line\"> <span class=\"string\">'css-loader'</span>,</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">loader</span>: <span class=\"string\">'postcss-loader'</span>,</span><br><span class=\"line\"> <span class=\"attr\">options</span>: {</span><br><span class=\"line\"> <span class=\"attr\">postcssOptions</span>: {</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"string\">'postcss-preset-env'</span>, <span class=\"comment\">// 能解决大多数样式兼容性问题</span></span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> preProcessor,</span><br><span class=\"line\"> ].<span class=\"title function_\">filter</span>(<span class=\"title class_\">Boolean</span>);</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"comment\">// 下面是用法</span></span><br><span class=\"line\"><span class=\"attr\">rules</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"comment\">// 用来匹配 .css 结尾的文件</span></span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.css$/</span>,</span><br><span class=\"line\"> <span class=\"comment\">// use 数组里面 Loader 执行顺序是从右到左</span></span><br><span class=\"line\"> <span class=\"attr\">use</span>: <span class=\"title function_\">getStyleLoaders</span>(),</span><br><span class=\"line\"> },</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.less$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">use</span>: <span class=\"title function_\">getStyleLoaders</span>(<span class=\"string\">'less-loader'</span>),</span><br><span class=\"line\"> },</span><br><span class=\"line\">];</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●处理图片资源\"><a href=\"#●处理图片资源\" class=\"headerlink\" title=\"●处理图片资源\"></a>●处理图片资源</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// webpack4中,处理图片要通过file-loader和url-loader进行处理,但是webpack5已经将两个loader功能内置到webpack里了,我们只需要简单配置即可处理图片资源</span></span><br><span class=\"line\"><span class=\"attr\">rules</span>: [</span><br><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.(png|jpe?g|gif|webp)$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">"asset"</span>,</span><br><span class=\"line\">}],</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 优化</span></span><br><span class=\"line\">{</span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.(png|jpe?g|gif|webp)$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">"asset"</span>,</span><br><span class=\"line\"> <span class=\"comment\">//将小于某个大小的图片转化成 data URI 形式(Base64 格式, 优点是能减 少请求次数,缺点是会导致体积变大</span></span><br><span class=\"line\"> <span class=\"attr\">parser</span>: {</span><br><span class=\"line\"> <span class=\"attr\">dataUrlCondition</span>: {</span><br><span class=\"line\"> <span class=\"attr\">maxSize</span>: <span class=\"number\">10</span> * <span class=\"number\">1024</span>, <span class=\"comment\">// 小于10kb的图片会被base64处理</span></span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"><span class=\"comment\">// 修改资源输入路径</span></span><br><span class=\"line\"><span class=\"attr\">generator</span>: {</span><br><span class=\"line\"> <span class=\"comment\">// 将图片文件输出到 static/imgs 目录中</span></span><br><span class=\"line\"> <span class=\"comment\">// 将图片文件命名 [hash:8][ext][query]</span></span><br><span class=\"line\"> <span class=\"comment\">// [hash:8]: hash值取8位</span></span><br><span class=\"line\"> <span class=\"comment\">// [ext]: 使用之前的文件扩展名</span></span><br><span class=\"line\"> <span class=\"comment\">// [query]: 添加之前的query参数</span></span><br><span class=\"line\"> <span class=\"attr\">filename</span>: <span class=\"string\">"static/imgs/[hash:8][ext][query]"</span>,</span><br><span class=\"line\">}},</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●处理js资源\"><a href=\"#●处理js资源\" class=\"headerlink\" title=\"●处理js资源\"></a>●处理js资源</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"number\">1</span>)针对 js 兼容性处理,我们使用 <span class=\"title class_\">Babel</span> 来完成</span><br><span class=\"line\"><span class=\"comment\">// 此处eslint具体配置省略,只写webpack配置</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title class_\">ESLintWebpackPlugin</span> = <span class=\"built_in\">require</span>(<span class=\"string\">"eslint-webpack-plugin"</span>);</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">ESLintWebpackPlugin</span>({</span><br><span class=\"line\"> <span class=\"comment\">// 指定检查文件的根目录</span></span><br><span class=\"line\"> <span class=\"attr\">context</span>: path.<span class=\"title function_\">resolve</span>(__dirname, <span class=\"string\">"src"</span>),</span><br><span class=\"line\"> }),</span><br><span class=\"line\"> ],</span><br></pre></td></tr></table></figure>\n\n<p>2)针对代码格式,我们使用 Eslint 来完成</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i babel-loader @babel/core @babel/preset-env -D</span><br><span class=\"line\"><span class=\"comment\">// babel.config.js</span></span><br><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"attr\">presets</span>: [<span class=\"string\">"@babel/preset-env"</span>],</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●处理html资源\"><a href=\"#●处理html资源\" class=\"headerlink\" title=\"●处理html资源\"></a>●处理html资源</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i html-webpack-plugin -D</span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title class_\">HtmlWebpackPlugin</span> = <span class=\"built_in\">require</span>(<span class=\"string\">"html-webpack-plugin"</span>);</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">HtmlWebpackPlugin</span>({</span><br><span class=\"line\"> <span class=\"comment\">// 以 public/index.html 为模板创建文件</span></span><br><span class=\"line\"> <span class=\"comment\">// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源</span></span><br><span class=\"line\"> <span class=\"attr\">template</span>: path.<span class=\"title function_\">resolve</span>(__dirname, <span class=\"string\">"public/index.html"</span>),</span><br><span class=\"line\"> }),</span><br><span class=\"line\"> ],</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"二、优化\"><a href=\"#二、优化\" class=\"headerlink\" title=\"二、优化\"></a>二、优化</h3><h4 id=\"●提升开发体验\"><a href=\"#●提升开发体验\" class=\"headerlink\" title=\"●提升开发体验\"></a>●提升开发体验</h4><p>(1)sourceMap方便出现问题时定位到具体代码</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"comment\">// 其他省略</span></span><br><span class=\"line\"> <span class=\"attr\">mode</span>: <span class=\"string\">'production'</span>,</span><br><span class=\"line\"> <span class=\"attr\">devtool</span>: <span class=\"string\">'source-map'</span>,</span><br><span class=\"line\">};</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"variable language_\">module</span>.<span class=\"property\">exports</span> = {</span><br><span class=\"line\"> <span class=\"comment\">// 其他省略</span></span><br><span class=\"line\"> <span class=\"attr\">mode</span>: <span class=\"string\">'development'</span>,</span><br><span class=\"line\"> <span class=\"attr\">devtool</span>: <span class=\"string\">'cheap-module-source-map'</span>,</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●提升打包构建速度\"><a href=\"#●提升打包构建速度\" class=\"headerlink\" title=\"●提升打包构建速度\"></a>●提升打包构建速度</h4><p>(1)oneOf</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">module</span>: {</span><br><span class=\"line\"> <span class=\"attr\">rules</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">oneOf</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"comment\">// 用来匹配 .css 结尾的文件</span></span><br><span class=\"line\"> <span class=\"attr\">test</span>: <span class=\"regexp\">/\\.css$/</span>,</span><br><span class=\"line\"> <span class=\"attr\">include</span>: <span class=\"variable constant_\">XXXX</span>,</span><br><span class=\"line\"> <span class=\"comment\">// use 数组里面 Loader 执行顺序是从右到左</span></span><br><span class=\"line\"> <span class=\"attr\">use</span>: [<span class=\"string\">"style-loader"</span>, <span class=\"string\">"css-loader"</span>],</span><br><span class=\"line\"> }]</span><br></pre></td></tr></table></figure>\n\n<p>(2) include exclude<br>(3)hotMdouleReplacement(HMR)<br>(4)cache</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 每次js打包都要经过eslint和babel编译,速度比较慢,可以缓存之前的eslint检查和babel编译结果,这样二次打包速度会快很多</span></span><br><span class=\"line\"><span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">ESLintWebpackPlugin</span>({</span><br><span class=\"line\"> <span class=\"comment\">// 指定检查文件的根目录</span></span><br><span class=\"line\"> <span class=\"attr\">context</span>: path.<span class=\"title function_\">resolve</span>(__dirname, <span class=\"string\">'../src'</span>),</span><br><span class=\"line\"> <span class=\"attr\">exclude</span>: <span class=\"string\">'node_modules'</span>, <span class=\"comment\">// 默认值</span></span><br><span class=\"line\"> <span class=\"attr\">cache</span>: <span class=\"literal\">true</span>, <span class=\"comment\">// 开启缓存</span></span><br><span class=\"line\"> <span class=\"comment\">// 缓存目录</span></span><br><span class=\"line\"> <span class=\"attr\">cacheLocation</span>: path.<span class=\"title function_\">resolve</span>(</span><br><span class=\"line\"> __dirname,</span><br><span class=\"line\"> <span class=\"string\">'../node_modules/.cache/.eslintcache'</span></span><br><span class=\"line\"> ),</span><br><span class=\"line\"> }),</span><br><span class=\"line\">];</span><br></pre></td></tr></table></figure>\n\n<p>(5)Thead多核,多进程</p>\n<h4 id=\"●减少代码体积\"><a href=\"#●减少代码体积\" class=\"headerlink\" title=\"●减少代码体积\"></a>●减少代码体积</h4><p>(1)tree shaking<br>(2)Image Minimizer<br>当项目中引入图片过多时(针对本地文件)可以进行压缩</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm i image-minimizer-webpack-plugin imagemin -D</span><br><span class=\"line\"><span class=\"comment\">// 无损压缩</span></span><br><span class=\"line\">npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D</span><br><span class=\"line\"><span class=\"comment\">// 有损压缩</span></span><br><span class=\"line\">npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title class_\">ImageMinimizerPlugin</span> = <span class=\"built_in\">require</span>(<span class=\"string\">"image-minimizer-webpack-plugin"</span>);</span><br><span class=\"line\"><span class=\"attr\">optimization</span>: {</span><br><span class=\"line\"> <span class=\"attr\">minimizer</span>: [</span><br><span class=\"line\"> <span class=\"comment\">// css压缩也可以写到optimization.minimizer里面,效果一样的</span></span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">CssMinimizerPlugin</span>(),</span><br><span class=\"line\"> <span class=\"comment\">// 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了</span></span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">TerserPlugin</span>({</span><br><span class=\"line\"> <span class=\"attr\">parallel</span>: threads, <span class=\"comment\">// 开启多进程</span></span><br><span class=\"line\"> }),</span><br><span class=\"line\"> <span class=\"comment\">// 压缩图片</span></span><br><span class=\"line\"> <span class=\"keyword\">new</span> <span class=\"title class_\">ImageMinimizerPlugin</span>({</span><br><span class=\"line\"> <span class=\"attr\">minimizer</span>: {</span><br><span class=\"line\"> <span class=\"attr\">implementation</span>: <span class=\"title class_\">ImageMinimizerPlugin</span>.<span class=\"property\">imageminGenerate</span>,</span><br><span class=\"line\"> <span class=\"attr\">options</span>: {</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> [<span class=\"string\">"gifsicle"</span>, { <span class=\"attr\">interlaced</span>: <span class=\"literal\">true</span> }],</span><br><span class=\"line\"> [<span class=\"string\">"jpegtran"</span>, { <span class=\"attr\">progressive</span>: <span class=\"literal\">true</span> }],</span><br><span class=\"line\"> [<span class=\"string\">"optipng"</span>, { <span class=\"attr\">optimizationLevel</span>: <span class=\"number\">5</span> }],</span><br><span class=\"line\"> [</span><br><span class=\"line\"> <span class=\"string\">"svgo"</span>,</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">plugins</span>: [</span><br><span class=\"line\"> <span class=\"string\">"preset-default"</span>,</span><br><span class=\"line\"> <span class=\"string\">"prefixIds"</span>,</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">"sortAttrs"</span>,</span><br><span class=\"line\"> <span class=\"attr\">params</span>: {</span><br><span class=\"line\"> <span class=\"attr\">xmlnsOrder</span>: <span class=\"string\">"alphabetical"</span>,</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br><span class=\"line\"> },</span><br><span class=\"line\"> }),</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> },</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●优化代码运行性能\"><a href=\"#●优化代码运行性能\" class=\"headerlink\" title=\"●优化代码运行性能\"></a>●优化代码运行性能</h4><p>(1)code split<br>●分割文件:将打包生成的文件进行分割,生产多个js文件<br>●按需加载,需要哪个文件就加载哪个</p>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">optimization</span>: {</span><br><span class=\"line\"> <span class=\"comment\">// 代码分割配置</span></span><br><span class=\"line\"> <span class=\"attr\">splitChunks</span>: {</span><br><span class=\"line\"> <span class=\"attr\">chunks</span>: <span class=\"string\">"all"</span>, <span class=\"comment\">// 对所有模块都进行分割</span></span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n"},{"title":"二次封装el-input","date":"2023-07-08T02:58:04.000Z","_content":"\n### 二次封装el-input\n\n#### v-model实现数据双向版本\n\n```js\n<input v-model=\"searchText\" />\n//等效于\n<input\n :value=\"searchText\"\n @input=\"searchText = $event.target.value\"\n/>\n\n//当在一个组件中使用时\n<CustomInput\n :modelValue=\"searchText\"\n @update:modelValue=\"newValue => searchText = newValue\"\n/>\n//等效于\n<CustomInput v-model=\"searchText\" />\n\n//CustomInput.vue\n<script setup>\ndefineProps(['modelValue'])\ndefineEmits(['update:modelValue'])\n</script>\n\n<template>\n <input\n :value=\"modelValue\"\n @input=\"$emit('update:modelValue', $event.target.value)\"\n />\n</template>\n\n\n//例子\n<UserName\n v-model:first-name=\"first\"\n v-model:last-name=\"last\"\n/>\n<script setup>\ndefineProps({\n firstName: String,\n lastName: String\n})\n\ndefineEmits(['update:firstName', 'update:lastName'])\n</script>\n\n<template>\n <input\n type=\"text\"\n :value=\"firstName\"\n @input=\"$emit('update:firstName', $event.target.value)\"\n />\n <input\n type=\"text\"\n :value=\"lastName\"\n @input=\"$emit('update:lastName', $event.target.value)\"\n />\n</template>\n```\n","source":"_posts/二次封装el-input.md","raw":"---\ntitle: 二次封装el-input\ndate: 2023-07-08 10:58:04\ntags:\ncategories:\n - UI组件\n---\n\n### 二次封装el-input\n\n#### v-model实现数据双向版本\n\n```js\n<input v-model=\"searchText\" />\n//等效于\n<input\n :value=\"searchText\"\n @input=\"searchText = $event.target.value\"\n/>\n\n//当在一个组件中使用时\n<CustomInput\n :modelValue=\"searchText\"\n @update:modelValue=\"newValue => searchText = newValue\"\n/>\n//等效于\n<CustomInput v-model=\"searchText\" />\n\n//CustomInput.vue\n<script setup>\ndefineProps(['modelValue'])\ndefineEmits(['update:modelValue'])\n</script>\n\n<template>\n <input\n :value=\"modelValue\"\n @input=\"$emit('update:modelValue', $event.target.value)\"\n />\n</template>\n\n\n//例子\n<UserName\n v-model:first-name=\"first\"\n v-model:last-name=\"last\"\n/>\n<script setup>\ndefineProps({\n firstName: String,\n lastName: String\n})\n\ndefineEmits(['update:firstName', 'update:lastName'])\n</script>\n\n<template>\n <input\n type=\"text\"\n :value=\"firstName\"\n @input=\"$emit('update:firstName', $event.target.value)\"\n />\n <input\n type=\"text\"\n :value=\"lastName\"\n @input=\"$emit('update:lastName', $event.target.value)\"\n />\n</template>\n```\n","slug":"二次封装el-input","published":1,"updated":"2023-07-08T04:30:38.595Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0j000va9li5yyw5u38","content":"<h3 id=\"二次封装el-input\"><a href=\"#二次封装el-input\" class=\"headerlink\" title=\"二次封装el-input\"></a>二次封装el-input</h3><h4 id=\"v-model实现数据双向版本\"><a href=\"#v-model实现数据双向版本\" class=\"headerlink\" title=\"v-model实现数据双向版本\"></a>v-model实现数据双向版本</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><input v-model=<span class=\"string\">"searchText"</span> /></span><br><span class=\"line\"><span class=\"comment\">//等效于</span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">input</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">:value</span>=<span class=\"string\">"searchText"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> @<span class=\"attr\">input</span>=<span class=\"string\">"searchText = $event.target.value"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\">/></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">//当在一个组件中使用时</span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">CustomInput</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">:modelValue</span>=<span class=\"string\">"searchText"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> @<span class=\"attr\">update:modelValue</span>=<span class=\"string\">"newValue => searchText = newValue"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\">/></span></span></span><br><span class=\"line\"><span class=\"comment\">//等效于</span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">CustomInput</span> <span class=\"attr\">v-model</span>=<span class=\"string\">"searchText"</span> /></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">//CustomInput.vue</span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">script</span> <span class=\"attr\">setup</span>></span><span class=\"language-javascript\"></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"><span class=\"title function_\">defineProps</span>([<span class=\"string\">'modelValue'</span>])</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"><span class=\"title function_\">defineEmits</span>([<span class=\"string\">'update:modelValue'</span>])</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"></span><span class=\"tag\"></<span class=\"name\">script</span>></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">template</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">input</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">:value</span>=<span class=\"string\">"modelValue"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> @<span class=\"attr\">input</span>=<span class=\"string\">"$emit('update:modelValue', $event.target.value)"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> /></span></span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"></<span class=\"name\">template</span>></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">//例子</span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">UserName</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">v-model:first-name</span>=<span class=\"string\">"first"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">v-model:last-name</span>=<span class=\"string\">"last"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\">/></span></span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">script</span> <span class=\"attr\">setup</span>></span><span class=\"language-javascript\"></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"><span class=\"title function_\">defineProps</span>({</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> <span class=\"attr\">firstName</span>: <span class=\"title class_\">String</span>,</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> <span class=\"attr\">lastName</span>: <span class=\"title class_\">String</span></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\">})</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"><span class=\"title function_\">defineEmits</span>([<span class=\"string\">'update:firstName'</span>, <span class=\"string\">'update:lastName'</span>])</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"></span><span class=\"tag\"></<span class=\"name\">script</span>></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">template</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">input</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">type</span>=<span class=\"string\">"text"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">:value</span>=<span class=\"string\">"firstName"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> @<span class=\"attr\">input</span>=<span class=\"string\">"$emit('update:firstName', $event.target.value)"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> /></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">input</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">type</span>=<span class=\"string\">"text"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">:value</span>=<span class=\"string\">"lastName"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> @<span class=\"attr\">input</span>=<span class=\"string\">"$emit('update:lastName', $event.target.value)"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> /></span></span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"></<span class=\"name\">template</span>></span></span></span><br></pre></td></tr></table></figure>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"二次封装el-input\"><a href=\"#二次封装el-input\" class=\"headerlink\" title=\"二次封装el-input\"></a>二次封装el-input</h3><h4 id=\"v-model实现数据双向版本\"><a href=\"#v-model实现数据双向版本\" class=\"headerlink\" title=\"v-model实现数据双向版本\"></a>v-model实现数据双向版本</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><input v-model=<span class=\"string\">"searchText"</span> /></span><br><span class=\"line\"><span class=\"comment\">//等效于</span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">input</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">:value</span>=<span class=\"string\">"searchText"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> @<span class=\"attr\">input</span>=<span class=\"string\">"searchText = $event.target.value"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\">/></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">//当在一个组件中使用时</span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">CustomInput</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">:modelValue</span>=<span class=\"string\">"searchText"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> @<span class=\"attr\">update:modelValue</span>=<span class=\"string\">"newValue => searchText = newValue"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\">/></span></span></span><br><span class=\"line\"><span class=\"comment\">//等效于</span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">CustomInput</span> <span class=\"attr\">v-model</span>=<span class=\"string\">"searchText"</span> /></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">//CustomInput.vue</span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">script</span> <span class=\"attr\">setup</span>></span><span class=\"language-javascript\"></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"><span class=\"title function_\">defineProps</span>([<span class=\"string\">'modelValue'</span>])</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"><span class=\"title function_\">defineEmits</span>([<span class=\"string\">'update:modelValue'</span>])</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"></span><span class=\"tag\"></<span class=\"name\">script</span>></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">template</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">input</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">:value</span>=<span class=\"string\">"modelValue"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> @<span class=\"attr\">input</span>=<span class=\"string\">"$emit('update:modelValue', $event.target.value)"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> /></span></span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"></<span class=\"name\">template</span>></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">//例子</span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">UserName</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">v-model:first-name</span>=<span class=\"string\">"first"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">v-model:last-name</span>=<span class=\"string\">"last"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\">/></span></span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">script</span> <span class=\"attr\">setup</span>></span><span class=\"language-javascript\"></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"><span class=\"title function_\">defineProps</span>({</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> <span class=\"attr\">firstName</span>: <span class=\"title class_\">String</span>,</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> <span class=\"attr\">lastName</span>: <span class=\"title class_\">String</span></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\">})</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"><span class=\"title function_\">defineEmits</span>([<span class=\"string\">'update:firstName'</span>, <span class=\"string\">'update:lastName'</span>])</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"></span><span class=\"tag\"></<span class=\"name\">script</span>></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">template</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">input</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">type</span>=<span class=\"string\">"text"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">:value</span>=<span class=\"string\">"firstName"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> @<span class=\"attr\">input</span>=<span class=\"string\">"$emit('update:firstName', $event.target.value)"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> /></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">input</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">type</span>=<span class=\"string\">"text"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> <span class=\"attr\">:value</span>=<span class=\"string\">"lastName"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> @<span class=\"attr\">input</span>=<span class=\"string\">"$emit('update:lastName', $event.target.value)"</span></span></span></span><br><span class=\"line\"><span class=\"tag\"><span class=\"language-xml\"> /></span></span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"></<span class=\"name\">template</span>></span></span></span><br></pre></td></tr></table></figure>\n"},{"title":"文件上传","date":"2023-07-08T02:51:04.000Z","_content":"\n### 一、文件上传方式\n\n#### ●通过formData上传,multipart/form-data方式\n\n```js\nvar formData = new FormData();\nformData.append('file', file);\n```\n\n#### ●通过fileReader读取文件数据,将文件转成base64编码再上传,application/json方式\n\n```js\n// HTML5的新api,兼容性不是特别好,只兼容到了IE10\nconst fr = new FileReader();\nfr.readAsDataURL(file);\nfr.onload = function (event) {\n const data = event.target.result; //此处获取的data是base64格式的数据\n img.src = data;\n // 将data发生给后端\n};\n```\n\n将文件转成base64编码会导致文件体积变大4/3倍,所以不适合大文件,会造成浏览器卡顿\n\n#### ●总结对比下这两种文件上传的方式优缺点\n\n1)multipart/form-data可以传输二进制流,效率较高,Base64需要编码解码,会耗费一定的性能,效率较低。\n2)Base64不受请求方式的限制,灵活度高,http文件二进制流方式传输只能通过multipart/form-data的方式,灵活度低。\n3)因为随着机器性能的提升,小文件通过二进制流传输和字符串传输,我们对这两种方式时间延迟的感知差异并不那么明显,因此大部分情况下我们更多考虑的是灵活性,所以采用Base64编码的情况也就比较多。\n\n### 二、在UI组件中使用\n\n#### ●elementUI\n\n```js\n<el-upload\n ref=\"upload\"\n action\n drag\n :auto-upload=\"true\"\n :http-request=\"fileUpload\"\n :before-upload=\"beforeUpload\"\n :limit=\"1\"\n :file-list=\"fileList\"\n>\n <i class=\"el-icon-upload\"></i>\n <div class=\"el-upload__text\">\n 将文件拖到此处,或<em>点击上传</em>更新文件\n </div>\n <div class=\"el-upload__tip\" slot=\"tip\">\n 上传文件只能为pdf文件\n </div>\n</el-upload>\n\nfileUpload(file) {\n // file 是 element 处理过的 raw 数据,不需要单独保存了\n updateFile(this.row.id, file).then(res => {\n this.$message({\n type: 'success',\n message: '上传文件成功!'\n })\n this.fileList = []\n })\n }\n},\nfunction updateFile(id, file) {\n let param = new FormData()\n // param.append('file', file) // 手动上传\n param.append('file', file.file) // 自动上传\n return request({\n url: `/request/upload-file?id=${id}`,\n method: 'post',\n headers: { 'Content-Type': 'multipart/form-data' },\n data: param\n })\n}\n```\n\n#### ●antd\n\n<https://ant.design/components/upload-cn>\n","source":"_posts/文件上传.md","raw":"---\ntitle: 文件上传\ndate: 2023-07-08 10:51:04\ntags:\ncategories:\n - UI组件\n---\n\n### 一、文件上传方式\n\n#### ●通过formData上传,multipart/form-data方式\n\n```js\nvar formData = new FormData();\nformData.append('file', file);\n```\n\n#### ●通过fileReader读取文件数据,将文件转成base64编码再上传,application/json方式\n\n```js\n// HTML5的新api,兼容性不是特别好,只兼容到了IE10\nconst fr = new FileReader();\nfr.readAsDataURL(file);\nfr.onload = function (event) {\n const data = event.target.result; //此处获取的data是base64格式的数据\n img.src = data;\n // 将data发生给后端\n};\n```\n\n将文件转成base64编码会导致文件体积变大4/3倍,所以不适合大文件,会造成浏览器卡顿\n\n#### ●总结对比下这两种文件上传的方式优缺点\n\n1)multipart/form-data可以传输二进制流,效率较高,Base64需要编码解码,会耗费一定的性能,效率较低。\n2)Base64不受请求方式的限制,灵活度高,http文件二进制流方式传输只能通过multipart/form-data的方式,灵活度低。\n3)因为随着机器性能的提升,小文件通过二进制流传输和字符串传输,我们对这两种方式时间延迟的感知差异并不那么明显,因此大部分情况下我们更多考虑的是灵活性,所以采用Base64编码的情况也就比较多。\n\n### 二、在UI组件中使用\n\n#### ●elementUI\n\n```js\n<el-upload\n ref=\"upload\"\n action\n drag\n :auto-upload=\"true\"\n :http-request=\"fileUpload\"\n :before-upload=\"beforeUpload\"\n :limit=\"1\"\n :file-list=\"fileList\"\n>\n <i class=\"el-icon-upload\"></i>\n <div class=\"el-upload__text\">\n 将文件拖到此处,或<em>点击上传</em>更新文件\n </div>\n <div class=\"el-upload__tip\" slot=\"tip\">\n 上传文件只能为pdf文件\n </div>\n</el-upload>\n\nfileUpload(file) {\n // file 是 element 处理过的 raw 数据,不需要单独保存了\n updateFile(this.row.id, file).then(res => {\n this.$message({\n type: 'success',\n message: '上传文件成功!'\n })\n this.fileList = []\n })\n }\n},\nfunction updateFile(id, file) {\n let param = new FormData()\n // param.append('file', file) // 手动上传\n param.append('file', file.file) // 自动上传\n return request({\n url: `/request/upload-file?id=${id}`,\n method: 'post',\n headers: { 'Content-Type': 'multipart/form-data' },\n data: param\n })\n}\n```\n\n#### ●antd\n\n<https://ant.design/components/upload-cn>\n","slug":"文件上传","published":1,"updated":"2023-07-08T04:30:38.595Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0l000ya9li3npkanum","content":"<h3 id=\"一、文件上传方式\"><a href=\"#一、文件上传方式\" class=\"headerlink\" title=\"一、文件上传方式\"></a>一、文件上传方式</h3><h4 id=\"●通过formData上传,multipart-x2F-form-data方式\"><a href=\"#●通过formData上传,multipart-x2F-form-data方式\" class=\"headerlink\" title=\"●通过formData上传,multipart/form-data方式\"></a>●通过formData上传,multipart/form-data方式</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">var</span> formData = <span class=\"keyword\">new</span> <span class=\"title class_\">FormData</span>();</span><br><span class=\"line\">formData.<span class=\"title function_\">append</span>(<span class=\"string\">'file'</span>, file);</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●通过fileReader读取文件数据,将文件转成base64编码再上传,application-x2F-json方式\"><a href=\"#●通过fileReader读取文件数据,将文件转成base64编码再上传,application-x2F-json方式\" class=\"headerlink\" title=\"●通过fileReader读取文件数据,将文件转成base64编码再上传,application/json方式\"></a>●通过fileReader读取文件数据,将文件转成base64编码再上传,application/json方式</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// HTML5的新api,兼容性不是特别好,只兼容到了IE10</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> fr = <span class=\"keyword\">new</span> <span class=\"title class_\">FileReader</span>();</span><br><span class=\"line\">fr.<span class=\"title function_\">readAsDataURL</span>(file);</span><br><span class=\"line\">fr.<span class=\"property\">onload</span> = <span class=\"keyword\">function</span> (<span class=\"params\">event</span>) {</span><br><span class=\"line\"> <span class=\"keyword\">const</span> data = event.<span class=\"property\">target</span>.<span class=\"property\">result</span>; <span class=\"comment\">//此处获取的data是base64格式的数据</span></span><br><span class=\"line\"> img.<span class=\"property\">src</span> = data;</span><br><span class=\"line\"> <span class=\"comment\">// 将data发生给后端</span></span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p>将文件转成base64编码会导致文件体积变大4/3倍,所以不适合大文件,会造成浏览器卡顿</p>\n<h4 id=\"●总结对比下这两种文件上传的方式优缺点\"><a href=\"#●总结对比下这两种文件上传的方式优缺点\" class=\"headerlink\" title=\"●总结对比下这两种文件上传的方式优缺点\"></a>●总结对比下这两种文件上传的方式优缺点</h4><p>1)multipart/form-data可以传输二进制流,效率较高,Base64需要编码解码,会耗费一定的性能,效率较低。<br>2)Base64不受请求方式的限制,灵活度高,http文件二进制流方式传输只能通过multipart/form-data的方式,灵活度低。<br>3)因为随着机器性能的提升,小文件通过二进制流传输和字符串传输,我们对这两种方式时间延迟的感知差异并不那么明显,因此大部分情况下我们更多考虑的是灵活性,所以采用Base64编码的情况也就比较多。</p>\n<h3 id=\"二、在UI组件中使用\"><a href=\"#二、在UI组件中使用\" class=\"headerlink\" title=\"二、在UI组件中使用\"></a>二、在UI组件中使用</h3><h4 id=\"●elementUI\"><a href=\"#●elementUI\" class=\"headerlink\" title=\"●elementUI\"></a>●elementUI</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><el-upload</span><br><span class=\"line\"> ref=<span class=\"string\">"upload"</span></span><br><span class=\"line\"> action</span><br><span class=\"line\"> drag</span><br><span class=\"line\"> :auto-upload=<span class=\"string\">"true"</span></span><br><span class=\"line\"> :http-request=<span class=\"string\">"fileUpload"</span></span><br><span class=\"line\"> :before-upload=<span class=\"string\">"beforeUpload"</span></span><br><span class=\"line\"> :limit=<span class=\"string\">"1"</span></span><br><span class=\"line\"> :file-list=<span class=\"string\">"fileList"</span></span><br><span class=\"line\">></span><br><span class=\"line\"> <span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">i</span> <span class=\"attr\">class</span>=<span class=\"string\">"el-icon-upload"</span>></span><span class=\"tag\"></<span class=\"name\">i</span>></span></span></span><br><span class=\"line\"> <span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"el-upload__text"</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> 将文件拖到此处,或<span class=\"tag\"><<span class=\"name\">em</span>></span>点击上传<span class=\"tag\"></<span class=\"name\">em</span>></span>更新文件</span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span></span><br><span class=\"line\"> <span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"el-upload__tip"</span> <span class=\"attr\">slot</span>=<span class=\"string\">"tip"</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> 上传文件只能为pdf文件</span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span></span><br><span class=\"line\"></el-upload></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"title function_\">fileUpload</span>(<span class=\"params\">file</span>) {</span><br><span class=\"line\"> <span class=\"comment\">// file 是 element 处理过的 raw 数据,不需要单独保存了</span></span><br><span class=\"line\"> <span class=\"title function_\">updateFile</span>(<span class=\"variable language_\">this</span>.<span class=\"property\">row</span>.<span class=\"property\">id</span>, file).<span class=\"title function_\">then</span>(<span class=\"function\"><span class=\"params\">res</span> =></span> {</span><br><span class=\"line\"> <span class=\"variable language_\">this</span>.$message({</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'success'</span>,</span><br><span class=\"line\"> <span class=\"attr\">message</span>: <span class=\"string\">'上传文件成功!'</span></span><br><span class=\"line\"> })</span><br><span class=\"line\"> <span class=\"variable language_\">this</span>.<span class=\"property\">fileList</span> = []</span><br><span class=\"line\"> })</span><br><span class=\"line\"> }</span><br><span class=\"line\">},</span><br><span class=\"line\"><span class=\"keyword\">function</span> <span class=\"title function_\">updateFile</span>(<span class=\"params\">id, file</span>) {</span><br><span class=\"line\"> <span class=\"keyword\">let</span> param = <span class=\"keyword\">new</span> <span class=\"title class_\">FormData</span>()</span><br><span class=\"line\"> <span class=\"comment\">// param.append('file', file) // 手动上传</span></span><br><span class=\"line\"> param.<span class=\"title function_\">append</span>(<span class=\"string\">'file'</span>, file.<span class=\"property\">file</span>) <span class=\"comment\">// 自动上传</span></span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"title function_\">request</span>({</span><br><span class=\"line\"> <span class=\"attr\">url</span>: <span class=\"string\">`/request/upload-file?id=<span class=\"subst\">${id}</span>`</span>,</span><br><span class=\"line\"> <span class=\"attr\">method</span>: <span class=\"string\">'post'</span>,</span><br><span class=\"line\"> <span class=\"attr\">headers</span>: { <span class=\"string\">'Content-Type'</span>: <span class=\"string\">'multipart/form-data'</span> },</span><br><span class=\"line\"> <span class=\"attr\">data</span>: param</span><br><span class=\"line\"> })</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●antd\"><a href=\"#●antd\" class=\"headerlink\" title=\"●antd\"></a>●antd</h4><p><a href=\"https://ant.design/components/upload-cn\">https://ant.design/components/upload-cn</a></p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"一、文件上传方式\"><a href=\"#一、文件上传方式\" class=\"headerlink\" title=\"一、文件上传方式\"></a>一、文件上传方式</h3><h4 id=\"●通过formData上传,multipart-x2F-form-data方式\"><a href=\"#●通过formData上传,multipart-x2F-form-data方式\" class=\"headerlink\" title=\"●通过formData上传,multipart/form-data方式\"></a>●通过formData上传,multipart/form-data方式</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">var</span> formData = <span class=\"keyword\">new</span> <span class=\"title class_\">FormData</span>();</span><br><span class=\"line\">formData.<span class=\"title function_\">append</span>(<span class=\"string\">'file'</span>, file);</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●通过fileReader读取文件数据,将文件转成base64编码再上传,application-x2F-json方式\"><a href=\"#●通过fileReader读取文件数据,将文件转成base64编码再上传,application-x2F-json方式\" class=\"headerlink\" title=\"●通过fileReader读取文件数据,将文件转成base64编码再上传,application/json方式\"></a>●通过fileReader读取文件数据,将文件转成base64编码再上传,application/json方式</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// HTML5的新api,兼容性不是特别好,只兼容到了IE10</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> fr = <span class=\"keyword\">new</span> <span class=\"title class_\">FileReader</span>();</span><br><span class=\"line\">fr.<span class=\"title function_\">readAsDataURL</span>(file);</span><br><span class=\"line\">fr.<span class=\"property\">onload</span> = <span class=\"keyword\">function</span> (<span class=\"params\">event</span>) {</span><br><span class=\"line\"> <span class=\"keyword\">const</span> data = event.<span class=\"property\">target</span>.<span class=\"property\">result</span>; <span class=\"comment\">//此处获取的data是base64格式的数据</span></span><br><span class=\"line\"> img.<span class=\"property\">src</span> = data;</span><br><span class=\"line\"> <span class=\"comment\">// 将data发生给后端</span></span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p>将文件转成base64编码会导致文件体积变大4/3倍,所以不适合大文件,会造成浏览器卡顿</p>\n<h4 id=\"●总结对比下这两种文件上传的方式优缺点\"><a href=\"#●总结对比下这两种文件上传的方式优缺点\" class=\"headerlink\" title=\"●总结对比下这两种文件上传的方式优缺点\"></a>●总结对比下这两种文件上传的方式优缺点</h4><p>1)multipart/form-data可以传输二进制流,效率较高,Base64需要编码解码,会耗费一定的性能,效率较低。<br>2)Base64不受请求方式的限制,灵活度高,http文件二进制流方式传输只能通过multipart/form-data的方式,灵活度低。<br>3)因为随着机器性能的提升,小文件通过二进制流传输和字符串传输,我们对这两种方式时间延迟的感知差异并不那么明显,因此大部分情况下我们更多考虑的是灵活性,所以采用Base64编码的情况也就比较多。</p>\n<h3 id=\"二、在UI组件中使用\"><a href=\"#二、在UI组件中使用\" class=\"headerlink\" title=\"二、在UI组件中使用\"></a>二、在UI组件中使用</h3><h4 id=\"●elementUI\"><a href=\"#●elementUI\" class=\"headerlink\" title=\"●elementUI\"></a>●elementUI</h4><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><el-upload</span><br><span class=\"line\"> ref=<span class=\"string\">"upload"</span></span><br><span class=\"line\"> action</span><br><span class=\"line\"> drag</span><br><span class=\"line\"> :auto-upload=<span class=\"string\">"true"</span></span><br><span class=\"line\"> :http-request=<span class=\"string\">"fileUpload"</span></span><br><span class=\"line\"> :before-upload=<span class=\"string\">"beforeUpload"</span></span><br><span class=\"line\"> :limit=<span class=\"string\">"1"</span></span><br><span class=\"line\"> :file-list=<span class=\"string\">"fileList"</span></span><br><span class=\"line\">></span><br><span class=\"line\"> <span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">i</span> <span class=\"attr\">class</span>=<span class=\"string\">"el-icon-upload"</span>></span><span class=\"tag\"></<span class=\"name\">i</span>></span></span></span><br><span class=\"line\"> <span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"el-upload__text"</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> 将文件拖到此处,或<span class=\"tag\"><<span class=\"name\">em</span>></span>点击上传<span class=\"tag\"></<span class=\"name\">em</span>></span>更新文件</span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span></span><br><span class=\"line\"> <span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"el-upload__tip"</span> <span class=\"attr\">slot</span>=<span class=\"string\">"tip"</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> 上传文件只能为pdf文件</span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span></span><br><span class=\"line\"></el-upload></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"title function_\">fileUpload</span>(<span class=\"params\">file</span>) {</span><br><span class=\"line\"> <span class=\"comment\">// file 是 element 处理过的 raw 数据,不需要单独保存了</span></span><br><span class=\"line\"> <span class=\"title function_\">updateFile</span>(<span class=\"variable language_\">this</span>.<span class=\"property\">row</span>.<span class=\"property\">id</span>, file).<span class=\"title function_\">then</span>(<span class=\"function\"><span class=\"params\">res</span> =></span> {</span><br><span class=\"line\"> <span class=\"variable language_\">this</span>.$message({</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'success'</span>,</span><br><span class=\"line\"> <span class=\"attr\">message</span>: <span class=\"string\">'上传文件成功!'</span></span><br><span class=\"line\"> })</span><br><span class=\"line\"> <span class=\"variable language_\">this</span>.<span class=\"property\">fileList</span> = []</span><br><span class=\"line\"> })</span><br><span class=\"line\"> }</span><br><span class=\"line\">},</span><br><span class=\"line\"><span class=\"keyword\">function</span> <span class=\"title function_\">updateFile</span>(<span class=\"params\">id, file</span>) {</span><br><span class=\"line\"> <span class=\"keyword\">let</span> param = <span class=\"keyword\">new</span> <span class=\"title class_\">FormData</span>()</span><br><span class=\"line\"> <span class=\"comment\">// param.append('file', file) // 手动上传</span></span><br><span class=\"line\"> param.<span class=\"title function_\">append</span>(<span class=\"string\">'file'</span>, file.<span class=\"property\">file</span>) <span class=\"comment\">// 自动上传</span></span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"title function_\">request</span>({</span><br><span class=\"line\"> <span class=\"attr\">url</span>: <span class=\"string\">`/request/upload-file?id=<span class=\"subst\">${id}</span>`</span>,</span><br><span class=\"line\"> <span class=\"attr\">method</span>: <span class=\"string\">'post'</span>,</span><br><span class=\"line\"> <span class=\"attr\">headers</span>: { <span class=\"string\">'Content-Type'</span>: <span class=\"string\">'multipart/form-data'</span> },</span><br><span class=\"line\"> <span class=\"attr\">data</span>: param</span><br><span class=\"line\"> })</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"●antd\"><a href=\"#●antd\" class=\"headerlink\" title=\"●antd\"></a>●antd</h4><p><a href=\"https://ant.design/components/upload-cn\">https://ant.design/components/upload-cn</a></p>\n"},{"title":"前端无感刷新token","_content":"\n## 目前存在的问题\n\ntoken因为考虑到安全性问题(token关系着用户的个人信息等相关资料),设置有一定时间的生命周期。当用户在已经登录后出现token过期,发送\n后端请求会返回401状态码,一般情况前端会重定向路由到登录页让用户重新登录。但是这样体验不佳。比如你刚填写完表单一大堆信息的情况下,点击提交按钮,\n但是因为token过期了,页面跳转到登录页,就是信息白填了。。。。为了优化这个体验,refreshToken就诞生了\n\n## 什么是无感刷新token\n\n两种token\n\n- requestToken\n 这个token是关系这用户个人信息的token,设置在请求头中,用于鉴权,一般设置比较短的生命周期\n- refreshToken\n 这个token是为了更新过期的requestToken,一般会设置较长的生命周期,如果是数据都保存在服务器的话可以设置永不过期\n\n当token过期,也就是出现状态码401时,可以调用通过refreshToken发送请求更新requestToken,然后再次发送刚才出现401状态码的请求,不需要用户再次重新登录\n\n## 怎么做\n\n- 在拦截器响应那里处理出现401状态码的请求\n\n```js\n// 设置一个变量isRefreshing,当出现多个并发请求时,只需要一个请求去发送刷新token的请求就满足了\nlet isRefreshing = false\n// 设置一个数据用于保存没有发送请求成功的请求,再获取到新token时再更新token重新发送\nlet requests = []\naxios.interceptors.response.use((res) => {\n return Promise.resolve(res.data)\n},(error) => {\n let { data, config } = error.response\n if(data.status === 401){\n handle401(error)\n }\n})\n\nconst handle401 = (error) => {\n let { data, config } = error.response\n if(config.url === '/api/token/refreshToken' || Number(data.errorCode) !== 1107){\n //这里处理refreshToken也失效了的情况,或者不是 token 过期的情况,可能是token无效或者异地登录之类的,不需要刷新token,直接退出到登录页\n window.location.href = 'XXX/login'\n }else{\n // 保存下来失败的请求\n const promise = new Promise((resolve, reject) => {\n requests.push(async () => {\n try {\n const rs = await axios(config);\n resolve(rs)\n } catch (e) {\n reject(e)\n }\n })\n })\n if(isRefreshing){\n return promise\n }else{\n isRefreshing = true\n // 发送刷新token请求\n const res = await axios({\n url: refreshTokenAPI,\n method: 'get',\n headers: {\n 'X-Authorization': refreshToken,\n }\n })\n\n if (Number(res.errorCode) !== 1000) {\n throw new Error('refresh failed')\n }\n\n const newToken = res.data;\n\n cookie.set('token', newToken, {\n domain: syncUserInfo.getDomain(),\n expires: 365,\n sameSite: 'strict',\n })\n requests.forEach(cb => cb())\n requests = []\n }\n }\n}\n```\n","source":"_posts/无感刷新token.md","raw":"---\ntitle: 前端无感刷新token\ntags:\ncategories:\n - 性能优化\n---\n\n## 目前存在的问题\n\ntoken因为考虑到安全性问题(token关系着用户的个人信息等相关资料),设置有一定时间的生命周期。当用户在已经登录后出现token过期,发送\n后端请求会返回401状态码,一般情况前端会重定向路由到登录页让用户重新登录。但是这样体验不佳。比如你刚填写完表单一大堆信息的情况下,点击提交按钮,\n但是因为token过期了,页面跳转到登录页,就是信息白填了。。。。为了优化这个体验,refreshToken就诞生了\n\n## 什么是无感刷新token\n\n两种token\n\n- requestToken\n 这个token是关系这用户个人信息的token,设置在请求头中,用于鉴权,一般设置比较短的生命周期\n- refreshToken\n 这个token是为了更新过期的requestToken,一般会设置较长的生命周期,如果是数据都保存在服务器的话可以设置永不过期\n\n当token过期,也就是出现状态码401时,可以调用通过refreshToken发送请求更新requestToken,然后再次发送刚才出现401状态码的请求,不需要用户再次重新登录\n\n## 怎么做\n\n- 在拦截器响应那里处理出现401状态码的请求\n\n```js\n// 设置一个变量isRefreshing,当出现多个并发请求时,只需要一个请求去发送刷新token的请求就满足了\nlet isRefreshing = false\n// 设置一个数据用于保存没有发送请求成功的请求,再获取到新token时再更新token重新发送\nlet requests = []\naxios.interceptors.response.use((res) => {\n return Promise.resolve(res.data)\n},(error) => {\n let { data, config } = error.response\n if(data.status === 401){\n handle401(error)\n }\n})\n\nconst handle401 = (error) => {\n let { data, config } = error.response\n if(config.url === '/api/token/refreshToken' || Number(data.errorCode) !== 1107){\n //这里处理refreshToken也失效了的情况,或者不是 token 过期的情况,可能是token无效或者异地登录之类的,不需要刷新token,直接退出到登录页\n window.location.href = 'XXX/login'\n }else{\n // 保存下来失败的请求\n const promise = new Promise((resolve, reject) => {\n requests.push(async () => {\n try {\n const rs = await axios(config);\n resolve(rs)\n } catch (e) {\n reject(e)\n }\n })\n })\n if(isRefreshing){\n return promise\n }else{\n isRefreshing = true\n // 发送刷新token请求\n const res = await axios({\n url: refreshTokenAPI,\n method: 'get',\n headers: {\n 'X-Authorization': refreshToken,\n }\n })\n\n if (Number(res.errorCode) !== 1000) {\n throw new Error('refresh failed')\n }\n\n const newToken = res.data;\n\n cookie.set('token', newToken, {\n domain: syncUserInfo.getDomain(),\n expires: 365,\n sameSite: 'strict',\n })\n requests.forEach(cb => cb())\n requests = []\n }\n }\n}\n```\n","slug":"无感刷新token","published":1,"date":"2023-07-16T08:37:33.619Z","updated":"2023-07-16T10:28:17.733Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0m0010a9lih80whz1a","content":"<h2 id=\"目前存在的问题\"><a href=\"#目前存在的问题\" class=\"headerlink\" title=\"目前存在的问题\"></a>目前存在的问题</h2><p>token因为考虑到安全性问题(token关系着用户的个人信息等相关资料),设置有一定时间的生命周期。当用户在已经登录后出现token过期,发送<br>后端请求会返回401状态码,一般情况前端会重定向路由到登录页让用户重新登录。但是这样体验不佳。比如你刚填写完表单一大堆信息的情况下,点击提交按钮,<br>但是因为token过期了,页面跳转到登录页,就是信息白填了。。。。为了优化这个体验,refreshToken就诞生了</p>\n<h2 id=\"什么是无感刷新token\"><a href=\"#什么是无感刷新token\" class=\"headerlink\" title=\"什么是无感刷新token\"></a>什么是无感刷新token</h2><p>两种token</p>\n<ul>\n<li>requestToken<br>这个token是关系这用户个人信息的token,设置在请求头中,用于鉴权,一般设置比较短的生命周期</li>\n<li>refreshToken<br>这个token是为了更新过期的requestToken,一般会设置较长的生命周期,如果是数据都保存在服务器的话可以设置永不过期</li>\n</ul>\n<p>当token过期,也就是出现状态码401时,可以调用通过refreshToken发送请求更新requestToken,然后再次发送刚才出现401状态码的请求,不需要用户再次重新登录</p>\n<h2 id=\"怎么做\"><a href=\"#怎么做\" class=\"headerlink\" title=\"怎么做\"></a>怎么做</h2><ul>\n<li>在拦截器响应那里处理出现401状态码的请求</li>\n</ul>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 设置一个变量isRefreshing,当出现多个并发请求时,只需要一个请求去发送刷新token的请求就满足了</span></span><br><span class=\"line\"><span class=\"keyword\">let</span> isRefreshing = <span class=\"literal\">false</span></span><br><span class=\"line\"><span class=\"comment\">// 设置一个数据用于保存没有发送请求成功的请求,再获取到新token时再更新token重新发送</span></span><br><span class=\"line\"><span class=\"keyword\">let</span> requests = []</span><br><span class=\"line\">axios.<span class=\"property\">interceptors</span>.<span class=\"property\">response</span>.<span class=\"title function_\">use</span>(<span class=\"function\">(<span class=\"params\">res</span>) =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"title class_\">Promise</span>.<span class=\"title function_\">resolve</span>(res.<span class=\"property\">data</span>)</span><br><span class=\"line\">},<span class=\"function\">(<span class=\"params\">error</span>) =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">let</span> { data, config } = error.<span class=\"property\">response</span></span><br><span class=\"line\"> <span class=\"keyword\">if</span>(data.<span class=\"property\">status</span> === <span class=\"number\">401</span>){</span><br><span class=\"line\"> <span class=\"title function_\">handle401</span>(error)</span><br><span class=\"line\"> }</span><br><span class=\"line\">})</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title function_\">handle401</span> = (<span class=\"params\">error</span>) => {</span><br><span class=\"line\"> <span class=\"keyword\">let</span> { data, config } = error.<span class=\"property\">response</span></span><br><span class=\"line\"> <span class=\"keyword\">if</span>(config.<span class=\"property\">url</span> === <span class=\"string\">'/api/token/refreshToken'</span> || <span class=\"title class_\">Number</span>(data.<span class=\"property\">errorCode</span>) !== <span class=\"number\">1107</span>){</span><br><span class=\"line\"> <span class=\"comment\">//这里处理refreshToken也失效了的情况,或者不是 token 过期的情况,可能是token无效或者异地登录之类的,不需要刷新token,直接退出到登录页</span></span><br><span class=\"line\"> <span class=\"variable language_\">window</span>.<span class=\"property\">location</span>.<span class=\"property\">href</span> = <span class=\"string\">'XXX/login'</span></span><br><span class=\"line\"> }<span class=\"keyword\">else</span>{</span><br><span class=\"line\"> <span class=\"comment\">// 保存下来失败的请求</span></span><br><span class=\"line\"> <span class=\"keyword\">const</span> promise = <span class=\"keyword\">new</span> <span class=\"title class_\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\"> requests.<span class=\"title function_\">push</span>(<span class=\"keyword\">async</span> () => {</span><br><span class=\"line\"> <span class=\"keyword\">try</span> {</span><br><span class=\"line\"> <span class=\"keyword\">const</span> rs = <span class=\"keyword\">await</span> <span class=\"title function_\">axios</span>(config);</span><br><span class=\"line\"> <span class=\"title function_\">resolve</span>(rs)</span><br><span class=\"line\"> } <span class=\"keyword\">catch</span> (e) {</span><br><span class=\"line\"> <span class=\"title function_\">reject</span>(e)</span><br><span class=\"line\"> }</span><br><span class=\"line\"> })</span><br><span class=\"line\"> })</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(isRefreshing){</span><br><span class=\"line\"> <span class=\"keyword\">return</span> promise</span><br><span class=\"line\"> }<span class=\"keyword\">else</span>{</span><br><span class=\"line\"> isRefreshing = <span class=\"literal\">true</span></span><br><span class=\"line\"> <span class=\"comment\">// 发送刷新token请求</span></span><br><span class=\"line\"> <span class=\"keyword\">const</span> res = <span class=\"keyword\">await</span> <span class=\"title function_\">axios</span>({</span><br><span class=\"line\"> <span class=\"attr\">url</span>: refreshTokenAPI,</span><br><span class=\"line\"> <span class=\"attr\">method</span>: <span class=\"string\">'get'</span>,</span><br><span class=\"line\"> <span class=\"attr\">headers</span>: {</span><br><span class=\"line\"> <span class=\"string\">'X-Authorization'</span>: refreshToken,</span><br><span class=\"line\"> }</span><br><span class=\"line\"> })</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">if</span> (<span class=\"title class_\">Number</span>(res.<span class=\"property\">errorCode</span>) !== <span class=\"number\">1000</span>) {</span><br><span class=\"line\"> <span class=\"keyword\">throw</span> <span class=\"keyword\">new</span> <span class=\"title class_\">Error</span>(<span class=\"string\">'refresh failed'</span>)</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">const</span> newToken = res.<span class=\"property\">data</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> cookie.<span class=\"title function_\">set</span>(<span class=\"string\">'token'</span>, newToken, {</span><br><span class=\"line\"> <span class=\"attr\">domain</span>: syncUserInfo.<span class=\"title function_\">getDomain</span>(),</span><br><span class=\"line\"> <span class=\"attr\">expires</span>: <span class=\"number\">365</span>,</span><br><span class=\"line\"> <span class=\"attr\">sameSite</span>: <span class=\"string\">'strict'</span>,</span><br><span class=\"line\"> })</span><br><span class=\"line\"> requests.<span class=\"title function_\">forEach</span>(<span class=\"function\"><span class=\"params\">cb</span> =></span> <span class=\"title function_\">cb</span>())</span><br><span class=\"line\"> requests = []</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h2 id=\"目前存在的问题\"><a href=\"#目前存在的问题\" class=\"headerlink\" title=\"目前存在的问题\"></a>目前存在的问题</h2><p>token因为考虑到安全性问题(token关系着用户的个人信息等相关资料),设置有一定时间的生命周期。当用户在已经登录后出现token过期,发送<br>后端请求会返回401状态码,一般情况前端会重定向路由到登录页让用户重新登录。但是这样体验不佳。比如你刚填写完表单一大堆信息的情况下,点击提交按钮,<br>但是因为token过期了,页面跳转到登录页,就是信息白填了。。。。为了优化这个体验,refreshToken就诞生了</p>\n<h2 id=\"什么是无感刷新token\"><a href=\"#什么是无感刷新token\" class=\"headerlink\" title=\"什么是无感刷新token\"></a>什么是无感刷新token</h2><p>两种token</p>\n<ul>\n<li>requestToken<br>这个token是关系这用户个人信息的token,设置在请求头中,用于鉴权,一般设置比较短的生命周期</li>\n<li>refreshToken<br>这个token是为了更新过期的requestToken,一般会设置较长的生命周期,如果是数据都保存在服务器的话可以设置永不过期</li>\n</ul>\n<p>当token过期,也就是出现状态码401时,可以调用通过refreshToken发送请求更新requestToken,然后再次发送刚才出现401状态码的请求,不需要用户再次重新登录</p>\n<h2 id=\"怎么做\"><a href=\"#怎么做\" class=\"headerlink\" title=\"怎么做\"></a>怎么做</h2><ul>\n<li>在拦截器响应那里处理出现401状态码的请求</li>\n</ul>\n<figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 设置一个变量isRefreshing,当出现多个并发请求时,只需要一个请求去发送刷新token的请求就满足了</span></span><br><span class=\"line\"><span class=\"keyword\">let</span> isRefreshing = <span class=\"literal\">false</span></span><br><span class=\"line\"><span class=\"comment\">// 设置一个数据用于保存没有发送请求成功的请求,再获取到新token时再更新token重新发送</span></span><br><span class=\"line\"><span class=\"keyword\">let</span> requests = []</span><br><span class=\"line\">axios.<span class=\"property\">interceptors</span>.<span class=\"property\">response</span>.<span class=\"title function_\">use</span>(<span class=\"function\">(<span class=\"params\">res</span>) =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"title class_\">Promise</span>.<span class=\"title function_\">resolve</span>(res.<span class=\"property\">data</span>)</span><br><span class=\"line\">},<span class=\"function\">(<span class=\"params\">error</span>) =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">let</span> { data, config } = error.<span class=\"property\">response</span></span><br><span class=\"line\"> <span class=\"keyword\">if</span>(data.<span class=\"property\">status</span> === <span class=\"number\">401</span>){</span><br><span class=\"line\"> <span class=\"title function_\">handle401</span>(error)</span><br><span class=\"line\"> }</span><br><span class=\"line\">})</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> <span class=\"title function_\">handle401</span> = (<span class=\"params\">error</span>) => {</span><br><span class=\"line\"> <span class=\"keyword\">let</span> { data, config } = error.<span class=\"property\">response</span></span><br><span class=\"line\"> <span class=\"keyword\">if</span>(config.<span class=\"property\">url</span> === <span class=\"string\">'/api/token/refreshToken'</span> || <span class=\"title class_\">Number</span>(data.<span class=\"property\">errorCode</span>) !== <span class=\"number\">1107</span>){</span><br><span class=\"line\"> <span class=\"comment\">//这里处理refreshToken也失效了的情况,或者不是 token 过期的情况,可能是token无效或者异地登录之类的,不需要刷新token,直接退出到登录页</span></span><br><span class=\"line\"> <span class=\"variable language_\">window</span>.<span class=\"property\">location</span>.<span class=\"property\">href</span> = <span class=\"string\">'XXX/login'</span></span><br><span class=\"line\"> }<span class=\"keyword\">else</span>{</span><br><span class=\"line\"> <span class=\"comment\">// 保存下来失败的请求</span></span><br><span class=\"line\"> <span class=\"keyword\">const</span> promise = <span class=\"keyword\">new</span> <span class=\"title class_\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\"> requests.<span class=\"title function_\">push</span>(<span class=\"keyword\">async</span> () => {</span><br><span class=\"line\"> <span class=\"keyword\">try</span> {</span><br><span class=\"line\"> <span class=\"keyword\">const</span> rs = <span class=\"keyword\">await</span> <span class=\"title function_\">axios</span>(config);</span><br><span class=\"line\"> <span class=\"title function_\">resolve</span>(rs)</span><br><span class=\"line\"> } <span class=\"keyword\">catch</span> (e) {</span><br><span class=\"line\"> <span class=\"title function_\">reject</span>(e)</span><br><span class=\"line\"> }</span><br><span class=\"line\"> })</span><br><span class=\"line\"> })</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(isRefreshing){</span><br><span class=\"line\"> <span class=\"keyword\">return</span> promise</span><br><span class=\"line\"> }<span class=\"keyword\">else</span>{</span><br><span class=\"line\"> isRefreshing = <span class=\"literal\">true</span></span><br><span class=\"line\"> <span class=\"comment\">// 发送刷新token请求</span></span><br><span class=\"line\"> <span class=\"keyword\">const</span> res = <span class=\"keyword\">await</span> <span class=\"title function_\">axios</span>({</span><br><span class=\"line\"> <span class=\"attr\">url</span>: refreshTokenAPI,</span><br><span class=\"line\"> <span class=\"attr\">method</span>: <span class=\"string\">'get'</span>,</span><br><span class=\"line\"> <span class=\"attr\">headers</span>: {</span><br><span class=\"line\"> <span class=\"string\">'X-Authorization'</span>: refreshToken,</span><br><span class=\"line\"> }</span><br><span class=\"line\"> })</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">if</span> (<span class=\"title class_\">Number</span>(res.<span class=\"property\">errorCode</span>) !== <span class=\"number\">1000</span>) {</span><br><span class=\"line\"> <span class=\"keyword\">throw</span> <span class=\"keyword\">new</span> <span class=\"title class_\">Error</span>(<span class=\"string\">'refresh failed'</span>)</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">const</span> newToken = res.<span class=\"property\">data</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> cookie.<span class=\"title function_\">set</span>(<span class=\"string\">'token'</span>, newToken, {</span><br><span class=\"line\"> <span class=\"attr\">domain</span>: syncUserInfo.<span class=\"title function_\">getDomain</span>(),</span><br><span class=\"line\"> <span class=\"attr\">expires</span>: <span class=\"number\">365</span>,</span><br><span class=\"line\"> <span class=\"attr\">sameSite</span>: <span class=\"string\">'strict'</span>,</span><br><span class=\"line\"> })</span><br><span class=\"line\"> requests.<span class=\"title function_\">forEach</span>(<span class=\"function\"><span class=\"params\">cb</span> =></span> <span class=\"title function_\">cb</span>())</span><br><span class=\"line\"> requests = []</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n"},{"title":"枚举","_content":"\n### 枚举基本使用\n\n```js\nenum abc {\n 'one' = 1,\n 'two' = 2,\n 'tree' = 3\n}\n\n```\n\n### 对于某些状态码,状态码代表不同文字、也需要不同颜色,文字和颜色如何一一对应,也可以使用枚举\n\n```js\n// 下面这样做可以使得代码更具语意化\nenum EStatusCode = {\n 'one' = 1,\n 'two' = 2,\n 'tree' = 3\n}\n\nenum EStatusStr = {\n 'one' = '一',\n 'two' = '二',\n 'tree' = '三'\n}\n\nenum EStatusStr = {\n 'one' = 'black',\n 'two' = 'yellow',\n 'tree' = 'pink'\n}\n\nconst statusStr = {\n [EStatusCode.one]: [EStatusStr.one],\n [EStatusCode.two]: [EStatusStr.two]\n}\n\nconst statusColor = {\n [EStatusCode.one]: [EStatusColor.one],\n [EStatusCode.two]: [EStatusColor.two]\n}\n\n```\n","source":"_posts/枚举.md","raw":"---\ntitle: 枚举\ntags:\n---\n\n### 枚举基本使用\n\n```js\nenum abc {\n 'one' = 1,\n 'two' = 2,\n 'tree' = 3\n}\n\n```\n\n### 对于某些状态码,状态码代表不同文字、也需要不同颜色,文字和颜色如何一一对应,也可以使用枚举\n\n```js\n// 下面这样做可以使得代码更具语意化\nenum EStatusCode = {\n 'one' = 1,\n 'two' = 2,\n 'tree' = 3\n}\n\nenum EStatusStr = {\n 'one' = '一',\n 'two' = '二',\n 'tree' = '三'\n}\n\nenum EStatusStr = {\n 'one' = 'black',\n 'two' = 'yellow',\n 'tree' = 'pink'\n}\n\nconst statusStr = {\n [EStatusCode.one]: [EStatusStr.one],\n [EStatusCode.two]: [EStatusStr.two]\n}\n\nconst statusColor = {\n [EStatusCode.one]: [EStatusColor.one],\n [EStatusCode.two]: [EStatusColor.two]\n}\n\n```\n","slug":"枚举","published":1,"date":"2023-12-25T06:56:09.366Z","updated":"2023-12-25T07:03:13.554Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0n0012a9li2jr95l20","content":"<h3 id=\"枚举基本使用\"><a href=\"#枚举基本使用\" class=\"headerlink\" title=\"枚举基本使用\"></a>枚举基本使用</h3><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">enum abc {</span><br><span class=\"line\"> <span class=\"string\">'one'</span> = <span class=\"number\">1</span>,</span><br><span class=\"line\"> <span class=\"string\">'two'</span> = <span class=\"number\">2</span>,</span><br><span class=\"line\"> <span class=\"string\">'tree'</span> = <span class=\"number\">3</span></span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"对于某些状态码,状态码代表不同文字、也需要不同颜色,文字和颜色如何一一对应,也可以使用枚举\"><a href=\"#对于某些状态码,状态码代表不同文字、也需要不同颜色,文字和颜色如何一一对应,也可以使用枚举\" class=\"headerlink\" title=\"对于某些状态码,状态码代表不同文字、也需要不同颜色,文字和颜色如何一一对应,也可以使用枚举\"></a>对于某些状态码,状态码代表不同文字、也需要不同颜色,文字和颜色如何一一对应,也可以使用枚举</h3><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 下面这样做可以使得代码更具语意化</span></span><br><span class=\"line\">enum <span class=\"title class_\">EStatusCode</span> = {</span><br><span class=\"line\"> <span class=\"string\">'one'</span> = <span class=\"number\">1</span>,</span><br><span class=\"line\"> <span class=\"string\">'two'</span> = <span class=\"number\">2</span>,</span><br><span class=\"line\"> <span class=\"string\">'tree'</span> = <span class=\"number\">3</span></span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">enum <span class=\"title class_\">EStatusStr</span> = {</span><br><span class=\"line\"> <span class=\"string\">'one'</span> = <span class=\"string\">'一'</span>,</span><br><span class=\"line\"> <span class=\"string\">'two'</span> = <span class=\"string\">'二'</span>,</span><br><span class=\"line\"> <span class=\"string\">'tree'</span> = <span class=\"string\">'三'</span></span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">enum <span class=\"title class_\">EStatusStr</span> = {</span><br><span class=\"line\"> <span class=\"string\">'one'</span> = <span class=\"string\">'black'</span>,</span><br><span class=\"line\"> <span class=\"string\">'two'</span> = <span class=\"string\">'yellow'</span>,</span><br><span class=\"line\"> <span class=\"string\">'tree'</span> = <span class=\"string\">'pink'</span></span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> statusStr = {</span><br><span class=\"line\"> [<span class=\"title class_\">EStatusCode</span>.<span class=\"property\">one</span>]: [<span class=\"title class_\">EStatusStr</span>.<span class=\"property\">one</span>],</span><br><span class=\"line\"> [<span class=\"title class_\">EStatusCode</span>.<span class=\"property\">two</span>]: [<span class=\"title class_\">EStatusStr</span>.<span class=\"property\">two</span>]</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> statusColor = {</span><br><span class=\"line\"> [<span class=\"title class_\">EStatusCode</span>.<span class=\"property\">one</span>]: [<span class=\"title class_\">EStatusColor</span>.<span class=\"property\">one</span>],</span><br><span class=\"line\"> [<span class=\"title class_\">EStatusCode</span>.<span class=\"property\">two</span>]: [<span class=\"title class_\">EStatusColor</span>.<span class=\"property\">two</span>]</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br></pre></td></tr></table></figure>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"枚举基本使用\"><a href=\"#枚举基本使用\" class=\"headerlink\" title=\"枚举基本使用\"></a>枚举基本使用</h3><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">enum abc {</span><br><span class=\"line\"> <span class=\"string\">'one'</span> = <span class=\"number\">1</span>,</span><br><span class=\"line\"> <span class=\"string\">'two'</span> = <span class=\"number\">2</span>,</span><br><span class=\"line\"> <span class=\"string\">'tree'</span> = <span class=\"number\">3</span></span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"对于某些状态码,状态码代表不同文字、也需要不同颜色,文字和颜色如何一一对应,也可以使用枚举\"><a href=\"#对于某些状态码,状态码代表不同文字、也需要不同颜色,文字和颜色如何一一对应,也可以使用枚举\" class=\"headerlink\" title=\"对于某些状态码,状态码代表不同文字、也需要不同颜色,文字和颜色如何一一对应,也可以使用枚举\"></a>对于某些状态码,状态码代表不同文字、也需要不同颜色,文字和颜色如何一一对应,也可以使用枚举</h3><figure class=\"highlight js\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 下面这样做可以使得代码更具语意化</span></span><br><span class=\"line\">enum <span class=\"title class_\">EStatusCode</span> = {</span><br><span class=\"line\"> <span class=\"string\">'one'</span> = <span class=\"number\">1</span>,</span><br><span class=\"line\"> <span class=\"string\">'two'</span> = <span class=\"number\">2</span>,</span><br><span class=\"line\"> <span class=\"string\">'tree'</span> = <span class=\"number\">3</span></span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">enum <span class=\"title class_\">EStatusStr</span> = {</span><br><span class=\"line\"> <span class=\"string\">'one'</span> = <span class=\"string\">'一'</span>,</span><br><span class=\"line\"> <span class=\"string\">'two'</span> = <span class=\"string\">'二'</span>,</span><br><span class=\"line\"> <span class=\"string\">'tree'</span> = <span class=\"string\">'三'</span></span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">enum <span class=\"title class_\">EStatusStr</span> = {</span><br><span class=\"line\"> <span class=\"string\">'one'</span> = <span class=\"string\">'black'</span>,</span><br><span class=\"line\"> <span class=\"string\">'two'</span> = <span class=\"string\">'yellow'</span>,</span><br><span class=\"line\"> <span class=\"string\">'tree'</span> = <span class=\"string\">'pink'</span></span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> statusStr = {</span><br><span class=\"line\"> [<span class=\"title class_\">EStatusCode</span>.<span class=\"property\">one</span>]: [<span class=\"title class_\">EStatusStr</span>.<span class=\"property\">one</span>],</span><br><span class=\"line\"> [<span class=\"title class_\">EStatusCode</span>.<span class=\"property\">two</span>]: [<span class=\"title class_\">EStatusStr</span>.<span class=\"property\">two</span>]</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> statusColor = {</span><br><span class=\"line\"> [<span class=\"title class_\">EStatusCode</span>.<span class=\"property\">one</span>]: [<span class=\"title class_\">EStatusColor</span>.<span class=\"property\">one</span>],</span><br><span class=\"line\"> [<span class=\"title class_\">EStatusCode</span>.<span class=\"property\">two</span>]: [<span class=\"title class_\">EStatusColor</span>.<span class=\"property\">two</span>]</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br></pre></td></tr></table></figure>\n"},{"title":"正则","date":"2023-07-08T02:37:52.000Z","_content":"\n### 一、基本规则\n\n1、\\转意符 \\d表示数字\n2、\\* 匹配0~n个\n3、+至少匹配1个\n4、{n,m}匹配n~m个\n5、?匹配0~1个\n6、^开头,$结尾\n7、[abcd] 匹配方括号中任意字符\n\n### 二、常用例子\n\n1、国内手机号码校验(11位,一般匹配位数就好\n^1[34578]\\d{9}$\n2、\n","source":"_posts/正则.md","raw":"---\ntitle: 正则\ndate: 2023-07-08 10:37:52\ntags:\ncategories:\n - 插件使用\n---\n\n### 一、基本规则\n\n1、\\转意符 \\d表示数字\n2、\\* 匹配0~n个\n3、+至少匹配1个\n4、{n,m}匹配n~m个\n5、?匹配0~1个\n6、^开头,$结尾\n7、[abcd] 匹配方括号中任意字符\n\n### 二、常用例子\n\n1、国内手机号码校验(11位,一般匹配位数就好\n^1[34578]\\d{9}$\n2、\n","slug":"正则","published":1,"updated":"2023-07-08T04:30:38.595Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clvyz4r0p0015a9li12sthzkd","content":"<h3 id=\"一、基本规则\"><a href=\"#一、基本规则\" class=\"headerlink\" title=\"一、基本规则\"></a>一、基本规则</h3><p>1、\\转意符 \\d表示数字<br>2、* 匹配0~n个<br>3、+至少匹配1个<br>4、{n,m}匹配n~m个<br>5、?匹配0~1个<br>6、^开头,$结尾<br>7、[abcd] 匹配方括号中任意字符</p>\n<h3 id=\"二、常用例子\"><a href=\"#二、常用例子\" class=\"headerlink\" title=\"二、常用例子\"></a>二、常用例子</h3><p>1、国内手机号码校验(11位,一般匹配位数就好<br>^1[34578]\\d{9}$<br>2、</p>\n","site":{"data":{}},"cover":false,"excerpt":"","more":"<h3 id=\"一、基本规则\"><a href=\"#一、基本规则\" class=\"headerlink\" title=\"一、基本规则\"></a>一、基本规则</h3><p>1、\\转意符 \\d表示数字<br>2、* 匹配0~n个<br>3、+至少匹配1个<br>4、{n,m}匹配n~m个<br>5、?匹配0~1个<br>6、^开头,$结尾<br>7、[abcd] 匹配方括号中任意字符</p>\n<h3 id=\"二、常用例子\"><a href=\"#二、常用例子\" class=\"headerlink\" title=\"二、常用例子\"></a>二、常用例子</h3><p>1、国内手机号码校验(11位,一般匹配位数就好<br>^1[34578]\\d{9}$<br>2、</p>\n"}],"PostAsset":[],"PostCategory":[{"post_id":"clvyz4qzu0001a9libld10tob","category_id":"clvyz4r010004a9liahasavcd","_id":"clvyz4r0a000da9li5lk78q7p"},{"post_id":"clvyz4qzz0003a9libcdvdhbp","category_id":"clvyz4r060009a9li57k60iuf","_id":"clvyz4r0d000ha9li1dvahvs8"},{"post_id":"clvyz4r09000ca9li4zvd4cao","category_id":"clvyz4r060009a9li57k60iuf","_id":"clvyz4r0e000la9li8denbsgi"},{"post_id":"clvyz4r040007a9li5icxggd8","category_id":"clvyz4r0a000ea9libg6ggbzh","_id":"clvyz4r0f000na9lia4fh9gh1"},{"post_id":"clvyz4r050008a9liftcy45bf","category_id":"clvyz4r0d000ia9lidlqzbrgg","_id":"clvyz4r0i000ra9libxpx2624"},{"post_id":"clvyz4r0h000qa9li304m2oqx","category_id":"clvyz4r0f000oa9lie44x0c2e","_id":"clvyz4r0k000wa9li6p6ubzdr"},{"post_id":"clvyz4r07000aa9ligv1hfzmq","category_id":"clvyz4r0f000oa9lie44x0c2e","_id":"clvyz4r0m000za9li612hg3gk"},{"post_id":"clvyz4r0i000sa9liegol40bx","category_id":"clvyz4r010004a9liahasavcd","_id":"clvyz4r0n0011a9li292u3viw"},{"post_id":"clvyz4r0j000ua9libl6balyo","category_id":"clvyz4r0a000ea9libg6ggbzh","_id":"clvyz4r0o0013a9li4lsq4xbv"},{"post_id":"clvyz4r0a000fa9li0awy675h","category_id":"clvyz4r0i000ta9lifjdo18yv","_id":"clvyz4r0p0016a9li9guy2atq"},{"post_id":"clvyz4r0j000va9li5yyw5u38","category_id":"clvyz4r0f000oa9lie44x0c2e","_id":"clvyz4r0p0017a9li8izabt6h"},{"post_id":"clvyz4r0l000ya9li3npkanum","category_id":"clvyz4r0f000oa9lie44x0c2e","_id":"clvyz4r0q0018a9li8gcif3m9"},{"post_id":"clvyz4r0d000ka9libl3u9k9v","category_id":"clvyz4r0f000oa9lie44x0c2e","_id":"clvyz4r0q0019a9li0kx36awq"},{"post_id":"clvyz4r0p0015a9li12sthzkd","category_id":"clvyz4r0d000ia9lidlqzbrgg","_id":"clvyz4r0q001aa9li73kg7fy6"},{"post_id":"clvyz4r0m0010a9lih80whz1a","category_id":"clvyz4r0o0014a9li5yrj9bop","_id":"clvyz4r0q001ba9liawrzfwek"}],"PostTag":[{"post_id":"clvyz4r050008a9liftcy45bf","tag_id":"clvyz4r08000ba9li3dgk19yw","_id":"clvyz4r0d000ja9lid9qw3sgb"}],"Tag":[{"name":"dayjs","_id":"clvyz4r08000ba9li3dgk19yw"}]}}