├── .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 |
2 |
3 |
4 |
10 |
11 |
{{tag}}
12 |
13 |
14 |
15 | {{ post.title }}
19 |
20 |
21 |
22 |
45 |
46 |
47 |
48 |
105 |
106 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/Bar.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
35 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/DropdownTransition.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
28 |
29 |
34 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/NavLink.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ item.text }}
9 |
17 | {{ item.text }}
18 |
19 |
20 |
21 |
22 |
55 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/Page.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
93 |
94 |
132 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/PageEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
97 |
131 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/PageNav.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ←
6 | {{ prev.title || prev.path }}
7 |
8 |
9 |
10 | {{ next.title || next.path }}
11 | →
12 |
13 |
14 |
15 |
16 |
101 |
118 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/QR.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 | 如果你对前端,Node,开源项目感兴趣请关注我的公众号 秋风的笔记。
6 |
7 |
8 |
9 |
10 |
15 |
16 |
35 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/Sidebar.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
22 |
23 |
60 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/SidebarButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
28 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/SidebarGroup.vue:
--------------------------------------------------------------------------------
1 |
2 |
54 |
55 |
56 |
74 |
75 |
133 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/SidebarLink.vue:
--------------------------------------------------------------------------------
1 |
96 |
97 |
127 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/SidebarLinks.vue:
--------------------------------------------------------------------------------
1 |
2 |
22 |
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 |
2 |
3 |
4 |
404
5 |
{{ getMsg() }}
6 |
Take me home.
7 |
8 |
9 |
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 | 
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 | 
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 | 
28 |
29 | 正如你看到的那样,我们将数组传递给 `Promise.all`。 当三个 promise 都完成时,`Promise.all` 就完成了,并且输出被打印了。
30 |
31 | 现在,让我们看看其中一个 promise 失败了的情况,如果这个 promise 失败了,又会 输出什么呢? 🛑
32 |
33 | 
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 | 
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 | 
66 |
67 | `promise.all()`
68 |
69 | 
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 |
8 |
9 | ### 第 2 步:
10 |
11 | 打开 `chrome://extensions/`
12 |
13 |
14 |
15 | ### 第 3 步:
16 |
17 | 点击 `加载已经解压的扩展程序` ,选择 omni-master 下面的 src 目录
18 |
19 |
20 |
21 | 大功告成!!!
22 |
23 |
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 | 
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 |
12 |
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 | 
48 |
49 | **样式以及 DOM 结构**
50 |
51 | ```css
52 |
89 |
90 |
91 |
92 |
93 |
96 |
97 | 1
张三
男
13788888888
浙江
删除
98 | 2
李四
女
13788887777
四川
删除
99 | 3
王二
男
13788889999
广东
删除
100 |
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 | 
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 | 
5 | 第一点击以降序排列,第二次点击以升序排列
6 | html 代码
7 |
8 | ```html
9 |
10 |
11 |
12 |
13 | Document
14 |
15 |
16 |
17 |
18 | 学号 |
19 | 名字 |
20 | 成绩 |
21 |
22 |
23 | 1002 |
24 | 小铭 |
25 | 34 |
26 |
27 |
28 | 1003 |
29 | 小红 |
30 | 64 |
31 |
32 |
33 | 1004 |
34 | 小黄 |
35 | 24 |
36 |
37 |
38 | 1005 |
39 | 小米 |
40 | 53 |
41 |
42 |
43 | 1006 |
44 | 小蒋 |
45 | 78 |
46 |
47 |
48 | 1007 |
49 | 小捷 |
50 | 97 |
51 |
52 |
53 | 1004 |
54 | 小邓 |
55 | 65 |
56 |
57 |
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 | 
7 | node 共有 12 类型。
8 | 
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 | 
43 |
44 | **3.操作节点**
45 | appendChild,用于向 childeNodes 的尾部追加一个节点。
46 |
47 | ```html
48 |
49 | - 1
50 | - 2
51 | - 3
52 | - 4
53 |
54 |
59 | ```
60 |
61 | 追加前
62 | 
63 | 追加后
64 | 
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 |
81 | - 1
82 | - 2
83 | - 3
84 | - 4
85 |
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 |
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 | 
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 | 
16 |
17 | 第一个结果就是 vue 的官网、后面都是 vue 开发相关的资料。
18 |
19 | 我们再来看看原百度的效果
20 |
21 | 
22 |
23 | 一屏下来全是广告....
24 |
25 | 虽然说,没有了广告,但是由于收录的站点实在是太少了,很多信息还是无法检索出来,还是非常的难用。例如我们需要搜搜一个相关的 npm 包。来看看查找某个 npm 库,用百度搜索、百度-开发者搜索 beta、谷歌搜索的效果。
26 |
27 | ### 百度搜索
28 |
29 | 
30 |
31 | ### 百度-开发者搜索 beta
32 |
33 | 
34 |
35 | ### 谷歌搜索
36 |
37 | 
38 |
39 | 然后还有一个致命的缺点,专用搜索引擎太封闭了... 搜索女神还要切换网页??
40 |
41 | 
42 |
43 | 
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 文件包含三种类型的顶级语言块 ``、`
56 |