├── .eslintrc.js
├── .github
└── workflows
│ └── docs.yml
├── .gitignore
├── .husky
└── pre-commit.txt
├── .lintstagedrc.json
├── .markdownlint-cli2.jsonc
├── .markdownlint.jsonc
├── .nvmrc
├── .prettierignore
├── LICENSE
├── README.md
├── deploy.sh
├── docs
├── .vuepress
│ ├── components
│ │ └── hide-outbound.vue
│ ├── config.ts
│ ├── configs
│ │ ├── index.ts
│ │ ├── navbar
│ │ │ ├── index.ts
│ │ │ └── zh.ts
│ │ └── sidebar
│ │ │ ├── index.ts
│ │ │ └── zh.ts
│ ├── public
│ │ ├── hero.png
│ │ ├── icons
│ │ │ ├── android-chrome-192x192.png
│ │ │ ├── android-chrome-512x512.png
│ │ │ ├── apple-touch-icon-120x120.png
│ │ │ ├── apple-touch-icon-152x152.png
│ │ │ ├── apple-touch-icon-180x180.png
│ │ │ ├── apple-touch-icon-60x60.png
│ │ │ ├── apple-touch-icon-76x76.png
│ │ │ ├── apple-touch-icon.png
│ │ │ ├── favicon-16x16.png
│ │ │ ├── favicon-32x32.png
│ │ │ ├── logo.svg
│ │ │ ├── msapplication-icon-144x144.png
│ │ │ ├── mstile-150x150.png
│ │ │ └── safari-pinned-tab.svg
│ │ └── manifest.json
│ └── styles
│ │ └── index.styl
├── README.md
├── REGEXP
│ ├── README.md
│ └── images
│ │ ├── regex.jpg
│ │ └── regexper.png
├── _images
│ ├── box-model-example.png
│ ├── css-grayscale-example.png
│ ├── event_loop.gif
│ ├── git-merge-difference.png
│ ├── koa-middleware.png
│ ├── libuv.jpeg
│ ├── youtube.png
│ └── z-index-stacking-level.png
├── dev-ops.md
├── develop
│ ├── README.md
│ ├── css
│ │ ├── README.md
│ │ ├── design
│ │ │ ├── botton
│ │ │ │ ├── css
│ │ │ │ │ ├── reset.css
│ │ │ │ │ └── styles.css
│ │ │ │ └── index.html
│ │ │ └── images
│ │ │ │ ├── auto-width.gif
│ │ │ │ ├── flexbox-1.gif
│ │ │ │ └── flexbox-2.gif
│ │ ├── images
│ │ │ ├── anima-loading.gif
│ │ │ ├── avatar-1.png
│ │ │ ├── background-more.png
│ │ │ ├── drawing_graphics.png
│ │ │ ├── image-hover.gif
│ │ │ ├── nav-anima.png
│ │ │ ├── nav-split.png
│ │ │ └── wildcard.png
│ │ ├── reset.css
│ │ └── theory.md
│ ├── html
│ │ └── README.md
│ ├── javascript
│ │ ├── README.md
│ │ ├── jq
│ │ │ └── jquery-back-top.js
│ │ ├── libs.md
│ │ ├── mini-program.md
│ │ ├── nodejs.md
│ │ ├── react.md
│ │ ├── typescript.md
│ │ ├── utlis.js
│ │ └── vue.md
│ ├── mobile
│ │ └── README.md
│ └── solution.md
├── further
│ ├── README.md
│ ├── books.md
│ ├── en.md
│ ├── glossary.md
│ ├── guide
│ │ └── js.md
│ └── links.md
├── git.md
├── hg.md
├── jira.md
└── topic
│ ├── DSA.md
│ ├── README.md
│ ├── browser.md
│ ├── complex.md
│ ├── css.md
│ ├── html.md
│ ├── images
│ ├── browse-http-request.png
│ ├── dom-render-process.png
│ ├── dom-tree.png
│ ├── event-loop.png
│ ├── http2-stack-vs-http3-stack.png
│ ├── mvvm-design.png
│ ├── react.jpg
│ ├── reconciliation.png
│ ├── tcp-1.png
│ ├── tcp-2.png
│ ├── vue-lifecycle-v3.svg
│ ├── vue-lifecycle.png
│ ├── vuejs.jpg
│ └── websocket-connect.png
│ ├── js.md
│ ├── network.md
│ ├── nodejs.md
│ ├── performance.md
│ ├── react.md
│ ├── vue.md
│ └── webpack.md
├── package.json
├── tsconfig.base.json
├── tsconfig.json
└── yarn.lock
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: "plugin:markdown/recommended",
3 | };
4 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: docs
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | workflow_dispatch:
8 |
9 | jobs:
10 | docs:
11 | runs-on: ubuntu-latest
12 |
13 | env:
14 | DOCS_GA_ID:
15 | NODE_VERSION: '20'
16 |
17 | steps:
18 | - uses: actions/checkout@v3
19 | with:
20 | # “最近更新时间” 等 git 日志相关信息,需要拉取全部提交记录
21 | fetch-depth: 0
22 |
23 | # - name: Install pnpm
24 | # uses: pnpm/action-setup@v2
25 | # with:
26 | # # 选择要使用的 pnpm 版本
27 | # version: 7
28 | # # 使用 pnpm 安装依赖
29 | # run_install: true
30 |
31 | - name: Setup Node.js
32 | uses: actions/setup-node@v3
33 | with:
34 | node-version: ${{ env.NODE_VERSION }}
35 | # cache: pnpm
36 |
37 | # - name: Install dependencies
38 | # run: pnpm install --frozen-lockfile
39 |
40 | # 运行构建脚本
41 | - name: Build documentation site
42 | run: yarn && yarn build
43 |
44 | # 查看 workflow 的文档来获取更多信息
45 | # @see https://github.com/crazy-max/ghaction-github-pages
46 | - name: Deploy to GitHub Pages
47 | uses: crazy-max/ghaction-github-pages@v2.2.0
48 | with:
49 | target_branch: gh-pages
50 | build_dir: docs/.vuepress/dist
51 | env:
52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # 编辑器配置
2 | .vscode
3 |
4 | # 本地临时文件
5 | buffer
6 |
7 | # 本地依赖
8 | node_modules
9 |
10 | docs/.vuepress/dist/**
11 |
12 | .cache
13 | .temp
14 |
--------------------------------------------------------------------------------
/.husky/pre-commit.txt:
--------------------------------------------------------------------------------
1 | npx lint-staged
2 |
--------------------------------------------------------------------------------
/.lintstagedrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "!*.md": "prettier --ignore-unknown --write",
3 | "*.md": [
4 | "markdownlint-cli2 --fix",
5 | "prettier --write"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.markdownlint-cli2.jsonc:
--------------------------------------------------------------------------------
1 | {
2 | "config": {
3 | "extends": "./.markdownlint.jsonc",
4 | },
5 | "customRules": ["markdownlint-rule-search-replace"],
6 | "ignores": ["node_modules", ".git", ".github", "tests"],
7 | }
8 |
--------------------------------------------------------------------------------
/.markdownlint.jsonc:
--------------------------------------------------------------------------------
1 | // This file defines our configuration for Markdownlint. See
2 | // https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md
3 | // for more details on each rule.
4 |
5 | {
6 | "default": true,
7 | // Disabled, as some callouts include headings.
8 | "heading-increment": false,
9 | "ul-style": {
10 | "style": "dash",
11 | },
12 | "ul-indent": {
13 | "indent": 2,
14 | },
15 | "no-hard-tabs": {
16 | "spaces_per_tab": 2,
17 | },
18 | "line-length": false,
19 | "no-duplicate-heading": {
20 | "siblings_only": true,
21 | },
22 | "single-title": {
23 | "front_matter_title": "^\\s*title\\s*[:=]",
24 | },
25 | "no-trailing-punctuation": {
26 | "punctuation": ".,;:",
27 | },
28 | // Consecutive Notes/Callouts currently don't conform with this rule
29 | "no-blanks-blockquote": false,
30 | // Force ordered numbering to catch accidental list ending from indenting
31 | "ol-prefix": false,
32 | "no-inline-html": {
33 | "allowed_elements": [
34 | "a",
35 | "abbr",
36 | "annotation",
37 | "br",
38 | "caption",
39 | "code",
40 | "col",
41 | "colgroup",
42 | "dd",
43 | "details",
44 | "div",
45 | "dl",
46 | "dt",
47 | "em",
48 | "h4",
49 | "h5",
50 | "img",
51 | "kbd",
52 | "li",
53 | "math",
54 | "menclose",
55 | "mfenced",
56 | "mfrac",
57 | "mfrac",
58 | "mi",
59 | "mmultiscripts",
60 | "mn",
61 | "mo",
62 | "mover",
63 | "mphantom",
64 | "mprescripts",
65 | "mroot",
66 | "mrow",
67 | "ms",
68 | "mspace",
69 | "mspace",
70 | "msqrt",
71 | "mstyle",
72 | "msub",
73 | "msubsup",
74 | "msup",
75 | "mtable",
76 | "mtd",
77 | "mtext",
78 | "mtr",
79 | "munder",
80 | "munderover",
81 | "none",
82 | "ol",
83 | "p",
84 | "pre",
85 | "q",
86 | "section",
87 | "semantics",
88 | "strong",
89 | "sub",
90 | "summary",
91 | "sup",
92 | "table",
93 | "tbody",
94 | "td",
95 | "tfoot",
96 | "th",
97 | "thead",
98 | "tr",
99 | "ul",
100 | "var",
101 | "iframe",
102 | "h1",
103 | ],
104 | },
105 | "first-line-heading": false,
106 | "no-emphasis-as-heading": false,
107 | "no-bare-urls": false,
108 | // Produces too many false positives
109 | "no-space-in-emphasis": false,
110 | "fenced-code-language": true,
111 | // See https://github.com/mdn/content/pull/20026, as macros currently break this
112 | "no-empty-links": false,
113 | "code-block-style": {
114 | "style": "fenced",
115 | },
116 | "emphasis-style": {
117 | "style": "underscore",
118 | },
119 | "strong-style": {
120 | "style": "asterisk",
121 | },
122 | // Disabled, as yari generates link fragments by replacing spaces with underscores, not dashes.
123 | "link-fragments": false,
124 |
125 | // https://github.com/OnkarRuikar/markdownlint-rule-search-replace
126 | "search-replace": {
127 | "rules": [
128 | {
129 | "name": "curly-single-quotes",
130 | "message": "Don't use curly single quotes",
131 | "searchPattern": "/‘|’/g",
132 | "replace": "'",
133 | "searchScope": "text",
134 | },
135 | {
136 | "name": "trailing-spaces",
137 | "message": "Avoid trailing spaces",
138 | "searchPattern": "/ +$/gm",
139 | "replace": "",
140 | "searchScope": "all",
141 | },
142 | {
143 | "name": "double-spaces",
144 | "message": "Avoid double spaces",
145 | "searchPattern": "/([^\\s>]) ([^\\s|])/g",
146 | "replace": "$1 $2",
147 | "searchScope": "text",
148 | },
149 | ],
150 | },
151 | }
152 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | v18.17
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | docs/.vuepress/dist/**
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Web Lab
2 |
3 |
4 |
5 |
6 |
8 |
10 |
12 |
13 |
14 |
15 | Website ·
16 | 目录概览
17 |
18 |
19 | > :art: 记录 Web 领域的研究与实践
20 |
21 | ## Start
22 |
23 | ```shell
24 | # 本地开发
25 | yarn start
26 |
27 | # 生成文档
28 | yarn build
29 | ```
30 |
31 | ## Branch
32 |
33 | | Branch | Description |
34 | | ------- | ---------------------------------------------------------------------- |
35 | | master | 主/文档分支。编写笔记在此分支进行更新 |
36 | | develop | 开发分支。项目构建类先在开发分支进行,开发完毕后再合并至 master 分支中 |
37 |
38 | ## commit type
39 |
40 | | Type | Description |
41 | | -------- | ---------------- |
42 | | `docs:` | 编写文档 |
43 | | `build:` | website 配置相关 |
44 | | `ci:` | CI 配置相关 |
45 |
46 | 由于更多情况是编写文档,还可以约定 emoji 来增强 commit message 的语义:
47 |
48 | | emoji | code | Description |
49 | | --------- | ----------- | ---------------------- |
50 | | :pencil2: | `:pencil2:` | 编写文档 (README 相关) |
51 | | :art: | `:art:` | 润色/完善内容 |
52 | | :truck: | `:truck:` | 内容拆分或重构 |
53 |
54 | ## 专栏与博客
55 |
56 | - [anran758's homepage](https://anran758.github.io/blog/): web 相关的效果展示页
57 | - [anran758's blog](https://anran758.github.io/blog/): 业务场景的分析与解决方案、计算机相关的笔记、简单的教程等。
58 | - [专栏 | 初级前端工程师的进阶之路](https://zhuanlan.zhihu.com/c_1147180666474176512): 专门针对初级工程师进阶时常遇到的一些问题专辑。
59 |
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # 确保脚本抛出遇到的错误
4 | set -e
5 |
6 | # 生成静态文件
7 | npm run build
8 |
9 | # 进入生成的文件夹
10 | cd docs/.vuepress/dist
11 |
12 | # 如果是发布到自定义域名
13 | # echo 'www.example.com' > CNAME
14 |
15 | git init
16 | git add -A
17 | git commit -m 'deploy'
18 |
19 | # 如果发布到 https://.github.io
20 | # git push -f git@github.com:/.github.io.git master
21 |
22 | # 如果发布到 https://.github.io/
23 | # git push -f git@github.com:/.git master:gh-pages
24 | git push -f git@github.com:anran758/front-end-lab.git master:gh-pages
25 |
26 | cd -
27 |
--------------------------------------------------------------------------------
/docs/.vuepress/components/hide-outbound.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
13 |
--------------------------------------------------------------------------------
/docs/.vuepress/config.ts:
--------------------------------------------------------------------------------
1 | import { defineUserConfig } from '@vuepress/cli';
2 | import { path } from '@vuepress/utils';
3 | import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics';
4 | import { registerComponentsPlugin } from '@vuepress/plugin-register-components';
5 | import { pwaPlugin } from '@vuepress/plugin-pwa';
6 | import { pwaPopupPlugin } from '@vuepress/plugin-pwa-popup';
7 | import { viteBundler } from '@vuepress/bundler-vite';
8 | import { webpackBundler } from '@vuepress/bundler-webpack';
9 | import { defaultTheme } from '@vuepress/theme-default';
10 | import { searchPlugin } from '@vuepress/plugin-search';
11 |
12 | import { navbar, sidebar } from './configs';
13 |
14 | const isProd = process.env.NODE_ENV === 'production';
15 |
16 | /**
17 | * @see {@link https://github.com/vuepress/vuepress-next/blob/main/docs/.vuepress/config.ts}
18 | */
19 | export default defineUserConfig({
20 | base: '/front-end-lab/',
21 | locales: {
22 | '/': {
23 | lang: 'zh-CN',
24 | title: 'Web 实验室',
25 | description: 'Web 开发笔记与解决方案',
26 | },
27 | },
28 |
29 | head: [
30 | ['link', { rel: 'icon', href: `/icons/logo.svg` }],
31 | ['link', { rel: 'manifest', href: '/manifest.json' }],
32 | ['meta', { name: 'theme-color', content: '#3eaf7c' }],
33 | ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }],
34 | [
35 | 'meta',
36 | { name: 'apple-mobile-web-app-status-bar-style', content: 'black' },
37 | ],
38 | [
39 | 'link',
40 | { rel: 'apple-touch-icon', href: `/icons/apple-touch-icon-152x152.png` },
41 | ],
42 | [
43 | 'link',
44 | {
45 | rel: 'mask-icon',
46 | href: '/icons/safari-pinned-tab.svg',
47 | color: '#3eaf7c',
48 | },
49 | ],
50 | [
51 | 'meta',
52 | {
53 | name: 'msapplication-TileImage',
54 | content: '/icons/msapplication-icon-144x144.png',
55 | },
56 | ],
57 | ['meta', { name: 'msapplication-TileColor', content: '#000000' }],
58 | ],
59 |
60 | bundler:
61 | // specify bundler via environment variable
62 | process.env.DOCS_BUNDLER === 'webpack' ? webpackBundler() : viteBundler(),
63 |
64 | alias: {
65 | '@image': path.resolve(__dirname, '../_images'),
66 | },
67 |
68 | // theme: '@vuepress/vue',
69 | theme: defaultTheme({
70 | repo: 'https://github.com/anran758/front-end-lab',
71 | editLinks: true,
72 | docsDir: 'docs',
73 | smoothScroll: true,
74 | backToTop: true,
75 | sidebarDepth: 4,
76 | displayAllHeaders: true,
77 | locales: {
78 | '/': {
79 | // navbar
80 | navbar: navbar.zh,
81 | selectLanguageName: '简体中文',
82 | selectLanguageText: '选择语言',
83 | selectLanguageAriaLabel: '选择语言',
84 |
85 | // sidebar
86 | sidebar: sidebar.zh,
87 |
88 | // page meta
89 | editLinkText: '在 GitHub 上编辑此页',
90 | lastUpdatedText: '上次更新',
91 | contributorsText: '贡献者',
92 |
93 | // custom containers
94 | tip: '提示',
95 | warning: '注意',
96 | danger: '警告',
97 |
98 | // 404 page
99 | notFound: [
100 | '这里什么都没有',
101 | '我们怎么到这来了?',
102 | '这是一个 404 页面',
103 | '看起来我们进入了错误的链接',
104 | ],
105 | backToHome: '返回首页',
106 |
107 | // a11y
108 | openInNewWindow: '在新窗口打开',
109 | toggleDarkMode: '切换夜间模式',
110 | toggleSidebar: '切换侧边栏',
111 | },
112 | },
113 | themePlugins: {
114 | // only enable git plugin in production mode
115 | git: isProd,
116 | // use shiki plugin in production mode instead
117 | prismjs: !isProd,
118 | },
119 | }),
120 | plugins: [
121 | /**
122 | * @see https://vuepress.github.io/zh/reference/plugin/search.html#locales
123 | */
124 | searchPlugin({
125 | locales: {
126 | '/': {
127 | placeholder: 'Search',
128 | },
129 | '/zh/': {
130 | placeholder: '搜索',
131 | },
132 | },
133 | }),
134 |
135 | pwaPlugin({}),
136 | pwaPopupPlugin({
137 | locales: {
138 | '/': {
139 | message: 'New content is available.',
140 | buttonText: 'Refresh',
141 | },
142 | '/zh/': {
143 | message: '发现新内容可用',
144 | buttonText: '刷新',
145 | },
146 | },
147 | }),
148 |
149 | googleAnalyticsPlugin({
150 | id: 'G-F07WV60EQR',
151 | }),
152 |
153 | registerComponentsPlugin({
154 | componentsDir: path.resolve(__dirname, './components'),
155 | }),
156 |
157 | // only enable shiki plugin in production mode
158 | // isProd ? shikiPlugin({ theme: 'dark-plus' }) : [],
159 | ],
160 |
161 | // extraWatchFiles: ['.vuepress/nav/zh.js']
162 | });
163 |
--------------------------------------------------------------------------------
/docs/.vuepress/configs/index.ts:
--------------------------------------------------------------------------------
1 | export * as navbar from './navbar'
2 | export * as sidebar from './sidebar'
3 |
--------------------------------------------------------------------------------
/docs/.vuepress/configs/navbar/index.ts:
--------------------------------------------------------------------------------
1 | export * from './zh'
2 |
--------------------------------------------------------------------------------
/docs/.vuepress/configs/navbar/zh.ts:
--------------------------------------------------------------------------------
1 | import type { NavbarConfig } from '@vuepress/theme-default';
2 |
3 | export const zh: NavbarConfig = [
4 | {
5 | text: 'Web 开发',
6 | link: '/develop/',
7 | },
8 | {
9 | text: '技术要点',
10 | link: '/topic/',
11 | },
12 | {
13 | text: '扩展阅读',
14 | link: '/further/',
15 | children: [
16 | {
17 | text: "Anran758's Homepage",
18 | link: 'https://anran758.github.io/',
19 | },
20 | {
21 | text: "Anran758's Blog",
22 | link: 'https://anran758.github.io/blog/',
23 | },
24 | ],
25 | },
26 | ];
27 |
--------------------------------------------------------------------------------
/docs/.vuepress/configs/sidebar/index.ts:
--------------------------------------------------------------------------------
1 | export * from './zh'
2 |
--------------------------------------------------------------------------------
/docs/.vuepress/configs/sidebar/zh.ts:
--------------------------------------------------------------------------------
1 | import type { SidebarConfig } from '@vuepress/theme-default';
2 |
3 | export const zh: SidebarConfig = {
4 | '/topic/': [
5 | {
6 | text: 'Web 技术栈',
7 | children: [
8 | '/topic/html.md',
9 | '/topic/css.md',
10 | '/topic/js.md',
11 | '/topic/nodejs.md',
12 | ],
13 | },
14 | {
15 | text: '开发框架与工具',
16 | children: ['/topic/react.md', '/topic/vue.md', '/topic/webpack.md'],
17 | },
18 | {
19 | text: '优化与原理解析',
20 | children: [
21 | '/topic/browser.md',
22 | '/topic/performance.md',
23 | '/topic/network.md',
24 | ],
25 | },
26 | '/topic/complex.md',
27 | ],
28 |
29 | '/': [
30 | {
31 | text: 'JavaScript 生态',
32 | children: [
33 | '/develop/javascript/README.md',
34 | '/develop/javascript/typescript.md',
35 | '/develop/javascript/vue.md',
36 | '/develop/javascript/react.md',
37 | '/develop/javascript/nodejs.md',
38 | '/develop/javascript/mini-program.md',
39 | '/develop/javascript/libs.md',
40 | ],
41 | },
42 | {
43 | text: 'Web 开发',
44 | children: [
45 | '/develop/html/README.md',
46 | '/develop/css/README.md',
47 | '/develop/css/theory.md',
48 | '/REGEXP/README.md',
49 | '/develop/solution.md',
50 | ],
51 | },
52 | {
53 | text: '项目管理',
54 | children: ['/git.md', '/hg.md', '/jira.md', '/dev-ops.md'],
55 | },
56 | {
57 | text: '更多',
58 | children: [
59 | '/further/glossary.md',
60 | '/further/books.md',
61 | '/further/README.md',
62 | ],
63 | },
64 | ],
65 | };
66 |
--------------------------------------------------------------------------------
/docs/.vuepress/public/hero.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/hero.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/android-chrome-192x192.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/android-chrome-512x512.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/msapplication-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/msapplication-icon-144x144.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/.vuepress/public/icons/mstile-150x150.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/icons/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
150 |
--------------------------------------------------------------------------------
/docs/.vuepress/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "FrontEndWiki",
3 | "short_name": "FrontEndWiki",
4 | "icons": [
5 | {
6 | "src": "/icons/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/icons/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "start_url": "/index.html",
17 | "display": "standalone",
18 | "background_color": "#fff",
19 | "theme_color": "#3eaf7c"
20 | }
21 |
--------------------------------------------------------------------------------
/docs/.vuepress/styles/index.styl:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | --vt-font-family-base: Quotes, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
4 |
5 | font-family: var(--vt-font-family-base);
6 | }
7 |
8 | details {
9 | margin: 1.6em 0;
10 |
11 | &[block] {
12 | display: block;
13 | position: relative;
14 | border-radius: 2px;
15 | padding: 1.6em;
16 | background-color: #eee;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | tagline:
4 | footer: GPL Licensed | Copyright © 2019-present anran758
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | > :books: 记录 Web 领域的研究与实践
20 |
21 | ## 导读
22 |
23 | **开发语言相关的笔记**
24 |
25 | - [HTML](./develop/html/README.md)
26 | - [CSS 实践笔记](./develop/css/README.md)
27 | - [CSS 理论笔记](./develop/css/theory.md)
28 | - [JavaScript](./develop/javascript/README.md)
29 | - [TypeScript](./develop/javascript/typescript.md)
30 | - [React](./develop/javascript/react.md)
31 | - [Vuejs](./develop/javascript/vue.md)
32 | - [RegExp (正则表达式)](./REGEXP)
33 |
34 | **项目管理**
35 |
36 | - [Git 使用指南](./git)
37 | - [Hg 使用指南](./hg)
38 | - [Jira 项目管理](./jira)
39 |
40 | **解决方案**
41 |
42 | - [Mobile 开发](./develop/mobile/README.md)
43 | - [DevOps](./operations/README.md)
44 |
45 | **其他**
46 |
47 | - [前端技术要点](./topic/README.md)
48 | - [扩展阅读](./further)
49 | - [术语表](./further/glossary.md)
50 | - [web 书单](./further/booklist.md)
51 | - [职场常用英语](./further/en.md)
52 | - [实用的在线工具](./further/booklist.md)
53 |
54 | ## 专栏与博客
55 |
56 | - [anran758's blog](https://anran758.github.io/blog/): 分享 web 相关的教程、科普实用/常用的工具库、实际业务场景分析与解决方案、计算机相关的笔记等。
57 | - [专栏 | 初级前端工程师的进阶之路](https://zhuanlan.zhihu.com/c_1147180666474176512): 专门针对初级工程师进阶时常遇到的一些问题专辑。
58 |
59 | ## 推荐阅读
60 |
61 | - [Introducing npx: an npm package runner | npx 简介](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b)
62 | - [usehooks | React Hooks 封装示例](https://usehooks.com/)
63 | - [The Missing Semester of Your CS Education (中译版) | 计算机教育中缺失的一课 | MIT](https://missing-semester-cn.github.io/)
64 |
--------------------------------------------------------------------------------
/docs/REGEXP/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebarDepth: 3
3 | ---
4 |
5 |
6 |
7 | # REGEXP (正则表达式)
8 |
9 | 
10 |
11 | > tips: 善用`Ctrl + F`输入关键字能提高查询的效率哟~
12 |
13 | 自己收集了一套针对工作中所需的正则表达式. 多适用于字符串处理、表单验证、日志数据分析等场合,实用高效, 将长期维护。
14 |
15 | - [常见正则校验](#常见正则校验)
16 | - [表单验证](#表单验证)
17 | - [网络相关](#网络相关)
18 | - [联系方式](#联系方式)
19 | - [匹配特定数字](#匹配特定数字)
20 | - [字符串相关](#字符串相关)
21 | - [匹配语系字符范围](#匹配语系字符范围)
22 | - [正则函数使用示例](#正则函数使用示例)
23 | - [replace](#replace)
24 | - [test](#test)
25 | - [正则技巧](#正则技巧)
26 | - [反向引用](#反向引用)
27 | - [忽略分組](#忽略分組)
28 | - [前瞻](#前瞻)
29 |
30 | ---
31 |
32 | **[REGEXP 可视化工具](https://regexper.com/)**
33 |
34 |
39 |
40 | ## 常见正则校验
41 |
42 | ### 表单验证
43 |
44 | ```javascript
45 | // 用户名正则,4到16位(字母,数字,下划线,减号)
46 | var userNameReg = /^[a-zA-Z0-9_-]{4,16}$/;
47 |
48 | // 必须拥有数字和特殊字符,并且在6 ~ 16位之间
49 | // (?=.*[0-9]) - 断言一个字符串至少有一个数字;
50 | // (?=.*[!@#$%^&*]) - 断言一个字符串至少有一个特殊字符。
51 | var reg = /^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,16}$/;
52 |
53 | // 匹配邮箱地址
54 | var mailReg = /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/;
55 |
56 | // 中国六位数的邮政编码
57 | var postalCode = /^\d{6}$/;
58 |
59 | // 匹配15~18位身份证
60 | var IDCard =
61 | /(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$)/;
62 |
63 | // 匹配18位的新版身份证
64 | var IDCard_18 =
65 | /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
66 |
67 | // 校验输入框是字符数为是否为 4~16 位(英文长度为1, 汉字长度为2)
68 | var numName = /^[a-zA-Z0-9]{4,16}$/;
69 | var mate = numName.test(value.replace(/[\u4e00-\u9fa5]/g, "aa"));
70 | ```
71 |
72 | ### 网络相关
73 |
74 | ```js
75 | //ipv4地址正则
76 | var IPReg =
77 | /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
78 |
79 | // Reg Hex颜色正则
80 | var pattern = /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/;
81 |
82 | // URL正则
83 | var urlReg =
84 | /^((https?|ftp|file):\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
85 |
86 | // 匹配JSON格式
87 | var reg = /^\w+\(({[^()]+})\)$/;
88 | ```
89 |
90 | 匹配`json`字符串
91 |
92 | ```js
93 | var ret = response.data;
94 | if (typeof ret === "string") {
95 | var reg = /^\w+\(({[^()]+})\)$/;
96 | var matches = ret.match(reg);
97 |
98 | if (matches) ret = JSON.parse(matches[1]);
99 | }
100 |
101 | res.json(ret);
102 | ```
103 |
104 | ### 联系方式
105 |
106 | ```js
107 | // 5-11位的腾讯qq号
108 | var qqReg = /^[1-9][0-9]{4,11}$/;
109 |
110 | // 微信号正则,6至20位,以字母开头,字母,数字,减号,下划线
111 | var qqReg = /^[a-zA-Z]([-_a-zA-Z0-9]{5,19})+$/;
112 |
113 | // 国内常见
114 | var phone = /^1[3|5|8|9]\d{9}$/;
115 |
116 | // 固定电话
117 | var telephone = /^(0[0-9]{2})\d{8}$|^(0[0-9]{3}(\d{7,8}))$/;
118 | ```
119 |
120 | ### 匹配特定数字
121 |
122 | ```javascript
123 | // 匹配正整数
124 | var reg = /^[1-9]\d*$/;
125 |
126 | // 匹配负整数
127 | var reg = /^-[1-9]\d*$/;
128 |
129 | // 匹配整数
130 | var reg = /^-?[1-9]\d*$/;
131 |
132 | // 匹配非负整数(正整数 + 0)
133 | var reg = /^[1-9]\d*|0$/;
134 |
135 | // 匹配非正整数(负整数 + 0)
136 | var reg = /^-[1-9]\d*|0$/;
137 |
138 | // 匹配正浮点数
139 | var reg = /^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$/;
140 |
141 | // 匹配负浮点数
142 | var reg = /^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$/;
143 |
144 | // 匹配浮点数
145 | var reg = /^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$/;
146 |
147 | // 匹配非负浮点数(正浮点数 + 0)
148 | var reg = /^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$/;
149 |
150 | // 匹配非正浮点数(负浮点数 + 0)
151 | var reg = /^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$/;
152 | ```
153 |
154 | ### 字符串相关
155 |
156 | ```javascript
157 | // 匹配由26个英文字母组成的字符串
158 | var reg = /^[A-Za-z]+$/;
159 |
160 | // 匹配由26个英文字母的大写组成的字符串
161 | var reg = /^[A-Z]+$/;
162 |
163 | // 匹配由26个英文字母的小写组成的字符串
164 | var reg = /^[a-z]+$/;
165 |
166 | // 匹配由数字和26个英文字母组成的字符串
167 | var reg = /^[A-Za-z0-9]+$/;
168 |
169 | // 匹配由数字、26个英文字母或者下;划线组成的字符串
170 | var reg = /^\w+$/;
171 |
172 | // 匹配空白行的正则表达式
173 | var reg = /\n\s*\r/;
174 |
175 | // 匹配首尾空白字符的正则表达式
176 | var reg = /^\s*|\s*$/;
177 | var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
178 |
179 | // 匹配双字节字符(包括汉字在内, 一个双字节字符长度计2,ASCII字符计1)
180 | var reg = /[^\x00-\xff]/g;
181 | ```
182 |
183 | ---
184 |
185 | ### 匹配语系字符范围
186 |
187 | 用法:`/^[\u4E00-\u9FA5]+$/`(匹配简体中文)
188 |
189 | `2E80~33FFh`:中日韩符号区。收容康熙字典部首、中日韩辅助部首、注音符号、日本假名、韩文音符,中日韩的符号、标点、带圈或带括符文数字、月份,以及日本的假名组合、单位、年号、月份、日期、时间等。
190 |
191 | `3400~4DFFh`:中日韩认同表意文字扩充A区,总计收容6,582个中日韩汉字。
192 |
193 | `4E00~9FFFh`:中日韩认同表意文字区,总计收容20,902个中日韩汉字。
194 |
195 | `A000~A4FFh`:彝族文字区,收容中国南方彝族文字和字根。
196 |
197 | `AC00~D7FFh`:韩文拼音组合字区,收容以韩文音符拼成的文字。
198 |
199 | `F900~FAFFh`:中日韩兼容表意文字区,总计收容302个中日韩汉字。
200 |
201 | `FB00~FFFDh`:文字表现形式区,收容组合拉丁文字、希伯来文、阿拉伯文、中日韩直式标点、小符号、半角符号、全角符号等。
202 |
203 | ## 正则函数使用示例
204 |
205 | ### replace
206 |
207 | ```javascript
208 | // 使用正则匹配中文字节, 将其替换为xx, 再获取字符串的长度就是完整的长度了.
209 | function getLen(str) {
210 | return str.replace(/[^\x00-\xff]/g, "xx").length;
211 | }
212 | ```
213 |
214 | ### test
215 |
216 | ```javascript
217 | // 匹配是否符合邮件规则
218 | var reg = /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/;
219 |
220 | // test返回一个布尔值, 表示是否匹配到制定字符串
221 | var mail = reg.test("anran758@gmail.com");
222 |
223 | if (mail) {
224 | // 如果邮件格式正确的话, 就可以做点啥了(雾
225 | }
226 | ```
227 |
228 | ## 正则技巧
229 |
230 | ### 反向引用
231 |
232 | ```javascript
233 | // 比如这里我们想让这个日期格式反转
234 | // 正则括号是一个分组, 下面的代码就捕获了三个分组
235 | // 通过$分组符来转换位置, 来达到我们想要的结果
236 | "2018-3-21".replace(/(\d{4})-(\d{1,2})-(\d{1,2})/g, "$2/$3/$1"); // "3/21/2018"
237 | ```
238 |
239 | ### 忽略分組
240 |
241 | 不希望捕获某些分组, 只需要分组内加上`?:`即可:
242 |
243 | ```javascript
244 | var reg = /(?:Byron).(ok)/;
245 | "Byron-ok".replace(reg, "$1"); // 只匹配了 ok
246 | ```
247 |
248 | ### 前瞻
249 |
250 | | 名字 | 正則 |
251 | | -------- | ------------- |
252 | | 正向前瞻 | exp(?=assert) |
253 | | 负向前瞻 | exp(?!assert) |
254 |
255 | 正向前瞻就是匹配前者, 效验后者是否存在.
256 |
257 | ```javascript
258 | // 这个正则的意思是: 匹配一个单词字符( [a-zA-Z0-9_] ), 然后验证后面是不是数字
259 | // 结果为: "X2*3". 因为3后面没有数字, 所以没有匹配到.
260 | "a2*3".replace(/\w(?=\d)/g, "X");
261 |
262 | // 结果为: "X2*X4X8"
263 | // 总的说就是
264 | "a2*34v8".replace(/\w(?=\d)/g, "X");
265 | ```
266 |
267 | 负向前瞻则相反, 匹配前面, 替代后面
268 |
269 | ```javascript
270 | // a 是单词字符, 后面是数字, 因此没有匹配到
271 | // 2 是单词字符, 后面不是数字, 被替换成X
272 | // * 不是单词字符 因此没有匹配到
273 | // 3 是单词字符, 后面是数字, 因此没有匹配到
274 | // 4 是单词字符, 后面不是数字, 被替换成X
275 | // v 是单词字符, 后面是数字, 因此没有匹配到
276 | // 8 是单词字符, 后面没有匹配到数字, 被替换成X
277 | // 结果: aX*4XvX
278 | "a2*34v8".replace(/\w(?!\d)/g, "X");
279 | ```
280 |
281 | ---
282 |
283 | 可视化正则表达式, 可以试试[regexper](https://regexper.com/), 让你看懂正则匹配的走向.
284 |
285 | 
286 |
287 | 如果有上述正则规则存在问题, 可在 issue 留言探讨~
288 |
--------------------------------------------------------------------------------
/docs/REGEXP/images/regex.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/REGEXP/images/regex.jpg
--------------------------------------------------------------------------------
/docs/REGEXP/images/regexper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/REGEXP/images/regexper.png
--------------------------------------------------------------------------------
/docs/_images/box-model-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/_images/box-model-example.png
--------------------------------------------------------------------------------
/docs/_images/css-grayscale-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/_images/css-grayscale-example.png
--------------------------------------------------------------------------------
/docs/_images/event_loop.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/_images/event_loop.gif
--------------------------------------------------------------------------------
/docs/_images/git-merge-difference.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/_images/git-merge-difference.png
--------------------------------------------------------------------------------
/docs/_images/koa-middleware.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/_images/koa-middleware.png
--------------------------------------------------------------------------------
/docs/_images/libuv.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/_images/libuv.jpeg
--------------------------------------------------------------------------------
/docs/_images/youtube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/_images/youtube.png
--------------------------------------------------------------------------------
/docs/_images/z-index-stacking-level.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/_images/z-index-stacking-level.png
--------------------------------------------------------------------------------
/docs/dev-ops.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # DevOps
4 |
5 | - [版本管理与编辑器](#版本管理与编辑器)
6 | - [vim](#vim)
7 | - [iTerm2](#iterm2)
8 | - [命令行工具](#命令行工具)
9 | - [macos](#macos)
10 | - [windows](#windows)
11 | - [环境配置](#环境配置)
12 | - [淘宝镜像](#淘宝镜像)
13 | - [更新 Node.js 版本](#更新-nodejs-版本)
14 | - [更新 package.json 中的版本号](#更新-packagejson-中的版本号)
15 | - [常用快捷键速览](#常用快捷键速览)
16 | - [windows 速查快捷键](#windows-速查快捷键)
17 | - [MacOS 常用快捷键](#macos-常用快捷键)
18 | - [nginx](#nginx)
19 | - [基础配置](#基础配置)
20 | - [启用 HTTPS 的配置](#启用-https-的配置)
21 | - [反向代理配置](#反向代理配置)
22 | - [启用 Gzip 压缩](#启用-gzip-压缩)
23 | - [配置 CORS](#配置-cors)
24 | - [常见错误](#常见错误)
25 | - [npm 发布失败](#npm-发布失败)
26 | - [npm 安装依赖报权限不足的问题](#npm-安装依赖报权限不足的问题)
27 |
28 | ## 版本管理与编辑器
29 |
30 | ### vim
31 |
32 | **Tips**
33 |
34 | 1. 输入 `vim` 命令前需要将输入法设为英文, 否则可能会遇到输入不了命令的问题.
35 | 2. 默认情况下 `vim` 属于普通模式,按下 `:` 进入命令行模式,以下命令并不是都用于命令行模式的命令。如普通模式输入 `gg` 可以将光标跳到文件首行,但在命令行模式输入是不起效的,必须退出命令行模式才可以使用。
36 | 3. 输入 `Esc` 恢复为普通模式。
37 |
38 | **退出 vim:**
39 |
40 | | 命令 | 说明 |
41 | | --------- | ---------------------------------------- |
42 | | `:q` | 不保存文件,退出vi. |
43 | | `:q!` | 不保存文件,强制退出vi. |
44 | | `:w` | 保存文件但不退出 `vim` |
45 | | `:wq` | 保存文件并退出 `vim` |
46 | | `:wq!` | 强制保存文件,并退出 `vim` |
47 | | `:w!` | 强制保存,不推出 `vim` |
48 | | `:w file` | 将修改另外保存到 `file` 中,不退出 `vim` |
49 | | `:e!` | 放弃所有修改,从上次保存文件开始再编辑 |
50 |
51 | **光标调整:**
52 |
53 | | 命令 | 说明 |
54 | | ---------------------- | ------------------------------ |
55 | | `0`、`^` | 跳到行首 |
56 | | `$` | 跳到行尾 |
57 | | `:` | 直接输入数字可以跳去指定的行号 |
58 | | `gg`、`:1` | 跳到文件第一行行首 |
59 | | `G`、`:$`、`Shift + G` | 跳到文件最后一行行首 |
60 | | `/{搜索的文本}` | 搜索内容 |
61 | | `n` | 搜索内容向前找 |
62 | | `N` | 搜索内容向后找 |
63 |
64 | **文本处理:**
65 |
66 | | 命令 | 说明 |
67 | | ----------------- | ---------------------------------------------- |
68 | | `dd` | 删除当前行 |
69 | | `:[start],[end]d` | 删除指定行,例如 `:3,5d` 是删除第 3~5 行的文本 |
70 |
71 | ### iTerm2
72 |
73 | iTerm 2是 Terminal 的替代品,是 iTerm 的后继产品。它有好看的 UI 界面与使用的功能,比如[分隔终端](https://www.iterm2.com/features.html)等功能。
74 |
75 | **常用快捷键**
76 |
77 | | 快捷键 | 说明 |
78 | | --------------- | ------------ |
79 | | `Command` + `F` | 查找内容 |
80 | | `Ctrl` + `P` | 上一条命令 |
81 | | `Ctrl` + `R` | 搜索命令历史 |
82 |
83 | **输入**
84 |
85 | | 快捷键 | 说明 |
86 | | --------------- | ---------------------------------- |
87 | | `Command` + `R` | 将输出过的信息隐藏到屏幕外(伪清屏) |
88 | | `Ctrl` + `L` | 清屏 |
89 | | `Ctrl` + `U` | 清除当前行 |
90 | | `Ctrl` + `A` | 跳到行首 |
91 | | `Ctrl` + `E` | 跳到行尾 |
92 | | `Ctrl` + `D` | 删除当前光标的字符 |
93 | | `Ctrl` + `H` | 删除光标之前的字符 |
94 | | `Ctrl` + `W` | 删除光标之前的单词 |
95 | | `Ctrl` + `K` | 删除到文本末尾 |
96 | | `Ctrl` + `T` | 交换光标处文本 |
97 |
98 | **标签页**
99 |
100 | | 快捷键 | 说明 |
101 | | ---------------------------------------------- | ------------------------ |
102 | | `Command` + `` | 调到第 `` 个 Tab |
103 | | `Command` + `T` | 新建标签 |
104 | | `Command` + `W` | 关闭标签 |
105 | | `Command` + `number`、`Command` + `left/right` | 切换标签 |
106 |
107 | **分屏**
108 |
109 | | 快捷键 | 说明 |
110 | | ----------------------------------------------------------------- | -------------- |
111 | | `Command` + `D` | 垂直分屏 |
112 | | `Command` + `Shift` + `D` | 水平分屏 |
113 | | `Command` + `Option` + `方向键`、`Command` + `[`、`Command` + `]` | 切换屏幕 |
114 | | `Command` + `;` | 查看历史命令 |
115 | | `Command` + `Shift` + `H` | 查看剪贴板历史 |
116 | | `Command` + `Enter` | 切换全屏 |
117 |
118 | **其他**
119 |
120 | - [iterm 配置utf8编码,本地终端中文不乱码,ssh 远程中文乱码](https://segmentfault.com/q/1010000002426378)
121 |
122 | ## 命令行工具
123 |
124 | 命令行工具是开发人员日常工作中不可或缺的部分,了解如何高效使用命令行可以显著提高工作效率。
125 |
126 | **通用命令**
127 |
128 | 在Windows和MacOS平台上,有许多命令是通用的,以下列出了一些基础且常用的命令:
129 |
130 | | command | 说明 |
131 | | -------------------------------- | ------------------------------ |
132 | | `pwd` | 显示当前路径 |
133 | | `mv ` | 移动文件 |
134 | | `mv ` | 重命名文件 |
135 | | `netstat –ano` | 查看所有进程端口和进程 ID |
136 | | `netstat –ano \| findstr 8080` | 查看所有 8080 端口 |
137 | | `dir`、`ls` | 查看当前目录下的文件 |
138 | | `type NUL > .nojekyll` | 新建文件, 并命名为 `.nojekyll` |
139 |
140 | ### macos
141 |
142 | | command | 说明 |
143 | | ------------------------ | -------------------------------------- |
144 | | `pbcopy` | 操作粘贴板 |
145 | | `pwd \| pbcopy` | 复制当前路径到粘贴板 |
146 | | `pbcopy < blog-post.txt` | 将文件 blog-post.text 的内容读入粘贴板 |
147 |
148 | **操作粘贴板**
149 |
150 | 将当前目录的路径复制到剪贴板:
151 |
152 | ```bash
153 | # `|` 是管道符,即前一个命令的输出结果会作为后一个命令接收的输入
154 | pwd | pbcopy
155 | ```
156 |
157 | 将当前目录下的 `file.txt` 文件的内容复制到剪贴板中:
158 |
159 | ```bash
160 | pbcopy < file.txt
161 | ```
162 |
163 | **批量修改文件名**
164 |
165 | 可以通过 Homebrew 安装 `rename` 可以实现批量修改文件名称。
166 |
167 | ```bash
168 | brew install rename
169 |
170 | # 替换文件
171 | rename 's/from/to/' *.txt
172 | ```
173 |
174 | 假如某目录有以下文件:
175 |
176 | - `report1_2023.txt`
177 | - `report2_2023.txt`
178 | - `summary_2023.txt`
179 |
180 | 现在,我们想将这些文件中的年份从 `2023` 改为 `2024`,可以执行以下命令:
181 |
182 | ```bash
183 | rename 's/_2023/_2024/' *.txt
184 | ```
185 |
186 | 解释:
187 |
188 | - `s/_2023/_2024/`:这是一个 Perl 正则表达式,表示将匹配到的字符串 `_2023` 替换为 `_2024`。
189 | - `s` 表示替换(substitute)操作。
190 | - `/` 是分隔符,用来区分不同部分的正则表达式。
191 | - `_2023` 是需要被替换的文本。
192 | - `_2024` 是替换后的文本。
193 | - `*.txt`:这指定了要操作的文件,`*`是一个通配符,表示匹配当前目录下所有以`.txt`结尾的文件。
194 |
195 | **整理文本**
196 |
197 | 假设有一个服务器的访问日志文件 `access.log`,其中每行记录包含了访问时间、IP 地址、请求类型、URL、返回状态码等信息,格式如下:
198 |
199 | ```log
200 | 127.0.0.1 - - [10/Oct/2023:13:55:36 +0200] "GET /index.html HTTP/1.1" 200 532 "-"
201 | "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
202 | 192.168.1.1 - - [10/Oct/2023:13:55:37 +0200] "POST /submit-form HTTP/1.1" 404 152 "-"
203 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
204 | ...
205 | ```
206 |
207 | 现在想要分析这些日志,提取每个 IP 地址的访问次数:
208 |
209 | ```bash
210 | awk '{print $1}' access.log | sort | uniq -c | sort -nr
211 | ```
212 |
213 | > awk 的字段区分默认是按照空格或制表符作为分隔符,$1 指的是第一个字段
214 |
215 | - `awk '{print $1}' access.log`:使用 `awk` 打印每行的第一个字段(IP 地址)。
216 | - `sort`:对输出的 IP 地址进行排序,以便 `uniq` 命令可以正确统计。
217 | - `uniq -c`:统计每个唯一 IP 地址的出现次数。
218 | - `sort -nr`:对结果按照访问次数进行降序排序。
219 |
220 | **"列出当前目录下的从大到小排序的文件名和大小"**
221 |
222 | 有时候在做构建优化的相关工作时,需要比较优化前与优化后的成果。因此需要将某构建目录下的文件信息记录下来,以方便比对:
223 |
224 | ```bash
225 | ls -lhS | awk 'NR > 1 {printf("| %-5s | %-46s |\n", $5, $9);}'
226 | ```
227 |
228 | 此命令使用 `ls` 和 `awk` 工具来筛选并格式化当前目录下的文件信息,便于进行构建优化前后的比对。
229 |
230 | `ls` 是列出目录内容的命令:
231 |
232 | - `-l` 选项表示以长格式列出信息,显示文件的详细信息,如权限、所有者、大小等。
233 | - `-h` 选项使得文件大小以易读的格式显示(如 KB、MB)。
234 | - `-S` 选项按文件大小排序,显示结果以文件大小降序排列。
235 |
236 | `awk` 命令用于文本处理,这里用于格式化 `ls` 命令的输出:
237 |
238 | - `NR > 1`:这是一个条件判断,`NR` 是 `awk` 的内置变量,代表"当前记录号",或者可以理解为"当前是第几行"。`NR > 1` 的意思是对除了第一行之外的每一行执行大括号 `{}` 里的命令。这通常用来跳过标题行或是特定的不需要处理的第一行数据。
239 | - `printf("| %-5s | %-46s |\n", $5, $9);`:是 `awk` 的 `printf` 函数调用,用于格式化输出数据。
240 | - `| %-5s |`:表示以竖线开始,然后输出第五个字段(`$5`),这里指的是文件大小。`%-5s` 表示该字段为字符串格式,左对齐,并保证至少有5个字符的宽度,如果不足5个字符,则用空格填充到5个字符宽。这样做可以确保输出的对齐美观。
241 | - `%-46s |`:表示输出第九个字段(`$9`),即文件名。同样,`%-46s` 表示该字段为字符串格式,左对齐,并保证至少有46个字符的宽度,不足部分用空格填充。这保证了即使文件名长度不一,输出也能整齐对齐。
242 | - `\n`:表示每条记录后输出一个换行符,即每条输出占用一行。
243 |
244 | 每行输出的结果为:
245 |
246 | ```log
247 | | 文件大小 | 文件名 |
248 | ```
249 |
250 | ### windows
251 |
252 | | 命令 | 说明 |
253 | | ------------ | ---------------------------- |
254 | | `explorer` | 打开文件管理器 |
255 | | `explorer .` | 打开**当前路径**的文件管理器 |
256 |
257 | ## 环境配置
258 |
259 | ### 淘宝镜像
260 |
261 | `npm` 和 `yarn` 都可以通过国内的淘宝镜像来安装依赖。
262 |
263 | 如果只想单个项目中使用淘宝镜像来安装依赖,可以输入以下命令:
264 |
265 | ```shell
266 | # npm
267 | npm install --registry=https://registry.npm.taobao.org
268 |
269 | # yarn
270 | yarn --registry=https://registry.npm.taobao.org
271 | ```
272 |
273 | 也可以安装他们定制的 `cnpm` 命令:
274 |
275 | ```shell
276 | # 全局安装命令
277 | npm install -g cnpm --registry=https://registry.npm.taobao.org
278 |
279 | # 使用 cnpm 安装依赖
280 | cnpm install
281 | ```
282 |
283 | ### 更新 Node.js 版本
284 |
285 | 推荐使用 `nvm` 来管理 `Node.js` 的版本:
286 |
287 | - Windows: [Node Version Manager (nvm) for Windows](https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows)
288 | - MacOS/unix: [Installing and Updating](https://github.com/nvm-sh/nvm#installing-and-updating)
289 |
290 | 使用方法如下:
291 |
292 | ```shell
293 | # [mac]: 查看可以安装的 Node.js 版本
294 | nvm ls-remote
295 |
296 | # [windows]: 查看本地已安装的版本
297 | # 加上 available 参数后查看 Node.js 可安装的版本
298 | nvm list [available]
299 |
300 | # 查看本地已安装的版本
301 | vm ls
302 |
303 | # 安装指定版本
304 | nvm install 6.14.4
305 |
306 | # 安装最新版本的 Node.js
307 | nvm install --lts
308 |
309 | # 使用已安装的版本
310 | nvm use 6.14.4
311 | ```
312 |
313 | 注意:在 mac 环境中,某些编辑器的插件会使用 bash 来执行 node 命令,哪怕最常用的是 `zsh`。因此即便你装了 `nvm` 并且能在 `zsh` 使用,但 `bash` 默认配置未设置的情况可能会抛出 `nvm not found` 的错误。
314 | 因此你可以尝试执行以下命令来修复路径的问题。
315 |
316 | ```bash
317 | source ~/.nvm/nvm.sh
318 | ```
319 |
320 | 从 `nvm ls` 可以看到当前安装的 node 版本,其中有个关键词是 `system`。`system` 是系统安装的版本,因此 `nvm` 不能直接删除或更新它。因此可以通过 `n` 包来更新:
321 |
322 | ```bash
323 | npx n latest
324 | ```
325 |
326 | ### 更新 package.json 中的版本号
327 |
328 | 使用 `npm-check-updates` 工具进行版本升级:
329 |
330 | ```shell
331 | # 全局安装
332 | npm -g npm-check-updates
333 | num -u
334 | ```
335 |
336 | 第三方库 `lerna` 中有个 `lerna version` 也能根据当前的版本引导开发者选择本次升级的版本。
337 |
338 | ## 常用快捷键速览
339 |
340 | 快捷键是提高工作效率的重要手段。以下列出了在Windows和MacOS操作系统上常用的快捷键。
341 |
342 | - [Mac 键盘快捷键](https://support.apple.com/zh-cn/HT201236)
343 | - [Windows 键盘快捷键](https://support.microsoft.com/zh-cn/help/12445/windows-keyboard-shortcuts)
344 | - [Chrome 键盘快捷键](https://support.google.com/chrome/answer/157179?hl=zh-Hans)
345 | - [VS Code Tips and Tricks](https://github.com/Microsoft/vscode-tips-and-tricks)
346 |
347 | ### windows 速查快捷键
348 |
349 | - `win` + `Tab`: 创建新的虚拟桌面
350 | - `win` + `Ctrl` + `D`: 创建新的虚拟桌面
351 | - `win` + `Ctrl` + `F4`: 删除当前虚拟桌面
352 | - `win` + `Ctrl` + `left/right`: 切换虚拟桌面
353 | - `win` + `E`: 打开资源管理器
354 |
355 | ### MacOS 常用快捷键
356 |
357 | | 快捷键 | 说明 |
358 | | ------------------------- | ------------------ |
359 | | `Shift` `+` `Alt` `+` `.` | 显示和隐藏隐藏文件 |
360 |
361 | ## nginx
362 |
363 | 修改完配置后在命令行输入 `nginx -s reload` 平滑使用 nginx 配置。reload 后会启动新的进程接受新请求,对于未处理完的请求还是用旧的配置,直到所有请求处理完毕后,旧的进程进行会退出。
364 |
365 | ### 基础配置
366 |
367 | ```nginx
368 | server {
369 | listen 80; # HTTP的默认端口
370 | server_name react-app.com; # 你的域名
371 |
372 | root /var/www/react-app; # 指向你的前端项目构建产物目录
373 | index index.html; # 默认文档
374 |
375 | location / {
376 | try_files $uri $uri/ /index.html; # 用于支持 SPA 的前端路由
377 | }
378 | }
379 | ```
380 |
381 | 这个配置告诉 Nginx 监听80端口,为 `example.com` 域名服务,并将所有 HTTP 请求定向到项目的根目录。`try_files` 指令用于处理SPA的前端路由,当直接访问一个不存在的路径时,Nginx 会返回 `index.html` 页面,由前端路由器处理请求路径。
382 |
383 | ### 启用 HTTPS 的配置
384 |
385 | 若已获取SSL证书及私钥,并存放于 `/etc/nginx/ssl` 目录,以下配置示例启用HTTPS支持:
386 |
387 | ```nginx
388 | # 注意, nginx 可以定义多个 server 块。因此上面 80 端口的配置和现在这个 443 端口的配置是可以共存的,不需要覆盖。
389 | server {
390 | listen 443 ssl; # HTTPS 的默认端口
391 | server_name react-app.com;
392 |
393 | ssl_certificate /etc/nginx/ssl/react-app.com.pem; # SSL证书路径
394 | ssl_certificate_key /etc/nginx/ssl/react-app.com.key; # 私钥路径
395 |
396 | root /var/www/react-app;
397 | index index.html;
398 |
399 | location / {
400 | try_files $uri $uri/ /index.html;
401 | }
402 | }
403 | ```
404 |
405 | ### 反向代理配置
406 |
407 | 对于前端应用中的 API 请求,通常需要通过 Nginx 将这些请求转发到后端服务。以下配置示例展示了如何将以`/api` 开头的请求转发到后端服务:
408 |
409 | ```nginx
410 | location /api {
411 | proxy_pass http://backend-server.com; # 后端服务器地址
412 | proxy_http_version 1.1;
413 | proxy_set_header Upgrade $http_upgrade;
414 | proxy_set_header Connection 'upgrade';
415 | proxy_set_header Host $host;
416 | proxy_cache_bypass $http_upgrade;
417 | }
418 | ```
419 |
420 | ### 启用 Gzip 压缩
421 |
422 | 为了提高网页加载速度,可以在Nginx配置中启用Gzip压缩。以下配置启用了对特定类型文件的压缩:
423 |
424 | ```nginx
425 | gzip on;
426 | gzip_disable "msie6";
427 | gzip_vary on;
428 | gzip_proxied any;
429 | gzip_comp_level 6;
430 | gzip_buffers 16 8k;
431 | gzip_http_version 1.1;
432 | gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
433 | ```
434 |
435 | 这些指令配置了Gzip压缩的各种参数,如压缩级别(`gzip_comp_level`)、压缩缓冲区大小(`gzip_buffers`),以及需要压缩的MIME类型(`gzip_types`)。
436 |
437 | ### 配置 CORS
438 |
439 | 为了允许跨域请求,可以在Nginx中配置CORS。以下配置为所有响应添加了CORS相关的头部,允许来自任何源的请求:
440 |
441 | ```nginx
442 | location / {
443 | if ($request_method = 'OPTIONS') {
444 | add_header 'Access-Control-Allow-Origin' '*';
445 | add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
446 | add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
447 | add_header 'Access-Control-Max-Age' 1728000;
448 | add_header 'Content-Type' 'text/plain; charset=utf-8';
449 | add_header 'Content-Length' 0;
450 | return 204;
451 | }
452 | add_header 'Access-Control-Allow-Origin' '*';
453 | add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
454 | add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
455 | }
456 | ```
457 |
458 | 此配置对预检请求(OPTIONS请求)和实际请求都添加了CORS头部,允许跨域资源共享。
459 |
460 | ## 常见错误
461 |
462 | 开发或运维时常常遇到的问题。
463 |
464 | ### npm 发布失败
465 |
466 | ```bash
467 | ➜ module-test git:(master) npm publish
468 | npm ERR! publish Failed PUT 403
469 | npm ERR! code E403
470 | npm ERR! [no_perms] Private mode enable, only admin can publish this module [no_perms] Private mode enable, only admin can publish this mod
471 | ule: module-test
472 | ****
473 | ```
474 |
475 | 没有权限的原因可能是我们按照了淘宝的`npm`镜像,发布通过镜像代理,就会有权限问题。这时候将权限调整回来即可:
476 |
477 | ```bash
478 | ➜ module-test git:(master) npm config set registry http://registry.npmjs.org
479 |
480 | ➜ module-test git:(master) npm publish
481 | npm ERR! code ENEEDAUTH
482 | npm ERR! need auth auth required for publishing
483 | npm ERR! need auth You need to authorize this machine using `npm adduser`
484 |
485 | npm ERR! A complete log of this run can be found in:
486 | npm ERR! /Users/anran/.npm/_logs/2019-04-27T13_56_25_234Z-debug.log
487 |
488 | # 添加账号
489 | ➜ module-test git:(master) npm adduser
490 | Username: anran758
491 | Password:
492 | Email: (this IS public) anran758@gmail.com
493 | Logged in as anran758 on http://registry.npmjs.org/.
494 |
495 | # 验证邮箱
496 | ➜ module-test git:(master) npm publish
497 | npm ERR! publish Failed PUT 403
498 | npm ERR! code E403
499 | npm ERR! you must verify your email before publishing a new package: https://www.npmjs.com/email-edit : module-test
500 |
501 | npm ERR! A complete log of this run can be found in:
502 | npm ERR! /Users/anran/.npm/_logs/2019-04-27T14_09_30_297Z-debug.log
503 |
504 | ➜ module-test git:(master) npm publish
505 | + module-test@1.0.0
506 | ```
507 |
508 | ### npm 安装依赖报权限不足的问题
509 |
510 | 如果在安装依赖时发现错误中由以下错误, 可以尝试通过[此指南](https://github.com/sindresorhus/guides/blob/master/npm-global-without-sudo.md)解决问题:
511 |
512 | ```log
513 | Please try running this command again as root/Administrator. npm
514 | (node:10370) UnhandledPromiseRejectionWarning: Error: EACCES: permission denied, open '/Users/anran/.zshrc'
515 | ```
516 |
517 | 如果是在项目内碰见权限问题,可以先检查是不是 `node_modules` 所属权限是 `root` 的,如是应该调整为当前用户才对(macOS 环境)。
518 |
--------------------------------------------------------------------------------
/docs/develop/README.md:
--------------------------------------------------------------------------------
1 | # Web 开发
2 |
3 | 本篇幅主要记录 web 开发中遇到的实现技巧、问题与解决方案,侧重点在于解决问题。
4 |
--------------------------------------------------------------------------------
/docs/develop/css/README.md:
--------------------------------------------------------------------------------
1 | # CSS 示例
2 |
3 | > css 实践搭配 codepen 预览效果会更佳噢~
4 |
5 | **Table of Contents:**
6 |
7 | [[toc]]
8 |
9 | ## Layout
10 |
11 | ### 圣杯布局
12 |
13 | 圣杯布局实际上是讨论「三栏液态布局」的实现, 主要思想是让中间主要的内容先渲染, 两边相对来说没那么重要的放在后面加载.
14 |
15 | 圣杯布局让`container`上构建三个模块, 分别为`left`、`main`、`right`,其中`main`独占一行.
16 | 实现的原理如下:
17 |
18 | 1. 三者都使用 `float` 进行浮动.
19 | 2. `container` 使用 `padding` 为两侧栏腾出空位.
20 | 3. 将主要内容 `main` 排在前头, 让**DOM 树**先加载.
21 | 4. 两侧栏添加 `relative` 定位,左列使用 `margin-left: -100%`,右例使用 `margin-left: -右列宽度`。
22 |
23 | [示例](https://anran758.github.io/pages/demos/layout/grail)
24 |
25 | 
26 |
27 | ### 双飞翼布局
28 |
29 | 双飞翼布局和圣杯布局类似,也是左,中,右三列,中列里面会再套一个容器。
30 |
31 | - 中列宽度设置为`100%`
32 | - 使用负边距`margin-left`把左右两列拉到和中列同一行
33 | - 在中列内的容器 div 设置`margin-left`和`margin-right`给左右两列留下对应的空间
34 |
35 | 实现代码也很简单:
36 |
37 | ```html
38 |
39 |
40 |
41 |
44 |
左边栏
45 |
右边栏
46 |
47 |
48 |
49 |
76 | ```
77 |
78 | 圣杯布局和双飞翼布局解决的问题是一样的,都是两边定宽,中间自适应的三栏布局,中间栏要在放在文档流前面以优先渲染。
79 |
80 | 这样做主要是因为早年的网络和设备没有现在这么优秀,为了让主要的内容先向用户呈现,所以很多时候都使用这两种布局方式。甚至可以说,现在很多人都还在使用这两种布局方式。
81 |
82 | ### FlexBox 布局
83 |
84 | `FlexBox` 是 `CSS` 的一个新特性,这个新特性解决我们以前在 `CSS` 中很多麻烦问题,比如说内容的伸缩与扩展、垂直居中、等分列、等高列等等。
85 |
86 | `FlexBox` 顾名思义就是弹性盒子, 它可以规定弹性元素如何分配空间或者布局的方式. 下面就是个例子. 利用`flex`的计算的特性, 配合 js 的`onclick`实现出来的效果.
87 | 
88 |
89 | 当我们将 Flex 布局运用在移动端, 更能体现出它的价值——它能适配移动端各种复杂的屏幕. qq 音乐的导航就是使用了`flex`的属性, 我们来随机测试一下机型. 能发现不管是什么尺寸屏幕下, `flex`都能合理的分配空间.
90 |
91 | 
92 |
93 | 以下是 `Flex` 布局的参考资料:
94 |
95 | - [FlexBox 布局入门](https://zhuanlan.zhihu.com/p/106311718)
96 | - [FlexBox 布局实际用例](https://zhuanlan.zhihu.com/p/109144068)
97 |
98 | ### 响应式布局
99 |
100 | 响应式布局实际上是一个设计理念, 它是多项技术的综合体. 能适应于各种的屏幕. 其核心围绕着媒体查询(@media)。`max-width`是媒体查询的一个特性,其意思是指媒体类型小于或等于指定的宽度时, `min-width`则相反。在 [Bootstrap](https://getbootstrap.com/docs/4.1/layout/overview/) 中已经有相关文档的指导。
101 |
102 | 以下代码是当设备的宽度**大于等于**指定尺寸时,代码会被应用:
103 |
104 | ```css
105 | /* Small devices (landscape phones, devices width >= 576px) */
106 | @media (min-width: 576px) { ... }
107 |
108 | /* Medium devices (tablets, devices width >= 768px) */
109 | @media (min-width: 768px) { ... }
110 |
111 | /* Large devices (desktops, devices width >= 992px) */
112 | @media (min-width: 992px) { ... }
113 |
114 | /* Extra large devices (large desktops, devices width >= 1200px) */
115 | @media (min-width: 1200px) { ... }
116 | ```
117 |
118 | 以下代码是当设备的宽度**小于**指定尺寸时,代码会被应用:
119 |
120 | ```css
121 | /* 超小型设备 (portrait phones, less than 576px) */
122 | @media (max-width: 575.98px) { ... }
123 |
124 | /* 小型设备 (landscape phones, less than 768px) */
125 | @media (max-width: 767.98px) { ... }
126 |
127 | /* 中型设备 (tablets, less than 992px) */
128 | @media (max-width: 991.98px) { ... }
129 |
130 | /* 大型设备 (desktops, less than 1200px) */
131 | @media (max-width: 1199.98px) { ... }
132 |
133 | /* 超大型设备 (large desktops, 1200px and up) */
134 | @media (min-width: 1200px) { ... }
135 | ```
136 |
137 | 以上使用 `.98px` 的原因在于避免 `max-width` 与 `min-width` 同时出现时规则用冲突的情况。具体原因参见: [Why does Bootstrap use a 0.02px difference between screen size thresholds in its media queries?](https://stackoverflow.com/questions/51566916/why-does-bootstrap-use-a-0-02px-difference-between-screen-size-thresholds-in-its)
138 |
139 | 还可以针对指定大小的设备宽度做定制化样式:
140 |
141 | ```css
142 | /* 超小型设备 (portrait phones, less than 576px) */
143 | @media (max-width: 575.98px) { ... }
144 |
145 | /* 小型设备 (landscape phones, 576px and up) */
146 | @media (min-width: 576px) and (max-width: 767.98px) { ... }
147 |
148 | /* 中型设备 (tablets, 768px and up) */
149 | @media (min-width: 768px) and (max-width: 991.98px) { ... }
150 |
151 | /* 大型设备 (desktops, 992px and up) */
152 | @media (min-width: 992px) and (max-width: 1199.98px) { ... }
153 |
154 | /* 超大型设备 (large desktops, 1200px and up) */
155 | @media (min-width: 1200px) { ... }
156 | ```
157 |
158 | 关于响应式布局设计的其他几个点可以看[这里](https://anran758.github.io/blog/2018/01/25/web-%E8%B5%B0%E8%BF%9Bweb%E7%A7%BB%E5%8A%A8%E5%BC%80%E5%8F%91/#%E5%93%8D%E5%BA%94%E5%BC%8F%E5%B8%83%E5%B1%80)
159 |
160 | ### Grid
161 |
162 | `Grid` 是新一代布局方式,下面是相关的学习资料:
163 |
164 | - [网格布局(Grid) | MDN](https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Grid_Layout)
165 | - [CSS Grid | freeCodeCamp](https://learn.freecodecamp.one/responsive-web-design/css-grid)
166 |
167 | ## Utils
168 |
169 | ### [display] 隐藏元素
170 |
171 | 如果项目用需要优化无障碍的体验,那应该避免使用`display: none`。因为辅助屏幕设备实际上是读不了设置了这个属性里的内容, 搜索引擎的爬虫蜘蛛也会过滤掉设置了`display: none` 里的内容.
172 |
173 | ```css
174 | .hidden {
175 | position: absolute;
176 | top: -9999em;
177 | }
178 |
179 | .hidden {
180 | position: absolute;
181 | clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
182 | clip: rect(1px, 1px, 1px, 1px);
183 | }
184 | ```
185 |
186 | 如果不用顾忌无障碍的话, 也可以这个方法来避免页面回流
187 |
188 | ```css
189 | .hidden {
190 | position: absolute;
191 | visibility: hidden;
192 | }
193 | ```
194 |
195 | ### [layout] 居中元素
196 |
197 | **常用的居中方法**:
198 |
199 | [单行垂直水平居中]: 容器 `height` 与 `line-height` 设为相同的值
200 |
201 | ```css
202 | .container {
203 | height: 30px;
204 | line-height: 30px;
205 | text-align: center;
206 | }
207 | ```
208 |
209 | `absolute` + `margin` 分配剩余空间。这个方法**需要设置宽高**.
210 |
211 | ```css
212 | .container {
213 | width: 600px;
214 | height: 400px;
215 | position: absolute;
216 | left: 0;
217 | top: 0;
218 | right: 0;
219 | bottom: 0;
220 | margin: auto;
221 | }
222 | ```
223 |
224 | `absolute` + `transform`自身宽高的一半, 副作用是`transform`会**占据原来的文档流位置**。
225 |
226 | ```css
227 | .container {
228 | position: absolute;
229 | top: 50%;
230 | left: 50%;
231 | transform: translate(-50%, -50%);
232 | }
233 | ```
234 |
235 | 基于 `vertical-align` 的水平垂直居中 --by 张鑫旭
236 |
237 | ```html
238 |
243 | ```
244 |
245 | ```css
246 | .container {
247 | position: fixed;
248 | top: 0;
249 | right: 0;
250 | bottom: 0;
251 | left: 0;
252 | /* for IE8 */
253 | /* background: url(data:image/png;base64,iVB...g==); */
254 | /* for IE9+ */
255 | background: rgba(0, 0, 0, 0.5);
256 | text-align: center;
257 | white-space: nowrap;
258 | z-index: 99;
259 | }
260 | .container:after {
261 | content: "";
262 | display: inline-block;
263 | height: 100%;
264 | vertical-align: middle;
265 | }
266 | .dialog {
267 | display: inline-block;
268 | vertical-align: middle;
269 | border-radius: 6px;
270 | background-color: #fff;
271 | text-align: left;
272 | white-space: normal;
273 | }
274 | ```
275 |
276 | `flex` 布局
277 |
278 | ```html
279 |
282 | ```
283 |
284 | ```css
285 | .parent {
286 | display: flex;
287 | justify-content: center;
288 | align-items: center;
289 | width: 100px;
290 | height: 100px;
291 | border: 1px solid red;
292 | }
293 | ```
294 |
295 | ### [text] 文本溢出隐藏
296 |
297 | **单行溢出:**
298 |
299 | `text-overflow` 只是用来说明文字溢出时用什么方式显示,要实现溢出时产生省略号的效果,还须配合其他属性.
300 |
301 | ```css
302 | /* 强制不断行, 单行超出范围出现省略号 */
303 | .overflow {
304 | overflow: hidden;
305 | white-space: nowrap;
306 | text-overflow: ellipsis;
307 | }
308 | ```
309 |
310 | **多行溢出:**
311 |
312 | ```css
313 | .line-clamp-2 {
314 | display: -webkit-box;
315 | -webkit-box-orient: vertical;
316 | -webkit-line-clamp: 2;
317 | line-clamp: 2;
318 | overflow: hidden;
319 | }
320 | ```
321 |
322 | 若项目中有使用 `unoCSS`,则我们可以在 `uno.config.js` 中配置:
323 |
324 | ```js
325 | export default defineConfig({
326 | // ...
327 | rules: [
328 | [
329 | /^line-clamp-(\d+)$/,
330 | ([, d], { constructCSS }) =>
331 | constructCSS({
332 | display: "-webkit-box",
333 | "-webkit-box-orient": "vertical",
334 | "-webkit-line-clamp": d,
335 | "line-clamp": d,
336 | overflow: "hidden",
337 | }),
338 | ],
339 | ],
340 | });
341 | ```
342 |
343 | 这样通过 `unoCSS` 的正则处理后可以直接在类名添加 `line-clamp-2` 等类名。
344 |
345 | ### [text] 文本颜色渐变
346 |
347 | ```css
348 | .text-gradient {
349 | background: linear-gradient(90deg, #00aeff, #3369e7);
350 | /* IE9+ */
351 | -webkit-background-clip: text;
352 | -webkit-text-fill-color: transparent;
353 | -webkit-box-decoration-break: clone;
354 | box-decoration-break: clone;
355 | text-shadow: none;
356 | }
357 | ```
358 |
359 | [点击此链接跳转至 codepen demo](https://codepen.io/anran758/pen/ExVRLeX)
360 |
361 | ## Feature
362 |
363 | ### [nav] 导航渐变色分割线
364 |
365 | 使用`after`对导航进行分割, 对`background`使用`linear-gradient`渐变.
366 |
367 | [点击此链接跳转至 codepen demo](https://codepen.io/anran758/pen/ypXYba)
368 |
369 | 
370 |
371 | ### [nav] 导航列表下标,悬浮动画显示
372 |
373 | 利用`:before`和`transition`实现悬浮后, 下标从底部中间向两边展开.
374 |
375 | [点击此链接跳转至 codepen demo](https://codepen.io/anran758/pen/BJZdLL)
376 |
377 | 
378 |
379 | ### [overflow] 查看更多
380 |
381 | 白色半透明遮罩的"查看更多",使用 `linear-gradient` 颜色渐变,再使用 `pointer-events: none` 清除默认事件.
382 |
383 | [点击此链接跳转至 codepen demo](https://codepen.io/anran758/pen/ppwwKN)
384 |
385 | 
386 |
387 | ### [animation] loading
388 |
389 | 我们可以利用 css3 属性来做一些动画 loading, 相对于图片既能节省 HTTP 请求, 仅需几行代码即可实现我们想要的功能功能. github 上也有很多这种动画库, 有兴趣的同学可以搜一搜.
390 |
391 | 
392 |
393 | [点击此链接跳转至 codepen demo](https://codepen.io/anran758/pen/dmOPdO)
394 |
395 | ### [image] 居中裁剪展示图片
396 |
397 | 我们经常能遇到这种情景, 做一个用户头像. 拿到的图片是一个长方形的长图, 但是我们并不需要这么长的图, 因此我们需要"裁剪". 这时我们只需设置图片中心为原点, 设置相应的宽高再加上圆角即可, 代码如下:
398 |
399 | ```css
400 | .user-info-box .avatar {
401 | width: 86px;
402 | height: 86px;
403 | border-radius: 50%;
404 | background: 50% / cover;
405 | background-color: #f1f1f1;
406 | background-image: url(https://avatars.githubusercontent.com/u/23024075?v=3);
407 | }
408 | ```
409 |
410 | 
411 |
412 | 其中`background: 50%/cover`是关键, 这一个方法同时也可以适用于其他有图片的场景.
413 |
414 | [点击此链接跳转至 codepen demo](https://codepen.io/anran758/pen/WdOvRY/)
415 |
416 | ### [image] 悬浮头像动画
417 |
418 | 我们利用 css3 属性的`transform`对悬浮后的`border`进行旋转, 通过`transition`进行过度, 从而实现悬浮后的炫酷效果.
419 |
420 | 
421 |
422 | [点击此链接跳转至 codepen demo](https://codepen.io/anran758/pen/YapWKd)
423 |
424 | ### [image] 图像置灰
425 |
426 | css 中的 filter 可以将**模糊**或**颜色偏移**等图形效果应用于元素。其中 `grayscale` 函数可以设置图像的灰度:
427 |
428 | ```css
429 | .image {
430 | filter: grayscale(100%);
431 | }
432 | ```
433 |
434 | 
435 |
436 | ### [table] 表格设置间隙
437 |
438 | 使用 `border-spacing` 属性,该属性只有在 `border-collapse` 值是 `separate` 的时候生效。
439 |
440 | ```css
441 | .table {
442 | /* 表格中相邻单元格共享边框 */
443 | border-collapse: separate;
444 | border-spacing: 16px 8px;
445 | }
446 | ```
447 |
448 | ### 图形绘制
449 |
450 | 可以利用`css`属性来绘制常见的图形, 来完成一些设计所需,同时还可以节省图片的 HTTP 请求。
451 |
452 | [点击此链接跳转至 codepen demo](https://codepen.io/anran758/pen/jxjGyo)
453 |
454 | 
455 |
456 | ## 技术细节
457 |
458 | ### 继承性与通配符
459 |
460 | 使用通配符(`*`), 意味着页面中的所有的标签都会加上通配符里的属性. 然而很多人在使用的时候, 尤其在不了解属性特性的情况下, 容易造成很大性能浪费.
461 |
462 | 就比如说有些属性是具有**继承性**的, 在下例中``标签在没有制定`color`属性时, 就逐级向上找到`.container`的`color`继承.
463 |
464 | ```html
465 |
470 |
471 |
472 | 这里是div容器内
473 |
这是一个演示的例子
474 |
475 | ```
476 |
477 | 这意味着如果我们用通配符设置这些属性时, 会徒劳给页面的增加没必要的性能负担.
478 |
479 | 再来看一个典型的例子. iOS 系统下, 点击一个链接或者通过 Javascript 定义的可点击元素的时候, 会出现一个半透明的灰色背景(就是所谓会闪一下), 这时`可以设置-webkit-tap-highlight-color`为透明来重置这个"BUG", 这里属性没用错, 但问题就出现在错误的使用了通配符. 如下图:
480 |
481 | 
482 |
483 | 还有一种就是使用`* {margin: 0; padding: 0}`则就过分了, `H1 ~ 6`标签本身就没有默认`padding`, 你特么非要给人家重置一下. ``就更无辜了, 没有默认的`padding`和`margin`也要被批斗. 因此我们应该避免使用通配符.
484 |
485 | ### 清除浮动
486 |
487 | Nicholas C. Zakas( 尼古拉斯)提出了个更好清除浮动的一个方案, 即:
488 |
489 | 设置 `display: table;` 可以创建一个匿名的表格单元,同时这个匿名的表格单元会触发 `BFC(block formatting context)` 来清除浮动。
490 |
491 | ```css
492 | .clearfix:before,
493 | .clearfix:after {
494 | content: "";
495 | display: block;
496 | }
497 |
498 | .clearfix:after {
499 | clear: both;
500 | }
501 | ```
502 |
503 | ### z-index design
504 |
505 | css 中的 z-index 可以控制元素的层级,在多人项目开发中很容易产生相互覆盖的情况,所以在事先需要对该部分做一个设计约束。
506 |
507 | 多数情况下,普通的元素若需要修改层级仅仅需要设置为低等级即可,如 `z-index: 1`。若设计全局组件为了避免业务代码的侵入,会设置一个大数值。以下变量可作为参考:
508 |
509 | ```scss
510 | $zindex-dropdown: 1000 !default;
511 | $zindex-sticky: 1020 !default;
512 | $zindex-fixed: 1030 !default;
513 | $zindex-modal-backdrop: 1040 !default;
514 | $zindex-modal: 1050 !default;
515 | $zindex-popover: 1060 !default;
516 | $zindex-tooltip: 1070 !default;
517 | ```
518 |
519 | ## 动画与特效
520 |
521 | - [使用一个 div 做动画](https://a.singlediv.com/)
522 | - [button 悬浮特效](https://codepen.io/anran758/pen/LejpaB/)
523 | - [loading.io](https://loading.io/): 商用的 loading 特效
524 |
--------------------------------------------------------------------------------
/docs/develop/css/design/botton/css/reset.css:
--------------------------------------------------------------------------------
1 | /* 简化reset, 对常用元素进行简化 */
2 |
3 | body,
4 | dl,
5 | dd,
6 | h1,
7 | h2,
8 | h3,
9 | h4,
10 | h5,
11 | h6,
12 | p,
13 | form,
14 | ol,
15 | ul {
16 | margin: 0;
17 | }
18 |
19 | ol,
20 | ul {
21 | padding: 0;
22 | list-style: none;
23 | }
24 |
25 | a {
26 | text-decoration: none;
27 | }
28 |
29 | body {
30 | font: 12px Helvetica Neue, Helvetica, Arial, Microsoft Yahei, Hiragino Sans GB, Heiti SC, WenQuanYi Micro Hei, sans-serif;
31 | }
32 |
33 | .clearfix:before,
34 | .clearfix:after {
35 | content: " ";
36 | display: block;
37 | }
38 |
39 | .clearfix:after {
40 | clear: both;
41 | }
--------------------------------------------------------------------------------
/docs/develop/css/design/botton/css/styles.css:
--------------------------------------------------------------------------------
1 | * {
2 | transition: all 0.6s ease;
3 | }
4 |
5 | html,
6 | body {
7 | box-sizing: border-box;
8 | height: 100%;
9 | width: 100%;
10 | }
11 |
12 | body {
13 | font-family: "Roboto", sans-serif;
14 | font-weight: 400;
15 | background: #e1332d;
16 | }
17 |
18 | .buttons {
19 | display: table;
20 | height: 100%;
21 | width: 100%;
22 | }
23 |
24 | .container {
25 | display: table-cell;
26 | padding: 1em;
27 | text-align: center;
28 | vertical-align: middle;
29 | }
30 |
31 | h1 {
32 | color: #fff;
33 | font-size: 1.25em;
34 | font-weight: 900;
35 | margin: 0 0 2em;
36 | }
37 |
38 | @media (min-width: 450px) {
39 | h1 {
40 | font-size: 1.75em;
41 | }
42 | }
43 |
44 | @media (min-width: 760px) {
45 | h1 {
46 | font-size: 3.25em;
47 | }
48 | }
49 |
50 | @media (min-width: 900px) {
51 | h1 {
52 | font-size: 5.25em;
53 | margin: 0 0 1em;
54 | }
55 | }
56 |
57 | .btn {
58 | position: relative;
59 | width: 100%;
60 | max-width: 160px;
61 | margin: 0 auto 2em;
62 | line-height: 45px;
63 | color: #fff;
64 | cursor: pointer;
65 | font-size: 16px;
66 | font-weight: 400;
67 | vertical-align: middle;
68 | text-transform: uppercase;
69 | }
70 |
71 | @media (min-width: 400px) {
72 | .btn {
73 | display: inline-block;
74 | margin-right: 2.5em;
75 | }
76 | .btn:nth-of-type(even) {
77 | margin-right: 0;
78 | }
79 | }
80 |
81 | @media (min-width: 600px) {
82 | .btn:nth-of-type(even) {
83 | margin-right: 2.5em;
84 | }
85 | .btn:nth-of-type(5) {
86 | margin-right: 0;
87 | }
88 | }
89 |
90 | .btn:hover {
91 | text-decoration: none;
92 | }
93 |
94 | .btn-1 {
95 | background: #e02c26;
96 | font-weight: 100;
97 | }
98 |
99 | .btn-1 svg {
100 | height: 45px;
101 | left: 0;
102 | position: absolute;
103 | top: 0;
104 | width: 100%;
105 | }
106 |
107 | .btn-1 rect {
108 | fill: none;
109 | stroke: #fff;
110 | stroke-width: 2;
111 | stroke-dasharray: 422, 0;
112 | }
113 |
114 | .btn-1:hover {
115 | background: rgba(225, 51, 45, 0);
116 | font-weight: 900;
117 | letter-spacing: 1px;
118 | }
119 |
120 | .btn-1:hover rect {
121 | stroke-width: 5;
122 | stroke-dasharray: 15, 310;
123 | stroke-dashoffset: 48;
124 | -webkit-transition: all 1.35s cubic-bezier(0.19, 1, 0.22, 1);
125 | transition: all 1.35s cubic-bezier(0.19, 1, 0.22, 1);
126 | }
127 |
128 | .btn-2 {
129 | letter-spacing: 0;
130 | }
131 |
132 | .btn-2:hover,
133 | .btn-2:active {
134 | letter-spacing: 5px;
135 | }
136 |
137 | .btn-2:after,
138 | .btn-2:before {
139 | position: relative;
140 | display: block;
141 | width: 0;
142 | border: 1px solid rgba(255, 255, 255, 0);
143 | bottom: 0px;
144 | content: " ";
145 | margin: 0 auto;
146 | backface-visibility: hidden;
147 | transition: all 280ms ease-in-out;
148 | }
149 |
150 | .btn-2:hover:after,
151 | .btn-2:hover:before {
152 | width: 70%;
153 | border-color: #fff;
154 | backface-visibility: hidden;
155 | transition: width 350ms ease-in-out;
156 | }
157 |
158 | .btn-2:hover:before {
159 | bottom: auto;
160 | top: 0;
161 | width: 70%;
162 | }
163 |
164 | .btn-3 {
165 | border: 1px solid #da251f;
166 | font-weight: 900;
167 | letter-spacing: 1px;
168 | background: #e3403a;
169 | transition: all 150ms linear;
170 | box-shadow: 0px 2px 0 #d6251f, 2px 4px 6px #e02a24;
171 | }
172 |
173 | .btn-3:hover {
174 | border: 1px solid rgba(0, 0, 0, 0.05);
175 | color: #ec817d;
176 | text-decoration: none;
177 | background: #e02c26;
178 | text-shadow: -1px -1px 0 #c2211c;
179 | box-shadow: 1px 1px 2px rgba(255, 255, 255, 0.2);
180 | transition: all 250ms linear;
181 | }
182 |
183 | .btn-4 {
184 | position: relative;
185 | border: 1px solid;
186 | overflow: hidden;
187 | }
188 |
189 | .btn-4 span {
190 | z-index: 20;
191 | }
192 |
193 | .btn-4:after {
194 | content: "";
195 | position: absolute;
196 | top: -50px;
197 | width: 50px;
198 | height: 155px;
199 | left: -75px;
200 | background: #fff;
201 | opacity: 0.2;
202 | transform: rotate(35deg);
203 | transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
204 | z-index: -10;
205 | }
206 |
207 | .btn-4:hover:after {
208 | left: 120%;
209 | transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
210 | }
211 |
212 | .btn-5 {
213 | border: 0 solid;
214 | box-shadow: inset 0 0 20px rgba(255, 255, 255, 0);
215 | outline: 1px solid;
216 | outline-color: rgba(255, 255, 255, 0.5);
217 | outline-offset: 0px;
218 | text-shadow: none;
219 | transition: all 1250ms cubic-bezier(0.19, 1, 0.22, 1);
220 | }
221 |
222 | .btn-5:hover {
223 | border: 1px solid;
224 | box-shadow: inset 0 0 20px rgba(255, 255, 255, 0.5),
225 | 0 0 20px rgba(255, 255, 255, 0.2);
226 | outline-color: rgba(255, 255, 255, 0);
227 | outline-offset: 15px;
228 | text-shadow: 1px 1px 2px #427388;
229 | }
230 |
--------------------------------------------------------------------------------
/docs/develop/css/design/botton/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | botton hover
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/docs/develop/css/design/images/auto-width.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/design/images/auto-width.gif
--------------------------------------------------------------------------------
/docs/develop/css/design/images/flexbox-1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/design/images/flexbox-1.gif
--------------------------------------------------------------------------------
/docs/develop/css/design/images/flexbox-2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/design/images/flexbox-2.gif
--------------------------------------------------------------------------------
/docs/develop/css/images/anima-loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/images/anima-loading.gif
--------------------------------------------------------------------------------
/docs/develop/css/images/avatar-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/images/avatar-1.png
--------------------------------------------------------------------------------
/docs/develop/css/images/background-more.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/images/background-more.png
--------------------------------------------------------------------------------
/docs/develop/css/images/drawing_graphics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/images/drawing_graphics.png
--------------------------------------------------------------------------------
/docs/develop/css/images/image-hover.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/images/image-hover.gif
--------------------------------------------------------------------------------
/docs/develop/css/images/nav-anima.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/images/nav-anima.png
--------------------------------------------------------------------------------
/docs/develop/css/images/nav-split.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/images/nav-split.png
--------------------------------------------------------------------------------
/docs/develop/css/images/wildcard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anran758/front-end-lab/d5e6bb152e0a52d3d66a4e8c769a7318c4944930/docs/develop/css/images/wildcard.png
--------------------------------------------------------------------------------
/docs/develop/css/reset.css:
--------------------------------------------------------------------------------
1 | /* 简化reset, 对常用元素进行简化 */
2 |
3 | body,
4 | dl,
5 | dd,
6 | h1,
7 | h2,
8 | h3,
9 | h4,
10 | h5,
11 | h6,
12 | p,
13 | form,
14 | ol,
15 | ul {
16 | margin: 0;
17 | }
18 |
19 | ol,
20 | ul {
21 | padding: 0;
22 | list-style: none;
23 | }
24 |
25 | a {
26 | text-decoration: none;
27 | }
28 |
29 | body {
30 | font: 14px Helvetica Neue, Helvetica, Arial, Microsoft Yahei, Hiragino Sans GB, Heiti SC, WenQuanYi Micro Hei, sans-serif;
31 | }
32 |
33 | .clearfix:before,
34 | .clearfix:after {
35 | content: " ";
36 | display: block;
37 | }
38 |
39 | .clearfix:after {
40 | clear: both;
41 | }
42 |
--------------------------------------------------------------------------------
/docs/develop/css/theory.md:
--------------------------------------------------------------------------------
1 | # CSS 原理
2 |
3 | 一些值得注意的 rule 或 defect:
4 |
5 | 1. css 选择符是从右至左进行匹配的,为了浏览器在匹配 rule 时消耗过的时间应避免嵌套太高层级,**建议最高不超过 3 层**。
6 | 2. 了解哪些属性可以通过继承而来,避免重复指定规则。
7 | 3. 滚动容器避免使用 `padding-bottom` 进行留白,IOS 低版本会直接忽略掉。除此之外 `IE`, 低版本的 `firefox` 据说也有这种情况。
8 |
9 | 在中文版 chrome 浏览器下, 最小的字号会有一个下限, 这个下限会强制改变小于该值的文字大小。使其成为默认浏览器最小的值。中文版最低是 `12px`,英文版则是 `10px`。
10 |
11 | **相关资料:**
12 |
13 | - [normalize 与 reset 的取舍](https://anran758.github.io/blog/2017/10/15/%E6%B5%85%E8%B0%88Normalize%E4%B8%8Ereset/)
14 |
15 | ## margin
16 |
17 | ### marin 百分比计算
18 |
19 | 普通元素的 `marin` 的百分比是根据父元素的宽度来计算的。例如:
20 |
21 | ```css
22 | .parents {
23 | width: 600px;
24 | }
25 |
26 | img {
27 | margin: 10%;
28 | }
29 | ```
30 |
31 | 那么子元素的 `margin` 计算后值为: `600px * 10% = 60px`。
32 |
33 | 绝对定位计算方式是相同的,只不过它不是相对父元素,而是相对于第一个定位元素 (`relative/absolute/fixed`) 的宽度计算的。
34 |
35 | ### margin 重叠通常特性
36 |
37 | 1. block 水平元素(不包括 `float` 和 `absolute` 元素)
38 | 2. 不考虑 `writing-mode`,只发生在垂直方向 (`margin-top` / `margin-bottom`)
39 |
40 | ### margin 重叠的场景
41 |
42 | 1. 相邻的兄弟元素
43 | 2. 父级和第一个 / 最后一个子元素
44 | 3. 空的 block 元素
45 |
46 | ### 父子 margin 重叠的其他条件
47 |
48 | **margin-top 重叠**:
49 |
50 | 1. 父元素非块状格式化上下文元素
51 | 2. 父元素没有 `border-top` 设置
52 | 3. 父元素没有 `padding-top` 值
53 | 4. 父元素和第一个子元素之间没有 `inline` 元素分隔
54 |
55 | **margin-bottom 重叠**:
56 |
57 | 1. 父元素非块状格式化上下文元素
58 | 2. 父元素没有 `border-bottom` 设置
59 | 3. 父元素没有 `padding-bottom` 值
60 | 4. 父元素和最后一个子元素之间没有 `inline` 元素分隔
61 | 5. 父元素没有 `height`、`min-height`、`max-height` 限制
62 |
63 | ### 空 block 元素重叠
64 |
65 | 1. 元素没有 `border`/`padding`/`inline` 元素;
66 | 2. 没有设置 `height`/`min-height`;
67 |
68 | ### margin 重叠计算规则
69 |
70 | 1. 正正取大值
71 | 2. 正负值相加
72 | 3. 正负最负值
73 |
74 | ### 清除 margin 重叠
75 |
76 | 1. -加入 css 属性 `overflow: hidden;`- 使父元素触发BFC,包括但不限于overflow:hidden;display:inline-block;等等
77 | 2. 加入边框 (`border`) 属性;
78 | 3. 加入 `padding-top`
79 | 4. 加入内联元素,如 ` `
80 | 5. 限制高度 `height`
81 |
82 | ### 善用 margin 重叠
83 |
84 | ```css
85 | .list {
86 | margin-top: 12px;
87 | margin-bottom: 12px;
88 | }
89 | ```
90 |
91 | 写垂直布局的时候,利用 margin 重叠 (外边距塌陷) 的特性,在容器上下加上 margin 会更具有稳定性,哪怕移除元素或者元素没加载出来都不会破坏布局。
92 |
93 | ### margin 分配空间
94 |
95 | `block` 元素可以使用 `margin` 分配剩余空间。
96 |
97 | 1. `margin:auto` 就是为了填充而设置的。
98 | 2. 如果一侧值是定值,另一侧是 auto,则 auto 为剩余值的空间大小
99 | 3. 如果两侧均是 `auto`,则平分剩余空间大小
100 |
101 | 元素上设置 `position: absolute;`、`width/height`,`left/right` 后可以通过 `margin: auto` 居中,兼容性: `IE8+`。
102 |
103 | ```css
104 | .element {
105 | width: 400px;
106 | height: 400px;
107 | position: absolute;
108 | left: 0;
109 | top: 0;
110 | right: 0;
111 | bottom: 0;
112 | margin: auto;
113 | }
114 | ```
115 |
116 | ### margin 实现等高布局
117 |
118 | 通过 `margin-bottom` 改变空间大小,`padding-bottom` 将内容填充回来,这时候元素占据的空间就是真实占高度据的空间。
119 |
120 | 副作用是必须要父元素 `overflow:hidden` 限制它,让 `margin-bottom` 不会影响外面的布局。
121 |
122 |
127 |
128 | ### margin 失效的情况
129 |
130 | 1. `inline` 元素的垂直 `margin` 无效。
131 | 2. `margin` 重叠
132 | 3. 元素处于 `display:table-cell` 或 `display:table-row`
133 | 4. `position: absolute` 与 `margin`。
134 |
135 | 绝对定位的 `margin` 值一直有效,只是表现形式不像普通元素那样。绝对定位元素是脱离文档流,它和相邻元素没有任何关系。可以理解为一个在地下,一个在天上,不在同一个维度)
136 |
137 | 5. 鞭长莫及导致的 margin 无效。
138 | 6. 内联特性导致的 margin 无效。(在有 `height` 限制下,`-margin` 小到一定程度时,会受制于内联默认对齐特性给限制住)
139 |
140 | ## float
141 |
142 | **特性**:父元素没有设置固定高度,子元素设置了浮动,会使父元素高度坍塌。
143 |
144 | ### 关于标准文档流
145 |
146 | **文档流**是相对于盒子模型,**文本流**是相对于文子段落。文本流是从上到下,从左到右的顺序进行文字排版。
147 |
148 | 元素浮动后,会让它脱离文档流。也就是说当它后面还有元素时,其他元素会无视它所占据的区域,直接在其身下布局。
149 | 但是文字还会认同浮动元素所占据的区域,围绕它布局,这意味着浮动元素脱离文档流但没有脱离文本流。
150 |
151 | 绝对定位元素脱离了文档流也脱离了文本流,文字都可以显示,这是**绝对定位和 float 的区别**。
152 |
153 | 总的来说,标准文档流=文档流+文本流。
154 |
155 | ## line-height
156 |
157 | `line-height` 的定义:行高,表示两行文字基线的距离。
158 |
159 | 1. 行高由于其继承性,影响无处不在,即使单行文本也不例外。
160 | 2. 行高只是幕后黑手,高度的表现不是行高,而是内容区域和行间距。
161 |
162 | ```css
163 | 内容区域高度 + 行间距 = 行高
164 | ```
165 |
166 | 1. 内容区域高度只与字号以及字体有关,与 `line-height` 没有关系.
167 | 2. 在 `simsun(宋体)` 字体下,内容区域等于文字大小值。
168 |
169 | ```css
170 | font-size + 行间距 = line-height
171 |
172 | font-size: 240px;
173 | line-height: 360px;
174 | 行间距 = 360px - 240px = 120px;
175 | ```
176 |
177 | ### 应用元素的差别
178 |
179 | - `line-height: 1.5` 所有可继承元素根据 `font-size` 重计算行高
180 | - `line-height: 150%/1.5em` 当前元素根据 `font-size` 计算行高,继承给下面的元素
181 |
182 | ### body 全局数值行高使用经验
183 |
184 | 面向用户: 匹配 `20px`的使用经验--方便心算
185 |
186 | ```css
187 | body {
188 | font-size: 14px;
189 | line-height: 20px;
190 | }
191 | ```
192 |
193 | ### 消除图片底部间隙的方法
194 |
195 | 1. 图片块状化 - 无基线对齐
196 |
197 | ```css
198 | img {
199 | display: block;
200 | }
201 | ```
202 |
203 | 2. 图片底线对齐
204 |
205 | ```css
206 | img {
207 | vertical-align: bottom;
208 | }
209 | ```
210 |
211 | 3. 行高足够小 - 基线位置上移
212 |
213 | ```css
214 | .box {
215 | line-height: 0;
216 | }
217 | ```
218 |
219 | ### middle
220 |
221 | `vertical-align: middle` 其实就是基线往上1/2高度。
222 |
223 | ## position relative
224 |
225 | ### relative 限制作用
226 |
227 | 1. 限制 left/top/right/bottom 定位;
228 | 2. 限制 z-index 层级; (相同relative不同层级,层级高的显示在前)
229 | 3. 限制 overflow
230 |
231 | ### relative 和定位
232 |
233 | 1. 相对自身
234 | 2. 无侵入 (无侵入定位的应用)
235 |
236 | top / bottom 和 left / right 对立属性同时存在会斗争,对立属性只有一个先来的会起作用
237 |
238 | ### relative 与 z-index 层级
239 |
240 | 1. 提高层叠上下文
241 | 2. 新建层叠上下文与层级控制
242 | 3. 设置 `position: relative` 的元素中 z-index 为 auto,不会限制内部 absolute 元素层叠问题.
243 | > :: IE6/IE7 auto 也会创建层叠上下文 (auto 不符合规范, 会出 bug)
244 |
245 | ### relative 的最小化影响原则
246 |
247 | 所谓 relative 的最小化影响原则,指的是尽量降低 relative 属性对其他元素或布局的潜在影响。
248 |
249 | 1. 尽量避免使用 relative
250 | 2. relative 最小化
251 |
252 | ## z-index
253 |
254 | ### z-index 的层级水平
255 |
256 | 
257 |
258 | 1. 层叠上下文 background/border
259 | 2. 负 z-index
260 | 3. block 块状水平盒子
261 | 4. float 浮动盒子
262 | 5. inline/inline-block 水平盒子
263 | 6. z-index: auto 或 z-index: 0 不依赖 z-index 的层叠上下文
264 | 7. 正 z-index
265 |
266 | ### z-index 的相关实践
267 |
268 | **最小化影响**
269 |
270 | - 目的: z-index 嵌套层叠关系混乱
271 | - 原因:
272 | 1. 元素的层叠水平主要由所在的层叠上下文决定;
273 | 2. IE7 z-index:auto 也会新建层叠上下文;
274 | - 做法:
275 | 1. 避免使用定位属性;
276 | 2. 定位属性从大容器平级分离为私有小容器;
277 |
278 | **避免滥用 z-index 层级**
279 |
280 | - 目的: 避免 z-index 混乱,一山比一山高的样式问题
281 | - 原因:
282 |
283 | 1. 多人维护以及后期维护;
284 |
285 | - 做法:
286 |
287 | 1. 对于非浮层元素 (e.g. 弹框),避免设置 z-index 值,z-index 值没有任何道理需要超过 2
288 | (避免弹框被非浮层元素覆盖)
289 |
290 | **组件层级计数器**
291 |
292 | - 目的: 避免浮层组件因 z-index 被覆盖的问题
293 | - 原因:
294 |
295 | 1. 总会遇到意想不到的高层级元素;
296 | 2. 组件的覆盖规则具有动态性;
297 |
298 | - 做法:
299 |
300 | 1. 组件层级计数器方法: 通过 js 获取 body 下子元素最大的 z-index 值, 然后最大值 + 1
301 |
302 | **可访问隐藏**
303 |
304 | z-index 负值元素在层叠上下文的背景之上, 其他元素之下.
305 |
--------------------------------------------------------------------------------
/docs/develop/html/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebarDepth: 3
3 | ---
4 |
5 |
6 |
7 | # HTML
8 |
9 | - [SEO(搜索引擎优化)](#seo搜索引擎优化)
10 | - [标签](#标签)
11 | - [img](#img)
12 | - [video](#video)
13 | - [视频首屏最先加载方法](#视频首屏最先加载方法)
14 | - [引用视频播放失败](#引用视频播放失败)
15 | - [pre, code](#pre-code)
16 | - [属性](#属性)
17 | - [href](#href)
18 | - [已知问题](#已知问题)
19 |
20 | ---
21 |
22 | ## SEO(搜索引擎优化)
23 |
24 | 搜索引擎优化(SEO)是一种通过优化网站来提高网站在搜索引擎中的自然排名的技术。以下内容将帮助开发者和内容创作者理解并实现有效的SEO策略。
25 |
26 | **标题和描述**
27 |
28 | - **Title 标签:** 每个页面都应有一个独特且描述性强的标题。这是搜索引擎结果中最先显示的部分。
29 | - **Meta Description:** 提供一个页面内容的简洁概述。虽然它不直接影响排名,但好的描述可以提高点击率。
30 |
31 | **语义化标签**
32 |
33 | 使用HTML5中的语义化标签(如``, `