├── .gitignore ├── .vscode └── settings.json ├── README.md ├── catalog.js ├── docs ├── .vuepress │ ├── algorithm.header.js │ ├── config.js │ ├── public │ │ └── favicon.ico │ ├── styles │ │ └── index.styl │ └── theme │ │ ├── LICENSE │ │ ├── components │ │ ├── AlgoliaSearchBox.vue │ │ ├── Archive.vue │ │ ├── Bar.vue │ │ ├── DropdownLink.vue │ │ ├── DropdownTransition.vue │ │ ├── Home.vue │ │ ├── NavLink.vue │ │ ├── NavLinks.vue │ │ ├── Navbar.vue │ │ ├── Page.vue │ │ ├── PageEdit.vue │ │ ├── PageNav.vue │ │ ├── QR.vue │ │ ├── Sidebar.vue │ │ ├── SidebarButton.vue │ │ ├── SidebarGroup.vue │ │ ├── SidebarLink.vue │ │ └── SidebarLinks.vue │ │ ├── global-components │ │ └── Badge.vue │ │ ├── index.js │ │ ├── layouts │ │ ├── 404.vue │ │ └── Layout.vue │ │ ├── noopModule.js │ │ ├── qr.jpg │ │ ├── styles │ │ ├── arrow.styl │ │ ├── code.styl │ │ ├── config.styl │ │ ├── custom-blocks.styl │ │ ├── index.styl │ │ ├── mobile.styl │ │ ├── palette.styl │ │ ├── toc.styl │ │ └── wrapper.styl │ │ └── util │ │ └── index.js ├── aipaint │ ├── README.md │ ├── ai-stable-diffusion-1.md │ ├── ai-stable-diffusion-2.md │ └── meta.json ├── algorithm │ ├── README.md │ ├── ball.md │ ├── binary-tree.md │ ├── level.md │ ├── meta.json │ └── sort.md ├── babel │ ├── babel-presets与plugins的区别.md │ └── meta.json ├── canvas │ ├── README.md │ ├── meta.json │ └── weixin-8.0-emoji.md ├── debug │ ├── README.md │ ├── debug1.md │ ├── debug2.md │ ├── debug3.md │ └── meta.json ├── frontend │ ├── Chrome这次更新事件机制,导致99%的文章都错了(包括MDN).md │ ├── Promise-allSettled-vs-Promise-all.md │ ├── README.md │ ├── assign-spread.md │ ├── best-practices-aysnc.md │ ├── best-practices-es6-promise.md │ ├── blog.md │ ├── chrome-extension-source-install.md │ ├── chrome-frontend.md │ ├── collapsing-margins.md │ ├── cors.md │ ├── css-lianglie.md │ ├── css-loading.md │ ├── debounce.md │ ├── demo │ │ └── 360-disney │ │ │ ├── 360.jpg │ │ │ ├── NoSleep.js │ │ │ ├── README.md │ │ │ ├── assets │ │ │ ├── photosphere-logo.gif │ │ │ ├── pin-blue.png │ │ │ └── pin-red.png │ │ │ ├── browser.js │ │ │ ├── gyroscope.js │ │ │ ├── mark.html │ │ │ ├── markers.css │ │ │ ├── markers.js │ │ │ ├── photo-sphere-viewer.css │ │ │ ├── photo-sphere-viewer.js │ │ │ ├── polyfill.js │ │ │ ├── simple.html │ │ │ ├── snow.js │ │ │ ├── stereo.js │ │ │ └── three.js │ ├── es2019.md │ ├── es2021.md │ ├── event.md │ ├── js-block.md │ ├── js-mouse.md │ ├── js-op.md │ ├── js-proto.md │ ├── js-proto2.md │ ├── js-sort.md │ ├── js-this.md │ ├── js-type.md │ ├── js-upload.md │ ├── js实现bind的三层,你在哪一层。.md │ ├── lazy-img.md │ ├── meta.json │ └── tc39 │ │ └── type.md ├── git │ ├── README.md │ ├── git-10-up.md │ ├── git-err.md │ ├── gitee-guide.md │ └── meta.json ├── grow │ ├── README.md │ ├── frontend-books.md │ ├── learn.md │ └── meta.json ├── interview │ ├── README.md │ ├── bytedance-add-sumOf.md │ ├── interview.md │ ├── interview2.md │ ├── interview3.md │ └── meta.json ├── machine-learning │ ├── README.md │ └── meta.json ├── news │ ├── 11-must-website.md │ ├── 2020-article.md │ ├── 2020-css.md │ ├── 2020-state-of-js.md │ ├── README.md │ ├── baidu-kaifa.md │ ├── codepen-vue-flutter.md │ ├── future-js.md │ ├── goabord.md │ ├── leanboard.md │ ├── meta.json │ ├── node-sass-eprecated.md │ └── seo-img.md ├── node │ ├── README.md │ ├── color.md │ ├── comment-parser.md │ ├── crawler.md │ ├── file-download.md │ ├── meta.json │ ├── mutiple-download.md │ ├── node-addon.md │ ├── node-cli-count.md │ ├── node-git-down.md │ ├── node-http-rpc.md │ ├── pkg.md │ ├── shark-cleaner.md │ ├── translate.md │ ├── upload.md │ └── websocket │ │ ├── meta.json │ │ ├── websocket-400.md │ │ ├── websocket0.md │ │ ├── websocket1.md │ │ ├── websocket2.md │ │ ├── websocket3.md │ │ └── websocket4.md ├── online │ └── README.md ├── op │ ├── README.md │ ├── ali-linux.md │ ├── bundleless-online.md │ ├── http2.md │ ├── meta.json │ ├── mongo-start.md │ ├── mongodb.md │ ├── nginx-5-way.md │ └── service-choice.md ├── open │ ├── README.md │ └── meta.json ├── practice │ ├── README.md │ ├── err-viewer.md │ ├── frontend-mutiple-download.md │ ├── markdown-resume.md │ ├── meta.json │ ├── new-yindao.md │ ├── watermark.md │ └── 微信8.0更新粑粑大作战看我是如何实现的.md ├── question │ ├── react-state.md │ └── react.md ├── react │ ├── 7-react-Conditional.md │ ├── README.md │ ├── cancel-react-hooks-request.md │ ├── deep │ │ ├── 1.js │ │ ├── index.html │ │ └── react-redux-source.md │ ├── meta.json │ ├── react-hook1.md │ ├── react-hook2.md │ ├── react-state-5-way.md │ └── shopping-cart.md ├── regexp │ └── base.md ├── snowpack │ ├── README.md │ ├── SUMMARY.md │ ├── advance │ │ └── README.md │ ├── build │ │ ├── README.md │ │ └── base.md │ ├── demo │ │ └── demo1 │ │ │ ├── index.js │ │ │ └── src │ │ │ ├── a.js │ │ │ └── b.js │ ├── hmr │ │ └── README.md │ └── parser │ │ └── README.md ├── svelte │ ├── 1.start-up.md │ ├── 2.compare-frame.md │ ├── 3.source-runtime-1.md │ ├── 4.source-runtime-2.md │ ├── README.md │ └── meta.json ├── three │ ├── 2-14-vr.md │ ├── README.md │ ├── lesson01.md │ ├── lesson02.md │ ├── lesson03.md │ ├── lesson04.md │ └── meta.json ├── typescript │ └── 快速给第三方包写声明.md ├── vscode │ ├── 7-vscode-extensions.md │ ├── README.md │ ├── friend-vscode.md │ ├── meta.json │ └── vscode-x.md ├── vue │ ├── README.md │ ├── element-ui-start.md │ ├── meta.json │ ├── svelte-vs-vue3.md │ ├── vue-class.md │ ├── vue-demo │ │ ├── .gitignore │ │ ├── index.html │ │ ├── package.json │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── App.vue │ │ │ ├── assets │ │ │ │ └── logo.png │ │ │ ├── components │ │ │ │ └── HelloWorld.vue │ │ │ └── main.js │ │ └── vite.config.js │ ├── vue-event-throttle.md │ ├── vue-lazy.md │ ├── vue-mixins.md │ ├── vue-music.md │ └── vue-router.md └── webpack │ ├── README.md │ ├── changjianwenti.md │ ├── meta.json │ ├── module-2.md │ ├── module-base.md │ ├── module.md │ ├── snowpack-deep.md │ └── snowpack.md ├── meta.js ├── mt-zhaopin.md └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | node_modules 49 | happy-file 50 | _book 51 | wx 52 | docs/online/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 秋风的博客 -------------------------------------------------------------------------------- /catalog.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const dir = process.env.dir; 4 | 5 | // dir=svelte node catalog.js 6 | 7 | if (!dir) return; 8 | 9 | const meta = require(`./docs/${dir}/meta.json`); 10 | const catalogPath = path.join(`./docs/${dir}/`, './README.md') 11 | 12 | const text = meta.map((item, index) => { 13 | return `${index+1}. [${item.title}](./${item.path})`; 14 | }) 15 | 16 | fs.writeFileSync(catalogPath, ` 17 | ## 目录 18 | ${text.join('\n\n')} 19 | `) 20 | -------------------------------------------------------------------------------- /docs/.vuepress/algorithm.header.js: -------------------------------------------------------------------------------- 1 | const algorithm = require('../algorithm/meta.json') 2 | const node = require('../node/meta.json') 3 | const frontend = require('../frontend/meta.json') 4 | const open = require('../open/meta.json') 5 | const react = require('../react/meta.json') 6 | const vue = require('../vue/meta.json') 7 | const debug = require('../debug/meta.json') 8 | const op = require('../op/meta.json') 9 | const webpack = require('../webpack/meta.json') 10 | const interview = require('../interview/meta.json') 11 | const canvas = require('../canvas/meta.json') 12 | const svelte = require('../svelte/meta.json') 13 | const three = require('../three/meta.json') 14 | 15 | const git = require('../git/meta.json') 16 | const grow = require('../grow/meta.json') 17 | const news = require('../news/meta.json') 18 | const practice = require('../practice/meta.json') 19 | const vscode = require('../vscode/meta.json') 20 | const aipaint = require('../aipaint/meta.json') 21 | 22 | 23 | function getHeader (posts) { 24 | const getPostPair = x => [x.path, x.sideTitle || x.title] 25 | if (posts[0] && posts[0].category) { 26 | let category = [] 27 | for (const post of posts) { 28 | if (post.category) { 29 | category = [...category, { title: post.category, collapsable: false, children: [ getPostPair(post) ] }] 30 | } else { 31 | category[category.length - 1].children.push(getPostPair(post)) 32 | } 33 | } 34 | return category 35 | } 36 | return posts.map(getPostPair) 37 | } 38 | 39 | module.exports = { 40 | algorithm: getHeader(algorithm), 41 | node: getHeader(node), 42 | frontend: getHeader(frontend), 43 | open: getHeader(open), 44 | vue: getHeader(vue), 45 | react: getHeader(react), 46 | debug: getHeader(debug), 47 | op: getHeader(op), 48 | webpack: getHeader(webpack), 49 | interview: getHeader(interview), 50 | canvas: getHeader(canvas), 51 | svelte: getHeader(svelte), 52 | three: getHeader(three), 53 | git: getHeader(git), 54 | grow: getHeader(grow), 55 | news: getHeader(news), 56 | practice: getHeader(practice), 57 | vscode: getHeader(vscode), 58 | aipaint: getHeader(aipaint), 59 | } 60 | -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hua1995116/vuepress-blog/cfcc41e1c37bb31916069f47871dbce3f3fc3959/docs/.vuepress/public/favicon.ico -------------------------------------------------------------------------------- /docs/.vuepress/styles/index.styl: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | .container { 6 | padding: 4.5rem 2rem 1rem; 7 | margin: 0 auto; 8 | width: 100%; 9 | display: flex; 10 | flex-direction: column; 11 | } 12 | 13 | .main-page { 14 | flex: 1; 15 | // padding-right: 3rem; 16 | h2 { 17 | border-bottom: 0; 18 | margin-top: 50px; 19 | text-align: center; 20 | } 21 | } 22 | 23 | .main-header { 24 | max-width: 800px; 25 | margin: 0 auto; 26 | display: flex; 27 | flex-direction: column; 28 | align-items: center; 29 | } 30 | 31 | .main-social { 32 | display: flex; 33 | justify-content: center; 34 | a { 35 | margin-left: 10px; 36 | color: #818181 37 | .iconfont { 38 | font-size: 28px 39 | } 40 | &:hover { 41 | color: #000 42 | } 43 | } 44 | 45 | } 46 | 47 | .main-bottom { 48 | margin-top: 50px; 49 | text-align: center; 50 | height: 40px; 51 | } 52 | 53 | .aside-item { 54 | margin: 10px 0; 55 | } 56 | 57 | .archive-post-date { 58 | font-family: 'Ubuntu Mono', monospace; 59 | font-weight: 500; 60 | margin-right: 2rem; 61 | display: none; 62 | } 63 | 64 | .archive-post-container { 65 | max-width: 800px; 66 | margin: 20px auto; 67 | } 68 | 69 | .archive-post { 70 | line-height: 1.5; 71 | margin-top: 20px; 72 | } 73 | 74 | .aside-page { 75 | flex-shrink: 1; 76 | } 77 | 78 | @media (min-width: 576px) { 79 | .container { 80 | max-width: 540px; 81 | flex-direction: column; 82 | } 83 | 84 | .archive-post-date { 85 | display: inline; 86 | } 87 | } 88 | 89 | @media (min-width: 768px) { 90 | .container { 91 | max-width: 720px; 92 | flex-direction: column; 93 | } 94 | 95 | .archive-post-date { 96 | display: inline; 97 | } 98 | } 99 | 100 | @media (min-width: 992px) { 101 | .container { 102 | max-width: 960px; 103 | flex-direction: row; 104 | } 105 | 106 | .archive-post-date { 107 | display: inline; 108 | } 109 | 110 | .aside-page { 111 | flex-basis: 360px; 112 | } 113 | } 114 | 115 | @media (min-width: 1200px) { 116 | .container { 117 | max-width: 1140px; 118 | flex-direction: row; 119 | } 120 | 121 | .archive-post-date { 122 | display: inline; 123 | } 124 | 125 | .aside-page { 126 | flex-basis: 360px; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Archive.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 105 | 106 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Bar.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 35 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/DropdownTransition.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 28 | 29 | 34 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/NavLink.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 55 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Page.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 93 | 94 | 132 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/PageEdit.vue: -------------------------------------------------------------------------------- 1 | 14 | 97 | 131 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/PageNav.vue: -------------------------------------------------------------------------------- 1 | 16 | 101 | 118 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/QR.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | 16 | 35 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | 23 | 60 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/SidebarButton.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 28 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/SidebarGroup.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 74 | 75 | 133 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/SidebarLink.vue: -------------------------------------------------------------------------------- 1 | 96 | 97 | 127 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/SidebarLinks.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 100 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/global-components/Badge.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | // Theme API. 4 | module.exports = (options, ctx) => { 5 | const { themeConfig, siteConfig } = ctx 6 | 7 | // resolve algolia 8 | const isAlgoliaSearch = ( 9 | themeConfig.algolia 10 | || Object 11 | .keys(siteConfig.locales && themeConfig.locales || {}) 12 | .some(base => themeConfig.locales[base].algolia) 13 | ) 14 | 15 | const enableSmoothScroll = themeConfig.smoothScroll === true 16 | 17 | return { 18 | alias () { 19 | return { 20 | '@AlgoliaSearchBox': isAlgoliaSearch 21 | ? path.resolve(__dirname, 'components/AlgoliaSearchBox.vue') 22 | : path.resolve(__dirname, 'noopModule.js') 23 | } 24 | }, 25 | 26 | plugins: [ 27 | ['@vuepress/active-header-links', options.activeHeaderLinks], 28 | '@vuepress/search', 29 | '@vuepress/plugin-nprogress', 30 | ['container', { 31 | type: 'tip', 32 | defaultTitle: { 33 | '/': 'TIP', 34 | '/zh/': '提示' 35 | } 36 | }], 37 | ['container', { 38 | type: 'warning', 39 | defaultTitle: { 40 | '/': 'WARNING', 41 | '/zh/': '注意' 42 | } 43 | }], 44 | ['container', { 45 | type: 'danger', 46 | defaultTitle: { 47 | '/': 'WARNING', 48 | '/zh/': '警告' 49 | } 50 | }], 51 | ['smooth-scroll', enableSmoothScroll] 52 | ] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/layouts/404.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/noopModule.js: -------------------------------------------------------------------------------- 1 | export default {} 2 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/qr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hua1995116/vuepress-blog/cfcc41e1c37bb31916069f47871dbce3f3fc3959/docs/.vuepress/theme/qr.jpg -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/arrow.styl: -------------------------------------------------------------------------------- 1 | @require './config' 2 | 3 | .arrow 4 | display inline-block 5 | width 0 6 | height 0 7 | &.up 8 | border-left 4px solid transparent 9 | border-right 4px solid transparent 10 | border-bottom 6px solid $arrowBgColor 11 | &.down 12 | border-left 4px solid transparent 13 | border-right 4px solid transparent 14 | border-top 6px solid $arrowBgColor 15 | &.right 16 | border-top 4px solid transparent 17 | border-bottom 4px solid transparent 18 | border-left 6px solid $arrowBgColor 19 | &.left 20 | border-top 4px solid transparent 21 | border-bottom 4px solid transparent 22 | border-right 6px solid $arrowBgColor 23 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/code.styl: -------------------------------------------------------------------------------- 1 | {$contentClass} 2 | code 3 | color lighten($textColor, 20%) 4 | padding 0.25rem 0.5rem 5 | margin 0 6 | font-size 0.85em 7 | background-color rgba(27,31,35,0.05) 8 | border-radius 3px 9 | .token 10 | &.deleted 11 | color #EC5975 12 | &.inserted 13 | color $accentColor 14 | 15 | {$contentClass} 16 | pre, pre[class*="language-"] 17 | line-height 1.4 18 | padding 1.25rem 1.5rem 19 | margin 0.85rem 0 20 | background-color $codeBgColor 21 | border-radius 6px 22 | overflow auto 23 | code 24 | color #fff 25 | padding 0 26 | background-color transparent 27 | border-radius 0 28 | 29 | div[class*="language-"] 30 | position relative 31 | background-color $codeBgColor 32 | border-radius 6px 33 | .highlight-lines 34 | user-select none 35 | padding-top 1.3rem 36 | position absolute 37 | top 0 38 | left 0 39 | width 100% 40 | line-height 1.4 41 | .highlighted 42 | background-color rgba(0, 0, 0, 66%) 43 | pre, pre[class*="language-"] 44 | background transparent 45 | position relative 46 | z-index 1 47 | &::before 48 | position absolute 49 | z-index 3 50 | top 0.8em 51 | right 1em 52 | font-size 0.75rem 53 | color rgba(255, 255, 255, 0.4) 54 | &:not(.line-numbers-mode) 55 | .line-numbers-wrapper 56 | display none 57 | &.line-numbers-mode 58 | .highlight-lines .highlighted 59 | position relative 60 | &:before 61 | content ' ' 62 | position absolute 63 | z-index 3 64 | left 0 65 | top 0 66 | display block 67 | width $lineNumbersWrapperWidth 68 | height 100% 69 | background-color rgba(0, 0, 0, 66%) 70 | pre 71 | padding-left $lineNumbersWrapperWidth + 1 rem 72 | vertical-align middle 73 | .line-numbers-wrapper 74 | position absolute 75 | top 0 76 | width $lineNumbersWrapperWidth 77 | text-align center 78 | color rgba(255, 255, 255, 0.3) 79 | padding 1.25rem 0 80 | line-height 1.4 81 | br 82 | user-select none 83 | .line-number 84 | position relative 85 | z-index 4 86 | user-select none 87 | font-size 0.85em 88 | &::after 89 | content '' 90 | position absolute 91 | z-index 2 92 | top 0 93 | left 0 94 | width $lineNumbersWrapperWidth 95 | height 100% 96 | border-radius 6px 0 0 6px 97 | border-right 1px solid rgba(0, 0, 0, 66%) 98 | background-color $codeBgColor 99 | 100 | 101 | for lang in $codeLang 102 | div{'[class~="language-' + lang + '"]'} 103 | &:before 104 | content ('' + lang) 105 | 106 | div[class~="language-javascript"] 107 | &:before 108 | content "js" 109 | 110 | div[class~="language-typescript"] 111 | &:before 112 | content "ts" 113 | 114 | div[class~="language-markup"] 115 | &:before 116 | content "html" 117 | 118 | div[class~="language-markdown"] 119 | &:before 120 | content "md" 121 | 122 | div[class~="language-json"]:before 123 | content "json" 124 | 125 | div[class~="language-ruby"]:before 126 | content "rb" 127 | 128 | div[class~="language-python"]:before 129 | content "py" 130 | 131 | div[class~="language-bash"]:before 132 | content "sh" 133 | 134 | div[class~="language-php"]:before 135 | content "php" 136 | 137 | @import '~prismjs/themes/prism-tomorrow.css' 138 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/config.styl: -------------------------------------------------------------------------------- 1 | $contentClass = '.theme-default-content' 2 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/custom-blocks.styl: -------------------------------------------------------------------------------- 1 | .custom-block 2 | .custom-block-title 3 | font-weight 600 4 | margin-bottom -0.4rem 5 | &.tip, &.warning, &.danger 6 | padding .1rem 1.5rem 7 | border-left-width .5rem 8 | border-left-style solid 9 | margin 1rem 0 10 | &.tip 11 | background-color #f3f5f7 12 | border-color #42b983 13 | &.warning 14 | background-color rgba(255,229,100,.3) 15 | border-color darken(#ffe564, 35%) 16 | color darken(#ffe564, 70%) 17 | .custom-block-title 18 | color darken(#ffe564, 50%) 19 | a 20 | color $textColor 21 | &.danger 22 | background-color #ffe6e6 23 | border-color darken(red, 20%) 24 | color darken(red, 70%) 25 | .custom-block-title 26 | color darken(red, 40%) 27 | a 28 | color $textColor 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/mobile.styl: -------------------------------------------------------------------------------- 1 | @require './config' 2 | 3 | $mobileSidebarWidth = $sidebarWidth * 0.82 4 | 5 | // narrow desktop / iPad 6 | @media (max-width: $MQNarrow) 7 | .sidebar 8 | font-size 15px 9 | width $mobileSidebarWidth 10 | .page 11 | padding-left $mobileSidebarWidth 12 | 13 | // wide mobile 14 | @media (max-width: $MQMobile) 15 | .sidebar 16 | top 0 17 | padding-top $navbarHeight 18 | transform translateX(-100%) 19 | transition transform .2s ease 20 | .page 21 | padding-left 0 22 | .theme-container 23 | &.sidebar-open 24 | .sidebar 25 | transform translateX(0) 26 | &.no-navbar 27 | .sidebar 28 | padding-top: 0 29 | 30 | // narrow mobile 31 | @media (max-width: $MQMobileNarrow) 32 | h1 33 | font-size 1.9rem 34 | {$contentClass} 35 | div[class*="language-"] 36 | margin 0.85rem -1.5rem 37 | border-radius 0 38 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/palette.styl: -------------------------------------------------------------------------------- 1 | $accentColor = #6d6d6d -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/toc.styl: -------------------------------------------------------------------------------- 1 | .table-of-contents 2 | .badge 3 | vertical-align middle 4 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/wrapper.styl: -------------------------------------------------------------------------------- 1 | $wrapper 2 | max-width $contentWidth 3 | margin 0 auto 4 | padding 2rem 2.5rem 5 | @media (max-width: $MQNarrow) 6 | padding 2rem 7 | @media (max-width: $MQMobileNarrow) 8 | padding 1.5rem 9 | 10 | -------------------------------------------------------------------------------- /docs/aipaint/README.md: -------------------------------------------------------------------------------- 1 | # AI 画图系列 2 | 3 | [1.AI数字绘画 stable-diffusion 保姆级教程](./ai-stable-diffusion-1.md) 4 | 5 | [2.用Colab免费部署自己的AI绘画云平台—— Stable Diffusion](./ai-stable-diffusion-2.md) -------------------------------------------------------------------------------- /docs/aipaint/meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "用Colab免费部署自己的AI绘画云平台—— Stable Diffusion", 4 | "date": "2022-09-12 23:51:17", 5 | "path": "ai-stable-diffusion-2" 6 | }, 7 | { 8 | "title": "AI数字绘画 stable-diffusion 保姆级教程", 9 | "date": "2022-09-05 23:51:17", 10 | "path": "ai-stable-diffusion-1" 11 | } 12 | ] -------------------------------------------------------------------------------- /docs/algorithm/README.md: -------------------------------------------------------------------------------- 1 | # 前端算法 2 | 3 | 4 | ## 基础算法 5 | [排序算法之堆排序](./sort.md) 6 | 7 | [二叉树之层次遍历(js)](./level.md) 8 | 9 | [二叉树之重建(js)](./binary-tree.md) 10 | 11 | 12 | ## 算法应用 13 | 14 | [二叉树之小球下落问题(js)](./ball.md) 15 | -------------------------------------------------------------------------------- /docs/algorithm/ball.md: -------------------------------------------------------------------------------- 1 | # 二叉树之小球下落问题(js) 2 | 3 | 有一棵二叉树,最大深度为 D,且所有叶子的深度都相同。所有结点从上到下从左到右编号为 1,2,3,...,2^D-1。在结点 1 处放一个小球,它会往下落。每个内结点上都有一个开关,初始全部关闭,当每次有小球落到一个开关上时,它的状态都会改变。当小球到达一个内结点时,如果该结点上的开关关闭,则往左走,否则往右走,知道走到叶子结点,如图。 4 | 5 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506284862.png) 6 | 一些小球从结点 1 处开始下落,最后一个小球将会落到哪里呢,输入叶子深度 D 和小球个数 I,输出第 I 个小球最后的叶子编号。假设 I 不超过整棵树的叶子个数。D<=20。 7 | **输入**: 8 | 4 2 9 | 3 4 10 | 10 1 11 | **输出**: 12 | 12 13 | 7 14 | 512 15 | 代码: 16 | 17 | ```javascript 18 | function drop(depth, count) { 19 | var arr = []; 20 | var r; 21 | for (var i = 0; i < count; i++) { 22 | for (var root = 1; root < Math.pow(2, depth - 1); ) { 23 | if (arr[root] && arr[root].open) { 24 | arr[root].open = false; 25 | root = root * 2 + 1; 26 | } else { 27 | if (!arr[root]) { 28 | arr[root] = { open: true }; 29 | } else if (arr[root].open === false) { 30 | arr[root].open = true; 31 | } 32 | root = root * 2; 33 | } 34 | } 35 | r = root; 36 | } 37 | return r; 38 | } 39 | console.log(drop(4, 2)); // 12 40 | console.log(drop(3, 4)); // 7 41 | console.log(drop(10, 1)); // 512 42 | ``` 43 | -------------------------------------------------------------------------------- /docs/algorithm/binary-tree.md: -------------------------------------------------------------------------------- 1 | # 二叉树之重建(js) 2 | 3 | 4 | 输入一颗二叉树的先序遍历和中序遍历,输出它的后序遍历。 5 | 输入: 6 | DBACEGF ABCDEFG 7 | BCAD CBAD 8 | 输出: 9 | ACBFGED 10 | CDAB 11 | 12 | ```javascript 13 | var root = {value: null, left: null, right: null}; 14 | function build(root, s1, s2) { 15 | if (s1.length === 0 || s2.length === 0 ) { 16 | return; 17 | } 18 | 19 | var midnode = s2.indexOf(s1[0]); 20 | var mleft = s2.substring(0, midnode), 21 | mright = s2.substring(midnode + 1); 22 | var pleft = s1.substring(1, mleft.length + 1), 23 | pright = s1.substring(mleft.length + 1); 24 | root.value = s1[0]; 25 | root.left = newchild(); 26 | root.right = newchild(); 27 | 28 | if(root.value) { 29 | build(root.left, pleft, mleft); 30 | build(root.right, pright, mright); 31 | } 32 | } 33 | function newchild() { 34 | return {value: null, left: null, right: null} 35 | } 36 | build(root, 'DBACEGF', 'ABCDEFG'); 37 | 38 | function postrav(root) { 39 | if(root.value!==null){ 40 | postrav(root.left); 41 | postrav(root.right); 42 | console.log(root.value); 43 | } 44 | 45 | } 46 | postrav(root); 47 | ``` -------------------------------------------------------------------------------- /docs/algorithm/level.md: -------------------------------------------------------------------------------- 1 | # 二叉树之层次遍历(js) 2 | 3 | 输入一棵二叉树,你的任务是从上到下,从左到右的顺序输出各个结点的值。每个结点都是按照从根节点到它移动序列给出(L 表示左,R 表示右)。在输入中,每个结点的左右括号之间没有空格,相邻节点之间用一个空格隔开。 4 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506284531.png) 5 | 6 | **输入:(11,LL)(7,LLL)(8,R)(5,)(4,L)(13,RL)(2,LLR)(1,RRR)(4,RR)** 7 | 8 | **输出:5 4 8 11 13 4 7 2 1** 9 | 10 | **思路:先建立一棵二叉树。再进行队列遍历。** 11 | 12 | 代码如下: 13 | 14 | ```javascript 15 | //建立二叉树 16 | function cengci(obj) { 17 | var obj = obj.split(")"); 18 | obj.pop(); 19 | var newobj = []; 20 | for (var i = 0; i < obj.length; i++) { 21 | newobj.push(obj[i].replace("(", "")); 22 | } 23 | var root = { 24 | value: null, 25 | left: null, 26 | right: null, 27 | have: 0, 28 | }; 29 | var u; 30 | for (var i = 0; i < newobj.length; i++) { 31 | var a1 = newobj[i].split(",")[0]; 32 | var a2 = newobj[i].split(",")[1]; 33 | u = root; 34 | if (a2 !== "") { 35 | for (var j = 0; j < a2.length; j++) { 36 | if (a2[j] === "L") { 37 | if (u.left === null) { 38 | u.left = newnode(); 39 | u = u.left; 40 | } else { 41 | u = u.left; 42 | } 43 | } else if (a2[j] === "R") { 44 | if (u.right === null) { 45 | u.right = newnode(); 46 | u = u.right; 47 | } else { 48 | u = u.right; 49 | } 50 | } 51 | } 52 | if (u.have === 1) { 53 | } else { 54 | u.value = a1; 55 | u.have = 1; 56 | } 57 | } else { 58 | root.value = a1; 59 | u.have = 1; 60 | } 61 | } 62 | return root; 63 | } 64 | //建立新结点 65 | function newnode() { 66 | return { value: null, left: null, right: null, have: 0 }; 67 | } 68 | //队列遍历 69 | function bfs() { 70 | var root = cengci("(11,LL)(7,LLL)(8,R)(5,)(4,L)(13,RL)(2,LLR)(1,RRR)(4,RR)"); 71 | var front = 0, 72 | rear = 1, 73 | n = 0; 74 | var q = [], 75 | ans = []; 76 | q[0] = root; 77 | while (front < rear) { 78 | var u = q[front++]; 79 | if (u.have !== 1) { 80 | return; 81 | } 82 | ans[n++] = u.value; 83 | if (u.left !== null) { 84 | q[rear++] = u.left; 85 | } 86 | if (u.right !== null) { 87 | q[rear++] = u.right; 88 | } 89 | } 90 | console.log(ans.join(" ")); 91 | } 92 | bfs(); 93 | ``` 94 | -------------------------------------------------------------------------------- /docs/algorithm/meta.json: -------------------------------------------------------------------------------- 1 | [{"title":" 二叉树之小球下落问题(js)","date":"2020-03-29 23:51:17","path":"ball"},{"title":" 二叉树之重建(js)","date":"2020-03-29 23:51:17","path":"binary-tree"},{"title":" 二叉树之层次遍历(js)","date":"2020-03-29 23:51:17","path":"level"},{"title":" 排序算法之堆排序(js)","date":"2020-03-29 23:51:17","path":"sort"}] -------------------------------------------------------------------------------- /docs/algorithm/sort.md: -------------------------------------------------------------------------------- 1 | # 排序算法之堆排序(js) 2 | 3 | 4 | ```javascript 5 | var floor = Math.floor; 6 | var H = { 7 | 1: 9, 8 | 2: 8, 9 | 3: 7, 10 | 4: 6, 11 | 5: 5, 12 | 6: 4, 13 | 7: 3, 14 | 8: 2, 15 | 9: 1 16 | }; 17 | // 向上 18 | function sift_up(H, i) { 19 | var done = false; 20 | if (i !== 1) { 21 | while (!done && i !== 1) { 22 | if (H[i] > H[floor(i / 2)]) { 23 | var temp; 24 | temp = H[i]; 25 | H[i] = H[floor(i / 2)]; 26 | H[floor(i / 2)] = temp; 27 | } else { 28 | done = true; 29 | } 30 | i = floor(i / 2); 31 | } 32 | } 33 | return H; 34 | } 35 | // 向下 36 | function sift_down(H, n, i) { 37 | var done = false; 38 | if ((2 * i) < n) { 39 | while (!done && ((i = i * 2) <= n)) { 40 | if ((i + 1) < n && (H[i + 1] > H[i])) { 41 | i = i + 1; 42 | } 43 | if (H[floor(i / 2)] < H[i]) { 44 | var temp; 45 | temp = H[i]; 46 | H[i] = H[floor(i / 2)]; 47 | H[floor(i / 2)] = temp; 48 | } else { 49 | done = true; 50 | } 51 | } 52 | } 53 | return H; 54 | } 55 | // 增加 56 | function insert(H, n, x) { 57 | n = n + 1; 58 | H[n] = x; 59 | return sift_up(H, n); 60 | } 61 | // 删除 62 | function deleteobj(H, n, i) { 63 | var x, y; 64 | x = H[i]; 65 | y = H[n]; 66 | delete H[n]; 67 | n = n - 1; 68 | if (i <= n) { 69 | H[i] = y; 70 | if (y > x) { 71 | return sift_up(H, i); 72 | } else { 73 | return sift_down(H, n, i); 74 | } 75 | } 76 | } 77 | // 创建 78 | function meakup(A, H, n) { 79 | var i, m = 0; 80 | for (i = 1; i <= n; i++) { 81 | H = insert(H, m, A[i]); 82 | m++; 83 | } 84 | return H; 85 | } 86 | // 创建 87 | var H1 = {}; 88 | H1 = meakup(H,H1,9) 89 | console.log(H1); 90 | // 向上 91 | H[9] = 10; 92 | var cc = sift_up(H, 9); 93 | console.log(cc); 94 | // 删除 95 | console.log(deleteobj(H, 9, 3)); 96 | ``` -------------------------------------------------------------------------------- /docs/babel/babel-presets与plugins的区别.md: -------------------------------------------------------------------------------- 1 | https://juejin.cn/post/6844903616554221576 -------------------------------------------------------------------------------- /docs/babel/meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "babel-presets与plugins的区别", 4 | "date": "2021-03-29 23:51:17", 5 | "path": "babel-presets与plugins的区别" 6 | } 7 | ] -------------------------------------------------------------------------------- /docs/canvas/README.md: -------------------------------------------------------------------------------- 1 | # canvas 2 | 3 | [教你实现微信8.0『炸裂』的🎉表情特效](./weixin-8.0-emoji.md) -------------------------------------------------------------------------------- /docs/canvas/meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "教你实现微信8.0『炸裂』的🎉表情特效", 4 | "date": "2021-02-17 12:04:17", 5 | "path": "weixin-8.0-emoji", 6 | "description": "canvas 实现微信8.0 表情礼花(confetti)特效", 7 | "keywords": "confetti canvas 教程" 8 | } 9 | ] -------------------------------------------------------------------------------- /docs/debug/README.md: -------------------------------------------------------------------------------- 1 | # Debug 2 | 3 | ### 前端 debug 系列 4 | 5 | [急速 debug 实战一(浏览器-基础篇)](./debug1.md) 6 | 7 | [急速 debug 实战二(浏览器 - 调试线上篇)](./debug2.md) 8 | 9 | [急速 debug 实战三(Node - webpack插件,babel插件,vue源码篇)](./debug3.md) 10 | 11 | -------------------------------------------------------------------------------- /docs/debug/meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": " 急速 debug 实战一(浏览器-基础篇)", 4 | "date": "2020-03-29 23:51:17", 5 | "path": "debug1", 6 | "description": "断点调试JS,单步调试代码,管理代码行断点,DOM 更改断点的类型,函数断点。", 7 | "keywords": "debugger javascript" 8 | }, 9 | { 10 | "title": " 急速 debug 实战二(浏览器 - 调试线上篇)", 11 | "date": "2020-03-29 23:51:17", 12 | "path": "debug2", 13 | "description": "Overrides调试,charles调试线上代码,sourceMap代理到本地。", 14 | "keywords": "debugger javascript charles" 15 | }, 16 | { 17 | "title": " 急速 debug 实战三(Node -\b \bwebpack插件,babel插件,vue源码篇)", 18 | "date": "2020-03-29 23:51:17", 19 | "path": "debug3", 20 | "description": "chrome调试node,node调试,babel 插件调试,源码调试(vue为例)", 21 | "keywords": "node debugger babel vue" 22 | } 23 | ] -------------------------------------------------------------------------------- /docs/frontend/Promise-allSettled-vs-Promise-all.md: -------------------------------------------------------------------------------- 1 | # 听说你还不知道 Promise 的 allSettled()和 all()的区别? 2 | 3 | > 译文来自 https://dev.to/viclafouch/promise-allsettled-vs-promise-all-in-javascript-4mle 4 | > 5 | > 原作者 Victor de la Fouchardière 6 | > 7 | > 译者: 蓝色的秋风(github/hua1995116) 8 | 9 | Hello! 🧑‍🌾 10 | 11 | 从 ES2015 起, promises 的出现,让我们简化了异步操作。(所以 promise 越来越流行,掌握它的相关 API 变得至关重要)。 12 | 13 | 让我们来看看以下两个 Promise 方式及他们差异: 14 | 15 | - [Promise.allSettled(可迭代)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled) 16 | 17 | - [Promise.all(可迭代)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) 18 | 19 | 他们两个都传入可 `迭代对象`,并返回一个已完成的 Promises 的`数组`。 20 | 21 | ❓ 那么,**它们之间有什么区别呢?** 22 | 23 | ## Promise.all()🧠 24 | 25 | `Promise.all()`方法将一组可迭代的 Promises 作为输入,并返回一个 Promise ,该 Promise resolve 的结果为刚才那组 输入 promises 的返回结果。 26 | 27 | ![Promise all](https://res.cloudinary.com/practicaldev/image/fetch/s--A7rnVVpd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/loq7cd72u055wl92yq2u.png) 28 | 29 | 正如你看到的那样,我们将数组传递给 `Promise.all`。 当三个 promise 都完成时,`Promise.all` 就完成了,并且输出被打印了。 30 | 31 | 现在,让我们看看其中一个 promise 失败了的情况,如果这个 promise 失败了,又会 输出什么呢? 🛑 32 | 33 | ![Promise all failed](https://res.cloudinary.com/practicaldev/image/fetch/s--MEAe2zoD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gcpmjldpgbfc8xgqgh10.png) 34 | 35 | `如果其中一个 promise 失败了`,则 `Promise.all` 整体将会失败。 例如,我们传递 2 个 promise, 一个完成的 promise 和 一个 失败的 promise,那么 `Promise.all` 将立即失败。 36 | 37 | ## Promise.allSettled()📪 38 | 39 | 从 ES2020 开始,你可以使用 `Promise.allSettled`。当所有的 promises 都已经结束无论是完成状态或者是失败状态,它都会返回一个 promise,这个 promise 将会包含一个关于描述每个 promise 状态结果的对象数组。 40 | 41 | 对于每个结果对象,都有一个`状态`字符串: 42 | 43 | - `fulfilled(完成)` ✅ 44 | 45 | - `rejected(失败)` ❌ 46 | 47 | 返回值(或原因)表现每个 promise 的完成(或失败)。 48 | 49 | 仔细观察结果数组的以下属性(`status-状态`,`value-值`,`reason-原因`)。 50 | 51 | ![allSettled](https://res.cloudinary.com/practicaldev/image/fetch/s--s2PC5oqi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/brvijnemnpmm9qvauhvp.png) 52 | 53 | ## 区别 👬 54 | 55 | - `Promise.all` 将在 Promises 数组中的其中一个 Promises 失败后立即失败。 56 | 57 | - `Promise.allSettled`将永远不会失败,一旦数组中的所有 Promises 被完成或失败,它就会完成。 58 | 59 | ## 浏览器支持 🚸 60 | 61 | 下面列出了`Promise.allSettled()`和`promise.all()`方法浏览器的支持情况: 62 | 63 | `Promise.allSettled()` 64 | 65 | ![image-20200819004559123](https://s3.mdedit.online/blog/image-20200819004559123.png) 66 | 67 | `promise.all()` 68 | 69 | ![image-20200819004619627](https://s3.mdedit.online/blog/image-20200819004619627.png) 70 | -------------------------------------------------------------------------------- /docs/frontend/README.md: -------------------------------------------------------------------------------- 1 | # 前端文章 2 | 3 | 4 | ## JS基础 5 | 6 | [ES2017 异步函数最佳实践(`async` /`await`)](./best-practices-aysnc.md) 7 | 8 | [ES6 Promise 的最佳实践](./best-practices-es6-promise.md) 9 | 10 | [10 种跨域解决方案(附终极方案)](./cors.md) 11 | 12 | [ 🎉喜大普奔,ES2019登场](./es2019.md) 13 | 14 | [[译] Object.assign 和 Object Spread 之争, 用谁?](./assign-spread.md) 15 | 16 | [debounce与throttle实现与原理](./debounce.md) 17 | 18 | [js中事件绑定3种方法以及事件委托](event.md) 19 | 20 | [未来的 JavaScript 应该是什么样的?现在还缺少什么?](future-js.md) 21 | 22 | [你不知道的javascript之函数作用域和块作用域(一)](./js-block.md) 23 | 24 | [javascript中onmousemove、onmouseover、onmouseenter 的不同](./js-mouse.md) 25 | 26 | [你不知道的javascript之运算符||和&&](./js-op.md) 27 | 28 | [你不知道的js类型转化和原型链](./js-proto.md) 29 | 30 | [你不知道的javascript之JS原型对象和原型链](./js-proto2.md) 31 | 32 | [js实现表格排序](./js-sort.md) 33 | 34 | [你不知道的javascript之this的全面解析之绑定规则(一)](./js-this.md) 35 | 36 | [你不知道的javascript之node类型详解](./js-type.md) 37 | 38 | [原生JS实现ajax上传文件并显示进度条](./js-upload.md) 39 | 40 | ## css 41 | 42 | [[重拾CSS]一道面试题来看伪元素、包含块和高度坍塌](./collapsing-margins.md) 43 | 44 | [css实现左边定宽右边自适应的两列布局5种方法](css-lianglie.md) 45 | 46 | [css3实现圆环加载进度条动画](./css-loading.md) 47 | -------------------------------------------------------------------------------- /docs/frontend/chrome-extension-source-install.md: -------------------------------------------------------------------------------- 1 | # 从源码安装谷歌浏览器插件 2 | 3 | ### 第 1 步: 4 | 5 | 解压下载好的 zip 包 `omni-master.zip` 6 | 7 | image-20220315000521853 8 | 9 | ### 第 2 步: 10 | 11 | 打开 `chrome://extensions/` 12 | 13 | image-20220315000832175 14 | 15 | ### 第 3 步: 16 | 17 | 点击 `加载已经解压的扩展程序` ,选择 omni-master 下面的 src 目录 18 | 19 | image-20220315000946624 20 | 21 | 大功告成!!! 22 | 23 | image-20220315114210552 24 | -------------------------------------------------------------------------------- /docs/frontend/css-lianglie.md: -------------------------------------------------------------------------------- 1 | # css 实现左边定宽右边自适应的两列布局 5 种方法 2 | 3 | 在项目实践中不乏有需要两列式布局,左侧固定右侧自适应是比较常见的布局方式,现在我就来总结一下我自己所知道的 5 种方法。 4 | html 代码结构: 5 | 6 | ```html 7 |
8 |
9 | 我是左边 10 |
11 |
12 | 我是右边 13 |
14 |
15 | ``` 16 | 17 | 第一种: 18 | css 代码: 19 | 20 | ```css 21 | .box { 22 | display: flex; 23 | display: -webkit-flex; 24 | } 25 | .con1 { 26 | flex: 0 1 100px; 27 | background: #ff0; 28 | } 29 | .con2 { 30 | flex: 1; 31 | background: #fe3; 32 | } 33 | ``` 34 | 35 | 效果如下 36 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506284786.png) 37 | 第二种: 38 | css 代码: 39 | 40 | ```css 41 | .con1 { 42 | width: 100px; 43 | float: left; 44 | background: #ff0; 45 | } 46 | .con2 { 47 | overflow: hidden; 48 | background: #fe3; 49 | } 50 | ``` 51 | 52 | 第三种: 53 | css 代码: 54 | 55 | ```css 56 | .con1 { 57 | width: 100px; 58 | float: left; 59 | background: #ff0; 60 | } 61 | .con2 { 62 | margin-left: 100px; 63 | background: #fe3; 64 | } 65 | ``` 66 | 67 | 第四种: 68 | css 代码: 69 | 70 | ```css 71 | .box { 72 | position: relative; 73 | } 74 | .con1 { 75 | position: absolute; 76 | left: 0; 77 | top: 0; 78 | width: 100px; 79 | background: #ff0; 80 | } 81 | .con2 { 82 | margin-left: 100px; 83 | background: #fe3; 84 | } 85 | ``` 86 | 87 | 第五种: 88 | css 代码: 89 | 90 | ```css 91 | .box { 92 | position: relative; 93 | } 94 | .con1 { 95 | position: absolute; 96 | left: 0; 97 | top: 0; 98 | width: 100px; 99 | background: #ff0; 100 | } 101 | .con2 { 102 | position: absolute; 103 | left: 100px; 104 | top: 0; 105 | right: 0; 106 | width: 100%; 107 | background: #fe3; 108 | } 109 | ``` 110 | -------------------------------------------------------------------------------- /docs/frontend/css-loading.md: -------------------------------------------------------------------------------- 1 | # css3实现圆环加载进度条动画 2 | 3 | 4 | 最近有人问我关于css3圆环的问题,要实现一个圆环,并且有加载特效。于是我看了看一般关于圆环实现的原理,以及自己手写了一个加载动画。可能体验还不是特别好,但是能用。话不多说,一下是代码: 5 | 6 | ####**html结构**: 7 | ```html 8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 60% 17 |
18 |
19 | ``` 20 | 21 | ####**css**: 22 | ```css 23 | .circle{ 24 | width: 200px; 25 | height: 200px; 26 | position: relative; 27 | border-radius: 50%; 28 | background: rgba(0,120,200,0.2); 29 | } 30 | .circle .left,.circle .right{ 31 | width: 200px; 32 | height: 200px; 33 | position: absolute; 34 | top: 0; 35 | left: 0; 36 | } 37 | .left{ 38 | clip: rect(0,100px,auto,0); 39 | } 40 | .right{ 41 | clip: rect(0,auto,auto,100px); 42 | } 43 | .left_con,.right_con{ 44 | display: block; 45 | width: 200px; 46 | height: 200px; 47 | border-radius: 50%; 48 | background: rgb(0,120,200); 49 | position: absolute; 50 | top: 0; 51 | left: 0; 52 | } 53 | .left_con{ 54 | clip: rect(0,100px,auto,0); 55 | } 56 | .right_con{ 57 | clip: rect(0,auto,auto,100px); 58 | } 59 | .mask { 60 | width: 150px; 61 | height: 150px; 62 | border-radius: 50%; 63 | left: 25px; 64 | top: 25px; 65 | background: #FFF; 66 | position: absolute; 67 | text-align: center; 68 | line-height: 150px; 69 | font-size: 16px; 70 | } 71 | ``` 72 | **为操作方便引入了jq** 73 | 74 | ```html 75 | 76 | ``` 77 | 78 | ####**js代码**: 79 | ```javascript 80 | var annulus = function(speed){ 81 | var _this = this; 82 | _this.speed = speed||10; 83 | function init(){ 84 | circle(); 85 | } 86 | function circle(){ 87 | $('.circle').each(function(index, el) { 88 | var numStart = 0; 89 | var num = $(this).find('span').text() * 3.6; 90 | var timer = null; 91 | var that = this; 92 | timer = setInterval(function(){ 93 | if(numStart>num){ 94 | clearInterval(timer); 95 | tiemr = null; 96 | } 97 | animateLoading(that,numStart); 98 | numStart += 3.6; 99 | },_this.speed); 100 | }); 101 | } 102 | function animateLoading(_this,num){ 103 | if (num <= 180) { 104 | $(_this).find('.right_con').css({'transform':"rotate(" + num + "deg)"}); 105 | 106 | } else { 107 | $(_this).find('.right_con').css({'transform': "rotate(180deg)"}); 108 | $(_this).find('.left_con').css({'transform': "rotate(" + (num - 180) + "deg)"}); 109 | }; 110 | }; 111 | return { 112 | init:init 113 | } 114 | } 115 | 116 | var a = new annulus(10); 117 | a.init(); 118 | ``` -------------------------------------------------------------------------------- /docs/frontend/demo/360-disney/360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hua1995116/vuepress-blog/cfcc41e1c37bb31916069f47871dbce3f3fc3959/docs/frontend/demo/360-disney/360.jpg -------------------------------------------------------------------------------- /docs/frontend/demo/360-disney/README.md: -------------------------------------------------------------------------------- 1 | # 360 全景示例 2 | 3 | -------------------------------------------------------------------------------- /docs/frontend/demo/360-disney/assets/photosphere-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hua1995116/vuepress-blog/cfcc41e1c37bb31916069f47871dbce3f3fc3959/docs/frontend/demo/360-disney/assets/photosphere-logo.gif -------------------------------------------------------------------------------- /docs/frontend/demo/360-disney/assets/pin-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hua1995116/vuepress-blog/cfcc41e1c37bb31916069f47871dbce3f3fc3959/docs/frontend/demo/360-disney/assets/pin-blue.png -------------------------------------------------------------------------------- /docs/frontend/demo/360-disney/assets/pin-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hua1995116/vuepress-blog/cfcc41e1c37bb31916069f47871dbce3f3fc3959/docs/frontend/demo/360-disney/assets/pin-red.png -------------------------------------------------------------------------------- /docs/frontend/demo/360-disney/mark.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | PhotoSphereViewer - markers demo 7 | 8 | 9 | 10 | 11 | 40 | 41 | 42 | 43 |
44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /docs/frontend/demo/360-disney/markers.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Photo Sphere Viewer 4.0.0-SNAPSHOT 3 | * @copyright 2014-2015 Jérémy Heleine 4 | * @copyright 2015-2020 Damien "Mistic" Sorel 5 | * @licence MIT (https://opensource.org/licenses/MIT) 6 | */ 7 | .psv-markers { 8 | -webkit-user-select: none; 9 | -moz-user-select: none; 10 | -ms-user-select: none; 11 | user-select: none; 12 | position: absolute; 13 | z-index: 10; 14 | width: 100%; 15 | height: 100%; 16 | } 17 | 18 | .psv-markers-svg-container { 19 | position: absolute; 20 | top: 0; 21 | left: 0; 22 | width: 100%; 23 | height: 100%; 24 | z-index: 20; 25 | } 26 | 27 | .psv-marker { 28 | display: none; 29 | } 30 | 31 | .psv-marker--normal { 32 | position: absolute; 33 | top: 0; 34 | left: 0; 35 | z-index: 30; 36 | background-size: contain; 37 | background-repeat: no-repeat; 38 | } 39 | 40 | .psv-marker--transparent { 41 | display: block; 42 | opacity: 0; 43 | } 44 | 45 | .psv-marker--visible { 46 | display: block; 47 | } 48 | 49 | .psv-marker--has-tooltip, .psv-marker--has-content { 50 | cursor: pointer; 51 | } 52 | 53 | .psv-markers-list { 54 | list-style: none; 55 | margin: 0; 56 | padding: 0; 57 | overflow: hidden; 58 | } 59 | 60 | .psv-markers-list-title { 61 | display: -webkit-box; 62 | display: -ms-flexbox; 63 | display: flex; 64 | -webkit-box-align: center; 65 | -ms-flex-align: center; 66 | align-items: center; 67 | font: 24px sans-serif; 68 | margin: 24px 0; 69 | } 70 | 71 | .psv-markers-list-title svg { 72 | width: 24px; 73 | height: 24px; 74 | margin: 0 12px; 75 | } 76 | 77 | .psv-markers-list-item { 78 | clear: both; 79 | min-height: 20px; 80 | padding: 0.5em 1em; 81 | cursor: pointer; 82 | -webkit-transform: translateX(0); 83 | transform: translateX(0); 84 | -webkit-transition: -webkit-transform 0.3s ease-in-out; 85 | transition: -webkit-transform 0.3s ease-in-out; 86 | transition: transform 0.3s ease-in-out; 87 | transition: transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; 88 | } 89 | 90 | .psv-markers-list-item::before { 91 | content: ""; 92 | position: absolute; 93 | top: 0; 94 | left: 0; 95 | height: 100%; 96 | width: 10px; 97 | margin-left: -10px; 98 | } 99 | 100 | .psv-markers-list-item:nth-child(odd), .psv-markers-list-item:nth-child(odd)::before { 101 | background: rgba(255, 255, 255, 0.1); 102 | } 103 | 104 | .psv-markers-list-item:nth-child(even), .psv-markers-list-item:nth-child(even)::before { 105 | background: transparent; 106 | } 107 | 108 | .psv-markers-list-image { 109 | float: left; 110 | width: 20px; 111 | } 112 | 113 | .psv-markers-list .psv-button-svg * { 114 | fill: currentColor; 115 | } 116 | 117 | .psv-markers-list-name { 118 | margin: 0; 119 | padding: 0; 120 | } 121 | 122 | .psv-markers-list-image + .psv-markers-list-name { 123 | padding-left: calc(20px + 0.5em); 124 | } 125 | 126 | .psv-container:not(.psv--is-touch) .psv-markers-list-item:hover { 127 | -webkit-transform: translateX(10px); 128 | transform: translateX(10px); 129 | -webkit-transition: -webkit-transform 0.1s ease-in-out; 130 | transition: -webkit-transform 0.1s ease-in-out; 131 | transition: transform 0.1s ease-in-out; 132 | transition: transform 0.1s ease-in-out, -webkit-transform 0.1s ease-in-out; 133 | } 134 | /*# sourceMappingURL=markers.css.map */ -------------------------------------------------------------------------------- /docs/frontend/demo/360-disney/simple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | PhotoSphereViewer - markers demo 7 | 8 | 9 | 10 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/frontend/event.md: -------------------------------------------------------------------------------- 1 | # js 中事件绑定 3 种方法以及事件委托 2 | 3 | ###事件绑定 4 | 首先,我先来介绍我们平时绑定事件的三种方法。 5 | **1.嵌入 dom** 6 | 7 | ```html 8 | 9 | 10 | 15 | ``` 16 | 17 | **2.直接绑定** 18 | 19 | ```html 20 | 21 | 26 | ``` 27 | 28 | **3.事件监听** 29 | 30 | ```html 31 | 32 | 41 | ``` 42 | 43 | ###事件委托 44 | 对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了事件冒泡,只制定一个事件处理程序,就可以管理某一类型的所有事件。例如 click 事件一直会冒泡到 document 层。也就是我们可以只指定 onclick 事件处理程序,而不必给每个事件分别添加处理程序。 45 | **下面我们来看一个阿里巴巴笔试题的例子。** 46 | 47 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506284537.png) 48 | 49 | **样式以及 DOM 结构** 50 | 51 | ```css 52 | 89 | 90 | 91 | 92 |
93 |
94 |
序号
姓名
性别
电话号码
省份
操作
95 |
96 | 101 |
102 | 103 | ``` 104 | 105 | **不用事件委托。**而这种方法造成的代价是,性能的大量浪费。如果是成千上万条数据,**页面将会严重卡顿,甚至崩溃。** 106 | 107 | ```javascript 108 | function Contact() { 109 | this.init(); 110 | } 111 | 112 | Contact.prototype.init = function() { 113 | var userdel = document.querySelectorAll(".user-delete"); 114 | for (var i = 0; i < lis.length; i++) { 115 | (function(j) { 116 | userdel[j].onclick = function() { 117 | userdel[j].parentNode.parentNode.removeChild(userdel[j].parentNode); 118 | }; 119 | })(i); 120 | } 121 | }; 122 | 123 | new Contact(); 124 | ``` 125 | 126 | **使用事件委托**,只绑定一次事件,大大减少了性能的损耗。也是在需要大量事件处理程序中一种非常好的解决方式。 127 | 128 | ```javascript 129 | function Contact() { 130 | this.init(); 131 | } 132 | 133 | Contact.prototype.init = function() { 134 | var lis = document.querySelector("#J_List"); 135 | lis.addEventListener("click", function(e) { 136 | var target = e.target || e.srcElement; 137 | if (!!target && target.className.toLowerCase() === "user-delete") { 138 | target.parentNode.parentNode.removeChild(target.parentNode); 139 | } 140 | }); 141 | }; 142 | 143 | new Contact(); 144 | ``` 145 | -------------------------------------------------------------------------------- /docs/frontend/js-block.md: -------------------------------------------------------------------------------- 1 | # 你不知道的javascript之函数作用域和块作用域(一) 2 | 3 | 4 | ## 立即执行函数表达式(IIFE) ## 5 | ####1.使用匿名函数表达式 6 | ```javascript 7 | var a = 2; 8 | (function IIFE(){ 9 | var a = 3; 10 | console.log(a);//3 11 | })(); 12 | console.log(a);//2 13 | ``` 14 | ####2.当作函数调用并传递参数进去 15 | ```javascript 16 | var a = 2; 17 | (function IIFE(global){ 18 | var a = 3; 19 | console.log(a);//3 20 | console.log(global.a);//2 21 | })(window); 22 | console.log(a);//2 23 | ``` 24 | ####3.解决undefined标识符默认值被错误覆盖 25 | ```javascript 26 | undefined = true; 27 | (function IITF(){ 28 | var a ; 29 | if(a === undefined){ 30 | console.log('Undefined is safe here!'); 31 | } 32 | })(); 33 | ``` 34 | ####4.倒置代码的运行顺序 35 | ```javascript 36 | var a = 2; 37 | (function IFEE(def){ 38 | def(window); 39 | })(function def(global){ 40 | var a = 3; 41 | console.log(a);//3 42 | console.log(global.a);//2 43 | }); 44 | ``` 45 | ## 块作用域 ## 46 | ####for语句,i会被绑定在外部作用域(函数或全局) 47 | 48 | ```javascript 49 | for(var i = 0 ; i < 10 ; i++){ 50 | console.log(i); 51 | } 52 | ``` 53 | ####if语句,当使用var声明变量时,在哪里都一样 54 | 55 | ```javascript 56 | var foo = true; 57 | if(foo){ 58 | var bar = foo*2; 59 | bar = something(bar); 60 | console.log(bar); 61 | } 62 | ``` 63 | ####以下是一个闭包结合自执行函数的实例 64 | ```javascript 65 | var i = 1; 66 | var IFun = (function(){ 67 | var i = 1; 68 | console.log(i); 69 | return function(){ 70 | i++; 71 | console.log(i); 72 | } 73 | })(); 74 | IFun(); 75 | IFun(); 76 | 最终输出的结果为1,2,3,很多会下意识的觉得结果会有4个值,但是运用了return 返回值以及自执行函数将函数返回给IFun变量,使得在第一次操作过程后,将返回函数直接赋给IFun。 77 | ``` -------------------------------------------------------------------------------- /docs/frontend/js-mouse.md: -------------------------------------------------------------------------------- 1 | # javascript中onmousemove、onmouseover、onmouseenter 的不同 2 | 3 | 4 | 在比较onmousemove、onmouseover、onmouseenter 的不同之前,首先我们先看看各种onmouse事件的作用: 5 | 6 | - onmousedown 当元素上按下鼠标按钮时出发 7 | - onmousemove 当鼠标指针移动到水元素上时触发 8 | - onmouseover 当鼠标指针移动元素上时触发 9 | - onmouseout 当鼠标指针移出指定的对象时发生。 10 | - onmouseup 当在元素上释放鼠标按钮时触发 11 | - onmouseenter 事件在鼠标指针移动到元素上时触发。(不冒泡) 12 | - onmouseleave 事件在鼠标移除元素时触发。(不冒泡) 13 | 14 | 要知道onmouseenter 和onmouseleave事件是不冒泡的 15 | 以下例子可以知道onmousemove、onmouseover、onmouseenter的不同之处,以及各个onmouse事件执行先后顺序,在onmouseover、onmouseenter中,over还可以通过子元素的触发。 16 | ```html 17 | 18 | 19 | 20 | 21 | Document 22 | 30 | 31 | 32 |
33 | 34 |
35 |
36 |

onmouseover:
鼠标移动到我这!

37 |
38 |
39 |

onmouseenter:
鼠标移动到我这!

40 |
41 |
42 |

onmousemove:
鼠标移动到我这!

43 |
44 | 45 | 88 | 89 | ``` -------------------------------------------------------------------------------- /docs/frontend/js-op.md: -------------------------------------------------------------------------------- 1 | # 你不知道的javascript之运算符||和&& 2 | 3 | 4 | 学过c,php这些语言的同学在学习javascript时候可能会有一些困扰,因为javascript中的||、&&和c或者是php中有很大的差别。因为在javascript中返回的类型并不是布尔值,他返回的而是两个操作值中之一,例如一下例子: 5 | 6 | ```javascript 7 | var a = 12; 8 | var b = "qwer"; 9 | var c = null; 10 | 11 | a||b; //12; 12 | a&&b; //qwer 13 | c||b; //qwer 14 | c&&b; null 15 | ``` 16 | 看了上面的例子相信大家都应该明白了把。||和&&首先对第一个操作数进行判断,如果其不是布尔值,先会进行强制类型转换,然后在执行条件判断。可以总结为两点: 17 | 18 | - 对于||来说,如果第一个数为真,那么返回第一个数,反之则为第二个数。 19 | - 而对于&&来说,如果第一个数为真,那么返回第二个数,反之则为第一个数。 20 | 21 | 上述中,c&&b,c为null,为假值,所以返回为第一个数,为null。 22 | 23 | 换一个角度来说就是这样: 24 | 25 | ```javascript 26 | a||b 相当于 a?a:b 27 | a&&b 相当于 a?b:a 28 | 29 | ``` 30 | 31 | 下面是一个常用的例子,相信大家都用过 32 | 33 | ```javascript 34 | function come(a,b){ 35 | a = a|| "hello"; 36 | b = b|| "world"; 37 | } 38 | come(); //"hellow world" 39 | come("happy","newyear");//"happy newyear" 40 | ``` 41 | 42 | a = a||"hello"检查变量a是否赋值,如果还未赋值,就给定一个默认值“hello”。 43 | 44 | 还有一种模式,在开发过程中不常见,但是在压缩工具中常见。 45 | 46 | ```javascript 47 | function come (){ 48 | console.log(a); 49 | } 50 | var a = 12; 51 | a&&come();//12 52 | ``` 53 | 而在日常开发中比较常用的确是 54 | 55 | ```javascript 56 | if(a){ 57 | come(); 58 | } 59 | ``` 60 | 但是相比,a&&come()更加简洁。 61 | 62 | 可能你会问为什么在javascript中返回的是值而不是布尔值,那为什么还有a&&(b||c)这样的式子成立呢,因为在javascript中在这些判断式中会执行隐式强制转化。例如 63 | 64 | ```javascript 65 | var a = 12; 66 | var b = null; 67 | var c = "hello"; 68 | if(a&&(b||c)){ 69 | console.log('yeah'); 70 | } 71 | ``` 72 | 这里a&&(b||c)的结果实际上是“hello”,然后由if将"hello"强转化为布尔值,所以最后结果为true。 73 | 74 | -------------------------------------------------------------------------------- /docs/frontend/js-proto2.md: -------------------------------------------------------------------------------- 1 | # 你不知道的 javascript 之 JS 原型对象和原型链 2 | 3 | ##**开篇** 4 | 之前对 js 中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述。有一句话说的好:如果你不能把一个很复杂的东西用最简单的话语描述出来,那就说明你没有真正的理解。最近正在读《Javascript 高级程序设计》,书中对原型对象和原型链的描述让我受益匪浅,下面仅用一个对比性的例子来说明。 ##**我们经常会这么写** 5 | 6 | ```javascript 7 | function Person() { 8 | this.name = "John"; 9 | } 10 | var person = new Person(); 11 | Person.prototype.say = function() { 12 | console.log("Hello," + this.name); 13 | }; 14 | person.say(); //Hello,John 15 | ``` 16 | 17 | 上述代码非常简单,Person 原型对象定义了公共的 say 方法,虽然此举在构造实例之后出现,但因为原型方法在调用之前已经声明,因此之后的每个实例将都拥有该方法。从这个简单的例子里,我们可以得出: 18 | **原型对象的用途是为每个实例对象存储共享的方法和属性,它仅仅是一个普通对象而已**。并且所有的实例是共享同一个原型对象,因此有别于实例方法或属性,原型对象仅有一份。所有就会有如下等式成立: 19 | 20 | ```javascript 21 | person.say == new Person().say; 22 | ``` 23 | 24 | ##**可能我们也会这么写** 25 | 26 | ```javascript 27 | function Person() { 28 | this.name = "John"; 29 | } 30 | var person = new Person(); 31 | Person.prototype = { 32 | say: function() { 33 | console.log("Hello," + this.name); 34 | }, 35 | }; 36 | person.say(); //person.say is not a function 37 | ``` 38 | 39 | 很不幸,person.say 方法没有找到,所以报错了。其实这样写的初衷是好的:因为如果想在原型对象上添加更多的属性和方法,我们不得不每次都要写一行 Person.prototype,还不如提炼成一个 Object 来的直接。但是此例子巧就巧在构造实例对象操作是在添加原型方法之前,这样就会造成一个问题: 40 | 当 var person = new Person()时,Person.prototype 为:Person {}(当然了,内部还有 constructor 属性),即 Person.prototype 指向一个空的对象{}。而对于实例 person 而言,其内部有一个原型链指针 proto,该指针指向了 Person.prototype 指向的对象,即{}。接下来重置了 Person 的原型对象,使其指向了另外一个对象,即 41 | Object {say: function}, 42 | 这时 person.proto 的指向还是没有变,它指向的{}对象里面是没有 say 方法的,因为报错。 43 | 从这个现象我们可以得出: 44 | **在 js 中,对象在调用一个方法时会首先在自身里寻找是否有该方法,若没有,则去原型链上去寻找,依次层层递进,这里的原型链就是实例对象的**proto**属性。** 45 | 46 | 若想让上述例子成功运行,最简单有效的方法就是交换构造对象和重置原型对象的顺序,即: 47 | 48 | ```javascript 49 | function Person() { 50 | this.name = "John"; 51 | } 52 | Person.prototype = { 53 | say: function() { 54 | console.log("Hello," + this.name); 55 | }, 56 | }; 57 | var person = new Person(); 58 | person.say(); //person.say is not a function 59 | ``` 60 | 61 | ##**一张图让你秒懂原型链** 62 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506284317.jpg) 63 | 其实,只需要明白原型对象的结构即可: 64 | 65 | ```javascript 66 | Function.prototype = { 67 | constructor : Function, 68 | __proto__ : parent prototype, 69 | some prototype properties: ... 70 | }; 71 | ``` 72 | 73 | **总结:函数的原型对象 constructor 默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针**proto**,该指针指向上一层的原型对象,而上一层的原型对象的结构依然类似,这样利用**proto**一直指向 Object 的原型对象上,而 Object 的原型对象用 Object.**proto** = null 表示原型链的最顶端,如此变形成了 javascript 的原型链继承,同时也解释了为什么所有的 javascript 对象都具有 Object 的基本方法。** 74 | -------------------------------------------------------------------------------- /docs/frontend/js-sort.md: -------------------------------------------------------------------------------- 1 | # js 实现表格排序 2 | 3 | 用 js 实现表格排序。 4 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506284765.png) 5 | 第一点击以降序排列,第二次点击以升序排列 6 | html 代码 7 | 8 | ```html 9 | 10 | 11 | 12 | 13 | Document 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
学号名字成绩
1002小铭34
1003小红64
1004小黄24
1005小米53
1006小蒋78
1007小捷97
1004小邓65
58 | 59 | 60 | ``` 61 | 62 | js 代码 63 | 64 | ```javascript 65 | 116 | ``` 117 | -------------------------------------------------------------------------------- /docs/frontend/js-this.md: -------------------------------------------------------------------------------- 1 | # 你不知道的javascript之this的全面解析之绑定规则(一) 2 | 3 | 4 | ##1.1 默认绑定 5 | 首先介绍的是函数调用类型:独立函数调用,在没有其他应用下的默认规则。 6 | 首先看以下代码 7 | ```javascript 8 | function foo(){ 9 | console.log(this.a); 10 | } 11 | var a = 2; 12 | foo();//2 13 | ``` 14 | 我们可以看到调用foo()时,this.a被解析成了全局变量a,为什么,因为在上述例子中,函数调用了默认绑定,因此this指向了全局对象。 15 | 那么我们怎么知道这里应用了默认绑定呢?可以通过分析调用位置来看看foo()是如何调用的。在代码中,foo()是直接使用不带任何修饰的函数引用进行调用的,因此只能使用默认绑定,无法应用其他规则。 16 | 如果使用严格模式,则不能将全局对象用于默认绑定,因此this会绑定undefind: 17 | 18 | ```javascript 19 | function foo(){ 20 | "use strict "; 21 | console.log(this.a); 22 | } 23 | var a = 2; 24 | foo();//TyoeError:this is undefind 25 | ``` 26 | ##1.2 隐式绑定 27 | 另一条规则是调用的位置是否有上下文对象,或者说是否被某个对象拥有或者包含,不过这种说法可能会造成一些误导。 28 | 29 | ```javascript 30 | function foo(){ 31 | console.log(this.a ); 32 | } 33 | var obj = { 34 | a : 2, 35 | foo:foo 36 | }; 37 | obj.foo();//2 38 | ``` 39 | 首先需要注意的是foo()的声明方式,及其之后是如何被当作引用属性添加到obj中的,但是无论是直接在obj中定义还是先定义再添加引用属性,这个函数严格来说都不属于obj对象。 40 | 然而,调用位置会使用obj上下文来引用函数,因此你可以说函数被调用时obj对象“拥有”或者“包含”它。 41 | 无论你如何称呼,当foo()被调用时,它的前面确实加上了对obj的引用,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。 42 | 对象属性引用链只有上一层或者说最后一层在调用中起作用。 43 | 44 | ```javascript 45 | function foo(){ 46 | console.log(this.a); 47 | } 48 | 49 | var obj = { 50 | a : 12, 51 | foo : foo 52 | } 53 | 54 | var obj2 = { 55 | a : 2, 56 | obj : obj 57 | } 58 | 59 | obj2.obj.foo()//12 60 | ``` 61 | ###1.2.1 隐式丢失 62 | type1 : 63 | 64 | ```javascript 65 | function foo(){ 66 | console.log(this.a); 67 | } 68 | 69 | var obj = { 70 | a : 2, 71 | foo : foo     72 | } 73 | 74 | var bar = obj.foo; 75 | var a = "happy new year"; 76 | bar ();//happy new yaer 77 | ``` 78 | type2 : 79 | 80 | ```javascript 81 | function foo(){ 82 | console.log(this.a); 83 | } 84 | 85 | function doFoo(fn){ 86 | fn(); 87 | } 88 | 89 | var obj = { 90 | a : 2, 91 | foo:foo 92 | } 93 | 94 | var a = "hello world"; 95 | 96 | doFoo(obj.foo)//hello world 97 | ``` 98 | type3 : 99 | 100 | ```javascript 101 | function foo (){ 102 | console.log(this.a); 103 | } 104 | 105 | var obj = { 106 | a : 2, 107 | foo : foo 108 | } 109 | var a = "gril !"; 110 | setTimeout(obj.foo,1000);//gril ! 111 | ``` 112 | 大家看了上述对this的解释,是否对this有了更加深刻的了解了呢?尽请看下期。 113 | 114 | 115 | -------------------------------------------------------------------------------- /docs/frontend/js-type.md: -------------------------------------------------------------------------------- 1 | # 你不知道的 javascript 之 node 类型详解 2 | 3 | 前段时间有做过一个关于节点操作的排序问题, 4 | [http://blog.csdn.net/blueblueskyhua/article/details/68929578](http://blog.csdn.net/blueblueskyhua/article/details/68929578) 5 | 今天就 node 类型,进行详细的讲解。首先看下他的兼容性。 6 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506284759.png) 7 | node 共有 12 类型。 8 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506284764.png) 9 | 类型详情可以参考[http://www.w3school.com.cn/jsref/prop_node_nodetype.asp](http://www.w3school.com.cn/jsref/prop_node_nodetype.asp) 10 | **1.nodeValue 和 nodeName** 11 | 其中最常用的就是 1 和 3,那今天我们就 1 和 3 来展开讲解,了解节点的属性主要有 nodeValue 和 nodeName 两个属性。分别获取节点类型和节点的名字。 12 | **2.节点关系** 13 | 每个节点含有 childNodes 属性,其中保存着一个 NodeList 对象,NodeList 对象是一个类数组对象,用于保存有序的节点,可以通过位置来访问。虽然可以用过方括号来访问 NodeList 的值,而且这个对象也有 length 属性,但是它并不是一个 Array 的实例。 14 | 15 | ```javascript 16 | //展示节点访问 17 | var node1 = node.childNodes[0]; 18 | var node2 = node.childNodes.item(0); 19 | var length = node.childNodes.length; 20 | ``` 21 | 22 | 如果需要操作 NodeList 就需要将它转化成数组。我就是因为一开始不知道他是个类数组对象,将他一直以数组进行操作,利用 slice 进行删除,怎么都删除不了。下面我就讲讲转化为数组的方法。 23 | 24 | ```javascript 25 | function ToArray(nodes) { 26 | var array = null; 27 | try { 28 | array = Array.prototype.slice.call(nodes, 0); 29 | } catch (ex) { 30 | array = new Array(); 31 | for (var i = 0; i < nodes.length; i++) { 32 | array.push(node[i]); 33 | } 34 | } 35 | return array; 36 | } 37 | ``` 38 | 39 | 通过转化成数组,可以进行一些常见的操作,例如表单排序,删除等操作。 40 | 下面用一张图讲解一些关于 node 的父子兄弟节点的关系。 41 | 42 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506286331.jpg) 43 | 44 | **3.操作节点** 45 | appendChild,用于向 childeNodes 的尾部追加一个节点。 46 | 47 | ```html 48 | 54 | 59 | ``` 60 | 61 | 追加前 62 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506284398.png) 63 | 追加后 64 | ![这里写图片描述](https://s3.mdedit.online/blog/1579506284907.png) 65 | 66 | insertBefore,接受两个参数:要插入的节点和参照的节点。 67 | 68 | ```javascript 69 | //插入后成为最后一个节点 70 | returnedNode = someNode.insertBefore(newNode, null); 71 | //插入后成为第一个节点 72 | returnedNode = someNode.insertBefore(newNode, someNode.firstNode); 73 | //插入到最后一个节点前面 74 | returnedNode = someNode.insertBefore(newNode, some.lastChild); 75 | ``` 76 | 77 | 这里需要防坑 78 | 79 | ```html 80 | 86 | ``` 87 | 88 | 以上获得的 childNodes 个数为 9 个。因为 Chrome、Firefox、IE9+等标准浏览器下,使用 childNodes 获取节点,它会将空格符、回车符、换行符也看做一个文本节点,而 IE8 及以下,则会无视空格、回车符。 89 | 所以,想要获取正确的节点个数。 90 | 需要使得 node.nodeType === 1 来过滤空白节点。 91 | replaceChild,接受两个参数:要插入的节点和要替换的节点。 92 | 93 | ```javascript 94 | //替换第一个子节点 95 | var returnedNode = someNode.replaceChild(newNode, someNode.firstChild); 96 | ``` 97 | -------------------------------------------------------------------------------- /docs/frontend/js-upload.md: -------------------------------------------------------------------------------- 1 | # 原生JS实现ajax上传文件并显示进度条 2 | 3 | html代码 4 | 5 | ```html 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 | ``` 14 | css代码 15 | ```css 16 | #fileimg{ 17 | width:300px; 18 | height: 300px; 19 | overflow: hidden; 20 | border:1px solid #ddd; 21 | position: relative; 22 | } 23 | #fileimg img { 24 | width: 100%; 25 | position: absolute; 26 | top:0; 27 | left: 0; 28 | z-index: 1; 29 | } 30 | #loading-cover{ 31 | width: 300px; 32 | height: 300px; 33 | position: absolute; 34 | background: rgba(0,0,0,0.3); 35 | top:0; 36 | left: 0; 37 | z-index: 2; 38 | } 39 | #showloading{ 40 | width: 300px; 41 | position: absolute; 42 | bottom: 0; 43 | text-align: center; 44 | z-index: 3; 45 | } 46 | ``` 47 | 48 | js代码 49 | 50 | ```javascript 51 | function uploadFile(){ 52 | var fileObj = document.getElementById('file').files[0]; 53 | showImg(fileObj); 54 | if(fileObj){ 55 | var url = "uploadimage.jsp"; 56 | var form = new FormData(); 57 | form.append('myfile',fileObj); 58 | xhr = new XMLHttpRequest(); 59 | xhr.open("post",url,true); 60 | xhr.onload = uploadComplete; //请求完成 61 | xhr.onerror = uploadFailed; //请求失败 62 | xhr.upload.onprogress = progressFunction; 63 | xhr.send(form); 64 | }else{ 65 | alert('请选择文件'); 66 | } 67 | } 68 | 69 | function showImg(fileObj){ 70 | var fileimg = document.getElementById('fileimg'); 71 | var src = window.URL.createObjectURL(fileObj); 72 | var img = document.createElement("img"); 73 | img.src = src; 74 | fileimg.appendChild(img); 75 | } 76 | function progressFunction(evt){ 77 | var loadingCover = document.getElementById('loading-cover'); 78 | var showloading = document.getElementById('showloading'); 79 | var progressBar = document.getElementById('progressbar'); 80 | var percentage = document.getElementById('percentage'); 81 | if(evt.lengthComputable){ 82 | progressbar.max = evt.total; 83 | progressBar.value = evt.loaded; 84 | var loading = Math.round(evt.loaded / evt.total * 100); 85 | percentage.innerHTML = loading + '%'; 86 | showloading.innerHTML = loading + '%'; 87 | loadingCover.style.top = -loading + '%'; 88 | if(loading==100){ 89 | showloading.style.display = 'none'; 90 | } 91 | } 92 | } 93 | function uploadComplete(evt) { 94 | //服务断接收完文件返回的结果 95 | // alert(evt.target.responseText); 96 | console.log("上传成功!"); 97 | } 98 | //上传失败 99 | function uploadFailed(evt) { 100 | console.log(evt); 101 | } 102 | ``` 103 | 104 | github地址:https://github.com/hua1995116/UploadLoading/(包含后台代码) -------------------------------------------------------------------------------- /docs/frontend/meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "从源码安装谷歌浏览器插件", 4 | "date": "2022-03-15 22:33:54", 5 | "path": "chrome-extension-source-install", 6 | "keywords": "chrome-extension", 7 | "description": "3个步骤搞定从源码安装 chrome 插件。" 8 | }, 9 | { 10 | "title": "ES2017 异步函数最佳实践(`async` /`await`)", 11 | "date": "2020-08-06 22:33:54", 12 | "path": "best-practices-aysnc" 13 | }, 14 | { 15 | "title": "ES6 Promise 的最佳实践", 16 | "date": "2020-07-31 22:33:54", 17 | "path": "best-practices-es6-promise" 18 | }, 19 | { 20 | "title": "[重拾CSS]一道面试题来看伪元素、包含块和高度坍塌", 21 | "date": "2020-05-19 22:33:54", 22 | "path": "collapsing-margins" 23 | }, 24 | { 25 | "title": "10种跨域解决方案(附终极方案)", 26 | "date": "2020-04-13 20:12:54", 27 | "path": "cors" 28 | }, 29 | { 30 | "title": " [译] Object.assign 和 Object Spread 之争, 用谁?", 31 | "date": "2020-03-30 10:41:15", 32 | "path": "assign-spread" 33 | }, 34 | { 35 | "title": " 教你如何搭建一个自动化构建的博客", 36 | "date": "2020-03-30 10:42:28", 37 | "path": "blog" 38 | }, 39 | { 40 | "title": " css实现左边定宽右边自适应的两列布局5种方法", 41 | "date": "2020-03-30 10:42:43", 42 | "path": "css-lianglie" 43 | }, 44 | { 45 | "title": " css3实现圆环加载进度条动画", 46 | "date": "2020-03-30 10:43:13", 47 | "path": "css-loading" 48 | }, 49 | { 50 | "title": " debounce与throttle实现与原理", 51 | "date": "2020-03-30 10:45:34", 52 | "path": "debounce" 53 | }, 54 | { 55 | "title": " 🎉喜大普奔,ES2019登场", 56 | "date": "2020-03-30 10:22:03", 57 | "path": "es2019" 58 | }, 59 | { 60 | "title": " js中事件绑定3种方法以及事件委托", 61 | "date": "2020-03-30 10:48:45", 62 | "path": "event" 63 | }, 64 | { 65 | "title": " 你不知道的javascript之函数作用域和块作用域(一)", 66 | "date": "2020-03-30 11:37:12", 67 | "path": "js-block" 68 | }, 69 | { 70 | "title": " javascript中onmousemove、onmouseover、onmouseenter 的不同", 71 | "date": "2020-03-30 11:37:44", 72 | "path": "js-mouse" 73 | }, 74 | { 75 | "title": " 你不知道的javascript之运算符||和&&", 76 | "date": "2020-03-30 11:37:57", 77 | "path": "js-op" 78 | }, 79 | { 80 | "title": " 你不知道的js类型转化和原型链", 81 | "date": "2020-03-30 11:38:22", 82 | "path": "js-proto" 83 | }, 84 | { 85 | "title": " 你不知道的javascript之JS原型对象和原型链", 86 | "date": "2020-03-30 11:40:35", 87 | "path": "js-proto2" 88 | }, 89 | { 90 | "title": " js实现表格排序", 91 | "date": "2020-03-30 11:38:32", 92 | "path": "js-sort" 93 | }, 94 | { 95 | "title": " 你不知道的javascript之this的全面解析之绑定规则(一)", 96 | "date": "2020-03-30 11:38:34", 97 | "path": "js-this" 98 | }, 99 | { 100 | "title": " 你不知道的javascript之node类型详解", 101 | "date": "2020-03-30 11:38:50", 102 | "path": "js-type" 103 | }, 104 | { 105 | "title": " 原生JS实现ajax上传文件并显示进度条", 106 | "date": "2020-03-30 11:39:40", 107 | "path": "js-upload" 108 | }, 109 | { 110 | "title": " web上的原生图片懒加载(译)", 111 | "date": "2020-03-30 11:39:48", 112 | "path": "lazy-img" 113 | } 114 | ] -------------------------------------------------------------------------------- /docs/frontend/tc39/type.md: -------------------------------------------------------------------------------- 1 | https://juejin.im/post/6860350998720970760#heading-4 2 | 3 | https://juejin.im/post/6873215243804213262#comment -------------------------------------------------------------------------------- /docs/git/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [几个提高幸福度的 Git 命令](./git-10-up.md) 5 | 6 | [git stderr(错误流)探秘](./git-err.md) 7 | 8 | [Github 备份到 Gitee 的3种方式](./gitee-guide.md) -------------------------------------------------------------------------------- /docs/git/meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "几个提高幸福度的 Git 命令", 4 | "date": "2021-03-25 22:33:54", 5 | "path": "git-10-up", 6 | "keywords": "git", 7 | "description": "" 8 | }, 9 | { 10 | "title": "git stderr(错误流)探秘", 11 | "date": "2020-05-25 22:33:54", 12 | "path": "git-err", 13 | "keywords": "git", 14 | "description": "" 15 | }, 16 | { 17 | "title": "Github 备份到 Gitee 的3种方式", 18 | "date": "2022-05-25 22:33:54", 19 | "path": "gitee-guide", 20 | "keywords": "git", 21 | "description": "" 22 | } 23 | ] 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/grow/README.md: -------------------------------------------------------------------------------- 1 | 2 | [2022 前端学习路径书单—自我成长之路](./frontend-books.md) 3 | 4 | [前端学习历程](./learn.md) -------------------------------------------------------------------------------- /docs/grow/learn.md: -------------------------------------------------------------------------------- 1 | # 前端学习历程 2 | 3 | 4 | # 前言 5 | 还记得刚接触前端应该是两年前了吧。我就顺着回忆,慢慢写下我对前端的学习路程以及一些资源。 6 | # 初入坑 7 | ## html/css基础 8 | 这个是学习前端最基础的部分了。一开始看的是[W3cschool](http://www.w3school.com.cn/),先看其中的html和css基础部分,一些常用标签,以及css中的盒子模型,定位的几种方式,几种选择器。我大概花了一周左右的时间学习。然后便开始做练手项目,比如你先模仿百度首页,学会之后再模仿天猫或者是京东首页,具体看个人喜好。 9 | 学习完以上部分,做出一个个案例,我觉得你自身会获得一些成就感。 10 | ## javascript(简称js) 11 | js可以说是前端学习中最重要的一个部分。在这里就不得不提一个学习js的圣地。[智能社](http://www.zhinengshe.com/video.html)这一套js可以说是非常的好,讲课老师非常的生活,让你理解起来也非常的舒服。看完这一套视频,跟着他做一些案例,我觉得你也会有非常大的收获。这个你能够做前端一些最基本的东西,一个页面,甚至可以写一些进行交互性的js。 12 | ## ps(切图) 13 | photoshop其实也是一个前端程序员,必须会的一样东西,在你一个人进行开发的时候,你肯定需要对一些图片进行裁剪,一般在小公司的话,前端来切图居多。 14 | 学习到这里,你可能觉得,哎,前端原来还是蛮简单的,呵呵,那你就错了,前端这个东西,操作起来,看似简单,实则暗藏杀机。我们接下来看。 15 | 16 | # 再来好好学学 17 | ## 深入html 18 | 之前我们说的html都是html4.0版本,所以为了能更加深入的了解html,我们必须学会html5。我这边有一套html5 的视频,我觉得是不错的,[html视频](https://pan.baidu.com/s/1kUYCkGv) (密码: 3h8r)。 19 | ## 深入css 20 | 之前说的css也是一样,基于2.0,对css3。我也没有特别好的资源,我当时看的是极客学院的css3。大家可以试试看,[css教程](http://www.jikexueyuan.com/course/966.html),如果大家有更好的资源的话,可以私信,或者留言,供大家一起学习。 21 | ## 深入javascript 22 | 对于上完以上javascript的人来说,我觉接下来的话,可以看一些书籍了,我最先看的是《javascript高级程序设计》第三版,看完,你就会对js有一个系统的认识。 23 | 学习完以上,我同样希望你能够自己做一个案例,这一次,你可以试着做一整个系统。至于是什么,你自己定吧。 24 | 慕课网上也有案例,你可以自己打一遍,[教程](http://www.imooc.com/learn/100) 25 | ## 认识jquery 26 | 虽然说现在mvvm的时代,但是不管怎么说jqury已然是一个非常经典的框架,解放了劳动力。jquery的话,我还是一样推荐看极客学院。 27 | ## 认识boostrap 28 | 这个也是一个框架,css的框架,也是有着解放劳动力之称。同样可以看极客学院。 29 | ## 了解响应式布局,和移动端页面开发 30 | 这个我推荐看,李炎恢的一个[html5的教程](http://class.qq.com/class/11399.html),看下面的实战部分就好了。 31 | 我们再来总结一些,别以为学习完上面的就已经差不多了,如果是开发几个页面,那是差不多了,当一个合格的前端工程师,那还是刚入门。 32 | # 进阶一下 33 | ## 关于css 34 | css可以说内容非常的多,关于选择器的层级关系,定位,以及一些块级元素和行内元素的区别。这个需要你自己慢慢去摸索,这一部分,慕课网上也有相应的视频,你可以看上面的标题,然后去百度一些文字形式的回答。 35 | [慕课网视频](http://www.imooc.com/course/list?c=html&type=1) 36 | ## node.js 37 | Node.js是一个Javascript运行环境(runtime),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js对一些特殊用例进行优化,提供替代的API,使得V8在非浏览器环境下运行得更好。 38 | 推荐书籍: 39 | [《Nodejs入门》](https://www.nodebeginner.org/index-zh-cn.html) 40 | 《深入浅出NodeJs》 41 | 教程: 42 | [从零开始nodejs系列文章](http://blog.fens.me/series-nodejs/) 43 | [饿了么面试文档](https://github.com/ElemeFE/node-interview) 44 | 如果你英语比较好,也可以看官网,[https://nodejs.org/en/](https://nodejs.org/en/) 45 | 视频教程: 46 | 1:进击Node.js基础(一)-慕课网NodeJs教程 47 | 2:进击Node.js基础(二)-慕课网 48 | Mongodb视频教程 49 | 3:mongoDB入门篇_mongoDB入门视频教程-慕课网 50 | ## 移动端框架zepto 51 | 这个框架和jquery非常类似,可以去看看。 52 | ## 打包工具grunt,gulp,webpack 53 | 现在最为流行的是webpack,这个教程,我也没有深入的研究,就请大家,自行百度吧。 54 | ## git 55 | Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git的读音为/gɪt/。 Git是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到非常大的项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 56 | [git常用命令](http://www.cnblogs.com/cspku/articles/Git_cmds.html) 57 | 开源托管平台:[github](https://github.com/) 58 | 59 | 到这里,你应该对前端有了一个大概的了解,具体要做些什么。 60 | # 冲刺 61 | ## 进阶css 62 | 推荐书籍: 63 | css揭秘 64 | ## 进阶javascript 65 | 推荐书籍: 66 | 你不知道的javascript(上,中) 67 | javascript设计模式(张容铭) 68 | ## vue,angular,react 69 | 这是最近现在最流行的用来实现单页操作的框架。 70 | vue 71 | vue官方学习网站: 72 | https://cn.vuejs.org/ 73 | vue-router: 74 | https://router.vuejs.org/zh-cn/index.html 75 | vuex: 76 | https://vuex.vuejs.org/zh-cn/ 77 | react 78 | react官方学习网站: 79 | https://facebook.github.io/react/ 80 | react-router,redux自行百度。 81 | ## 算法 82 | 推荐书籍: 83 | 算法导论 84 | ## 操作系统,linux 85 | 推荐书籍: 86 | 暂无 87 | ## 计算机网络 88 | 推荐书籍: 89 | 计算机网络 90 | 图解http 91 | # 超神 92 | 多看一些开源框架的源码。例如vue,react,jquery之类的。以及多一些实践。熟练运用算法,掌握底层实现原理。 93 | 94 | # 结尾 95 | 1。不会问题,多百度,多谷歌。 96 | 2。多逛一些技术论坛,csdn,知乎,掘金,博客园,简书。 97 | 3。多看一些大咖的博客,阮一峰,廖雪峰,张旭鑫等等 98 | 4。常用视频教程网站,慕课网,智能社,汇智网,后盾网,腾讯课程,51cto学院,极客学院。 99 | (文中不足之处望大家见谅与大胆指出) -------------------------------------------------------------------------------- /docs/grow/meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "前端学习历程", 4 | "date": "2019-03-25 22:33:54", 5 | "path": "learn", 6 | "keywords": "前端学习历程", 7 | "description": "" 8 | }, 9 | { 10 | "title": "2022 前端学习路径书单—自我成长之路", 11 | "date": "2022-05-25 22:33:54", 12 | "path": "frontend-books", 13 | "keywords": "前端学习路径书单", 14 | "description": "" 15 | } 16 | ] 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/interview/README.md: -------------------------------------------------------------------------------- 1 | # 面试 2 | 3 | [送你一道字节前端原题(Add sumOf)](./bytedance-add-sumOf.md) 4 | 5 | [2018前端校招总结(拿到网易,美团offer)](./interview.md) 6 | 7 | [2018网易前端实习笔试题](./interview2.md) 8 | 9 | [关于2018网易游戏web前端实习生面试经历](./interview3.md) 10 | 11 | -------------------------------------------------------------------------------- /docs/interview/bytedance-add-sumOf.md: -------------------------------------------------------------------------------- 1 | # 送你一道字节前端原题(Add sumOf) 2 | 3 | ## 前言 4 | 5 | 最近学弟去面了字节跳动,但是由于面试经验少,面试的时候紧张了,一时之间没有写出来,之后来我交流了一下。那我就来分析分析这道题目。 6 | 7 | ![image-20200906001022824](https://s3.mdedit.online/blog/image-20200906001022824.png) 8 | 9 | ## 正文 10 | 11 | 这题的规则是这样的 12 | 13 | ```js 14 | 给定有一个 Add 函数,要支持以下形式的调用 15 | 16 | Add(1)(2)(3).sumOf(); // 输出 6 17 | Add(1,2)(3)(4).sumOf(); // 输出 10 18 | Add(1,2,...)(3)(4)(...).sumOf(); // ... 19 | ``` 20 | 21 | 拿到这种题目,我先来说说我自己的做题流程,一般会去找它最简单的形态。我们一步一步来拆解。 22 | 23 | 先去掉 `sumOf()` 变成了以下形态 24 | 25 | ``` 26 | Add(1,2,...)(3)(4)(...) 27 | ``` 28 | 29 | 嗯....有点熟悉...但是还是有点复杂,那我们再去掉无限调用这个限制。 30 | 31 | ``` 32 | Add(1,2,...)(3)(4) 33 | ``` 34 | 35 | 唔,还是有点难呀...没关系,再砍, 不要传入多个参数。 36 | 37 | ```js 38 | Add(1)(2)(3); 39 | ``` 40 | 41 | 有....有....有那味了....这....这不就是柯里化吗.... 42 | 43 | 有些小朋友可能没有听过,对于大朋友而言耳熟能详,融会贯通。 44 | 45 | 我们还是来介绍一下。 46 | 47 | 在《javascript 高级程序设计》这本书中有如下介绍: 48 | 49 | > 与函数绑定紧密相关的主题是函数柯里化,它用于创建已经设置好的一个或者多个参数的函数。函数柯里化的基本方法和函数绑定是一样的:使用一个闭包返回一个函数。两者的区别在于,当函数被调用时,返回的函数还需要设置一些传入的参数。 50 | 51 | 我们来写写看: 52 | 53 | ```js 54 | function Add(x) { 55 | return function (y) { 56 | return return functio (z) { 57 | return x + y + z; 58 | } 59 | } 60 | } 61 | // 简洁写法 62 | const Add = x => y => z => x+y+z; 63 | ``` 64 | 65 | 执行一下 66 | 67 | ``` 68 | Add(1)(2)(3) // 6 69 | ``` 70 | 71 | 是我们要的那味~ 72 | 73 | 那么我们既然已经写出了这个形态,我们就一步一步反推。 74 | 75 | > 这个时候千万别紧张,我们从最低级的形态出发,写出一个最基本的形态,能够有效地帮助我们建立自信心,吃下定心丸,按照这种方式,哪怕我们最终没有写出完美的结果,让面试官看到你思考解题的过程,也是一种加分。 76 | 77 | 好,接着说~ 78 | 79 | 那我们接下来需要实现这个样子。 80 | 81 | ``` 82 | Add(1,2,...)(3)(4) 83 | ``` 84 | 85 | 传入参数不止一个 86 | 87 | 我们知道,对于不确定参数个数,我们可以使用 `arguments` 这个对象来获取到所有的入参,但是 `arguments` 不是一个 `Array`,但是我们可以使用 ES6 中的 **Spread syntax** (**展开语法**)去将他变成一个数组。表演继续。 88 | 89 | ```js 90 | function Add() { 91 | const nums = [...arguments]; 92 | return function() { 93 | nums.push(...arguments); 94 | return function() { 95 | nums.push(...arguments); 96 | return nums.reduce((a, b) => a + b); 97 | }; 98 | }; 99 | } 100 | ``` 101 | 102 | nice!已经离我们最终的形态越来越近了。接下来是这个函数能够无限的进行调用。 103 | 104 | ``` 105 | Add(1,2,...)(3)(4)(...) 106 | ``` 107 | 108 | 那么怎么样才能无限调用呢?没错,用递归。 109 | 110 | ```js 111 | function Add() { 112 | const nums = [...arguments]; 113 | function AddPro() { 114 | nums.push(...arguments); 115 | return AddPro; 116 | } 117 | return AddPro; 118 | } 119 | ``` 120 | 121 | 嗯,其实我们写到这里发现了... 由于是无限递归,我们没办法确定最后一次函数调用,因此我们需要最后显式调用一个结束的方法来打印出最后的数据。 122 | 123 | 很自然地,我们可以在 `AddPro` 添加一个方法 `sumOf` 来解决这个问题。 124 | 125 | > 学弟就是卡在这里地方,被函数添加上一个方法搞懵了。你是否知道呢? 126 | 127 | ```js 128 | function Add() { 129 | const nums = [...arguments]; 130 | function AddPro() { 131 | nums.push(...arguments); 132 | return AddPro; 133 | } 134 | AddPro.sumOf = () => { 135 | return nums.reduce((a, b) => a + b); 136 | }; 137 | return AddPro; 138 | } 139 | ``` 140 | 141 | 好啦好啦,结束啦。 142 | 143 | 等等 144 | 145 | 在最后,我再来补充一种方案,`function` 不仅可以继续挂载 `function` ~ 还可以挂载变量哦~ 146 | 147 | ```js 148 | function Add() { 149 | if (!Add.nums) { 150 | Add.nums = []; 151 | } 152 | Add.nums.push(...arguments); 153 | return Add; 154 | } 155 | Add.sumOf = () => { 156 | return Add.nums.reduce((a, b) => a + b); 157 | }; 158 | ``` 159 | 160 | 如果上述回答有更优解,请公众号后台回复,留下你的微信,红包相送。 161 | 162 | 我们总结一下,小小的面试题涉及到的基础知识。 163 | 164 | **闭包、递归、作用域、函数与对象** 165 | 166 | 基础就是基础,永远是你爸爸,掌握好基础,以不变应万变。 167 | 168 | ## 一个彩蛋 169 | 170 | ```js 171 | function Add() { 172 | const nums = [...arguments]; 173 | return () => { 174 | nums.push(...arguments); 175 | return () => { 176 | nums.push(...arguments); 177 | return nums.reduce((a, b) => a + b); 178 | }; 179 | }; 180 | } 181 | // 如果我上述代码中间换成箭头函数又会怎么样呢~,公众号号后台回复自己的理解,抽取2位优秀回答者送红包(6.6元)哦~大朋友就别来了~ 182 | ``` 183 | 184 | ## 后记 185 | 186 | 也许你觉得这题有点简单,通过简单的重复练习就能轻松记住,但是最主要的是思路,很多事情都是一样,掌握事情的方法和方向是最重要的。毕竟淘宝也不是一蹴而就的~ 但是只要方向正确了,都会好起来的。 187 | -------------------------------------------------------------------------------- /docs/interview/interview.md: -------------------------------------------------------------------------------- 1 | # 2018前端校招总结(拿到网易,美团offer) 2 | 3 | # 引言 4 | 5 | 可以说自己从找工作是从今年的3月份开始的,面试一直拉锯到现在,整整8个月,拿到了美团,网易,51信用卡,有赞的offer。面试的公司也不计其数,数了下知名的大概有,阿里巴巴,网易,网易游戏,美团,京东,有赞,51信用卡等。最终也拿到了满意的offe,校招已经告一段落。现在细细总结下面试的经验。 6 | 7 | 8 | 9 | # 网易 10 | 11 | ### 一面 12 | 13 | 一面是电话面试。 14 | 15 | 1.css盒子模型 16 | 17 | 2.浮动清除,清除原理 18 | 19 | 3.js基本数据类型,引用类型 20 | 21 | 4.事件循环机制(macro-task大概包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。micro-task大概包括: process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性) 22 | 23 | 5.react,vue和普通的区别 24 | 25 | 6.jquery和jquery.fn(有什么区别,方法是写在哪里的) 26 | 27 | 7.订阅模式 28 | 29 | 8.webpack组成部分 30 | 31 | 9.amd和cmd的区别 32 | 33 | ### 二面 34 | 35 | 二面去的网易大厦 36 | 37 | 1.react和vue区别和相同点 38 | 39 | 2.vue和传统框架的区别 40 | 41 | 3.vue-router两种运行方式(hash和history) 42 | 43 | 4.url后面哈希的作用(锚点和传递数据) 44 | 45 | 4.异步变成的解决方案,回调,promise,generator,各自的区别(generator的原理,es5下generator实现方式) 46 | 47 | 5.判断类别,undefined和null的区别,如何正确判断类别(typeof 和Object.prototype.toString.call()方法) 48 | 49 | 6.js基本数据类型 50 | 51 | 7.继承原理 52 | 53 | 8.如何去重 54 | 55 | 9.es6/es7有了解哪些,(答了map,set,generator,symbol,class,module,promise,async,await,生成器的原理) 56 | 57 | 10.如何判断一个类的属性来自自身还是原型链 58 | 59 | 11.如何去除一个数组的后两位 60 | 61 | 12.call,apply,bind区别,以及bind的实现方式,参数形式 62 | 63 | 13.手撕new 的实现原理 64 | 65 | 14.splice,slice区别 66 | 67 | 15.fun的原型链顶端是什么,object顶端是什么 68 | 69 | 16.如何遍历一个数组和对象,(判断数组和对象,和一种方式实现) 70 | 71 | 17.for in 遍历对象会不会遍历原型链属性 72 | 73 | 18.for in 遍历对象会不会遍历原型链上的方法 74 | 75 | 19.webpack和gulp的区别、 76 | 77 | ### 三面 78 | 79 | 三面是hr面,和hr姐姐谈了谈人生和理想~~。最后拿到了offer。 80 | 81 | 82 | 83 | 84 | 85 | # 美团 86 | 87 | ### 一面 88 | 89 | 视频面试 90 | 91 | 1.es6/es7有了解哪些,map,set,generator,symbol,class,module,promise,async,await,生成器的原理 92 | 93 | 2.http2和http1的区别 94 | 95 | 3.cdn原理 96 | 97 | 4.01-背包,动态规划 98 | 99 | 5.计算机网络的缓存,https原理 100 | 101 | 具体有点记不清楚了。 102 | 103 | ### 二面 104 | 105 | 视频面试 106 | 107 | 主要是聊我做过的项目。 108 | 109 | 1.做的一个聊天项目https://github.com/hua1995116/webchat 110 | 111 | 聊了切页效果的实现(3d加速,如何开启3d加速(说了大概8种),3d加速的原理,哪些情况3d加速不好),首屏的优化,优化后与优化前的对比(优化请求,图片大小等),用什么工具检测(chrome的performance),以及项目用户基础,前后端自己搭建,自己手写的localstroage缓存,缓存有哪些,大数据缓存用什么比较好。 112 | 113 | 2.在公司做的一个活动项目 114 | 115 | 聊了移动端布局,(淘宝flex结局方案),rem,css动画,requestAnimationFrame,自己写的动画有什么优化方式,图片加载,手撕一个进度条(啪啦啪啦)等。 116 | 117 | 3.手写一个promise形式,并有随机返回值。 118 | 119 | 其他的具体想不起来了,面了1个多小时,挺多东西的。。 120 | 121 | ### 三面 122 | 123 | 还是视频面试,主要是谈一些工作上以及自身的一些个性把,这个你自己答,开放性的。最后拿到了offer。 -------------------------------------------------------------------------------- /docs/interview/interview3.md: -------------------------------------------------------------------------------- 1 | # 关于2018网易游戏web前端实习生面试经历 2 | 3 | 去年报名的网易前端面试,没想到过了3个月居然收到了面试的通知,心里也是激动,花了一天时间面试,自己总结一下面试过的问题,问题可能不全,但是这些是我所能记起来的问题。 4 | 5 | 一面 6 | 1.css高度坍塌(两个盒子,一个下边据20px,一个上边据50px,最后为两个盒子之间的距离为多少,对于这个问题,幸好我之前看过,轻松的回答为50px,原理为css设计时候大多为文档,可能是css当时一个缺陷) 7 | 2.如何解决高度坍塌(当时回答的是用overflow:hidden在面试官的指引下回答对了。其他方法可以百度) 8 | 3.两侧固定,中间自适应(我提了三种,1.float2.flex布局3.通过position) 9 | 4.浮动是怎么样的(脱离文档流) 10 | 5.如何清楚浮动(当时我回答了两中,overflow:hidden和clear:both) 11 | 6.原型链(这个就不用我说了吧,基本要会的) 12 | 7.闭包(同上) 13 | 8.rem和em的区别(rem是根据最顶级,em是根据父级) 14 | 9.自适应布局(通过media查询设置字体大小和百分比) 15 | 10.jsonp 16 | 11.移动端解决屏幕旋转问题(这个我一开始没回答上来,后来想到了通过检测浏览器的宽来实现,虽然面试官说有一个内置的函数,但是也算勉强回答对了) 17 | 12.zepto和jquery区别(我回答了,体积大小不一样,但是后来面试官又问,为什么体积大小会不一样,我稍微有点犹豫,后来在面试官的提示下,知道了,因为移动端的兼容性不需要要考虑很多) 18 | 13.性能动画方面,为什么用css3(因为css3动画能启动GPU渲染) 19 | 14.css3动画和jquery动画的差别是什么 20 | 15.tap为什么有300毫秒的延迟 21 | 16.如何解决ajax无法后退的问题(我回答了用哈希值,然后用history函数,面试官又问,那你知道history的什么函数吗,。这个我真不知道,之前看阮一峰的教程上,有写那两个函数,但是我实在是想不起来了。) 22 | 最后面试官的建议,多写原生代码,自己试着多写一些组件,在现在这个前端框架变化快的时代,如果你不掌握基础,万一某个框架没了,你就得从头开始,你就不必追着别人一直学,可以看别人的框架,但是别活在别人的屋檐下。 23 | 24 | 二面 25 | 1.rem如何定位 26 | 2.调用了高德api的那些(因为我建立上写了一个用高德api实现的项目) 27 | 3.是否熟悉webpack 28 | 4.有用过svn吗? 29 | 5.平时除了bootstrap会布局吗? 30 | 6.用过canvas吗,你了解多少? 31 | 7.你用过ES6吗? 32 | 8.你知道ES6那些属性?(当时只回答了const和let的作用域 ,以及箭头函数的区别) 33 | 9.平时项目中有遇到最难的问题是什么? 34 | 10.在和队友沟通的时候遇到什么麻烦? 35 | 36 | 三面 37 | 1.xxs知道吗 38 | 2.有看过jq源码吗 39 | 3.你什么时候开始做前端的, 40 | 3.你以后的打算是一直做前端吗? 41 | 3.你试过把css代码写body最后吗? 42 | 4.对于安全,数据方面比较注重? 43 | 44 | 三面问的问题我有点懵逼,所以记得不是特别清楚,面试官问的问题也很奇怪。有点偏向于生活。面试结果下周才出,只能祈祷自己能拿下offer了。最后,继续努力,失败也不怕! -------------------------------------------------------------------------------- /docs/interview/meta.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "送你一道字节前端原题(Add sumOf)", 4 | "date": "2020-09-06 22:33:54", 5 | "path": "bytedance-add-sumOf", 6 | "description": "字节跳动前端面试题Add sumOf,Add(1)(2)(3).sumOf();Add(1,2)(3)(4).sumOf();Add(1,2,...)(3)(4)(...).sumOf();", 7 | "keywords": "字节跳动 面试题 前端面试" 8 | }, 9 | { 10 | "title": "2018前端校招总结(拿到网易,美团offer)", 11 | "date": "2017-08-06 22:33:54", 12 | "path": "interview", 13 | "description": "美团面试、网易面试、css盒子模型,事件循环机制,react,vue和普通的区别,amd和cmd的区别,继承原理,splice,slice区别。", 14 | "keywords": "美团 网易 面试题 前端面试" 15 | }, 16 | { 17 | "title": "2018网易前端实习笔试题", 18 | "date": "2017-12-06 22:33:54", 19 | "path": "interview2", 20 | "description": "网易笔试,小易学了集合,已知集合有三个性质:确定性、互异性、无序性;小易生活的世界没有除号,而且所有的运算都是从左往右依次进行计算,有一串数字。如下,去重,并且取重复数字的最后一次出现位置。", 21 | "keywords": "网易 面试题 前端笔试" 22 | }, 23 | { 24 | "title": "关于2018网易游戏web前端实习生面试经历", 25 | "date": "2017-03-06 22:33:54", 26 | "path": "interview3", 27 | "description": "css高度坍塌,tap为什么有300毫秒的延迟,webpack,你知道ES6那些属性", 28 | "keywords": "网易游戏 web前端 网易 面试题 前端笔试" 29 | } 30 | ] -------------------------------------------------------------------------------- /docs/machine-learning/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hua1995116/vuepress-blog/cfcc41e1c37bb31916069f47871dbce3f3fc3959/docs/machine-learning/README.md -------------------------------------------------------------------------------- /docs/machine-learning/meta.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /docs/news/README.md: -------------------------------------------------------------------------------- 1 | 2 | [提高前端开发者效率的11个必备的网站](./11-must-website.md) 3 | 4 | [2020 公众号前端文章精选汇总(10大方向)](./2020-article.md) 5 | 6 | [2020年度CSS报告新鲜出炉,从业者平均年薪35w](./2020-css.md) 7 | 8 | [2020 全球 JS 调查结果报告](./2020-state-of-js.md) 9 | 10 | [2021年,推荐一个百度新出开发专用搜索引擎,没有广告!](./baidu-kaifa.md) 11 | 12 | [CodePen vue SFC 、flutter 在线玩耍来袭](./codepen-vue-flutter.md) 13 | 14 | [未来的 JavaScript 应该是什么样的?现在还缺少什么?](./future-js.md) 15 | 16 | [肉身翻墙应该注意什么,一个澳洲程序员的自述](./goabord.md) 17 | 18 | [白板协作工具 LeanBoard](./leanboard.md) 19 | 20 | [Node Sass 弃用,以 Dart Sass 代替](./node-sass-eprecated.md) 21 | 22 | [一个快速找出待SEO图片的技巧](./seo-img.md) 23 | 24 | -------------------------------------------------------------------------------- /docs/news/baidu-kaifa.md: -------------------------------------------------------------------------------- 1 | # 2021 年,推荐一个百度新出开发专用搜索引擎,没有广告! 2 | 3 | 最近看朋友在用百度搜索相关的问题,但是自信一看发现不是百度,但是却也是百度。 4 | 5 | 原来百度新出了一个 beta 版本的开发者搜索引擎。 6 | 7 | 为什么说是开发者专用呢?这一点,我们可以从他的域名就可以看出。 8 | 9 | https://kaifa.baidu.com/ 10 | 11 | 目前他主要是从 博客园、CSDN、知乎 爬虫检索。 12 | 13 | 我们先来搜索 `vue` 看看开发者搜索引擎的效果。 14 | 15 | ![image-20210101163903028](https://s3.mdedit.online/blog/image-20210101163903028.png) 16 | 17 | 第一个结果就是 vue 的官网、后面都是 vue 开发相关的资料。 18 | 19 | 我们再来看看原百度的效果 20 | 21 | ![image-20210101164331618](https://s3.mdedit.online/blog/image-20210101164331618.png) 22 | 23 | 一屏下来全是广告.... 24 | 25 | 虽然说,没有了广告,但是由于收录的站点实在是太少了,很多信息还是无法检索出来,还是非常的难用。例如我们需要搜搜一个相关的 npm 包。来看看查找某个 npm 库,用百度搜索、百度-开发者搜索 beta、谷歌搜索的效果。 26 | 27 | ### 百度搜索 28 | 29 | ![image-20210101165648536](https://s3.mdedit.online/blog/image-20210101165648536.png) 30 | 31 | ### 百度-开发者搜索 beta 32 | 33 | ![image-20210101165717682](https://s3.mdedit.online/blog/image-20210101165717682.png) 34 | 35 | ### 谷歌搜索 36 | 37 | ![image-20210101165752893](https://s3.mdedit.online/blog/image-20210101165752893.png) 38 | 39 | 然后还有一个致命的缺点,专用搜索引擎太封闭了... 搜索女神还要切换网页?? 40 | 41 | ![image-20210101170631871](https://s3.mdedit.online/blog/image-20210101170631871.png?imageView2/0/q/75|watermark/1/image/aHR0cHM6Ly9zMy5xaXVmZW5naC5jb20vd2F0ZXJtYXJrL3dhdGVybWFyay5wbmc=/dissolve/50/gravity/SouthEast/dx/0/dy/0) 42 | 43 | ![image-20210101170828131](https://s3.mdedit.online/blog/image-20210101170828131.png) 44 | 45 | 总结起来谷歌搜索还是太香了。 46 | 47 | 2021 年的第一篇文章就这样水了,祝大家元旦快乐。 48 | -------------------------------------------------------------------------------- /docs/news/codepen-vue-flutter.md: -------------------------------------------------------------------------------- 1 | # CodePen vue SFC 、flutter 在线玩耍来袭 2 | 3 | 首先介绍下,CodePen 是一个在线社区,用于测试和展示用户创建的 HTML,CSS 和 JavaScript 代码段。在上面有非常多的代码片段,以及 CSS 的各种有创意的 demo。我可以说很多各种奇幻的效果都产自于它,例如用 CSS 画出一幅油画,以及 CSS 画出各种卡通人物,这也是我第一个用的在线编辑网站。 4 | 5 | 接下来我们介绍,CodePen 新出的这两个在线功能,真的是爱了爱了,无论是对分享代码片段,还是快速尝鲜来说,都是非常好的体验。 6 | 7 | ## vue SFC 8 | 9 | 什么是 vue SFC ? 即`Single File Components` 一个`.vue 文件`。 `.vue` 文件是一个自定义的文件类型,用类 HTML 语法描述一个 Vue 组件。每个 .vue 文件包含三种类型的顶级语言块 `