├── .commitlintrc.js ├── .gitattributes ├── .gitignore ├── .husky └── commit-msg ├── LICENSE ├── README.md ├── docs ├── .vuepress │ ├── client.ts │ ├── config.ts │ ├── navbar.ts │ ├── public │ │ ├── avatar.png │ │ ├── dslogo.png │ │ ├── favicon.ico │ │ ├── ikun.jpeg │ │ └── logo.png │ ├── sidebar.ts │ ├── styles │ │ ├── config.scss │ │ ├── index.scss │ │ ├── palette.scss │ │ └── rainbow.scss │ ├── templateBuild.html │ └── theme.ts ├── README.md ├── apps │ ├── AppNotes.md │ ├── Applist.md │ ├── ChatGPT.md │ ├── Chrome.md │ └── design.md ├── back_end │ ├── database │ │ ├── mongodb │ │ │ └── 01.md │ │ └── mysql │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ ├── 05.md │ │ │ ├── 06.md │ │ │ ├── 07.md │ │ │ ├── 08.md │ │ │ ├── 09.md │ │ │ ├── 10.md │ │ │ └── 11.md │ ├── linux │ │ ├── 01.md │ │ ├── 02.md │ │ ├── 03.md │ │ ├── 04.md │ │ ├── 05.md │ │ ├── 06.md │ │ ├── 07.md │ │ ├── 08.md │ │ ├── 09.md │ │ ├── 10.md │ │ └── 11.md │ └── nodeJs │ │ ├── 01.md │ │ ├── 02.md │ │ ├── 03.md │ │ ├── 04.md │ │ ├── 05.md │ │ ├── 06.md │ │ ├── 07.md │ │ ├── 08.md │ │ ├── 09.md │ │ ├── 10.md │ │ ├── 11.md │ │ ├── 12.md │ │ ├── 13.md │ │ ├── 14.md │ │ ├── 15.md │ │ ├── 16.md │ │ ├── 17.md │ │ └── 18.md ├── deploy │ ├── Cloudflare.md │ ├── DNS.md │ ├── GitHub.md │ ├── Static.md │ └── VPS.md ├── front_end │ ├── css_advanced │ │ ├── less │ │ │ └── 01.md │ │ ├── scss │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ ├── 05.md │ │ │ ├── 06.md │ │ │ ├── 07.md │ │ │ ├── 08.md │ │ │ ├── 09.md │ │ │ ├── 10.md │ │ │ └── 11.md │ │ └── tailwind │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ └── 04.md │ ├── front_end_base │ │ ├── html_css │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ ├── 05.md │ │ │ ├── 06.md │ │ │ ├── 07.md │ │ │ ├── 08.md │ │ │ ├── 09.md │ │ │ ├── 10.md │ │ │ ├── 11.md │ │ │ ├── 12.md │ │ │ ├── 13.md │ │ │ ├── 14.md │ │ │ ├── 15.md │ │ │ ├── 16.md │ │ │ ├── 17.md │ │ │ ├── 18.md │ │ │ ├── 19.md │ │ │ ├── 20.md │ │ │ ├── 21.md │ │ │ ├── 22.md │ │ │ └── 23.md │ │ └── javascript │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ ├── 05.md │ │ │ ├── 06.md │ │ │ ├── 07.md │ │ │ ├── 08.md │ │ │ ├── 09.md │ │ │ ├── 10.md │ │ │ ├── 11.md │ │ │ ├── 12.md │ │ │ ├── 13.md │ │ │ ├── 14.md │ │ │ ├── 15.md │ │ │ ├── 16.md │ │ │ ├── 17.md │ │ │ ├── 18.md │ │ │ ├── 19.md │ │ │ ├── 20.md │ │ │ ├── 21.md │ │ │ ├── 22.md │ │ │ ├── 23.md │ │ │ ├── 24.md │ │ │ ├── 25.md │ │ │ ├── 26.md │ │ │ ├── 27.md │ │ │ ├── 28.md │ │ │ ├── 29.md │ │ │ ├── 30.md │ │ │ ├── 31.md │ │ │ ├── 32.md │ │ │ ├── 33.md │ │ │ ├── 34.md │ │ │ ├── 35.md │ │ │ └── 36.md │ ├── front_end_framework │ │ ├── react │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ ├── 05.md │ │ │ ├── 06.md │ │ │ ├── 07.md │ │ │ ├── 08.md │ │ │ ├── 09.md │ │ │ ├── 10.md │ │ │ ├── 11.md │ │ │ ├── 12.md │ │ │ ├── 13.md │ │ │ ├── 14.md │ │ │ ├── 15.md │ │ │ ├── 16.md │ │ │ ├── 17.md │ │ │ ├── 18.md │ │ │ ├── 19.md │ │ │ ├── 20.md │ │ │ ├── 21.md │ │ │ ├── 22.md │ │ │ └── 23.md │ │ ├── uniapp │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ ├── 05.md │ │ │ ├── 06.md │ │ │ ├── 07.md │ │ │ ├── 08.md │ │ │ ├── 09.md │ │ │ ├── 10.md │ │ │ └── 11.md │ │ ├── vue2 │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ ├── 05.md │ │ │ ├── 06.md │ │ │ ├── 07.md │ │ │ ├── 08.md │ │ │ ├── 09.md │ │ │ ├── 10.md │ │ │ ├── 11.md │ │ │ ├── 12.md │ │ │ ├── 13.md │ │ │ ├── 14.md │ │ │ ├── 15.md │ │ │ └── 16.md │ │ └── vue3 │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ ├── 06.md │ │ │ ├── 07.md │ │ │ ├── 08.md │ │ │ ├── 09.md │ │ │ ├── 10.md │ │ │ ├── 11.md │ │ │ ├── 12.md │ │ │ ├── 13.md │ │ │ ├── 14.md │ │ │ ├── 15.md │ │ │ ├── 16.md │ │ │ ├── 17.md │ │ │ └── 18.md │ ├── js_advanced │ │ ├── ajax │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ └── 04.md │ │ ├── echarts │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ └── 05.md │ │ ├── es6 │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ ├── 05.md │ │ │ ├── 06.md │ │ │ ├── 07.md │ │ │ ├── 08.md │ │ │ ├── 09.md │ │ │ ├── 10.md │ │ │ ├── 11.md │ │ │ ├── 12.md │ │ │ ├── 13.md │ │ │ └── 14.md │ │ ├── typescript │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ ├── 04.md │ │ │ ├── 05.md │ │ │ └── 06.md │ │ └── webpack │ │ │ ├── 01.md │ │ │ ├── 02.md │ │ │ ├── 03.md │ │ │ └── 04.md │ └── other │ │ └── electron │ │ ├── 01.md │ │ ├── 02.md │ │ ├── 03.md │ │ ├── 04.md │ │ ├── 05.md │ │ ├── 06.md │ │ ├── 07.md │ │ ├── 08.md │ │ ├── 09.md │ │ └── 10.md ├── intro.md ├── professional_knowledge │ ├── computer_network │ │ ├── 01.md │ │ ├── 02.md │ │ ├── 03.md │ │ ├── 04.md │ │ ├── 05.md │ │ └── 06.md │ └── software_engineer │ │ ├── 01.md │ │ ├── 02.md │ │ ├── 03.md │ │ ├── 04.md │ │ ├── 05.md │ │ ├── 06.md │ │ ├── 07.md │ │ ├── 08.md │ │ ├── 09.md │ │ └── 10.md ├── tool │ ├── efficiency │ │ ├── bookmark-scripts.md │ │ ├── online-tools.md │ │ └── software │ │ │ ├── browser.md │ │ │ ├── cross-platform.md │ │ │ ├── images │ │ │ └── instasll.jpg │ │ │ ├── vscode.md │ │ │ ├── webstorm.md │ │ │ └── windows.md │ ├── git │ │ ├── 01.md │ │ ├── 02.md │ │ ├── 03.md │ │ └── 04.md │ └── lint │ │ ├── 01.md │ │ ├── 02.md │ │ └── 03.md └── web │ ├── Comments.md │ ├── VuePress.md │ └── docsify.md └── package.json /.commitlintrc.js: -------------------------------------------------------------------------------- 1 | // @see: https://cz-git.qbenben.com/zh/guide 2 | /** @type {import('cz-git').UserConfig} */ 3 | 4 | module.exports = { 5 | ignores: [commit => commit.includes('init')], 6 | extends: ['@commitlint/config-conventional'], 7 | rules: { 8 | // @see: https://commitlint.js.org/#/reference-rules 9 | 'body-leading-blank': [2, 'always'], 10 | 'footer-leading-blank': [1, 'always'], 11 | 'header-max-length': [2, 'always', 108], 12 | 'subject-empty': [2, 'never'], 13 | 'type-empty': [2, 'never'], 14 | 'subject-case': [0], 15 | 'type-enum': [ 16 | 2, 17 | 'always', 18 | [ 19 | 'feat', 20 | 'fix', 21 | 'docs', 22 | 'style', 23 | 'refactor', 24 | 'perf', 25 | 'test', 26 | 'build', 27 | 'ci', 28 | 'chore', 29 | 'revert', 30 | 'wip', 31 | 'workflow', 32 | 'types', 33 | 'release', 34 | ], 35 | ], 36 | }, 37 | prompt: { 38 | messages: { 39 | type: '选择你要提交的类型 :', 40 | scope: '选择一个提交范围(可选):', 41 | customScope: '请输入自定义的提交范围 :', 42 | subject: '填写简短精炼的变更描述 :\n', 43 | body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n', 44 | breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n', 45 | footerPrefixesSelect: '选择关联issue前缀(可选):', 46 | customFooterPrefix: '输入自定义issue前缀 :', 47 | footer: '列举关联issue (可选) 例如: #31, #I3244 :\n', 48 | confirmCommit: '是否提交或修改commit ?', 49 | }, 50 | types: [ 51 | { value: 'feat', name: 'feat: ✨ 新增功能 | A new feature', emoji: ':sparkles:' }, 52 | { value: 'fix', name: 'fix: 🐛 修复缺陷 | A bug fix', emoji: ':bug:' }, 53 | { value: 'docs', name: 'docs: 📝 文档更新 | Documentation only changes', emoji: ':memo:' }, 54 | { 55 | value: 'style', 56 | name: 'style: 💄 代码格式 | Changes that do not affect the meaning of the code', 57 | emoji: ':lipstick:', 58 | }, 59 | { 60 | value: 'refactor', 61 | name: 'refactor: ♻️ 代码重构 | A code change that neither fixes a bug nor adds a feature', 62 | emoji: ':recycle:', 63 | }, 64 | { value: 'perf', name: 'perf: ⚡️ 性能提升 | A code change that improves performance', emoji: ':zap:' }, 65 | { 66 | value: 'test', 67 | name: 'test: ✅ 测试相关 |Adding missing tests or correcting existing tests', 68 | emoji: ':white_check_mark:', 69 | }, 70 | { 71 | value: 'build', 72 | name: 'build: 📦️ 构建相关 | Changes that affect the build system or external dependencies', 73 | emoji: ':package:', 74 | }, 75 | { 76 | value: 'ci', 77 | name: 'ci: 🎡 持续集成 | Changes to our CI configuration files and scripts', 78 | emoji: ':ferris_wheel:', 79 | }, 80 | { 81 | value: 'chore', 82 | name: "chore: 🔨 其他修改 | Other changes that don't modify src or test files", 83 | emoji: ':hammer:', 84 | }, 85 | { value: 'revert', name: 'revert: ⏪️ 回退代码 | Reverts a previous commit', emoji: ':rewind:' }, 86 | ], 87 | useEmoji: true, 88 | themeColorCode: '', 89 | scopes: [], 90 | allowCustomScopes: true, 91 | allowEmptyScopes: true, 92 | customScopesAlign: 'bottom', 93 | customScopesAlias: 'custom', 94 | emptyScopesAlias: 'empty', 95 | upperCaseSubject: false, 96 | allowBreakingChanges: ['feat', 'fix'], 97 | breaklineNumber: 100, 98 | breaklineChar: '|', 99 | skipQuestions: [], 100 | issuePrefixs: [{ value: 'closed', name: 'closed: ISSUES has been processed' }], 101 | customIssuePrefixsAlign: 'top', 102 | emptyIssuePrefixsAlias: 'skip', 103 | customIssuePrefixsAlias: 'custom', 104 | allowCustomIssuePrefixs: true, 105 | allowEmptyIssuePrefixs: true, 106 | confirmColorize: true, 107 | maxHeaderLength: Infinity, 108 | maxSubjectLength: Infinity, 109 | minSubjectLength: 0, 110 | scopeOverrides: undefined, 111 | defaultBody: '', 112 | defaultIssues: '', 113 | defaultScope: '', 114 | defaultSubject: '', 115 | }, 116 | } 117 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .temp 3 | .cache 4 | dist -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit $1 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 dselegent 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 博客地址 2 | 3 | [博客地址](https://blog.dselegent.icu) 4 | 5 | 有什么错误的地方可以提出来,笔记在我的另外一个仓库[Learning-Notes](https://github.com/dselegent/Learning-Notes) 6 | 7 | # 必看 8 | 9 | 1. 由于以前书写方法不规范,所以有些文章在博客网站上展示不太好,正在修改格式中 10 | 2. 因为改文章进行了大量替换,可能把图片链接的字符给替换导致图片失效,请一定要告诉我,我在 csdn 也是发布了一份,可以引用那边的进行修复。当然你也可以直接去我的 csdn 进行阅读[DSelegent 的博客\_CSDN 博客](https://blog.csdn.net/DSelegent) 11 | -------------------------------------------------------------------------------- /docs/.vuepress/client.ts: -------------------------------------------------------------------------------- 1 | import { defineClientConfig } from '@vuepress/client' 2 | import { onMounted } from 'vue' 3 | 4 | export default defineClientConfig({ 5 | setup() { 6 | onMounted(() => { 7 | console.log(String.raw` 8 | 9 | __ __ _ _ _ _ _ 10 | \ \ / / | | | | | | | | | | 11 | \ \ /\ / /__| | ___ ___ _ __ ___ ___ | |_ ___ _ __ ___ _ _ | |__ | | ___ __ _| | 12 | \ \/ \/ / _ \ |/ __/ _ \| '_ ${'`'} _ \ / _ \ | __/ _ \ | '_ ${'`'} _ \| | | | | '_ \| |/ _ \ / _${'`'} | | 13 | \ /\ / __/ | (_| (_) | | | | | | __/ | || (_) | | | | | | | |_| | | |_) | | (_) | (_| |_| 14 | \/ \/ \___|_|\___\___/|_| |_| |_|\___| \__\___/ |_| |_| |_|\__, | |_.__/|_|\___/ \__, (_) 15 | __/ | __/ | 16 | |___/ |___/ 17 | 18 | `) 19 | }) 20 | }, 21 | }) 22 | -------------------------------------------------------------------------------- /docs/.vuepress/config.ts: -------------------------------------------------------------------------------- 1 | import { defineUserConfig } from 'vuepress' 2 | // import { webpackBundler } from "@vuepress/bundler-webpack"; 3 | // import { defineUserConfig } from "@vuepress/cli"; 4 | // import { searchProPlugin } from 'vuepress-plugin-search-pro' 5 | import { docsearchPlugin } from '@vuepress/plugin-docsearch' 6 | import { sitemapPlugin } from 'vuepress-plugin-sitemap2' 7 | import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics' 8 | import { path } from '@vuepress/utils' 9 | import theme from './theme' 10 | 11 | export default defineUserConfig({ 12 | // 网站语言,默认为中文 13 | lang: 'zh-CN', 14 | // 网站标题 15 | title: 'dselegent-blog', 16 | // 网站描述 17 | description: '开源工具、效率方法的自我提升笔记,记录并输出一切能让自己提升的知识。', 18 | 19 | // 网站路径默认为主域名。如果网站部署在子路径下,比如 xxx.com/yyy,那么 base 应该被设置为 "/yyy/" 20 | base: '/', 21 | head: [['meta', { name: 'referrer', content: 'no-referrer' }]], 22 | theme, 23 | // 是否开启页面预拉取,如果服务器宽带足够,可改为 true,会提升其他页面加载速度 24 | shouldPrefetch: false, 25 | 26 | // 修改页面模板,https://github.com/vuepress-theme-hope/vuepress-theme-hope/blob/main/packages/theme/templates/index.build.html 27 | // 配置参考:https://vuepress.github.io/zh/reference/theme-api.html#templatebuild 28 | templateBuild: path.resolve(__dirname, 'templateBuild.html'), 29 | 30 | // 禁止文件夹生成静态文件,参考 [VuePress 文档](https://v2.vuepress.vuejs.org/zh/guide/page.html#routing) 31 | pagePatterns: ['**/*.md', '!_temp', '!reading', '!.vuepress', '!node_modules'], 32 | 33 | plugins: [ 34 | // algolia 全文搜索:没设置爬虫的话,需删除 docsearchPlugin 区块以使用节点搜索 35 | // docsearchPlugin({ 36 | // indexName: 'newzone', 37 | // appId: 'M4EXXEZIEG', 38 | // apiKey: 'fd8891a9c4cc21e0ef4f11bf44f7a11e', 39 | // }), 40 | docsearchPlugin({ 41 | appId: 'B1SZXOAN50', 42 | apiKey: '3068368ebb2ca88821ae37fa2b2813a0', 43 | indexName: 'dselegent', 44 | placeholder: '搜索文档', 45 | translations: { button: { buttonText: '搜索文档' } }, 46 | }), 47 | sitemapPlugin({ 48 | hostname: 'https://blog.dselegent.icu', 49 | }), 50 | // 本地搜索,删除上方 docsearchPlugin 区块后生效 51 | // searchProPlugin({ 52 | // indexContent: true, 53 | // hotReload: true, 54 | // customFields: [ 55 | // { 56 | // getter: ({ frontmatter }) => frontmatter.tag as string[], 57 | // formatter: `Tag: $content`, 58 | // }, 59 | // ], 60 | // }), 61 | // 谷歌分析 ID 62 | googleAnalyticsPlugin({ 63 | id: 'G-RWKZTY2P9R', 64 | }), 65 | ], 66 | }) 67 | -------------------------------------------------------------------------------- /docs/.vuepress/public/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dselegent/dselegent-blog/39b171793b69ed8b3bc914bd88d42174e534fd3c/docs/.vuepress/public/avatar.png -------------------------------------------------------------------------------- /docs/.vuepress/public/dslogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dselegent/dselegent-blog/39b171793b69ed8b3bc914bd88d42174e534fd3c/docs/.vuepress/public/dslogo.png -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dselegent/dselegent-blog/39b171793b69ed8b3bc914bd88d42174e534fd3c/docs/.vuepress/public/favicon.ico -------------------------------------------------------------------------------- /docs/.vuepress/public/ikun.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dselegent/dselegent-blog/39b171793b69ed8b3bc914bd88d42174e534fd3c/docs/.vuepress/public/ikun.jpeg -------------------------------------------------------------------------------- /docs/.vuepress/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dselegent/dselegent-blog/39b171793b69ed8b3bc914bd88d42174e534fd3c/docs/.vuepress/public/logo.png -------------------------------------------------------------------------------- /docs/.vuepress/styles/config.scss: -------------------------------------------------------------------------------- 1 | // 代码块主题设置,而非网站主题 2 | // https://vuepress-theme-hope.gitee.io/v2/zh/guide/interface/code-theme.html 3 | @use './rainbow'; 4 | 5 | // $theme-colors: #2196f3, #f26d6d, #3eaf7c, #fb9b5f; 6 | 7 | $code-light-theme: 'one-light'; 8 | $code-dark-theme: 'one-dark'; 9 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/index.scss: -------------------------------------------------------------------------------- 1 | // toc.scss, navbar.scss, sidebar.scss 2 | 3 | .toc-place-holder { 4 | // 从原本距离导航栏 2rem 改为 5rem 5 | top: calc(var(--navbar-height) + 5rem); 6 | } 7 | 8 | // #toc { 9 | // // 增加 toc 与内容区的距离 10 | // // left: calc(100% + 2rem); 11 | 12 | // // 隐藏目录文字「此页内容」 13 | // .toc-header { 14 | // visibility: hidden; 15 | // } 16 | // } 17 | 18 | /*爱的魔力转圈圈*/ 19 | .vp-project-home .vp-hero-image { 20 | width: 300px; 21 | height: 300px; 22 | border-radius: 50%; 23 | 24 | &:hover { 25 | transform: translate(-50%, -50%) rotate(666turn) !important; 26 | transition: transform 59s 1s cubic-bezier(0.3, 0, 0.8, 1) !important; 27 | } 28 | } 29 | 30 | :root { 31 | --vp-home-hero-image-background-image: linear-gradient(-45deg, var(--theme-color) 30%, var(--theme-color-next)); 32 | --vp-home-hero-image-filter: blur(80px); 33 | } 34 | 35 | .vp-hero-info-wrapper { 36 | position: relative; 37 | z-index: 0; 38 | 39 | &::after { 40 | content: ''; 41 | position: absolute; 42 | z-index: -1; 43 | top: 50%; 44 | left: 11%; 45 | border-radius: 50%; 46 | transform: translateY(-50%); 47 | width: 320px; 48 | height: 320px; 49 | opacity: 0.8; 50 | transition: opacity 1s ease; 51 | background-image: var(--vp-home-hero-image-background-image); 52 | filter: var(--vp-home-hero-image-filter); 53 | } 54 | } 55 | 56 | @media (max-width: 960px) { 57 | .vp-hero-info-wrapper::after { 58 | top: 23%; 59 | left: 35%; 60 | width: 280px; 61 | height: 280px; 62 | } 63 | } 64 | 65 | @media (max-width: 640px) { 66 | .vp-hero-info-wrapper::after { 67 | top: 24%; 68 | left: 24%; 69 | width: 256px; 70 | height: 256px; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/palette.scss: -------------------------------------------------------------------------------- 1 | /* 2 | 参考样式: 3 | https://moonvy.com/blog/post/2022/diffusion-accelerates-diffusion/#%E7%BB%98%E7%94%BB%E8%BE%85%E5%8A%A9%E5%B7%A5%E5%85%B7 4 | 代码来源:https://theme-hope.vuejs.press/zh/config/style.html 5 | */ 6 | 7 | $text-color: ( 8 | light: #2c3e50, 9 | dark: #b0aeb7, 10 | ); 11 | 12 | // content 13 | $bg-color: ( 14 | light: #fff, 15 | dark: #252232, 16 | ); 17 | 18 | $bg-color-secondary: ( 19 | light: #f8f8f8, 20 | dark: #2c293d, 21 | ); 22 | 23 | $bg-color-tertiary: ( 24 | light: #efeef4, 25 | dark: #3a3755, 26 | ); 27 | 28 | // 边框 29 | $border-color: ( 30 | light: #eaecef, 31 | dark: #302d28, 32 | ); 33 | 34 | // shadow 35 | $box-shadow: ( 36 | light: #f0f1f2, 37 | dark: #282a32, 38 | ); 39 | 40 | $card-shadow: ( 41 | light: rgb(0 0 0 / 15%), 42 | dark: rgb(0 0 0 / 30%), 43 | ); 44 | -------------------------------------------------------------------------------- /docs/.vuepress/templateBuild.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 22 | 30 | 31 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /docs/.vuepress/theme.ts: -------------------------------------------------------------------------------- 1 | import { path } from '@vuepress/utils' 2 | import { hopeTheme } from 'vuepress-theme-hope' 3 | import navbar from './navbar' 4 | import sidebar from './sidebar' 5 | 6 | export default hopeTheme({ 7 | // 主题选项:https://theme-hope.vuejs.press/zh/config/theme/layout.html 8 | hostname: 'https://blog.dselegent.icu', 9 | 10 | author: { 11 | name: 'dselegent', 12 | url: 'https://blog.dselegent.icu', 13 | }, 14 | 15 | iconAssets: 'iconfont', 16 | logo: '/logo.png', 17 | 18 | // 是否全局启用路径导航 19 | breadcrumb: true, 20 | 21 | // 页面元数据:贡献者,最后修改时间,编辑链接 22 | contributors: false, 23 | lastUpdated: true, 24 | editLink: true, 25 | 26 | darkmode: 'toggle', 27 | themeColor: false, 28 | 29 | // 默认为 GitHub. 同时也可以是一个完整的 URL 30 | repo: 'dselegent/dselegent-blog', 31 | // 编辑此页的地址设置 32 | docsRepo: 'https://github.com/dselegent/dselegent-blog', 33 | docsBranch: 'main', 34 | docsDir: 'docs', 35 | editLinkPattern: ':repo/edit/:branch/:path', 36 | // 自定义仓库链接文字。默认从 `repo` 中自动推断为 "GitHub" / "GitLab" / "Gitee" / "Bitbucket" 其中之一,或是 "Source"。 37 | repoLabel: 'GitHub', 38 | // 是否在导航栏内显示仓库链接,默认为 `true` 39 | repoDisplay: true, 40 | 41 | // navbar 42 | navbar: navbar, 43 | // 导航栏布局 44 | navbarLayout: { 45 | start: ['Brand', 'Search'], 46 | center: ['Links'], 47 | end: ['Repo', 'Outlook'], 48 | }, 49 | // 是否在向下滚动时自动隐藏导航栏 50 | // navbarAutoHide: "always", 51 | 52 | // sidebar 53 | sidebar: sidebar, 54 | // 侧边栏排序规则 55 | // sidebarSorter: ['readme', 'order', 'title'], 56 | 57 | // footer: "默认页脚", 58 | displayFooter: true, 59 | 60 | // 页面布局 Frontmatter 配置:https://theme-hope.vuejs.press/zh/config/frontmatter/layout.html#pageinfo 61 | pageInfo: ['Category', 'Tag', 'Word', 'ReadingTime', 'PageView'], 62 | 63 | // 主题功能选项:https://theme-hope.vuejs.press/zh/config/theme/feature.html 64 | blog: { 65 | articleInfo: ['Date', 'PageView', 'Category', 'Tag', 'ReadingTime'], 66 | name: 'dselegent', 67 | avatar: '/avatar.png', 68 | description: '迷信新工具,热衷于研究开源软件,定期分享探索成果', 69 | intro: '/intro.html', 70 | roundAvatar: true, 71 | medias: { 72 | GitHub: 'https://github.com/dselegent', 73 | Gitee: 'https://gitee.com/dselegent', 74 | QQ: 'https://i0.hdslb.com/bfs/album/93b93def4e70622a4f53d86cd06be2af72c5c845.png', 75 | Wechat: 'https://i0.hdslb.com/bfs/album/c8869ecfc0fcae869a2b6999d3e56b6c3abf3227.png', 76 | Email: 'mailto:1799661558@qq.com', 77 | Gmail: 'mailto:dselegent@gmail.com', 78 | BiliBili: 'https://space.bilibili.com/95443509', 79 | }, 80 | }, 81 | // 开发模式下是否启动热更新,显示所有更改并重新渲染 82 | hotReload: true, 83 | plugins: { 84 | blog: { 85 | excerpt: true, 86 | }, 87 | 88 | // 评论配置(仅做样例,记得更换) 89 | comment: { 90 | provider: 'Waline', 91 | serverURL: 'https://waline.dselegent.icu', 92 | reaction: [ 93 | 'https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-y/twemoji/13.1.0/72x72/1f44d.png', 94 | 'https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-y/twemoji/13.1.0/72x72/1f44f.png', 95 | 'https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-y/twemoji/13.1.0/72x72/1f60e.png', 96 | 'https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-y/twemoji/13.1.0/72x72/1f602.png', 97 | 'https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-y/twemoji/13.1.0/72x72/1f635-200d-1f4ab.png', 98 | ], 99 | // 部署 Waline:https://waline.js.org/guide/get-started.html 100 | pageview: true, // 浏览量统计 101 | locales: { 102 | '/': { 103 | // 表情互动提示文字 104 | reactionTitle: '已到达文章底部,欢迎留言、表情互动~', 105 | reaction0: '赞一个', 106 | reaction1: '支持下', 107 | reaction2: '有点酷', 108 | reaction3: '啥玩意', 109 | reaction4: '看不懂', 110 | // Waline 等级标签 111 | admin: '盛年不重来,一日难再晨', 112 | level0: '锻体', 113 | level1: '炼气', 114 | level2: '筑基', 115 | level3: '金丹', 116 | level4: '元婴', 117 | level5: '化神', 118 | }, 119 | }, 120 | 121 | // Giscus 备用配置 122 | /* 123 | provider: "Giscus", 124 | repo: "rockbenben/LearnData", 125 | repoId: "R_kgDOHdfk6Q", 126 | category: "Comments", 127 | categoryId: "DIC_kwDOHdfk6c4CQYNn", 128 | */ 129 | }, 130 | 131 | // 组件库 132 | // components: { 133 | // components: ['Badge', 'BiliBili', 'VideoPlayer', 'YouTube'], 134 | // }, 135 | 136 | // 禁用不需要的配置 137 | mdEnhance: { 138 | align: true, 139 | attrs: true, // 使用特殊标记为 Markdown 元素添加属性 140 | // chart: true, 141 | // codetabs: true, // 代码块分组 142 | container: true, 143 | // demo: true, //代码演示 144 | // echarts: true, 145 | // flowchart: true, 146 | gfm: true, 147 | imgLazyload: true, 148 | // imgMark: true, 149 | imgSize: true, 150 | figure: true, 151 | include: true, //导入文件 152 | // katex: true, 153 | mark: true, 154 | // mermaid: true, 155 | footnote: true, 156 | tasklist: true, 157 | sub: true, // 上下角标 158 | sup: true, 159 | // tabs: true, // 选项卡 160 | // vpre: true, 161 | // vuePlayground: true, // Vue 交互演示 162 | }, 163 | 164 | // rss 属性 165 | feed: { 166 | rss: true, 167 | count: 10, 168 | }, 169 | 170 | // pwa 171 | pwa: { 172 | favicon: '/favicon.ico', 173 | }, 174 | }, 175 | }) 176 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | #博客首页设置:https://theme-hope.vuejs.press/zh/guide/blog/home.html 3 | home: true 4 | # layout: BlogHome 5 | icon: home 6 | heroImage: /dslogo.png 7 | heroText: dselegent-blog 8 | tagline: 目前域名已更换为 blog.dselegent.icu,之前的 blog.dselegent.cf 域名已设置重定向到此域名,请小伙伴们更新一下链接 9 | bgImage: http://tc.seoipo.com/home-bg-1.jpg 10 | # heroFullScreen: true 11 | actions: 12 | - text: 前端导航 13 | link: /front_end/ 14 | type: primary 15 | 16 | - text: 后端导航 17 | link: /back_end/ 18 | type: primary 19 | 20 | features: 21 | - title: 页面开发 22 | icon: network 23 | details: 静态站点生成器 24 | link: /web/ 25 | 26 | - title: 应用 27 | icon: computer 28 | details: 应用推荐 29 | link: /apps/ 30 | 31 | - title: 专业知识 32 | icon: computer 33 | details: 计算机基础知识笔记 34 | link: /professional_knowledge/ 35 | 36 | - title: 前端导航 37 | icon: html 38 | details: 前端笔记 39 | link: /front_end/ 40 | 41 | - title: 后端导航 42 | icon: network 43 | details: 后端笔记 44 | link: /back_end/ 45 | 46 | - title: 工具导航 47 | icon: tool 48 | details: 编程工具记录 49 | link: /tool/ 50 | 51 | - title: 笔记 52 | icon: note 53 | details: Github 笔记源文件仓库 54 | link: https://github.com/dselegent/Learning-Notes 55 | 56 | #footer: 自定义你的页脚文字 57 | --- 58 | -------------------------------------------------------------------------------- /docs/apps/design.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | title: 平面设计 4 | icon: pic 5 | order: 3 6 | --- 7 | 8 | ## 电子白板 9 | 10 | 在电子白板功能普及之前,我用 Figma 对海报、图片素材进行简单剪辑,制作流程图。但电子白板的美观与自由度远胜 Figma,我现在的流程图与示意图都通过 Excalidraw 与 canvas 来完成。 11 | 12 | 在电子白板功能普及之前,我使用 Figma 对海报、图片素材进行简单剪辑,制作流程图。但是,电子白板的美观和自由度远远超过 Figma,我现在的流程图和示意图都是通过 Excalidraw 和 Canvas 完成的。 13 | 14 | ### Excalidraw 15 | 16 | [Excalidraw](https://github.com/excalidraw/excalidraw) 是一款开源免费的手绘风格画图应用,可以简单地制作美观漂亮的流程图、示意图和开发架构图等常用图片,也支持插入图片,是一款自由便捷的电子白板应用。Excalidraw 已被集成到各类白板应用中。 17 | 18 | 不过,Excalidraw 没有中文手写字体,需手动修改,比如 [Excalidraw 官方版添加中文手写字体](https://blog.csdn.net/qq_34802028/article/details/127927960),[Obsidian 中文手写体设置](https://blog.csdn.net/qq_26176515/article/details/126005295),[网页端中文手写字体配置](https://zhuanlan.zhihu.com/p/577420136)。 19 | 20 | ![](http://tc.seoipo.com/2023-01-23-20-53-36.png "手绘样例") 21 | 22 | ### Canvas 23 | 24 | Canvas(画布)是所有 UI 组件的「容器」。一个场景中,可以允许多个 canvas 对象存在,也允许 canvas 之间进行「嵌套」使用。需要注意的是,场景中的任何一个 UI 对象,都必定是某个 canvas 对象的「子级」。我最常用的是 Obsidian 和秒笔的 Canvas 功能: 25 | 26 | - Obsidian Canvas:可以将图片、视频、文本、网页、文件和 Excalidraw 聚合在一起,并建立连接线和分组。 27 | 28 | ![等后续替代本图](https://obsidian.md/images/canvas/canvas-hero.png "Obsidian canvas 样例") 29 | 30 | - 秒笔白板:支持聚合图片、文本、表格、清单、看板和 Excalidraw,但根据作者回复,妙笔的连接线和分组功能会在 2023 的下半年才摆上开发计划。 31 | 32 | ## 获取页面 logo 33 | 34 | 一些页面图标路径是隐藏的,无法在前端获取,可以使用 [ImageAssistant](https://chrome.google.com/webstore/detail/imageassistant-batch-imag/dbjbempljhcmhlfpfacalomonjpalpko) 扩展提取页面所有图片,或者通过搜索引擎搜索,获取网站提交给搜索引擎的 logo 图片。 35 | 36 | 如果获取的图标较小,可以使用 [waifu2x](http://waifu2x.udp.jp/index.zh-CN.html) 进行最大降噪,然后多次放大 logo。其他放大算法会令 logo 变化,而 waifu2x 不会改变原图。 37 | 38 | 如果图标 svg 不符合要求,可以使用 [SVG-edit](https://svgedit.netlify.app/editor/index.html) 进行简单编辑。 39 | 40 | ## Eagle 41 | 42 | Eagle 非常适合管理图片素材。其优势之一是去重,我的素材库有几十万个文件,无法一个个清理,但导入 Eagle 就可以去除重复素材。 43 | 44 | Eagle 导入流程:搜索文件夹中的 ZIP/RAR 文件,确认全部解压。 45 | 46 | ## 字体 47 | 48 | 字体是海报的灵魂,海报主标题不要用纯黑色,建议 `#1F2937`。 49 | 50 | 以下是我常用的几种字体: 51 | 52 | - [阿里巴巴普惠体 2.0](https://fonts.alibabagroup.com/#/font):简称「Alibaba PuHuiTi 2.0」,免费可商用,覆盖中英文。 53 | - [阿里妈妈数黑体](https://fonts.alibabagroup.com/#/more):简称「Alimama ShuHeiTi」,数黑体为中文简体字库,适用于电商、广告、品牌形象、推广物料等场景。 54 | - [思源字体](https://github.com/adobe-fonts/source-han-sans/):简称「Source Han Sans」,这是比较规规矩矩的一款字体,谷歌出品。用在商务风 PPT,或者是用在正文中,阅读效果都很赞。 55 | - [FOT-MatissePro](https://www.mianfeiziti.com/fonts-fotmatisseprom):原本为 EVA 的常用日语字体,也支持大部分的繁体。 56 | - [优设标题黑](https://www.fonts.net.cn/font-38213257557.html):简称「YouSheBiaoTiHei-2」,以黑体字型为基础,整体字形沉稳,同时采用较大字面和粗壮的笔画来强化力量感。每个字体水平倾斜 8° 的设计,赋予了字体极强的速度感,为了让字体倾斜后也能保持稳固,设计师将整体字身设定宽扁。而起笔和弯钩上独具匠心的尖角设计,不仅突显了设计的几何感,而且方便后期修改。 57 | - [优设好身体](https://www.fonts.net.cn/font-38877223362.html):简称「YSHaoShenTi-2」,一款亲和力、现代感极强的专业美术标题字体。它以圆体字型为基础,通过瘦高的字面、偏向几何的曲线,让整宽字体富有亲和力和时尚感。在同样的面积里,更窄的字面就意味着能容纳更多的信息,所以这款字体非常适用在需要体现亲和力与时尚感的各类品牌宣传广告和产品包装设计的标题上。 58 | - [851 手书体](https://www.100font.com/thread-114.htm):851 手書き雑フォント,虽为日系字体但覆盖了大部分的中英文,是以硬笔为主的手写字型,我喜欢用在 Excalidraw。 59 | - [濑户体](https://www.100font.com/thread-69.htm):简称「SetoFont」,是一款偏可爱风的字体,支持简体中文、繁体中文、日文。 60 | - [杨任东竹石体](https://www.fonts.net.cn/font-35850420097.html):手写字体,简称为「YRDZST」。 61 | - [得意黑字体](https://github.com/atelier-anchor/smiley-sans/releases):非手写字体,但用在 Excalidraw 也不错。 62 | - [锐字真言体](https://www.fonts.net.cn/font-35961736892.html):简称「Zhenyan」,真言体笔触浑厚有力,笔画曲折有度,字形个性鲜明,刚柔并济,落笔简洁有序,给人以遒劲有力、端正凝练的感受。直角与圆角的错落搭配使得字体婉转有度,落落大方,具有自己独到的风格!这款字体特别适用于文字标题、竞技视觉、广告设计、个性品牌设计推广、企业宣传及时尚品牌的设计应用。 63 | 64 | 字体格式建议 OTC > OTF > TTC > TTF,如果只在 Windows 平台使用,TTC/TTF 体验更佳。如果您是一名设计师并进行大量的印刷设计,您可以使用 Adobe 软件进行大量工作。在这种情况下,建议使用 OTF 字体,因为 .otf 是 基于 postscript(类似于 PDF) 并由 Adobe 开发。OTF 格式还提供了更多风格的替代方案和字距调整选项,设计师可能会觉得这些 选项有用。如果您使用 MS Ofce 进行大量工作时,建议使用 TTF 字体,因为 .ttf 是由 Microsoft 和 Apple 开发的。例如:您只能将.ttf 字体嵌入到 MS Word 和 MS PowerPoint 中,而不能嵌入 .otf 字体。 65 | -------------------------------------------------------------------------------- /docs/back_end/database/mysql/05.md: -------------------------------------------------------------------------------- 1 | # 05 【排序与分页】 2 | 3 | ## 1.排序数据 4 | 5 | ==注:如果没有使用排序操作,默认情况下查询返回的数据是按照添加数据的顺序显示的。== 6 | 7 | ### 1.1 排序规则 8 | 9 | - 使用 ORDER BY 子句排序 10 | - **ASC(ascend): 升序(默认)** 11 | - **DESC(descend):降序** 12 | - **ORDER BY 子句在SELECT语句的结尾。** 13 | 14 | ### 1.2 单列排序 15 | 16 | ```sql 17 | SELECT last_name, job_id, department_id, hire_date 18 | FROM employees 19 | ORDER BY hire_date; 20 | ``` 21 | 22 | ![image-20221010172549064](https://i0.hdslb.com/bfs/album/57be74b30aea8a1fe43cb0d305fbdce7d4b5c4be.png) 23 | 24 | ```sql 25 | SELECT last_name, job_id, department_id, hire_date 26 | FROM employees 27 | ORDER BY hire_date DESC ; 28 | ``` 29 | 30 | ![image-20221010172611271](https://i0.hdslb.com/bfs/album/d7c67209566c350aceb6aed01397bbbd584b623e.png) 31 | 32 | ```sql 33 | SELECT employee_id, last_name, salary*12 annsal 34 | FROM employees 35 | ORDER BY annsal; 36 | ``` 37 | 38 | ![image-20221010174002420](https://i0.hdslb.com/bfs/album/cd4ec20458d11e419bcd3cb724126b03a87d2e02.png) 39 | 40 | 列的别名只能在 ORDER BY中使用,不能在WHERE中使用。 41 | 42 | ```sql 43 | -- 如下操作报错! 44 | SELECT employee_id, last_name, salary*12 annsal 45 | FROM employees 46 | where annal > 10000 47 | ``` 48 | 49 | ### 1.3 多列排序 50 | 51 | ```sql 52 | SELECT last_name, department_id, salary 53 | FROM employees 54 | ORDER BY department_id, salary DESC; 55 | ``` 56 | 57 | ![image-20221010174033683](https://i0.hdslb.com/bfs/album/2550a4caaecf240d5b6215de0c14bada6682439f.png) 58 | 59 | - 可以使用不在SELECT列表中的列排序。 60 | - 在对多列进行排序的时候,首先排序的第一列必须有相同的列值,才会对第二列进行排序。如果第一列数据中所有值都是唯一的,将不再对第二列进行排序。 61 | 62 | ## 2.分页 63 | 64 | ### 2.1 背景 65 | 66 | 背景1:查询返回的记录太多了,查看起来很不方便,怎么样能够实现分页查询呢? 67 | 68 | 背景2:表里有 4 条数据,我们只想要显示第 2、3 条数据怎么办呢? 69 | 70 | ### 2.2 实现规则 71 | 72 | - 分页原理 73 | 74 | 所谓分页显示,就是将数据库中的结果集,一段一段显示出来需要的条件。 75 | 76 | - **MySQL中使用 LIMIT 实现分页** 77 | 78 | - 格式: 79 | 80 | ```sql 81 | LIMIT [位置偏移量,] 行数 82 | ``` 83 | 84 | 第一个“位置偏移量”参数指示MySQL从哪一行开始显示(`默认从0开始`),是一个可选参数,如果不指定“位置偏移量”,将会从表中的第一条记录开始(第一条记录的位置偏移量是0,第二条记录的位置偏移量是1,以此类推);第二个参数“行数”指示返回的记录条数。 85 | 86 | - 举例 87 | 88 | ```sql 89 | -- 前10条记录: 90 | SELECT * FROM 表名 LIMIT 0,10; 91 | 或者 92 | SELECT * FROM 表名 LIMIT 10; 93 | 94 | -- 第11至20条记录: 95 | SELECT * FROM 表名 LIMIT 10,10; 96 | 97 | -- 第21至30条记录: 98 | SELECT * FROM 表名 LIMIT 20,10; 99 | ``` 100 | 101 | MySQL 8.0中可以使用“`LIMIT 3 OFFSET 4`”,意思是获取从第5条记录开始后面的3条记录,和“LIMIT 4,3;”返回的结果相同。 102 | 103 | - 分页显式公式**:`(当前页数-1)\*每页条数,每页条数`** 104 | 105 | ```sql 106 | SELECT * FROM table 107 | LIMIT (PageNo - 1)*PageSize,PageSize; 108 | ``` 109 | 110 | - **注意:LIMIT 子句必须放在整个SELECT语句的最后!** 111 | - 使用 LIMIT 的好处 112 | 113 | 约束返回结果的数量可以`减少数据表的网络传输量`,也可以`提升查询效率`。如果我们知道返回结果只有 1 条,就可以使用`LIMIT 1`,告诉 SELECT 语句只需要返回一条记录即可。这样的好处就是 SELECT 不需要扫描完整的表,只需要检索到一条符合条件的记录即可返回。 114 | 115 | ## 3.课后练习 116 | 117 | **1. 查询员工的姓名和部门号和年薪,按年薪降序 按姓名升序显示** 118 | 119 | ```sql 120 | SELECT last_name,department_id,salary * 12 annual_sal 121 | FROM employees 122 | ORDER BY annual_sal DESC,last_name ASC; 123 | ``` 124 | 125 | **2.选择工资不在 8000 到17000 员工的姓名和工资,按工资降序,显示第 21到40位置的数据** 126 | 127 | ```sql 128 | SELECT last_name,salary 129 | FROM employees 130 | WHERE salary NOT BETWEEN 8000 AND 17000 131 | ORDER BY salary DESC 132 | LIMIT 20,20; 133 | ``` 134 | 135 | **3. 查询邮箱中包含 e 的员工信息,并先按邮箱的字节数降序,再按部门号 升序** 136 | 137 | ```sql 138 | SELECT last_name,email,department_id 139 | FROM employees 140 | -- where email like '%e%' 141 | WHERE email REGEXP '[e]' 142 | ORDER BY LENGTH(email) DESC,department_id ASC; 143 | ``` -------------------------------------------------------------------------------- /docs/back_end/nodeJs/02.md: -------------------------------------------------------------------------------- 1 | # 02 【nodejs开发环境安装】 2 | 3 | ## 1.版本介绍 4 | 5 | - 在命令窗口中输入 node -v 可以查看版本 6 | - 0.x 完全不技术 ES6 7 | - 4.x 部分支持 ES6 特性 8 | - 5.x 部分支持ES6特性(比4.x多些),属于过渡产品,现在来说应该没有什么理由去用这个了 9 | - 6.x 支持98%的 ES6 特性 10 | - 8.x 支持 ES6 特性 11 | 12 | ## 2.Node.js 运行环境配置:通过 Node.js 安装包(不推荐) 13 | 14 | 去 Node.js 的[官网](https://nodejs.org/en/)下载安装包: 15 | 16 | ![image-20221102141924455](https://i0.hdslb.com/bfs/album/baa4a48fa8ff1f6e0c463671d144ae9c1111e60c.png) 17 | 18 | 我们也可以在https://nodejs.org/en/download/releases/ 里下载历史版本。 19 | 20 | ![image-20221102142121523](https://i0.hdslb.com/bfs/album/ae6cded001336936a7580bbdff40d77214b0799c.png) 21 | 22 | 后续如果需要安装其他版本,可以这样做:重新下载最新的安装包,覆盖安装即可。 23 | 24 | 但我们并不推荐直接采用 Node.js.msi(windows)或者 Node.js.pkg(Mac) 安装包进行安装,因为会产生如下问题。 25 | 26 | **通过 Node.js 安装包产生的问题**: 27 | 28 | - 安装新版本时,需要覆盖就版本;而且以前版本安装的很多全局工具包,需要重新安装。 29 | - 无法回滚到之前的旧版本。 30 | - 无法在多个版本之间切换(很多时候,不同的项目需要使用特定版本。或者,我想临时尝鲜一下新版本的特性) 31 | 32 | 因此,我们暂时先不用安装 Node.js,稍后用 NVM 的方式来安装 Node.js。通过 NVM 的方式,可以让多个版本的 Node.js 共存,并灵活切换。 33 | 34 | > ### Node.js 版本常识 35 | > 36 | > - 偶数版本为稳定版(0.6.x ,0.8.x ,8.10.x) 37 | > - 奇数版本为非稳定版(0.7.x ,0.9.x ,9.11.x) 38 | > - LTS(Long Term Support) 39 | > 40 | > 参考链接:[node.js 中 LTS 和 Current 的区别](https://blog.csdn.net/u012532033/article/details/73332099) 41 | 42 | ## 3.Node.js 运行环境安装:通过 NVM(推荐) 43 | 44 | **[NVM](https://github.com/nvm-sh/nvm)**:node.js version manager,用来管理 node 的版本。 45 | 46 | **我们可以先安装 NVM,然后通过 NVM 安装 Node.js**。这是官方推荐的做法。 47 | 48 | Windows 安装的 Node.js 的步骤如下。 49 | 50 | ### 3.1 安装 NVM: 51 | 52 | (1)我们去 https://github.com/coreybutler/nvm-windows/releases 下载 NVM 的安装包: 53 | 54 | ![image-20221102142420968](https://i0.hdslb.com/bfs/album/57f120a95801261ccefa395f7ed3f766fadb5332.png) 55 | 56 | 下载下来后,直接解压到 `D:\web`目录下: 57 | 58 | ![image-20221102143322915](https://i0.hdslb.com/bfs/album/9052989c7c1c99956b5ed5caafa46964867d0733.png) 59 | 60 | (2)在上面的目录中,新建一个`settings.txt`文件,里面的内容填充如下: 61 | 62 | ```sh 63 | root: D:\web\nvm 64 | path: D:\web\nodejs 65 | arch: 64 66 | proxy 67 | ``` 68 | 69 | 上方内容的解释: 70 | 71 | - root 配置为:当前 nvm.exe 所在的目录 72 | - path 配置为:node 快捷方式所在的目录 73 | - arch 配置为:当前操作系统的位数(32/64) 74 | - proxy 不用配置 75 | 76 | (3)配置环境变量: 77 | 78 | - `NVM_HOME` = `D:\web\nvm`(当前 nvm.exe 所在目录) 79 | - `NVM_SYMLINK` = `D:\web\nodejs` (node 快捷方式所在的目录) 80 | - PATH += `;%NVM_HOME%;%NVM_SYMLINK%` 81 | 82 | 配置成功后,重启资源管理器。 83 | 84 | ### 3.2 验证 85 | 86 | (1)输入`nvm`命令查看环境变量是否配置成功 87 | 88 | (2)输入 `nvm ls`,查看已安装的所有 node 版本。 89 | 90 | (3)输入 `nvm -v`,查看 已安装的 nvm 版本。 91 | 92 | (4)输入 `node -v`,查看正在使用的 node 版本。 93 | 94 | 如果 Node 安装失败,可以参考上面这个链接。 95 | 96 | ### 3.3 安装指定版本的 Node.js 97 | 98 | ```shell 99 | nvm install 版本号 100 | 101 | # 举例 102 | nvm install 8.10.0 103 | ``` 104 | 105 | 输入 `node -v`,查看当前使用的 node 版本。 106 | 107 | 关于 NVM 的常用命令,详见下一段。 108 | 109 | 补充: 110 | 111 | 如果 Node 安装失败,可以在上方的 `settings.txt`文件中,新增如下两行,修改镜像源: 112 | 113 | ```text 114 | node_mirror: https://npmmirror.com/mirrors/node/ 115 | npm_mirror: https://npmmirror.com/mirrors/npm/ 116 | ``` 117 | 118 | - 参考链接:[安装 npm,nvm,node](https://segmentfault.com/a/1190000011114680) 119 | 120 | ## 4.NVM 的常用命令 121 | 122 | > 注意,这一段说的是 NVM 的常用命令,不是 Node 的常用命令。 123 | 124 | 查看当前使用的 nvm 版本: 125 | 126 | ```bash 127 | nvm --version 128 | ``` 129 | 130 | 查看本地安装的所有的 Node.js 版本: 131 | 132 | ```bash 133 | # 方式1 134 | nvm ls 135 | 136 | # 方式2 137 | nvm list 138 | ``` 139 | 140 | **安装指定版本的 Node.js:** 141 | 142 | ```bash 143 | nvm install 版本号 144 | 145 | # 举例 146 | nvm install 8.10.0 147 | ``` 148 | 149 | 卸载指定版本 Node.js: 150 | 151 | ```bash 152 | nvm uninstall 版本号 153 | ``` 154 | 155 | **切换使用指定版本的 node**: 156 | 157 | ```bash 158 | nvm use 版本号 159 | ``` 160 | 161 | **设置node的默认版本**: 162 | 163 | ```bash 164 | nvm alias default 版本号 165 | ``` 166 | 167 | **查看全局npm包的安装路径**: 168 | 169 | ```text 170 | npm root -g 171 | ``` 172 | 173 | 查看远程服务器端的所有 Node 版本: 174 | 175 | ```bash 176 | nvm ls-remote 177 | ``` 178 | 179 | 执行上面的命令后,在列出的版本清单中,凡是用 `Latest LTS`标注的版本,则表明是**长期维护**的版本。我们在安装时,建议安装这些版本。当然,我们也可以在网址 https://nodejs.org/en/download/releases/ 查看 LTS 的历史版本。 180 | 181 | ## 5.Node.js 的常用命令 182 | 183 | 查看 node 的版本: 184 | 185 | ```bash 186 | $ node -v 187 | ``` 188 | 189 | 执行脚本字符串: 190 | 191 | ```bash 192 | $ node -e 'console.log("Hello World")' 193 | ``` 194 | 195 | 运行脚本文件: 196 | 197 | ```bash 198 | $ node index.js 199 | 200 | $ node path/index.js 201 | 202 | $ node path/index 203 | ``` 204 | 205 | 查看帮助: 206 | 207 | ```bash 208 | $ node --help 209 | ``` -------------------------------------------------------------------------------- /docs/back_end/nodeJs/11.md: -------------------------------------------------------------------------------- 1 | # 11 【Express服务端渲染】 2 | 3 | ## 1.Express脚手架的安装 4 | 5 | 安装Express脚手架有两种方式: 6 | 7 | ### 1.1 使用express-generator安装 8 | 9 | 使用命令行进入项目目录,依次执行: 10 | 11 | ```bash 12 | cnpm i -g express-generator 13 | ``` 14 | 15 | 可通过express -h查看命令行的指令含义 16 | 17 | ```bash 18 | express -h 19 | ``` 20 | 21 | ```bash 22 | Usage: express [options] [dir] 23 | ``` 24 | 25 | ```bash 26 | Options: 27 | --version 输出版本号 28 | -e, --ejs 添加对 ejs 模板引擎的支持 29 | --pug 添加对 pug 模板引擎的支持 30 | --hbs 添加对 handlebars 模板引擎的支持 31 | -H, --hogan 添加对 hogan.js 模板引擎的支持 32 | -v, --view 添加对视图引擎(view) 的支持 (ejs|hbs|hjs|jade|pug|twig|vash) (默认是 jade 模板引擎) 33 | --no-view 创建不带视图引擎的项目 34 | -c, --css 添加样式表引擎 的支持 (less|stylus|compass|sass) (默认是普通的 css 文件) 35 | --git 添加 .gitignore 36 | -f, --force 强制在非空目录下创建 37 | -h, --help 输出使用方法 38 | ``` 39 | 40 | 创建了一个名为 myapp 的 Express 应用,并使用ejs模板引擎 41 | 42 | ```bash 43 | express --view=ejs myapp 44 | ``` 45 | 46 | 进入app,并安装依赖 47 | 48 | ```bash 49 | cd myapp 50 | npm install 51 | ``` 52 | 53 | **在Windows 下,使用以下命令启Express应用:** 54 | 55 | ```bash 56 | set DEBUG=app:* & npm start 57 | ``` 58 | 59 | **在 MacOS 或 Linux 下,使用以下命令启Express应用:** 60 | 61 | ```bash 62 | DEBUG=app:* npm start 63 | ``` 64 | 65 | ### 1.2 使用 express 命令 来快速从创建一个项目目录 66 | 67 | express 项目文件夹的名字 -e 如 使用命令行进入项目目录,依次执行: 68 | 69 | ```bash 70 | express app -e 71 | cd app 72 | cnpm install 73 | ``` 74 | 75 | 这时,你也可以看到在app文件夹下的文件结构; 76 | 77 | ```bash 78 | bin: 启动目录 里面包含了一个启动文件 www 默认监听端口是 3000 (直接node www执行即可) 79 | node_modules:依赖的模块包 80 | public:存放静态资源 81 | routes:路由操作 82 | views:存放ejs模板引擎 83 | app.js:主文件 84 | package.json:项目描述文件 85 | ``` 86 | 87 | 第一个Express应用“Hello World” 88 | 89 | 在这里,我们不使用npm构建的脚手架,而是向最开始那样直接在主目录中新建一个app.js文件。 90 | 91 | 在app.js中输入 92 | 93 | ```js 94 | const express = require('express'); //引入express模块 95 | var app= express(); //express()是express模块顶级函数 96 | 97 | app.get('/',function(req,res){ //访问根路径时输出hello world 98 | res.send(`

hello world

`); 99 | }); 100 | 101 | app.listen(8080); //设置访问端口号 102 | ``` 103 | 104 | 命令行进入项目文件夹后,键入 105 | 106 | ``` 107 | npm run start/npm start 108 | ``` 109 | 110 | 即已开启服务器,接下来只需在浏览器中运行 http://localhost:3000/ 就可以访问到服务器得到响应后的数据 111 | 112 | ## 2.模板引擎简介 113 | 114 | 相比于jade模板引擎,ejs对原HTML语言就未作出结构上的改变,只不过在其交互数据方面做出了些许修改,相比于jade更加简单易用。因此其学习成本是很低的。您也可参考ejs官网:https://ejs.bootcss.com/ 115 | 116 | ![image-20220618170512237](https://tva1.sinaimg.cn/large/0074UQWJgy1h3eh73418lj30pf0ah0zy.jpg) 117 | 118 | > 服务端渲染可以在源码中看到,客户端渲染不能再源码中看到 119 | 120 | ## 3.ejs基本使用 121 | 122 | 需要在应用中进行如下设置才能让 Express 渲染模板文件: 123 | 124 | ![image-20220618190604147](https://tva1.sinaimg.cn/large/0074UQWJgy1h3eh8z7bmwj307j0hmq5q.jpg) 125 | 126 | 这里我们使用如下配置文件: 127 | 128 | 可以通过下面的方式实现基本的ejs操作: app.js文件: 129 | 130 | ```js 131 | const express=require("express"); 132 | const ejs=require("ejs"); 133 | const fs=require("fs"); 134 | 135 | var app=express(); 136 | 137 | //引用ejs 138 | app.set('views',"./views"); //设置视图的对应目录 139 | app.set("view engine","ejs"); //设置默认的模板引擎 140 | 141 | app.get("/",function(req,res){ 142 | res.render("index",{title: "

express

"}); 143 | //会去找views目录下的index.ejs文件 144 | }); 145 | 146 | app.listen(8080); 147 | ``` 148 | 149 | ejs文件: 150 | 151 | ```ejs 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | <% for(var i=0;i<10;i++){ %> 160 | <%= i %> 161 | <% } %> 162 | 163 |
164 |

获取变量:

165 | <%- title %> 166 | <%= title %> 167 |
168 | 169 | 170 | ``` 171 | 172 | 由此可以知道: 173 | 174 | ```ejs 175 | <% xxx %>:里面写入的是js语法, 176 | <%= xxx %>:里面是服务端发送给ejs模板转义后的变量,输出为原数据 177 | <%- xxx %>:里面也是服务端发送给ejs模板后的变量,解析html 178 | 如果写html的注释,那样会在源码中显示,下面这种ejs注释不会在源码中显示 179 | <%# 注释标签,不执行、不输出内容 %> 180 | ``` 181 | 182 | 同理res.render()函数也是支持回调的: 183 | 184 | ```js 185 | res.render('user', { name: 'Tobi' }, function(err, html) { 186 | console.log(html); 187 | }); 188 | ``` 189 | 190 | 这样我们即可将看到html的内容。 191 | 192 | **关于res.redirect()** 193 | 194 | ```js 195 | const express = require('express'); 196 | const router = express.Router(); 197 | 198 | router.get('/', (req, res) => { 199 | res.render('login', { 200 | isShow: false, 201 | error: '', 202 | }); 203 | }); 204 | 205 | router.post('/', (req, res) => { 206 | if (req.body.username === 'ds' && req.body.password === '123') { 207 | console.log('登录成功'); 208 | // res.send("成功") 209 | // 重定向到home 210 | res.redirect('/index'); 211 | } else { 212 | console.log('登录失败'); 213 | res.render('login', { error: '用户名密码不匹配', isShow: true }); 214 | } 215 | }); 216 | 217 | module.exports = router; 218 | 219 | ``` 220 | 221 | ## 4.ejs 标签各种含义 222 | 223 | ```ejs 224 | <% '脚本' 标签,用于流程控制,无输出。 225 | <%_ 删除其前面的空格符 226 | <%= 输出数据到模板(输出是转义 HTML 标签) 227 | <%- 输出非转义的数据到模板 228 | <%# 注释标签,不执行、不输出内容 229 | <%% 输出字符串 '<%' 230 | %> 一般结束标签 231 | -%> 删除紧随其后的换行符 232 | _%> 将结束标签后面的空格符删除 233 | ``` 234 | 235 | ![image-20220618170943284](https://tva1.sinaimg.cn/large/0074UQWJgy1h3eh7h67twj30me05tads.jpg) 236 | 237 | 以上就为ejs基本用法,往后对数据库操作就直接把json数据从服务器返送给模板引擎就行; 238 | 239 | ## 5.导入公共模板样式 240 | 241 | `header.ejs` 242 | 243 | ```ejs 244 |
245 | 我是公共样式 246 |
247 | <% if(isShowSchool) {%> 248 |

校园招聘

249 | <% } %> 250 |
251 |
252 | ``` 253 | 254 | `index.ejs` 255 | 256 | ```ejs 257 | <%- include("./header.ejs",{ isShowSchool:true }) %> index <%# 我的注释 %> 258 | ``` 259 | 260 | ![image-20220618191129477](https://tva1.sinaimg.cn/large/0074UQWJgy1h3eh7cbp4jj31hc0rq7oj.jpg) 261 | 262 | -------------------------------------------------------------------------------- /docs/back_end/nodeJs/13.md: -------------------------------------------------------------------------------- 1 | # 13 【操作mysql数据库】 2 | 3 | ## 1.mysql 介绍 4 | 5 | 付费的商用数据库: 6 | 7 | - Oracle,典型的高富帅; 8 | - SQL Server,微软自家产品,Windows定制专款; 9 | - DB2,IBM的产品,听起来挺高端; 10 | - Sybase,曾经跟微软是好基友,后来关系破裂,现在家境惨淡。 11 | 12 | 这些数据库都是不开源而且付费的,最大的好处是花了钱出了问题可以找厂家解决,不过在Web的世界里,常常需要部署成千上万的数据库服务器,当然不能把大把大把的银子扔给厂家,所以,无论是Google、Facebook,还是国内的BAT,无一例外都选择了免费的开源数据库: 13 | 14 | - MySQL,大家都在用,一般错不了; 15 | - PostgreSQL,学术气息有点重,其实挺不错,但知名度没有MySQL高; 16 | - sqlite,嵌入式数据库,适合桌面和移动应用。 17 | 18 | 作为一个JavaScript全栈工程师,选择哪个免费数据库呢?当然是MySQL。因为MySQL普及率最高,出了错,可以很容易找到解决方法。而且,围绕MySQL有一大堆监控和运维的工具,安装和使用很方便。 19 | 20 | ![image-20220420083146539](https://i0.hdslb.com/bfs/album/8fc1c58bb05d52c4afa0641a099c92d078a55789.png) 21 | 22 | 23 | 24 | ## 2.与非关系数据库区别 25 | 26 | 关系型和非关系型数据库的主要差异是数据存储的方式。关系型数据天然就是表格式的,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。 27 | 28 | 与其相反,非关系型数据不适合存储在数据表的行和列中,而是大块组合在一起。非关系型数据通常存储在数据集中,就像文档、键值对或者图结构。你的数据及其特性是选择数据存储和提取方式的首要影响因素。 29 | 30 | **关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织** 31 | 优点: 32 | 1、易于维护:都是使用表结构,格式一致; 33 | 2、使用方便:SQL语言通用,可用于复杂查询; 34 | 3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。 35 | 缺点: 36 | 1、读写性能比较差,尤其是海量数据的高效率读写; 37 | 2、固定的表结构,灵活度稍欠; 38 | 3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。 39 | 40 | **非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。** 41 | 42 | 优点: 43 | 44 | 1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。 45 | 2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘; 46 | 3、高扩展性; 47 | 4、成本低:nosql数据库部署简单,基本都是开源软件。 48 | 49 | 缺点: 50 | 51 | 1、不提供sql支持; 52 | 2、无事务处理; 53 | 3、数据结构相对复杂,复杂查询方面稍欠。 54 | 55 | ## 3.MySQL2的历史以及选择原因 56 | 57 | MySQL2 项目是 [MySQL-Native](https://github.com/sidorares/nodejs-mysql-native) 的延续。 协议解析器代码从头开始重写,api 更改为匹配流行的 [mysqljs/mysql](https://github.com/mysqljs/mysql)。 MySQL2 团队正在与 [mysqljs/mysql](https://github.com/mysqljs/mysql) 团队合作,将共享代码分解并移至 [mysqljs](https://github.com/mysqljs/mysql) 组织下。 58 | 59 | MySQL2 大部分 API 与 [mysqljs](https://github.com/mysqljs/mysql) 兼容,并支持大部分功能。 MySQL2 还提供了更多的附加功能 60 | 61 | - 更快、更好的性能 62 | - [支持预处理](https://github.com/sidorares/node-mysql2/tree/master/documentation/Prepared-Statements.md) 63 | - MySQL二进制日志协议 64 | - [MySQL Server](https://github.com/sidorares/node-mysql2/tree/master/documentation/MySQL-Server.md) 65 | - 对编码和排序规则有很好的支持 66 | - [Promise封装](https://github.com/sidorares/node-mysql2/tree/master/documentation/Promise-Wrapper.md) 67 | - 支持压缩 68 | - SSL 和 [Authentication Switch](https://github.com/sidorares/node-mysql2/tree/master/documentation/Authentication-Switch.md) 69 | - [自定义流](https://github.com/sidorares/node-mysql2/tree/master/documentation/Extras.md) 70 | - [连接池](https://github.com/sidorares/node-mysql2/tree/master/documentation_zh-cn#using-connection-pools) 71 | 72 | MySQL2 可以跨平台使用,毫无疑问可以安装在 Linux、Mac OS 或 Windows 上。 73 | 74 | ```bash 75 | npm install --save mysql2 76 | ``` 77 | 78 | ## 4.连接数据库 79 | 80 | `config/db.config.js` 81 | 82 | ```js 83 | const mysql = require('mysql2/promise') 84 | 85 | // 通过createPool方法连接服务器 86 | const db = mysql.createPool({ 87 | host: '127.0.0.1', // 表示连接某个服务器上的mysql数据库 88 | user: 'root', // 数据库的用户名 (默认为root) 89 | password: '123456', // 数据库的密码 (默认为root) 90 | database: 'dbtest11', // 创建的本地数据库名称 91 | }) 92 | 93 | // 测试数据库是否连接成功 94 | db.getConnection((err, conn) => { 95 | conn.connect(err => { 96 | if (err) { 97 | console.log('连接失败~') 98 | } else { 99 | console.log('连接成功~') 100 | } 101 | }) 102 | }) 103 | 104 | module.exports = db 105 | ``` 106 | 107 | ## 5.查询 108 | 109 | - 导入mysql 110 | - 通过createPool方法将mysql数据库连接到服务器,并声明一个db变量 111 | - 通过db.query方法测试是否连接成功 112 | - 将数据返回给客户端 113 | - 导入express 114 | - 创建服务器 115 | - 启动服务器 116 | - 注册路由 117 | - 通过db.query(查询数据库)来执行sql语句 118 | - 如果执行成功将数据响应给客户端 119 | 120 | ```js 121 | var express = require('express') 122 | const db = require('../config/db.config') 123 | var router = express.Router() 124 | 125 | // 通过nodejs获取数据库中的数据 并返回给客户端- 126 | router.get('/', async (req, res) => { 127 | // 通过db.query方法来执行mysql 测试是否连接成功 128 | // 查询语句 data 得到的是一个数组, 增删改得到的是受影响的行数 129 | let users = await db.query('select * from users') 130 | console.log(users[0]) 131 | res.send({ 132 | ok: 1, 133 | data: users[0], 134 | }) 135 | }) 136 | 137 | module.exports = router 138 | ``` 139 | 140 | 控制台输出: 141 | 142 | ![image-20221105230812798](https://i0.hdslb.com/bfs/album/8ab5e75aff0d880a7842e5c9faff295ff16936f8.png) 143 | 144 | 返回的数据: 145 | 146 | ![image-20221105230828022](https://i0.hdslb.com/bfs/album/2b34f7577230de56f5d481588c7758ea024d53f4.png) 147 | 148 | ## 6.插入 149 | 150 | ```js 151 | // 给user中添加用户名和密码 152 | router.get('/addUser', async (req, res) => { 153 | const sql = 'insert into users (userid,department_id) values (?,?)' // 构建sql语句 154 | // 执行sql语句 155 | let ret = await db.query(sql, ['Mary', 2]) 156 | console.log(ret) 157 | res.send({ 158 | ok: 1, 159 | }) 160 | }) 161 | ``` 162 | 163 | 控制台输出: 164 | 165 | ![image-20221105231625375](https://i0.hdslb.com/bfs/album/e881a7c9d4663f1f81817f0a4d899a0428c67b64.png) 166 | 167 | ## 7.修改 168 | 169 | ````js 170 | // 修改数据 171 | router.get('/updateUser', async (req, res) => { 172 | const sql = 'update users set userid=?,department_id=? where id=?' // 构建sql语句 173 | // 执行sql语句 174 | let ret = await db.query(sql, ['Jerry', 10, 8]) 175 | console.log(ret) 176 | res.send({ 177 | ok: 1, 178 | }) 179 | }) 180 | ```` 181 | 182 | 控制台输出: 183 | 184 | ![image-20221106095506641](https://i0.hdslb.com/bfs/album/be9866defbe7223d33530db79638606752fc3b9f.png) 185 | 186 | ## 8.删除 187 | 188 | ```js 189 | // 删除数据 190 | router.get('/deleteUser', async (req, res) => { 191 | const sql = 'delete from users where id=?' // 构建sql语句 192 | // 执行sql语句 193 | let ret = await db.query(sql, [8]) 194 | console.log(ret) 195 | res.send({ 196 | ok: 1, 197 | }) 198 | }) 199 | ``` 200 | 201 | 控制台输出: 202 | 203 | ![image-20221106100105915](https://i0.hdslb.com/bfs/album/45f7756833e7a6b94fe54c92ae3c350e12614d92.png) -------------------------------------------------------------------------------- /docs/deploy/DNS.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | title: 域名 DNS 托管 4 | icon: sitemap 5 | order: 5 6 | --- 7 | 8 | 国内访问为主的话,域名建议备案后托管在国内厂商。之前试过 Cloudflare,光域名解析就用了 500 ms,换回阿里云后速度稳定许多。 9 | 10 | - DNS 迁移是在域名管理商处修改。比如我的域名是在阿里云购买,试过 DNS 迁移到 Cloudflare,之后再次迁移 DNS,需要回到阿里云操作。 11 | - 如果阿里云的安全验证一直被卡住,可以换个浏览器,比如 Firefox。 12 | - 子域名可以使用 [NS 记录](https://help.aliyun.com/document_detail/29725.html?#h2-ns-7),托管到其他域名服务商。但 Cloudflare 不支持单独子域名托管。 13 | 14 | 域名 DNS 服务器修改(阿里云): 15 | -------------------------------------------------------------------------------- /docs/deploy/GitHub.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | title: GitHub 4 | icon: github 5 | order: 3 6 | --- 7 | 8 | ## GitHub Actions 9 | 10 | GitHub Actions 是一个持续集成和持续交付 (CI/CD) 平台,可用于自动执行构建、测试和部署管道。您可以创建工作流程来构建和测试存储库的每个拉取请求,或将合并的拉取请求部署到生产环境。将 GitHub Actions 命令保存为 `main.yml`,放于 `.github\workflows` 目录下,repo 发生指定调节的改变时,Actions 会自动运行。^[[了解 GitHub Actions](https://docs.github.com/cn/actions/learn-github-actions/understanding-github-actions)] 11 | 12 | - [GitHub Actions 官方市场](https://github.com/marketplace?type=actions) 13 | - [Awesome Actions](https://github.com/sdras/awesome-actions) 14 | 15 | 如果 GitHub Actions 命令中有涉及密码等私密信息,则进入项目仓库的「setting」>「Secrets」>「Action」,添加密钥进行加密处理。比如新建密钥 PERSONAL_TOKEN,Actions 命令中使用 `${{ secrets.PERSONAL_TOKEN }}` 来指代该密钥。 16 | 17 | ### 不同仓库间复制 18 | 19 | 复制文件到目的地,文档没变化则不会执行。案例为将当前仓库 main 分支下 docs 的 README.md 文件复制到另一个仓库 rockbenben/LearnData/ 路径下,如果目标路径存在相同文件,则将覆盖。如果让 `clean: true` 生效,Actions 会将目标路径情况,然后执行复制。 20 | 21 | 此动作需按 [Creating a personal access token](https://docs.github.com/cn/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-token) 建立[个人访问令牌](https://github.com/settings/tokens),勾选权限「repo Full control of private repositories」,然后将该 token 值其保存在项目仓库的 Action 密钥。 22 | 23 | ```yml 24 | - name: Copy file 25 | uses: andstor/copycat-action@v3 26 | with: 27 | personal_token: ${{ secrets.PERSONAL_TOKEN }} 28 | src_path: docs/README.md 29 | dst_path: / 30 | dst_owner: rockbenben 31 | dst_repo_name: LearnData 32 | dst_branch: main 33 | src_branch: main 34 | #clean: true 35 | ``` 36 | 37 | ### Actions 失败重试 38 | 39 | 在 job 和 step 中使用 if 语句,只有满足条件时才执行具体的 job 或 step。^[[最全总结,GitHub Action 自动化部署](https://blog.csdn.net/Ber_Bai/article/details/120310024)] 40 | 41 | ```bash 42 | # 任务状态检查函数 43 | success() # 当上一步执行成功时返回 true 44 | always() # 总是返回 true 45 | cancelled() # 当 workflow 被取消时返回 true 46 | failure() # 当上一步执行失败时返回 true 47 | ``` 48 | 49 | first_step 会总是执行,second_step 需要上一步 first_step 执行成功才会执行,third_step 只有上一步 second_step 执行失败才执行。当 third_step 与 second_step 命令相同时,就可以达到失败重试的效果了。 50 | 51 | ```yml 52 | jobs: 53 | first_job: 54 | name: My first job 55 | runs-on: ubuntu-latest 56 | steps: 57 | - name: first_step 58 | if: always() 59 | 60 | - name: second_step 61 | if: success() 62 | 63 | - name: third_step 64 | if: failure() 65 | ``` 66 | 67 | ### uses 版本号 68 | 69 | `uses: SamKirkland/FTP-Deploy-Action@4.3.1`:uses 会指定此步骤运行 SamKirkland/FTP-Deploy-Action 存储库中的 4.3.1 版本。 70 | 71 | 但有时 Actions 的版本不会这么快更新,又必须使用最新版,可以将版本号改为 branch name,比如 `uses: SamKirkland/FTP-Deploy-Action@master`。 72 | 73 | ## 常见问题 74 | 75 | ### GitHub 忽略指定文件 76 | 77 | 项目路径新建一个命名为 .gitignore 的文件,将想要忽略的文件夹和文件写入 .gitignore 文件,换行分隔。 78 | 79 | 比如要忽略 node_modules 文件夹,就直接在文件中输入 node_modules。 80 | -------------------------------------------------------------------------------- /docs/deploy/Static.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | title: 静态部署 4 | icon: generic 5 | order: 1 6 | --- 7 | 8 | ## 静态托管 9 | 10 | 如果国内静态资源库没有你要的静态包,推荐用 `npm i` 命令将静态包下载到本地,并部署到阿里云/七牛云的国内服务器上,避免网页受 UNPKG 和 jsDelivr 屏蔽影响而出现偏差。 11 | 12 | 静态资源库: 13 | 14 | - [字节 CDN](https://cdn.bytedance.com/):国内测速表现最佳,缓存过期时间最长设置一年。 15 | - [Staticfile CDN](https://www.staticfile.org/):CDN 加速由七牛云提供。 16 | 17 | emoji 等可以使用静态资源库上的项目,比如 twemoji,上面有集成 png 图片。 18 | 19 | ### NPM 包 20 | 21 | - UNPKG:**有墙风险且不稳定**,默认为最新版本,无需 `@latest` 标签。 22 | - 将静态文件发布为 npm 包,参考[一分钟教你发布 npm 包](https://segmentfault.com/a/1190000023075167)。 23 | - 加速:在 [npm 官方源](https://www.npmjs.com/)中搜索包位置,然后使用前缀 `https://unpkg.com/`。 24 | - [NPM MIRROR](https://npmmirror.com/):NPM 项目的国内镜像镜像,不能做静态托管用途。`https://registry.npmmirror.com/项目名/版本号` 可以看见项目的各种信息,但看不了里面的文件。 25 | - UNPKG 镜像:有资源可以用服务器自建服务,反向代理 unpkg。 26 | - ~~饿了么 CDN(已关):国内唯一能用的 npm 镜像,2022.07.13 发现外部访问被拒绝。之前饿了么并没说支持对外,可能已经彻底取消了。使用饿了么 CDN 时,注意 `https://npm.elemecdn.com/react@latest/` 需要时间更新,具体频率未知,可固定大版本号来获取更新 `https://npm.elemecdn.com/react@^18/`。~~ 27 | - GitHub:基于 GitHub 公共仓库的资源托管,资源不会失效,但有时需要根据 CDN 服务商而更换域名。 28 | - ~~[Statically](https://statically.io/):jsDeliver 的替代品,在中国大陆所有地区连接异常。~~ 29 | - ~~jsDelivr(已墙):速度最快,原本是最稳的,但域名暴雷后,经常断开,2022.06.01 彻底打不开。配合 Github action,更新后自动访问 jsdelivr CDN 缓存刷新链接,保持页面常新。刷新命令参考 `curl https://purge.jsdelivr.net/gh/username/project/file`。~~ 30 | 31 | 第三方托管过于不稳定,最终我转为自托管 oss.newzone.top。 32 | 33 | ### 部署平台 34 | 35 | - Cloudflare:Pages 和 Workers 两类部署方式。 36 | - [Workers](../deploy/Cloudflare.html#反向代理):复制镜像网站,可直接访问,但反向代理稳定性成疑。 37 | - Pages:部署简单,外网速度很快,但国内速度不稳,而且 page.dev 域名有时会被墙,可购买便宜的临时域名(一年)来解决该问题。 38 | - Netlify:国内速度慢点,图片容易卡死,但还算稳定。 39 | - Vercel:推荐使用 GitHub 账户登录,有可能需要绑定国外手机号(不支持 Voice)。2022.08.26,「\*.vercel.app」域名被 DNS 污染,需要绑定自定义域名。 40 | - AWS: 邮箱注册,不过需要信用卡认证。 41 | - 国内平台:Gitee、WuliHub、CODING,都需要实名认证。 42 | 43 | ### IPFS 44 | 45 | IPFS 无需服务器就可建立静态网站,号称永不失效,但**国内稳定性成疑问,实用性一般**。IPFS 托管在一个网关上,并不会自动复制到所有网关。 46 | 47 | [pinata](https://pinata.cloud/) 上传网站构建的目录文件夹,上传后,即可通过 IPFS Hash 访问。网站目录中必须有 index.html,否则网页中将显示网站目录。即使有 index.html,其他人在拥有 CID 后,可以通过 IPFS Desktop 来获取网站的完整目录。为确保私密性,建议只上传单文件。使用单文件 CID 视为单一网站,不可调用原目录中的文件。^[[How to Easily Host a Website on IPFS](https://medium.com/pinata/how-to-easily-host-a-website-on-ipfs-9d842b5d6a01)] 48 | 49 | 上传 ipfs 到 pinata 之后,cloudflare 等其他网关不一定会完全复制文件,php 无法抓取加载,所以不建议使用 cloudflare 网关。 50 | 51 | cloudflare 接管 pinata 后,ipfs 域名需通过「pinata 托管」>「cloudflare DNS」>「cloudflare SSL」。如果中途将 DNS 指向 `http://gateway.pinata.cloud` 等非 cloudflare ipfs 网关域名,cloudflare SSL 证书将失效。即便把链接改为非加密的 http,pinata 依然会视之为无效链接而拒绝访问。 52 | 53 | 对于文件较少且链接有效的域名,可按 [Cloudflare IPFS](https://www.cloudflare.com/zh-cn/distributed-web-gateway/) 页面说明来设置 DNS,提交 IPFS 域名 30 分钟后,即可获取 SSL 证书。 54 | 55 | 1. 添加 CNAME 记录,将你的 IPFS 域名 (xxx.example.com) 指向 `cloudflare-ipfs.com`。 56 | 2. `_dnslink.xxx.example.com` 设置为 `dnslink=/ipfs/`。 57 | 58 | ## GitHub 同步到 VPS 59 | 60 | 代码、文章推送到 GitHub 后,会自动生成可访问的网页,但国内访问 GitHub Pages 的速度极不稳定,为了确保网站能被正常访问,必须增加国内的访问节点。 61 | 62 | 很多人选择 Gitee Pages 作为国内节点,GitHub Actions 将新文档同步到 Gitee,生成位于国内的静态页面 Gitee Pages。但是,Gitee Pages 的限制非常多,免费版无法自定义域名,必须实名验证,更别提近期的下架风波。因此,我没选 Gitee,而是把文档同步到国内服务器(域名需备案)。 63 | 64 | !> 注意:文件夹不要有大写字母,否则同步时容易出错。 65 | 66 | ### 同步到 FTP 67 | 68 | 如果你有 FTP 服务器,可使用 [FTP-Deploy-Action](https://github.com/SamKirkland/FTP-Deploy-Action) 将 github 代码推送到服务器上。Actions 步骤参考 [GitHub 说明](../deploy/GitHub.html)。 69 | 70 | ```shell 71 | on: push 72 | name: 🚀 Deploy website on push 73 | jobs: 74 | web-deploy: 75 | name: 🎉 Deploy 76 | runs-on: ubuntu-latest 77 | steps: 78 | - name: 🚚 Get latest code 79 | uses: actions/checkout@v3 80 | 81 | - name: 📂 Sync files 82 | uses: SamKirkland/FTP-Deploy-Action@4.3.0 83 | with: 84 | server: ${{ secrets.ftp_host }} 85 | username: ${{ secrets.ftp_username }} 86 | password: ${{ secrets.ftp_password }} 87 | port: ${{ secrets.ftp_port }} # 建议更改默认的 21 端口 88 | ``` 89 | 90 | 新建 FTP 时,需在云服务商的安全组和服务器上开放 FTP 端口,并临时暂停宝塔系统加固等安全插件(新建 FTP 容易与安全插件冲突)。 91 | 92 | 如果出现 `FTPError: 530 Login authentication failed`,则说明 FTP 密码错误或账号不存在,需用 FileZilla 测试 FTP 的有效性。确认 FTP 无效后,检查 FTP 密码是否填写正确,是否只有大小写字母和数字。如果密码错误,则在 github secrets 重新 update 密钥。如果密码正确,则进入 `/www/server/pure-ftpd/etc/pureftpd.passwd`,检查是否有该 FTP 账户。没有 FTP 账户的话,**暂停宝塔系统加固**等安全插件后,重新新建 FTP。 93 | 94 | 如果出现 `Error: Timeout (control socket)`,则说明同步服务器超时,可进入 Actions 页面点击右侧按钮「Re-run all jobs」,重新进行部署。如果错误连续出现,可以尝试关闭防火墙,测试是否 GitHub 服务器被拉黑了。 95 | 96 | ### SSH 同步 97 | 98 | 如果你拥有服务器所有权限,可以使用 [web-deploy](https://github.com/SamKirkland/web-deploy) 以 SSH 同步方式发布页面。但与 FTP 同步方式相比,是否安全性、速度、时间有区别,我还没测试过,仅做记录, 99 | 100 | ### 同步到 oss 101 | 102 | 如果没有服务器,可以把文件部署在云运营商的云存储上。比如用 [aliyun-oss-website-action](https://github.com/marketplace/actions/aliyun-oss-website-action),将 repo 文件 build 成网站文件,然后同步到阿里云 oss 并运行网站。 103 | 104 | ```shell 105 | name: deploy md to oss 106 | on: 107 | push: 108 | branches: [ "main" ] 109 | pull_request: 110 | branches: [ "main" ] 111 | jobs: 112 | build: 113 | runs-on: ubuntu-latest 114 | steps: 115 | # load repo to /github/workspace 116 | - uses: actions/checkout@v3 117 | - name: Use Node.js 118 | uses: actions/setup-node@v3 119 | with: 120 | node-version: '14.x' 121 | # 打包文档命令 122 | # - run: npm install yarn@1.22.4 -g 123 | # - run: yarn install 124 | # - run: yarn docs:build #需要配合 yarn 的 package.json 125 | - name: aliyun-oss-website-action 126 | uses: fangbinwei/aliyun-oss-website-action@v1.3.0 127 | with: 128 | accessKeyId: ${{ secrets.ACCESS_KEY_ID }} 129 | accessKeySecret: ${{ secrets.ACCESS_KEY_SECRET }} 130 | bucket: learndata-notes 131 | # use your own endpoint 132 | endpoint: oss-cn-shanghai.aliyuncs.com 133 | # 全目录上传 134 | folder: . 135 | # 不上传的文件 136 | exclude: | 137 | .github/ 138 | .gitattributes 139 | ``` 140 | -------------------------------------------------------------------------------- /docs/deploy/VPS.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | title: 服务器 VPS 4 | icon: IO 5 | order: 2 6 | --- 7 | 8 | ## 环境部署 9 | 10 | 部署应用前,为服务器配置好包管理工具,以便节省部署时间。主流的前端包管理工具有 npm、yarn、pnpm、以及国内的镜像 cnpm、tyarn 等,这些包管理器都是基于 nodejs。 11 | 12 | ### 包管理安装 13 | 14 | 通过集成了 npm 的 [Node.js](https://nodejs.org/en/download/) 来安装 npm,然后执行 npm i 命令安装其他。 15 | 16 | 全局安装 yarn 是 `npm i yarn -g`,pnpm 是 `npm i pnpm -g`。如果不想全局安装,则去除 `-g`。 17 | 18 | ### 包管理源 19 | 20 | 包管理源的修改命令类似,将下方的 npm 替换 yarn 或 pnpm 即可修改包管理源。 21 | 22 | ```shell 23 | #查看源 24 | npm config get registry 25 | #更换国内源 26 | npm config set registry https://registry.npmmirror.com/ 27 | #换回默认源 28 | npm config set registry https://registry.npmjs.org/ 29 | ``` 30 | 31 | ### 部署包 32 | 33 | npm、yarn 和 pnpm 的包安装及管理命令。 34 | 35 | ```shell 36 | #全局安装 37 | npm i 包 -g 38 | yarn global add 包 39 | pnpm add 包 -g 40 | 41 | #移除全局包 42 | pnpm remove 包 --global 43 | #更新全局包 44 | pnpm upgrade 包 --global 45 | 46 | #升级当前目录的依赖以确保你的项目只包含单个版本的相关包 47 | #本方法能解决大部分的部署报错 48 | npm i && npm update 49 | yarn && yarn upgrade 50 | pnpm i && pnpm up 51 | ``` 52 | 53 | ### 本地测试 54 | 55 | 有些静态文件不支持直接打开,需要架构本地服务器来进行测试。 56 | 57 | ```shell 58 | # 安装静态服务 anywhere 59 | npm install anywhere -g 60 | # 进入静态页面存放目录,执行 anywhere 61 | anywhere -p 8081 62 | ``` 63 | 64 | ## 网站字体 65 | 66 | 网站为了提高访问速度并保持设计的一致性,通常会选默认字体。这导致网站设计难以突出重点。针对这点,我通常会修改网站的导航栏字体,将其从默认字体改为 `思源黑体 - 粗`。 67 | 68 | 1. 进入 [iconfont‑webfont](https://www.iconfont.cn/webfont),输入导航栏内所有文字,并设置所需字体。 69 | 2. 点击「生成字体」后,在选中字体的下方,点击「本地下载」。 70 | 3. 将字体包上传到服务器,修改新字体的位置参数。 71 | 4. 在导航栏的 `class` 属性中添加 `web-font`。 72 | 73 | ## 米拓 74 | 75 | - 后台忘记密码,使用 [Metinfo 米拓重置工具](https://www.metinfo.cn/download/54.html)。 76 | - metinfo 新版静态页会删除 index.html,后续都改用 index.php。 77 | 78 | ## 服务器 ECS 79 | 80 | 服务器系统为 Debian 11。 81 | 82 | ```shell 83 | apt-get update # 从数据源更新软件包的列表,运行产生软件包数据库 84 | apt-get install wget && apt-get install sudo # 安装 wget 和 sudo 85 | 86 | # 大版本升级必须先建立快照 87 | apt-get upgrade # 更新所有软件包(慎用,不要用!)之前 CentOS 系统错误就是使用了 upgrade 命令。 88 | 89 | # 新建用户,非 root 权限 90 | adduser xxx 91 | # 为新用户设置密码 92 | passwd xxx 93 | ``` 94 | 95 | ### 网站重定向 96 | 97 | 更改 nginx 配置后,nginx 重载配置后实现网站重定向。`$1` 表示第一个 `()` 内的正则匹配内容,`$2` 为第二个。^[[Nginx rewrite 设置](https://www.w3cschool.cn/nginxsysc/nginxsysc-rewrite.html)] 98 | 99 | [网站重定向](https://www.jb51.net/article/146957.htm) 100 | 101 | ```ini 102 | #隐性链接跳转 103 | location /xx1 {proxy_pass } 104 | 105 | #404 前,将旧文章链接格式转为新的,使用绝对路径 106 | location ^~ /p{ 107 | rewrite ^/p/(.*)$ https://newzone.top/posts/$1.html; 108 | } 109 | 110 | # huginn 设置中 location 添加 301 定向,兼容老路径链接 111 | if ( $request_uri = "/users/1/web_requests/21/guoke.xml" ) { 112 | rewrite ^ http://xxx.com/users/1/web_requests/19/guoke.xml permanent; 113 | } 114 | 115 | #只匹配主页,将主页跳转为其中一个子页面 116 | location = / { 117 | rewrite https://xxx.com/ permanent; 118 | } 119 | ``` 120 | 121 | ### 全新安装服务器 122 | 123 | 1. 安装[宝塔面板](https://www.bt.cn/bbs/thread-19376-1-1.html)。 124 | 2. 删除阿里云主机监控。 125 | 126 | ```shell 127 | service aegis stop #停止服务 128 | chkconfig --del aegis # 删除服务 129 | ``` 130 | 131 | 3. 配置[阿里云端口开放](https://www.bt.cn/bbs/thread-2897-1-1.html),导入安全规则。 132 | 4. 宝塔上修改默认账号密码,并修改登录 22 的默认 SSH 端口。如果开通了 FTP,修改 FTP 端口。 133 | 5. 选择「网站」>「添加站点」,将站点根目录放在 /www/wwwroot/xxx,同时新建数据库。 134 | 6. 上传全站文件并解压,然后按照安装提示重新安装一次,最后导入备份数据库。 135 | 7. 404.html 起效,宝塔网站配置文件中,删除 `error_page 404 /404.html;` 中的 `#`。 136 | 8. SSL 证书设置,开启强制 HTTPS;PHP 版本;301 重定向;添加伪静态设置(metinfo 或其他网站后台有代码)。如果 301 设置失败,直接在「伪静态」配置中,放入跳转代码。 137 | 9. 服务器设置参考 [NginxConfig](https://www.digitalocean.com/community/tools/nginx?global.app.lang=zhCN) 适合新手配置高性能、安全、稳定的 NGINX 服务器的最简单方法。 138 | 10. [ECS 宝塔设置优化](https://www.bt.cn/bbs/forum.php?mod=viewthread&tid=3117): 139 | 140 | - 添加计划任务,定期释放内存,建议设置每天释放一次,执行时机为半夜,如:04:00。 141 | - 打开 Linux 工具箱添加 Swap。Swap 推荐与物理内存相同。 142 | - 安装 PHP 缓存扩展,尽量使用更高的 PHP 版本,另外安装 opcache(脚本缓存)、redis(内容缓存)、imagemagick、fileinfo、exif。 143 | - Redis 优化,在/etc/sysctl.conf 中添加 `net.core.somaxconn = 2048`,然后终端运行 `sysctl -p`。 144 | 145 | 11. 防火墙白名单(自定义),如:添加 url 规则 `^/rss.php` 到防火墙 URL 白名单,防止 rss 服务被屏蔽。 146 | 147 | ### 服务器迁移 148 | 149 | 1. 购买按量付费服务器。 150 | 2. 用[服务器迁移中心 SMC](https://smc.console.aliyun.com/overview) 将旧服务器同步到临时服务器。 151 | 3. 将域名解析到临时系统,确定服务基本正常。 152 | 4. 对旧服务器先建立云盘快照,然后更换操作系统,进行全新部署。 153 | 5. 对比新旧服务器,确认配置正常。 154 | 155 | ## 常见问题 156 | 157 | ### CPU 100% 158 | 159 | 当服务器 CPU 或内存突然飙升 100% 时,依次排除当前运行进程,检查是否安装更新了插件、应用或服务。 160 | 161 | 如果找不到原因,可以临时设置定期任务。每隔 3 小时重启一次 nginx/apache。有时重启不正常,因此重启命令后 10 秒,再启动一次 nginx/apache。 162 | 163 | ```shell 164 | /etc/init.d/nginx restart 165 | sleep 10s 166 | /etc/init.d/nginx start 167 | ``` 168 | 169 | ### SSL 证书 170 | 171 | 如果 SSL 证书部署报错,可以按自动生成来部署。 172 | 173 | ```shell 174 | #证书设置修改 /www/server/panel/vhost/nginx 175 | if ($server_port !~ 443){ 176 | rewrite ^(.*) permanent; 177 | } 178 | #证书修改 179 | /www/server/panel/vhost/cert/ 180 | #证书位置 181 | /www/server/panel/vhost/ssl 182 | ``` 183 | 184 | ### CORS 跨域 185 | 186 | POST 表单等操作需要涉及第三方 API,需要添加扩域域名,避免 CORS 报错。 187 | 188 | ```bash 189 | add_header Access-Control-Allow-Origin "*"; 190 | add_header Access-Control-Allow-Credentials "true"; 191 | add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; 192 | add_header Access-Control-Allow-Headers "DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range"; 193 | add_header Access-Control-Expose-Headers "Content-Length,Content-Range"; 194 | ``` 195 | 196 | ### 数据库出错解决 197 | 198 | 1. mysql 配置中 `mysqld` 在一行添加 `innodb_force_recovery=4`,数值可以 0-6,数值越大对数据库损害越大。正常启动 mysql 后,备份所有数据库和管理密码,并下载到本地。 199 | 2. 在宝塔的「数据库」中删除所有数据库,卸载并重装 mysql。 200 | 3. 重新导入数据库。 201 | 202 | ### piwik 手动升级 203 | 204 | Matomo/Piwik 是免费的统计服务。有时无法使用自动安装包,需要手动升级。 205 | 206 | 1. 下载最新版应用,并解压到服务器。 207 | 2. 将原目录中的 config/config.ini.php 粘贴到新版中,然后就可以更新数据库进行升级了。 208 | 3. 选择「设置」>「系统」>「地理位置」,拖到页面底部,按页面要求下载 DBIP 包,并重命名保存为 `/www/wwwroot/piwik/misc/DBIP-City.mmdb`。 209 | -------------------------------------------------------------------------------- /docs/front_end/css_advanced/scss/02.md: -------------------------------------------------------------------------------- 1 | # 02 【Sass语法介绍-变量】 2 | 3 | sass有两种语法格式Sass(早期的缩进格式:Indented Sass)和SCSS(Sassy CSS) 4 | 5 | 目前最常用的是SCSS,任何css文件将后缀改为scss,都可以直接使用`Sassy CSS`语法编写。 6 | 7 | **所有有效的 CSS 也同样都是有效的 SCSS。** 8 | 9 | # Sass语法介绍-变量 10 | 11 | ## 1.前言 12 | 13 | Sass 为 CSS 引入了变量这一功能,在实际项目中使用最普遍的除了 Sass 嵌套 就是 Sass 变量了,你可以把 CSS 的某个**属性值**定义为变量,然后在项目中任何需要它的地方来使用它。本节主要讲解 Sass 变量的主要语法:变量的声明、引用、作用域等,同时还会讲解在实际项目中一般是如何来维护 Sass 变量的。 14 | 15 | ## 2.什么是 Sass 变量 ? 16 | 17 | Sass 简介中提到 Sass是 CSS的扩展语言,变量是 CSS的扩展功能。 18 | 举个例子,假如我们项目中很多地方要设置一个字体颜色为红色,那么我们完全可以把这个颜色抽出来作为一个**变量**,然后在需要设置字体颜色的地方引用这个变量。这样有一个好处就是,假如产品大大说要修改所有字体颜色的时候,我们就不需要每处都去修改了,直接更改变量的值就 OK 了,我们用 Sass 代码来直观的感受下: 19 | 20 | ```scss 21 | $variable: red; 22 | 23 | .title { 24 | color: $variable; 25 | } 26 | h1 { 27 | color: $variable; 28 | } 29 | ``` 30 | 31 | 可以看到上面的代码,我们定义了 $variable 这个变量,然后在多个元素的样式中使用它,那么变量的值都可以是什么呢?这个一定要记住,变量的值可以是: 32 | 33 | - 字符串 34 | - 数字 35 | - 颜色值 36 | - 布尔值 37 | - 列表 38 | - Null 值 39 | 40 | 下面我们将详细的讲解 Sass 变量的语法。 41 | 42 | ## 3.使用变量 43 | 44 | sass使用`$`符号来标识变量。 45 | 46 | 变量的作用就是,让你在整个样式表中保存并重用一些信息或数据。 47 | 48 | 比如存储颜色(color)、字体集,或任何你想重用的CSS值。 49 | 50 | ### 3.1 变量声明 51 | 52 | 和css属性的声明(`property declaration`)很像! 53 | 54 | 如,声明值为 `#F90` 的变量 `$highlight-color`,字体集变量: 55 | 56 | ```scss 57 | $highlight-color: #F90; 58 | $font-stack: Helvetica, sans-serif; 59 | 60 | body { 61 | font: 100% $font-stack; 62 | color: $highlight-color; 63 | } 64 | ``` 65 | 66 | 输出结果为: 67 | 68 | ```css 69 | body { 70 | font: 100% Helvetica, sans-serif; 71 | color: #F90; 72 | } 73 | ``` 74 | 75 | **变量有作用域,当变量定义在css规则块内,则该变量只能在此规则块内使用。** 76 | 77 | ### 3.2 变量引用 78 | 79 | 凡是css属性的标准值(比如说1px或者bold)可存在的地方,就可以使用变量。 80 | 81 | css生成时,变量会被它们的值所替代。 82 | 83 | ```scss 84 | $color:#A34554; 85 | 86 | .box { 87 | width: 300px; 88 | height: 400px; 89 | &-left{ 90 | width: 30%; 91 | color: $color; 92 | } 93 | } 94 | ``` 95 | 96 | 生成css为: 97 | 98 | ```css 99 | .box { 100 | width: 300px; 101 | height: 400px; 102 | } 103 | .box-left{ 104 | width: 30%; 105 | color: #A34554; 106 | } 107 | ``` 108 | 109 | 声明变量时,变量的值也可以引用其他变量,如下 `$highlight-border` 变量中使用了 `$highlight-color` 变量: 110 | 111 | ```scss 112 | $highlight-color: #F90; 113 | $highlight-border: 1px solid $highlight-color; 114 | .selected { 115 | border: $highlight-border; 116 | } 117 | 118 | //编译后 119 | 120 | .selected { 121 | border: 1px solid #F90; 122 | } 123 | ``` 124 | 125 | ### 3.3 变量名中的中横线(`hyphen`)和下划线(`underscore`) 126 | 127 | sass的变量名可以使用中划线和下划线,用中划线声明的变量可以使用下划线的方式引用,反之亦然。 128 | 129 | 也就是,变量名中的中横线和下划线没有区别,两者互通。 130 | 131 | 比如下面的示例,中横线的`$link-color`,可以通过下划线的`$link_color`引用。 132 | 133 | ```scss 134 | $link-color: blue; 135 | a { 136 | color: $link_color; 137 | } 138 | 139 | //编译后 140 | 141 | a { 142 | color: blue; 143 | } 144 | ``` 145 | 146 | > 相对,使用中横线更普遍些! 147 | 148 | ## 4.变量的作用域 149 | 150 | 从 Sass 3.4.x 版本开始,Sass 中开始有作用域的概念。和 javascript 中的变量类似,Sass 的变量也是有作用域这个概念的,也有全局作用域和局部作用域之分,我们举个例子来看下: 151 | 152 | ```scss 153 | $main-color: red; 154 | h1 { 155 | $main-color: green; // 局部变量 156 | color:$main-color; 157 | } 158 | h2 { 159 | color:$main-color; 160 | } 161 | ``` 162 | 163 | 我们看到在第一行代码我们声明了一个全局变量 $main-color ,在 h1 的样式中我们又声明了一个和全局变量同名的 $main-color ,在 h1 样式中声明的这个 $main-color 就是局部变量,在 h1 的样式中会引用局部变量而不是全局变量,最终转换为 CSS 的代码如下: 164 | 165 | ```css 166 | h1 { 167 | color: green; 168 | } 169 | 170 | h2 { 171 | color: red; 172 | } 173 | ``` 174 | 175 | ### 4.1 !global 标识符 176 | 177 | 上面我们讲解了局部变量和全局变量,那么如果我想用局部变量去改变全局变量呢? Sass 允许使用 **!global** 标识符来设置局部变量为全局,以此来改变局部变量的作用范围,我们还是用上面的代码,来改变局部变量的作用域为全局: 178 | 179 | ```scss 180 | $main-color: red; 181 | h1 { 182 | $main-color: green!global; 183 | color:$main-color; 184 | } 185 | h2 { 186 | color:$main-color; 187 | } 188 | ``` 189 | 190 | 我们来看下,上面这段转换为 CSS 是这样的: 191 | 192 | ```css 193 | h1 { 194 | color: green; 195 | } 196 | 197 | h2 { 198 | color: green; 199 | } 200 | ``` 201 | 202 | 可以看到我们覆盖掉了全局变量 $main-color 的值 red ,不过请你记住,在大型项目中尽量不要使用这种方式去改变全局变量,这可能会影响到其他页面的样式改变! 203 | 204 | ### 4.2 !default标识符 205 | 206 | 一般来说我们反复的声明一个重名变量,那么最后一个声明的变量值会覆盖上面所有的,比如像下面这样: 207 | 208 | ```scss 209 | $main-color: red; 210 | $main-color: green; 211 | h1 { 212 | color:$main-color; 213 | } 214 | ``` 215 | 216 | 那么最后编译的时候会使用最后一次声明的变量值,也就是 green ,我们看下编译后的代码: 217 | 218 | ```css 219 | h1 { 220 | color: green; 221 | } 222 | ``` 223 | 224 | 这样就有一个问题,在实际的项目开发中,假如需要你来写一段公共的 Sass 代码给其他开发者使用,那么如果你的代码中声明了 $main-color 这个变量,那么其他开发者在自己页面也声明了 $main-color 这个变量,并且他是在导入你的这段代码之前声明的,那么他的就会被覆盖掉,这是不行的! 225 | 226 | 所以这里你需要使用 **!default** 标识符,顾名思义,就是默认值,如果这个变量被声明并赋值了,那么就使用声明的值,否则就使用默认值。我们还是用上面的例子来看下: 227 | 228 | ```scss 229 | $main-color: red; // 假如这个是其他开发者自己声明的 230 | $main-color: green!default; // 假如这个是你的代码片段声明的 231 | h1 { 232 | color:$main-color; 233 | } 234 | ``` 235 | 236 | 那么在最后编译的时候会使用 red 这个变量值,如果其他开发者没有声明这个变量,就会使用 green 这个变量值,我们来看下编译后的效果: 237 | 238 | ```css 239 | h1 { 240 | color: red; 241 | } 242 | ``` 243 | 244 | 上面我们演示了 !default 标识符的作用,这个在你使用 Sass 开发一个独立的模块的时候,或者使用 Sass 开发一个库来供他人使用的时候,!default 标识符石非常有用的! 245 | 246 | ## 5.实战经验 247 | 248 | 上面我们已经讲解了 Sass 变量的语法和使用,那在企业的实际项目中是怎么应用 Sass 变量的呢?这里以一个使用 webpack 搭建的前端项目为例,一般我们都会抽离出 1~n 个文件来专门声明 Sass 变量(抽离出几个文件视项目大小而定),如下图所示: 249 | 250 | ![image-20220823183201014](https://i0.hdslb.com/bfs/album/bd416afc39899b1f9c4cee4f63433c1e3fe1ee6d.png) 251 | 252 | 如上图所示,我们一般会在 styles 目录下新建一个 variables.scss 文件来管理声明的全局变量,我们接着来看下在这个文件中是怎么写的: 253 | 254 | ![image-20220823183220638](https://i0.hdslb.com/bfs/album/7dae9a402ae3b6eed35a652b1e68bd04da921fb8.png) 255 | 256 | 我们可以看到,在这个文件中不但声明了很多变量,还对其做了注释,这样就很易于后期的管理,尤其是在多人开发的大型项目中,对整个项目的样式提取出一些全局变量是很有必要的! 257 | 258 | ## 6.小结 259 | 260 | Sass 变量的使用及语法,主要包括: 261 | 262 | - 变量的声明 263 | - 变量的引用 264 | - 变量的作用域 265 | 266 | 我们还是通过下图来回忆一下本节的内容: 267 | 268 | ![image-20220823183316776](https://i0.hdslb.com/bfs/album/1cafa46bfec00abd4c1dfd2d5c86ac8bf960bad8.png) 269 | 270 | 在实际的项目中,Sass 变量的使用频率也是非常高的,不亚于 Sass 嵌套,所以一定要好好掌握这一节的内容,变量的应用会让你更加顺手的去管理项目中的样式! 271 | -------------------------------------------------------------------------------- /docs/front_end/css_advanced/scss/05.md: -------------------------------------------------------------------------------- 1 | # 05 【Sass语法介绍-插值】 2 | 3 | ## 1.前言 4 | 5 | 在很多编程器语言中都有插值这个概念,在 Sass 样式表的任何地方几乎都可以使用插值,你可以将这些包裹在 #{} 中来使用,所以记住在 Sass 中使用插值的方式是 **#{}** ,本节我们一起来看一下插值在 Sass 中的使用场景以及它的语法 6 | 7 | ## 2.什么是插值? 8 | 9 | 插值也就是可以在**特定的区域**插入一段表达式或者插入一个变量,以此来实现内容动态变换的需求。 10 | 11 | > 类似 es6 中的插值表达,插值几乎可以用在任何地方。 12 | > 13 | > Sass的插值写法为:`#{$variable_name}`。 14 | 15 | 应用于以下的一些场景: 16 | 17 | - 在选择器中使用 18 | - 在属性名中使用 19 | - 在属性值中使用 20 | - 在注释中使用 21 | 22 | 这里我们暂且详细讲解这五种使用场景,在 Sass 指令和在 Sass 函数中也是可以使用的,不过我们会在其对应的章节再去做讲解。下面我们先看下这四种使用场景。 23 | 24 | ## 3.在选择器中使用 25 | 26 | 我们一般在写页面的时候会为 DOM 元素定义一些 class 或 id ,当我们为其写样式的时候会用不同的选择器,那么在选择器中我们可以湿用插值来拼接一些类名等等,我们举个例子来看下: 27 | 28 | ```scss 29 | $name: item; 30 | .ul-#{$name} { // 使用插值 31 | width: 200px; 32 | .li-#{$name} { // 使用插值 33 | width: 100%; 34 | } 35 | } 36 | .box-#{$name} { // 使用插值 37 | height:100px; 38 | .#{$name} { // 使用插值 39 | height:100%; 40 | } 41 | } 42 | ``` 43 | 44 | 可以看到上面的代码,我制定了一个 DOM 层级结构,这种结构也是很常见的,可能很多子元素的类名我们都带有 item ,那么我们就可以把它提取为一个变量然后通过在选择器中应用插值来拼接,这样就很方便我们维护,我们想改子元素类名的时候就不需要逐一的去更改了。上面这段 Sasd 代码转换为 CSS 如下: 45 | 46 | ```css 47 | .ul-item { 48 | width: 200px; 49 | } 50 | .ul-item .li-item { 51 | width: 100%; 52 | } 53 | 54 | .box-item { 55 | height: 100px; 56 | } 57 | .box-item .item { 58 | height: 100%; 59 | } 60 | ``` 61 | 62 | ## 4.在属性名中使用 63 | 64 | 除了在选择器中使用,在 Sass 属性名上也是可以使用插值的,也就是说你在写 CSS 属性名的时候你也是可以使用插值来拼接的,我们举个例子来看下: 65 | 66 | ```scss 67 | $name: color; 68 | $position: top; 69 | body { 70 | background-#{$name}: red; 71 | border-#{$name}: blue; 72 | padding-#{$position}: 5px; 73 | margin-#{$position}: 10px; 74 | #{$position}: 20px; 75 | } 76 | ``` 77 | 78 | 可以看到上面的代码中我对 CSS 的属性名使用了插值,可以用这种方式来拼接属性名,不过在实际项目中不是很常用,一般都是在指令里这么运用,就像在前面语法示例中举的例子一样。上面这段代码转换成 CSS 为: 79 | 80 | ```css 81 | body { 82 | background-color: red; 83 | border-color: blue; 84 | padding-top: 5px; 85 | margin-top: 10px; 86 | top: 20px; 87 | } 88 | ``` 89 | 90 | ## 5.在属性值中使用 91 | 92 | 在属性值中使用插值应该算是比较常用的,插值使你在属性值中不仅可以插入值,还可以插入表达式来计算。除此之外我们在前面的运算章节中,不知道你是否还记得,我们对两个变量使用 / 标识符的时候,如果你不想对这两个变量进行除法运算而是进行分隔,那么就可以**使用插值避免运算**。 93 | 94 | 可以说插值在属性值中的应用很广泛也很实用,我们来举例看下: 95 | 96 | ```scss 97 | $one: 20px; 98 | $two: 2; 99 | $family: "UaTy"; 100 | div { 101 | margin: $one / $two; // 除法运算 102 | margin: #{$one} / #{$two}; // 分隔 103 | font-family: "MyFo #{$family}"; // 带引号的字符串会转换为不带引号 104 | width: calc(100% - $one * 2 *$two); // calc函数中内容会被当作字符串处理 105 | width: calc(100% - #{$one * 2 *$two}); // calc函数中插值的内容会进行运算 106 | } 107 | ``` 108 | 109 | 上面的代码中我对每一行都进行了标注,你要仔细看下,在属性值中你可以用这些方式来使用插值,上面的代码将会被转换为如下的 CSS 代码: 110 | 111 | ```css 112 | div { 113 | margin: 10px; 114 | margin: 20px/2; 115 | font-family: "MyFo UaTy"; 116 | background-image: url(http://xxx.xxx.xxx/a.jpg); 117 | width: calc(100% - $one * 2 *$two); 118 | width: calc(100% - 80px); 119 | } 120 | ``` 121 | 122 | 在属性值中应用插值的场景还蛮多的,你可以这么来使用以提高你的开发效率~ 123 | 124 | ## 6.在注释中使用 125 | 126 | 在 Sass 中的注释里也是可以使用插值的,而且如果插值中的内容是一段表达式,将会返回表达式的结果,举个例子来看下: 127 | 128 | ```scss 129 | /* 在注释中使用插值: 130 | * 2 + 2 = #{2 + 2} */ 131 | /* #{9 + 8 * 2} */ 132 | ``` 133 | 134 | 我们可以在注释中可以这么使用插值,具体什么时候需要使用看你的需求,你需要知道插值的这种使用方式,上面的代码将会被转换为如下的 CSS 代码: 135 | 136 | ```css 137 | /* 在注释中使用插值: 138 | * 2 + 2 = 4 */ 139 | /* 25 */ 140 | ``` 141 | 142 | ## 7.实战经验 143 | 144 | 在我的实际项目中,在函数和指令中使用插值比较多,在后面函数和指令的章节你会看到插值的更多运用,这里我列出在属性值以及选择器中的使用。在我项目中专门维护变量的文件中,定义了如下的几个变量: 145 | 146 | ```scss 147 | $primary-dom-name: "box"; // 主要父级元素类名 148 | $primary-child-name: "item"; // 主要子元素类名 149 | $public-top: 10px; 150 | $public-bottom: 10px; 151 | $public-margin: 12px; 152 | $public-padding: 14px; 153 | ``` 154 | 155 | 在我项目中的导航样式中我使用了上面的这些变量,代码如下: 156 | 157 | ```scss 158 | .menu-#{$primary-dom-name} { 159 | width: 200px; 160 | height: calc(100% - #{40px - $public-bottom}); 161 | background: #cccccc; 162 | overflow-x:hidden; 163 | overflow-y: auto; 164 | padding: $public-padding; 165 | .li-#{$primary-child-name} { 166 | width:100%; 167 | height: 40px; 168 | margin-bottom: $public-margin; 169 | text-align:center; 170 | line-height:40px; 171 | color: blue; 172 | .txt-#{$primary-dom-name} { 173 | border-bottom: 2px solid #999999; 174 | } 175 | &:hover { 176 | background: #999999; 177 | } 178 | } 179 | .logo-#{$primary-dom-name} { 180 | width: 50px; 181 | } 182 | } 183 | ``` 184 | 185 | 可以看到,当有一天我们因为业务或者什么其他的需要,我们需要**更换类名或者调整间距**的时候,我们直接更改变量值就 ok 了,这样维护起来方便的多!不过一般在公司的项目中,这种公共的样式代码维护一般是由架构组或者专门的人来维护的,如果你不负责维护这些,你一定不要轻易去改动这些代码! 186 | 187 | ## 8.小结 188 | 189 | 本节内容我们讲解了 Sass 中的插值以及它的使用场景,一般我们会在如下的场景使用: 190 | 191 | - 在函数和指令中使用 192 | - 在选择器中使用 193 | - 在属性名中使用 194 | - 在属性值中使用 195 | - 在注释中使用 196 | 197 | 我们通过下图来更深地回忆下本节插值的使用场景: 198 | 199 | ![image-20220823192137071](https://i0.hdslb.com/bfs/album/d6890af7337563009618bc694bf160e233eb9c7a.png) 200 | 201 | 总体来说插值在 Sass 中用的还是比较多的,使用也比较简单不是那么复杂,后面在函数或指令中、在你项目的 Sass 中看见 **#{}** 要知道这是 Sass 的插值! -------------------------------------------------------------------------------- /docs/front_end/css_advanced/scss/06.md: -------------------------------------------------------------------------------- 1 | # 06 【Sass语法介绍-函数】 2 | 3 | > 这篇文章只更新了颜色函数,由于Sass使用时间过短,其它函数暂时不太会用 4 | 5 | ## 1.前言 6 | 7 | Sass 中的函数,这在 Sass 中是比较强大的一个功能,同时使用场景和语法也比较多,所以本节内容篇幅较长,但你一定要好好学习, Sass 函数很重要!在 Sass 中函数中几乎可以用到前面你学的所有章节的内容,所以说函数包括万象同时功能也非常强大,本节我们将详细讲解 Sass 中各种函数的功能和用法。 8 | 9 | ## 2.什么是函数? 10 | 11 | 函数是一段可以被另外的程序或代码调用的“子程序”,一个函数由称为函数体的一系列代码语句组成,并且函数也可以接收值,在大多数语言中函数都是这样的,Sass 中的函数也是一样。 12 | 13 | ## 3.Sass 函数简介 14 | 15 | Sass 为我们提供了很多内置模块,其中就包含了很多函数(包括一些指令),我们可以通过 @use 去加载它们,然后我们就可以调用了,当然还有一些函数可以直接在 CSS 语句中调用,在 Sass 中常用的函数有: 16 | 17 | - 字符串函数 18 | - 数字函数 19 | - 列表函数 20 | - Introspection函数 21 | - 条件函数 22 | - Map 函数 23 | - 颜色函数 24 | 25 | 上面这些函数为我们提供了强大而丰富的功能来更高效地编写样式,下面我们来详细讲解 Sass 函数。 26 | 27 | ## 4.颜色函数 28 | 29 | Sass 中提供了非常非常多的颜色函数用来处理颜色值,它们很多需要你具有专业的调色及配色知识才能发挥出作用,所以本节我们不讲的那么复杂,本节内容中我们只讲几种常见的、比较简单的颜色函数,其他特别复杂的用于调色的函数在以后你可以再慢慢研究。 30 | 31 | ### 4.1 用于获取通道色值的函数 32 | 33 | Sass 提供了可以获取一个色值中红色通道、绿色通道和蓝色通道色值的函数,它们分别是 red($color) 、green($color) 和 blue($color)。你可能还不太了解这三种通道是什么,不要紧,只要知道这三种函数和它的使用就可以。我们举例看下: 34 | 35 | ```scss 36 | blue(#BA55D3) //=> 211 37 | red(#BA55D3) //=> 186 38 | green(#BA55D3) //=> 85 39 | ``` 40 | 41 | ### 4.2 saturate($color, $amount) 42 | 43 | saturate($color, $amount) 函数用于调整 $color 的饱和度,第 1 个参数 $color 是一个颜色值,第 2 个参数是 0% ~ 100% 之间的百分数,其返回值也是一个颜色值。 44 | 45 | ```scss 46 | saturate(#BA55D3, 20%) //=> #c740e8 47 | ``` 48 | 49 | ### 4.3 scale-color(…) 50 | 51 | 这是一个非常强大的颜色函数,它**接收很多个参数**,可以**调整一个色值的很多属性**,包括这个颜色的红、绿、蓝通道,以及亮度等等,我们只能举例来直观的看下: 52 | 53 | ```scss 54 | scale-color(#BA55D3, $red: 15%) //=> #c455d3 调整红色通道 55 | scale-color(#BA55D3, $blue: 15%) //=> #ba55da 调整蓝色通道 56 | scale-color(#BA55D3, $lightness: -10%, $saturation: 10%) //=> #b338d2 调整亮度和饱和度 57 | scale-color(#BA55D3, $alpha: -30%) //=> rgba(186, 85, 211, 0.7) 调整不透明度 58 | ``` 59 | 60 | 通过上面的例子可以看到颜色函数提供了非常强大的用于调色的函数,驾驭它的前提是你要有非常丰富的调色知识以及一定的美术基础。在实际的项目中我们非常少的用到颜色函数,因为一般都是由公司的 UI 设计师来进行调色,所以作为入门教程,你只需要了解 Sass 中的颜色函数就好。 61 | 62 | ## 5. 小结 63 | 64 | 本节内容我们讲了 Sass 提供的各种各样的函数,基本覆盖到了比较常用的、常见的函数,它们分别是: 65 | 66 | - 字符串函数 67 | - 数字函数 68 | - 列表函数 69 | - Introspection函数 70 | - 条件函数 71 | - Map 函数 72 | - 颜色函数 -------------------------------------------------------------------------------- /docs/front_end/css_advanced/scss/09.md: -------------------------------------------------------------------------------- 1 | # 09 【Sass语法介绍-函数指令】 2 | 3 | ## 1.前言 4 | 5 | 在之前的章节我们学习过 Sass 提供的各种各样的函数,那么如果我们需要自定定义函数来使用就需要用到**函数指令 @function**了。本节内容我们来学习 Sass 函数指令的语法和使用,在 Sass 中自定义函数是必须要掌握的! 6 | 7 | ## 2.什么是 Sass 函数指令 8 | 9 | 函数指令也叫自定义函数让你可以容易的处理各种逻辑和定义复杂的操作,而且你可以在任何需要的地方复用函数,这使得我们可以抽离出来一些常见的公式或者逻辑,我们先来看下它长什么样,代码如下: 10 | 11 | ```scss 12 | // 定义函数 13 | @function a() { 14 | @return "a" 15 | } 16 | // 使用函数 17 | .p { 18 | font: a(); 19 | } 20 | ``` 21 | 22 | 回忆一下,上面的代码在之前的章节中也出现过,这就是函数指令,定义好一个函数后我们就可以使用了,下面我们开始详细讲解函数指令。 23 | 24 | 函数指令是**通过 @function 来定义**,它的写法是 @function name(arguments…){},@function 后面跟函数名,然后是一个 () ,() 里面是这个函数接收的参数,可以接收也可以不接收,最后是 {} 中放的是你的逻辑代码。函数名**将连字符和下划线视为相同**,也就是说 a_b 和 a-b 是同一个函数。我们举例看下: 25 | 26 | ```scss 27 | @function fun-name() { 28 | // 在这里编写逻辑代码 29 | } 30 | ``` 31 | 32 | ## 3.函数的参数 33 | 34 | 函数指令的参数和之前我们讲的混合指令的参数很像,函数如果接收参数那么使用的时候就**必须传入这些参数**,但是你**可以定义默认值使参数成为可选的**,我们举例来看下: 35 | 36 | ```scss 37 | // 有默认值的参数 38 | @function a($arg: 1) { 39 | @return $arg; 40 | } 41 | // 无默认值的参数 42 | @function b($arg) { 43 | @return $arg; 44 | } 45 | .p { 46 | font: a(); 47 | font: b(4); 48 | } 49 | ``` 50 | 51 | 上面的代码转换为 CSS 如下: 52 | 53 | ```css 54 | .p { 55 | font: 1; 56 | font: 4; 57 | } 58 | ``` 59 | 60 | 要注意的是,为参数设置的默认值,也可以引用前面的参数或者是任何表达式。 61 | 62 | ## 4.接收任意数量的参数 63 | 64 | 和前面章节讲的 @mixin 类似,函数指令也**可以接收任意数量的参数**,同样是将最后一个参数以 … 结尾,我们来举例看下: 65 | 66 | ```scss 67 | @function fonts($familys...) { 68 | @return $familys; 69 | } 70 | .p { 71 | font: fonts("one", "two", "three") 72 | } 73 | ``` 74 | 75 | 上面这段代码转换为 CSS 如下: 76 | 77 | ```css 78 | .p { 79 | font: "one", "two", "three"; 80 | } 81 | ``` 82 | 83 | 同样的函数的参数也可以接收任意的参数列表,就像之前在混合指令章节讲的一样,可以用过 meta.keywords() 来获取和使用这些参数,不过这个我们一般不是很常用。 84 | 85 | ## 5.@return 86 | 87 | 在前面的代码中,可以看到很多次我们在函数指令中使用了 @return。@return 指令表示作为函数调用结果的值,说的简单点就是这个函数的返回值,这和在 javascript 的函数中使用 return 很类似。 88 | 89 | 在 Sass 中 **@return 指令只能在 @function** 中使用,并且**每个 @function 都必须以 @return 结尾!** 在 @function 的逻辑代码中,如遇到 @return 会立即结束函数并返回其结果,这在一些 @if 判断的情况下很有用。我们举例看下: 90 | 91 | ```scss 92 | @function a($str: "a") { 93 | @if $str == "a" { 94 | @return 10px; 95 | } @else if $str == "b" { 96 | @return 20px; 97 | } @else if $str == "c" { 98 | @return 30px; 99 | } @else { 100 | @return 40px; 101 | } 102 | } 103 | 104 | p { 105 | padding: a(); 106 | width: a("f"); 107 | height: a("c"); 108 | margin: a("b"); 109 | } 110 | ``` 111 | 112 | 从上面的代码中我们可以可看到,在函数 a 中,我们根据不同的参数返回不同的结果,然后在 p 的样式中通过传入不同的参数来获取不同的结果。上面这段代码会转换为如下的 CSS 代码: 113 | 114 | ```css 115 | p { 116 | padding: 10px; 117 | width: 40px; 118 | height: 30px; 119 | margin: 20px; 120 | } 121 | ``` 122 | 123 | ## 6.实战经验 124 | 125 | 在实际的项目中使用函数指令是必不可少的,我们会定义很多函数来帮助我们解决逻辑问题,一般我们会独立抽出来一个 function.scss 文件来管理整个项目中的函数指令,一般这些函数都是根据你的项目特性以及样式需要封装出来的。 126 | 127 | 由于函数一般是和你的业务强相关的,一般就是为自己的项目定义一些工具和方法,这里我就不贴出代码示例了。在实际的应用中,这个函数指令就是需要你“随机应变”,按需封装和使用! 128 | 129 | ## 7.小结 130 | 131 | 本节内容我们讲了 Sass 函数指令 @function ,还有函数指令的用法和参数。我们可以使用函数来编写各种各样我们自己的函数。函数指令和前面的混合指令很类似,我们通过下图来回一下函数指令的用法: 132 | 133 | ![image-20220825225712402](https://i0.hdslb.com/bfs/album/ab773841b5921e39b687a9c007eea2c52641e31b.png) 134 | 135 | 除此之外 Sass 提供了大量的内置函数,这些我们在前面的章节 Sass 函数中都做了讲解,你可以借用这些函数再配合你自己定义的函数指令,来实现各种复杂的逻辑和强大的效果。 -------------------------------------------------------------------------------- /docs/front_end/css_advanced/scss/10.md: -------------------------------------------------------------------------------- 1 | # 10 【Sass语法介绍-继承】 2 | 3 | ## 1.前言 4 | 5 | 在我们编写样式的时候,很多情况下我们几个不同的类会有相同的样式代码,同时这几个类又有其自己的样式代码,这使我们就可以通过 Sass 提供的**继承** @extend 来实现。本节内容我们将讲解 Sass 继承的语法以及继承的多重延伸等等,在 Sass 中继承也是非常好用的功能之一,所以你要重点熟悉 @extend 的用法,下面我们一起来学习它。 6 | 7 | ## 2.什么是 Sass 继承 8 | 9 | 继承,我们也叫做代码重用,在 Sass 中支持对样式进行继承。 10 | 11 | 首先我们看一段代码,看看在 Sass 中的继承是长什么样子的: 12 | 13 | ```scss 14 | .a { 15 | width: 10px; 16 | } 17 | 18 | .b { 19 | @extend .a; 20 | height: 10px; 21 | color: red; 22 | } 23 | ``` 24 | 25 | 从上面的代码中可以看见,我在 .b 的样式中使用 @extend 继承了 .a 的样式,那么这段代码转换为 CSS 如下: 26 | 27 | ```css 28 | .a, .b { 29 | width: 10px; 30 | } 31 | 32 | .b { 33 | height: 10px; 34 | color: red; 35 | } 36 | ``` 37 | 38 | 上面的代码中我们看到了 Sass 中继承的样子,它的写法是 @extend selector 也就是**在 @extend 后面跟一个选择器**,表示**继承这个选择器的样式**,下面我们详细讲解下它的语法。 39 | 40 | @extend 会包含包含扩展的样式规则,同时在 Sass 中它会**确保复杂的选择器是交错的**,这样无论你的 DOM 元素是如何嵌套的它都能保证正常工作。它还可以**根据实际情况将选择器组合在一起**,可以**更智能的处理选择器以及包含伪类的选择器**。我们举个稍复杂点的例子来看下: 41 | 42 | ```scss 43 | .a { 44 | width: 100px; 45 | height: 200px; 46 | background-color: orange; 47 | &:hover { 48 | background-color: green; 49 | } 50 | .link { 51 | width: 50%; 52 | height: 50%; 53 | color: red; 54 | &:active { 55 | color: blue; 56 | } 57 | i { 58 | font-size: 18px; 59 | font-weight: 600; 60 | } 61 | } 62 | } 63 | 64 | .b { 65 | @extend .a; 66 | width: 400px; 67 | height: 200px; 68 | } 69 | ``` 70 | 71 | 我们仔细解读上面的代码,我为 .a 写了一大堆的样式,包括它的子元素以及它的伪类;而 .b 下面有同样的子元素,同样的伪类别,只是宽高不同,那么我直接在 .b 中继承 .a 的样式,它会转换为什么样子的代码呢?它转换为 CSS 的代码如下: 72 | 73 | ```css 74 | .a, .b { 75 | width: 100px; 76 | height: 200px; 77 | background-color: orange; 78 | } 79 | .a:hover, .b:hover { 80 | background-color: green; 81 | } 82 | .a .link, .b .link { 83 | width: 50%; 84 | height: 50%; 85 | color: red; 86 | } 87 | .a .link:active, .b .link:active { 88 | color: blue; 89 | } 90 | .a .link i, .b .link i { 91 | font-size: 18px; 92 | font-weight: 600; 93 | } 94 | 95 | .b { 96 | width: 400px; 97 | height: 200px; 98 | } 99 | ``` 100 | 101 | 从上面转换成 CSS 的代码我们可以看出,引用相同样式的部分都以逗号做了分隔,在 CSS 中使用逗号的含义你应该很了解,继承 @extend 就可以为你自动创建这些组合,提取相同的样式,所以如果有选择器使用了相同的样式,请使用继承的方式来实现! 102 | 103 | ## 3.占位符选择器 104 | 105 | 在 Sass 中有一种特殊的选择器叫占位符选择器,它的写法像我们写的 id 或 class 选择器一样,只不过**占位符选择器是以 % 开头的**。在 Sass 中你单独使用这种选择器是不会转换为 CSS 的,只能是**通过 @extend 来使用**。 106 | 107 | 比如说有时候你想编写一个可扩展的样式,然后在各处继承它,你就可以使用占位符选择器,我们结合实际的例子来看下: 108 | 109 | ```scss 110 | %placeholder { 111 | box-sizing: border-box; 112 | border-top: 1px #666666 solid; 113 | width: 100%; 114 | 115 | &:hover { border: 2px #999999 solid; } 116 | &:active {color: blue;} 117 | } 118 | 119 | .buttons { 120 | @extend %placeholder; 121 | color: #4285f4; 122 | } 123 | .btn { 124 | @extend %placeholder; 125 | } 126 | ``` 127 | 128 | 从上面的代码中看到,我通过占位符选择器 %placeholder 定义了一堆样式,然后在其他的样式表中继承它,这个告诉你一个简单的理解方式,占位符选择器你就理解为一个虚拟的选择器,这个名是不会编译到 CSS 中的,最终编译出的选择器名是根据你使用继承的选择器名来定的。上面这段代码会转化为如下的 CSS 代码: 129 | 130 | ```css 131 | .btn, .buttons { 132 | box-sizing: border-box; 133 | border-top: 1px #666666 solid; 134 | width: 100%; 135 | } 136 | .btn:hover, .buttons:hover { 137 | border: 2px solid; 138 | } 139 | .btn:active, .buttons:active { 140 | color: blue; 141 | } 142 | 143 | .buttons { 144 | color: #4285f4; 145 | } 146 | ``` 147 | 148 | 从上面的代码中可以看到,编译成 CSS 后 %placeholder 这个选择器不见了,但它的样式被继承了,这就是**占位符选择器结合继承 @extend 的用法**。 149 | 150 | ## 4.在 @media 中使用 @extend 151 | 152 | 如果你需要在 @media 中使用继承,一定要注意使用方式!如果你**在外部定义样式**,然后**在 @media 内部继承外部的样式**,Sass 是**会报错**的。我们首先举个**错误的例子**看下: 153 | 154 | ```scss 155 | .error { 156 | border: 1px red solid; 157 | background-color: red; 158 | } 159 | 160 | @media screen and (max-width: 600px) { 161 | .btn-error { 162 | @extend .error; 163 | } 164 | } 165 | ``` 166 | 167 | 如上面的代码所示,这样的写法在 Sass 中是会报错的,也不会编译成功。 Sass 规定继承只能在给定的媒体上下文中使用,所以**正确的写法**如下: 168 | 169 | ```scss 170 | @media screen and (max-width: 600px) { 171 | .error { 172 | border: 1px red solid; 173 | background-color: red; 174 | } 175 | .btn-error { 176 | @extend .error; 177 | } 178 | } 179 | ``` 180 | 181 | 上面这个正确的写法将会被编译为如下的 CSS 代码: 182 | 183 | ```css 184 | @media screen and (max-width: 600px) { 185 | .error, .btn-error { 186 | border: 1px red solid; 187 | background-color: red; 188 | } 189 | } 190 | ``` 191 | 192 | > 在 @media 中使用继承,一定要注意写法! 193 | 194 | ## 5.实战经验 195 | 196 | 在实际的项目中,继承是非常好用的一个功能,不过这个就需要你自己根据需求来判断是否使用,因地制宜,而且尽量把公共的样式提取到一个单独的文件来维护。 197 | 198 | 还有一个需要注意的是除了继承 @mixin 也是可以封装和复用样式的,那么什么时候使用 @mixin 什么时候使用 @extend 呢?假如你需要使用参数来配置样式的时候,也就是**需要传参数**的时候毫无疑问**使用 @mixin** 。但如果你只是需要复用一部分样式那么还是使用继承会更方便些。 199 | 200 | ## 6.小结 201 | 202 | ![image-20220825230233770](https://i0.hdslb.com/bfs/album/cfde0cfe18268eff4c308f08af6ee83d2823bab1.png) 203 | 204 | 本节内容我们讲解了 Sass 中的继承 @extend 。我们可以使用继承很方便的**复用样式代码**,同时我们也可以使用**占位选择器**配合 @extend 来扩展和复用样式代码,还有一定要**注意在 @media 中使用继承的方式**。记住 Sass 中的 @extend ,它可以让你的样式代码写起来更高效! -------------------------------------------------------------------------------- /docs/front_end/css_advanced/scss/11.md: -------------------------------------------------------------------------------- 1 | # 11【Sass语法介绍-导入】 2 | 3 | ## 1.前言 4 | 5 | 在 CSS 中我们可以通过 @import 来导入一个样式文件,Sass 扩展了 CSS 的 @import 规则,使得可以导入 CSS 后缀的样式文件和 Scss 后缀的样式文件,并且提供了对 mixin 、函数和变量的访问。 6 | 7 | 与 CSS 的 @import 不同的是, CSS 使用 @import 导入文件是在页面渲染的时候发起多个 http 请求来获取文件内容,而 Sass 的导入 @import 是在编译时获取文件内容导入的。 8 | 9 | ## 2.语法详情 10 | 11 | Sass 的导入和 CSS 中的导入语法类似,只不过在 Sass 中**可以导入用逗号分隔的多个文件**, 我们举个例子看下: 12 | 13 | ```scss 14 | @import 'a.scss', 'b.scss'; 15 | ``` 16 | 17 | 上面的代码意思是导入 a.scss 和 b.scss 文件,那么导入后 a 和 b 中的任何mixin 、函数和变量都是可以使用的。 18 | 19 | 我们知道在 CSS 中也有 @import 语句,在以下几种情况 Sass 会认为 @import 是 CSS 语句: 20 | 21 | - 使用 url() 22 | - 文件的扩展名是 .css 23 | - @import 包含 media queries 24 | - 文件名以 http:// 开头 25 | 26 | 在使用的时候要注意上面的几种情况,如果导入的扩展名是 .scss 或 .sass 那么肯定用的是 Sass 提供的 @import 。如果**导入文件没有指定文件扩展名,那么 Sass 会尝试寻找文件名相同的扩展名为 .sass 或 .scss 的文件**。 27 | 28 | ## 3.加载路径 29 | 30 | Sass 允许我们自行提供文件的加载路径,在我们导入文件的时候,Sass 总是会相对于当前文件进行解析,如果没有加载到则会使用**加载路径**。假如我们将加载路径设置为 node_modules/public/sass ,那么我们使用如下的导入方式: 31 | 32 | ```scss 33 | @import 'a'; 34 | ``` 35 | 36 | 假如当前目录下没有 a.scss 文件,那么 Sass 就会去加载 node_modules/public/sass/a.scss ,这就是使用了加载路径,不过这种方式我们在项目中**极少应用**,你只需要了解即可。 37 | 38 | ## 4.部分导入 39 | 40 | 什么是部分导入呢? 我的理解是**局部的使用导入**,也就是说可以**仅导入 Sass 或 Scss 文件,而不将它们编译为 CSS,** 那么应该怎么做呢?假如我要导入一个 my.scss 文件,我不希望将它编译为 CSS ,那么需要**使用下划线开头的文件名**,也就是说需要改名为 _my.scss ,然后使用如下导入代码: 41 | 42 | ```scss 43 | @import 'my'; 44 | ``` 45 | 46 | 上面的代码导入的就是 _my.scss 文件,并且不会将它编译为 CSS 。另外需要注意的是:**不可以同时存在带有下划线和不带下划线的同名文件!** 47 | 48 | ## 5.索引文件 49 | 50 | 在 Sass 中什么是索引文件呢?_index.scss 文件,那它有什么用呢?假如我有一个 my 目录,这个目录下有两个文件,一个是 a.scss 一个是 _index.scss ,那么我使用如下文件导入代码: 51 | 52 | ```scss 53 | @import 'my'; 54 | ``` 55 | 56 | 那么上面的代码导入的就是 _index.scss 文件,也就是说 _index.scss 是这个目录下的**默认文件**,这就想你在写 vue 或者 html 中目录下的 index 文件类似。 57 | 58 | ## 6.使用 @use 替代 @import 59 | 60 | Sass 官方团队不鼓励使用 @import 导入,并且在未来几年将逐步淘汰它,并最终将 @import 从 Sass 中完全删除。所以使用 @use 是官方团队更推荐的方式,下面我们开始讲解使用 @use 导入。 61 | 62 | @use 与 @import 的语法基本相同,我们先看一个简单的使用 @use 导入的例子: 63 | 64 | ```scss 65 | @use 'my/a.scss'; 66 | @use 'my/b'; 67 | ``` 68 | 69 | 从上面的代码中可以看到其使用方式与 @import 是相同的,那么为什么还要替换掉 @import 呢? 主要是以下几个原因你需要了解下: 70 | 71 | - @import 会使得所有变量、mixin 和函数都可以全局访问,这使开发者很难去维护这些定义的东西。 72 | - 因为所有的都是全局的,那么 Sass 必须为所有的成员添加前缀,以避免命名冲突。 73 | - @extend 也是全局的,这样将很难预测哪些样式将被扩展。 74 | - 每次使用 @import 时,每个样式表都会被执行,这会增加编译时间 75 | - 无法定义下游样式表无法访问的私有成员。 76 | 77 | 基于上述的这些原因,Sass 官方团队将会逐渐淘汰 @import,可以使用 @use 替代,语法是相同的,所以我们在 **v4.x.x 及以上的版本**中尽量使用 @use 来导入。 78 | 79 | ## 7.实战经验 80 | 81 | 其实在实际的项目中我们一般就是用 @import 来简单的导入文件,更多的时候是用它来方便整个项目中的 Sass 样式管理,如下图所示: 82 | 83 | ![image-20220825230946960](https://i0.hdslb.com/bfs/album/914fa27c933c7268f301b1ac3ea60c37273ca975.png) 84 | 85 | 图中所演示的是我的项目中的一个使用方式。每个项目的样式管理方式都不同,你的公司中的项目中肯定也会使用 @import 或 @use 来管理样式文件,不过目前应该是使用 @import 的居多,这个功能其实很简单也没有太多的说法,在你的项目中需要你灵活的使用它,当然,慢慢的使用 @use 去替换掉它也是非常重要的! 86 | 87 | ## 8.小结 88 | 89 | ![image-20220825232019448](https://i0.hdslb.com/bfs/album/01981baf9dad809208f4ecee5c182e8840b80e39.png) 90 | 91 | 本节内容我们讲解了 Sass 中的导入 @import,这在 CSS 中也是有这个功能的,这个功能我们可以理解就是导入文件中的内容的,一般在项目中我们也是用它来操作文件而已。 92 | 93 | 还有需要注意的是,Sass 官方推荐使用 @use 来替代 @import 使用,所以我们在导入的时候尽量使用 @use,如果你的项目中已经大量的使用了 @import (这是目前很常见的现状),可以找个时机替换掉,不过一定要确保 Sass 的**版本是 v4.x.x 及以上!** -------------------------------------------------------------------------------- /docs/front_end/css_advanced/tailwind/01.md: -------------------------------------------------------------------------------- 1 | # 01 【Tailwind CSS 安装使用】 2 | 3 | > **简介:**Tailwind CSS 是一个功能类优先的 CSS 框架,它集成了诸如 flex, pt-4, text-center 和 rotate-90 这样的的类,它们能直接在脚本标记语言中组合起来,构建出任何设计。 4 | 5 | ## 1.使用 CDN 快速体验 Tailwind CSS 6 | 7 | > 使用 Play CDN 直接在浏览器中试用 Tailwind,无需任何构建步骤。Play CDN 仅用于开发目的,不是生产的最佳选择。 8 | 9 | 将 Play CDN 脚本标记添加到 HTML 文件的 ,然后开始使用 Tailwind 的实用工具类来设置内容的样式。`` 10 | 11 | ```html 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
1
22 |
2
23 |
3
24 |
25 | 26 | 27 | ``` 28 | 29 | ## 2.使用 npm 安装 Tailwind CSS 30 | 31 | **第一步:安装 Tailwind CSS** 32 | 33 | 安装 `Tailwind CSS` 并创建 `tailwind.config.js` 配置文件 34 | 35 | ```shell 36 | mkdir demo 37 | cd demo 38 | 39 | # 安装 tailwindcss 40 | npm install -D tailwindcss 41 | # 初始化会生成 tailwind.config.js 配置文件 42 | npx tailwindcss init 43 | ``` 44 | 45 | > 1)npm install -D tailwindcss 会生成文件及目录 46 | > 47 | > node_modules package-lock.json package.json 48 | > 49 | > 50 | > 51 | > 2)npx tailwindcss init 生成如下配置文件 52 | > 53 | > tailwind.config.js 54 | 55 | **第二步:编辑 tailwind.config.js 配置文件** 56 | 57 | 添加文件到配置文件中 58 | 59 | ```js 60 | module.exports = { 61 | content: ["./src/**/*.{html,js}"], 62 | theme: { 63 | extend: {}, 64 | }, 65 | plugins: [], 66 | } 67 | ``` 68 | 69 | **第三步:添加 Tailwind 样式指令到 CSS文件中** 70 | 71 | ``` 72 | @tailwind base; 73 | @tailwind components; 74 | @tailwind utilities; 75 | ``` 76 | 77 | > 有警告的在vscode中安装`PostCSS Language Support`插件 78 | 79 | **第四步:使用 Tailwind Cli 构建 CSS样式** 80 | 81 | ```shell 82 | npx tailwindcss -i ./src/style.css -o ./dist/mystyle.css --watch 83 | ``` 84 | 85 | 该命令会将 `src/style.css` 中 `Tailwind CSS` 编译到 `demo/dist/mystyle.css` 文件中,`mystyle.css` 就是编译后样式,项目中引入的就是它。 86 | 87 | 现在打开 `package.json` 文件,添加以下运行脚本: 88 | 89 | ```json 90 | "scripts": { 91 | "build": "tailwindcss -i ./src/style.css -o ./dist/output.css --watch" 92 | } 93 | ``` 94 | 95 | 这时候只要运行`npm run build`就可以自动监听你的页面改动并且实时编译了。 96 | 97 | **第五步:小试牛刀** 98 | 99 | 经过上面 4 个小步骤,`Tailwind CSS` 就已经安装好,下面就来瞅瞅。 100 | 101 | ```html 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 |

111 | Hello world! 112 |

113 | 114 | 115 | ``` 116 | 117 | > ### 自动刷新HTML文件 118 | > 119 | > 这是个题外话,不属于Tailwind CSS的范畴,如果你在写静态页面的时候,需要每次修改html页面,浏览器就自动刷新这个页面,那么只需要在vscode内搜索`Live Preview`并且安装,之后在你需要预览的页面,右键,选择`Live Preview:Show Preview`即可。 -------------------------------------------------------------------------------- /docs/front_end/css_advanced/tailwind/02.md: -------------------------------------------------------------------------------- 1 | # 02 【TailWind CSS 初体验】 2 | 3 | 经过上一篇 `Tailwind CSS` 的学习,现在已经安装好了,万事俱备,只欠东风。这篇文章不往后学习,先来找找**成就感!**,体验一把 `Tailwind CSS` 的案例。 4 | 5 | ```html 6 | 7 | 8 | 9 | 10 | 11 | 12 | Document 13 | 14 | 15 | 16 |
17 |
18 |
Hello world
19 |
20 |
21 |
Hello TailWind CSS
22 |
23 |
24 | 25 | 29 | 30 |
31 |
32 |
33 |
你好,TailWind CSS。
34 |
35 |
36 | 37 | 38 | ``` 39 | 40 | ![image-20220816124340412](https://i0.hdslb.com/bfs/album/38c7b2d62e38832a28fd0c946911e4d313107558.png) 41 | 42 | ```html 43 | 44 | 45 | 46 | 47 | 48 | 49 | Document 50 | 51 | 52 | 53 |

TailWind CSS

54 |
57 |

hello tailwind css

58 |
59 | 60 |
61 |
Laravel
62 |
Tailwind CSS
63 |
Livewire
64 |
65 | 66 | 67 | ``` 68 | 69 | ![image-20220816124411029](https://i0.hdslb.com/bfs/album/37eda129387ca8126c42efcb0e4f58734079186b.png) 70 | 71 | -------------------------------------------------------------------------------- /docs/front_end/front_end_base/html_css/05.md: -------------------------------------------------------------------------------- 1 | # 05 【CSS引入方式 CSS的元素显示模式】 2 | 3 | ## 1.CSS的引入方式 4 | 5 | ### 1.1 CSS的三种引入方式 6 | 7 | 按照 CSS 样式书写的位置(或者引入的方式),CSS 样式表可以分为三大类: 8 | 9 | - 行内样式表(行内式) 10 | - 内部样式表(嵌入式) 11 | - 外部样式表(外链式) 12 | 13 | ### 1.2 行内样式表 14 | 15 | 行内样式表(内联样式表)是在元素标签内部的 style 属性中设定 CSS 样式,适合于修改简单样式。 16 | 17 | ```html 18 |
19 | 青春不常在,抓紧谈恋爱 20 |
21 | ``` 22 | 23 | - `style` 其实就是标签的属性 24 | - 在双引号中间,写法要符合 CSS 规范 25 | - 可以控制当前的标签设置样式 26 | - 由于书写繁琐,并且没有体现出结构与样式相分离的思想,所以不推荐大量使用,只有对当前元素添加简单样式的时候,可以考虑使用 27 | - 使用行内样式表设定 CSS,通常也被称为 `行内式引入` 28 | 29 | > 问题:使用内联样式,样式只能对一个标签生效。如果希望影响到多个元素,必须在每一个元素中都复制一遍;并且当样式发生变化时,我们必须要一个一个的修改,非常的不方便。(注意:开发时绝对不要使用内联样式) 30 | 31 | ### 1.3 内部样式表 32 | 33 | 将样式编写到`head`中的`style`标签里然后通过css的选择器来选中元素并为其设置各种样式可以同时为多个标签设置样式,并且修改时只需要修改一处即可。内部样式表更加方便对样式进行复用 34 | 35 | ```html 36 | 42 | ``` 43 | 44 | - ` 23 | 24 | 25 |
0
26 | 46 | ``` 47 | 48 | **节流小案例-页面打开,可以记录上一次的视频播放位置** 49 | 50 | ```html 51 | 67 | ``` 68 | 69 | ## 2.防抖(debounce) 70 | 71 | **所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间** 72 | 73 | ```tex 74 | 开发使用场景- 搜索框防抖 75 | 假设输入就可以发送请求,但是不能每次输入都去发送请求,输入比较快发送请求会比较多 76 | 我们设定一个时间,假如300ms, 当输入第一个字符时候,300ms后发送请求,但是在200ms的时候又输入了一个字符,则需要再等300ms 后发送请求 77 | ``` 78 | 79 | ```html 80 | 90 | 91 | 92 |
0
93 | 110 | ``` 111 | 112 | ```tex 113 | 节流和防抖的使用场景是? 114 | 节流: 鼠标移动,页面尺寸发生变化,滚动条滚动等开销比较大的情况下 115 | 防抖: 搜索框输入,设定每次输入完毕n秒后发送请求,如果期间还有输入,则从新计算时间 116 | ``` 117 | -------------------------------------------------------------------------------- /docs/front_end/front_end_framework/react/08.md: -------------------------------------------------------------------------------- 1 | # 08 【状态提升】 2 | 3 | ## 1.介绍 4 | 5 | 所谓 **状态提升** 就是将各个子组件的 公共state 提升到它们的父组件进行统一存储、处理(这就是所谓的”单一数据源“),负责`setState`的函数传到下边的子级组件,然后再将父组件处理后的数据或函数props到各子组件中。 6 | 7 | 那么如果子组件 要 修改父组件的state该怎么办呢?我们的做法就是 将父组件中负责setState的函数,以props的形式传给子组件,然后子组件在需要改变state时调用即可。 8 | 9 | **实现方式** 10 | 11 | 实现方式是 利用最近的共同的父级组件中,用props的方式传过去到两个子组件,props中传的是一个setState的方法,通过子组件触发props传过去的方法,进而调用父级组件的setState的方法,改变了父级组件的state,调用父级组件的render方法,进而同时改变了两个子级组件的render。 12 | 13 | 这是 两个有关连的同级组件的传值,因为react的单项数据流,所以不在两个组件中进行传值,而是提升到 最近的共同的父级组件中,改变父级的state,进而影响了两个子级组件的render。 14 | 15 | > 官网介绍 16 | > 17 | > 通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。 18 | 19 | ## 2.案例 20 | 21 | 先写一个温度输入组件: 22 | 23 | ```js 24 | class TemperatureInput extends React.Component { 25 | state = { 26 | temperature: '' 27 | }; 28 | handleChange = (e) => { 29 | this.setState({ 30 | temperature : e.target.value 31 | }) 32 | }; 33 | render() { 34 | return ( 35 |
36 | 输入{scaleNames[this.props.scale]}: 37 | 39 | ) 40 | } 41 | } 42 | ``` 43 | 44 | 这个组件就是一个普通的**受控组件**,有`state`和`props`以及处理函数。 45 | 46 | 我们在写另一个组件: 47 | 48 | ```js 49 | class Calculator extends React.Component { 50 | render () { 51 | return ( 52 |
53 | 54 | 55 |
56 | ) 57 | } 58 | } 59 | ``` 60 | 61 | 这个组件现在没有什么存在的价值,我们仅仅是给两个温度输入组件提供一个父组件,以便我们进行后续的**状态提升**。 62 | 63 | 现在我们看看网页的样子: 64 | 65 | ![image-20221025123600431](https://i0.hdslb.com/bfs/album/a4228155682c5b7715204c99d704b8f4b9daf6a6.png) 66 | 67 | 我们可以输入摄氏度和华氏度,但是我们现在想要让这两个温度保持一致,就是我们如果输入摄氏度,那么下面的华氏度可以自动算出来,如果我们输入华氏度,那么摄氏度就可以自动算出来。 68 | 69 | 那么我们按照现在这种结构的话,是非常难以实现的,因为我们知道这两个组件之间没有任何关系,它们之间是不知道对方的存在,所以我们需要把它们的状态进行提升,提升到它们的父组件当中。 70 | 71 | 那我们看看如何做修改,首先把子组件(温度输入组件)的状态(state)全部删除,看看是什么样子: 72 | 73 | ```js 74 | class TemperatureInput extends React.Component { 75 | 76 | handleChange = (e) => { 77 | 78 | }; 79 | 80 | render() { 81 | return ( 82 |
83 | 输入{scaleNames[this.props.scale]}: 84 | 85 |
86 | ) 87 | } 88 | } 89 | ``` 90 | 91 | 可以看到所有与`state`有关的东西全部删掉了,然后`input`的`value`也变成了`props`,通过父组件传入。那么现在这个温度输入组件其实就是一个受控组件了,仔细回忆一下我们之前讲的受控组件,看看是不是这样意思? 92 | 93 | 我们通常会在受控组件发生改变的时候传入一个`onChange`函数来改变受控组件的状态,那么我们这里也是一样,我们通过给 温度输入组件 传入某个函数来让 温度输入组件 中的`input`发生变化的时候调用,当然这个函数我们可以随意命名,假如我们这里叫做`onTemperatureChange`函数,那么我们继续修改子组件: 94 | 95 | ```jsx 96 | class TemperatureInput extends React.Component { 97 | 98 | handleChange = (e) => { 99 | this.props.onTemperatureChange(e.target.value); 100 | }; 101 | 102 | render() { 103 | return ( 104 |
105 | 输入{scaleNames[this.props.scale]}: 106 | 107 |
108 | ) 109 | } 110 | } 111 | ``` 112 | 113 | 好了,我们的子组件差不多就是这样了,当然我们可以省略那个`handleChange`函数,因为可以看到这个函数就是调用了一下那个`props`里的函数,所以我们完全把`input`的`onChange`这么写 ``这么写的话注意`onTemperatrueChange`函数的参数是那个事件,而不是我这里写的`e.target.value`。 114 | 115 | 再看看我们的父组件如何修改,我们首先补上`state`,以及子组件对应的`onChange`处理方法,以及子组件的值。写好之后大概是这个样子: 116 | 117 | ```jsx 118 | class Calculator extends React.Component { 119 | state = { 120 | celsius: '', 121 | fahrenheit: '' 122 | }; 123 | 124 | onCelsiusChange = (value) => { 125 | this.setState({ 126 | celsius: value, 127 | fahrenheit: tryConvert(value, toFahrenheit) 128 | }); 129 | }; 130 | 131 | onFahrenheitChange = (value) => { 132 | this.setState({ 133 | celsius: tryConvert(value, toCelsius), 134 | fahrenheit: value 135 | }); 136 | }; 137 | 138 | render() { 139 | return ( 140 |
141 | 143 | 145 |
146 | ) 147 | } 148 | } 149 | ``` 150 | 151 | 这里我们省略的摄氏度与华氏度的转换函数,比较简单,大家自行搜索方法。 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/front_end/front_end_framework/react/09.md: -------------------------------------------------------------------------------- 1 | # 09 【组合组件】 2 | 3 | ## 1.包含关系 4 | 5 | 有些组件无法提前知晓它们子组件的具体内容。在 `Sidebar`(侧边栏)和 `Dialog`(对话框)等展现通用容器(box)的组件中特别容易遇到这种情况。 6 | 7 | 我们建议这些组件使用一个特殊的 `children` prop 来将他们的子组件传递到渲染结果中: 8 | 9 | > 组件标签里面包含的子元素会通过 `props.children` 传递进来。 10 | 11 | ```js 12 | function One(props) { 13 | return ( 14 |
{props.children}
15 | //特殊的children props 16 | ); 17 | } 18 | 19 | function Two(props) { 20 | return ( 21 | //这使别的组件可以通过JSX嵌套,来将任意组件作为子组件来传递给他们 22 | 23 |
Hello
24 |
World
25 |
26 | ); 27 | } 28 | ``` 29 | 30 | ![image-20221025135313079](https://i0.hdslb.com/bfs/album/1c38a6b492f958e4474609b0e0205d919275819b.png) 31 | 32 | ## 2.特例关系问题 33 | 34 | 有些时候,我们会把一些组件看作是其他组件的特殊实例,比如 `WelcomeDialog` 可以说是 `Dialog` 的特殊实例。 35 | 36 | 在 React 中,我们也可以通过组合来实现这一点。“特殊”组件可以通过 props 定制并渲染“一般”组件: 37 | 38 | ```css 39 | .FancyBorder { 40 | padding: 10px 10px; 41 | border: 10px solid; 42 | } 43 | 44 | .FancyBorder-blue { 45 | border-color: blue; 46 | } 47 | 48 | .Dialog-title { 49 | margin: 0; 50 | font-family: sans-serif; 51 | } 52 | 53 | .Dialog-message { 54 | font-size: larger; 55 | } 56 | ``` 57 | 58 | ```js 59 | function Dialog(props) { 60 | return ( 61 | 62 |

63 | {props.title} 64 |

65 |

66 | {props.message} 67 |

68 |
69 | ); 70 | } 71 | 72 | function WelcomeDialog() { 73 | return ( 74 | 77 | ); 78 | } 79 | ``` 80 | 81 | [**在 CodePen 上尝试**](https://codepen.io/gaearon/pen/kkEaOZ?editors=0010) 82 | 83 | 组合也同样适用于以 class 形式定义的组件。 84 | 85 | ```js 86 | function Dialog(props) { 87 | return ( 88 | 89 |

90 | {props.title} 91 |

92 |

93 | {props.message} 94 |

95 | {props.children} 96 |
97 | ); 98 | } 99 | 100 | class SignUpDialog extends React.Component { 101 | constructor(props) { 102 | super(props); 103 | this.handleChange = this.handleChange.bind(this); 104 | this.handleSignUp = this.handleSignUp.bind(this); 105 | this.state = {login: ''}; 106 | } 107 | 108 | render() { 109 | return ( 110 | 112 | 114 | 117 | 118 | ); 119 | } 120 | 121 | handleChange(e) { 122 | this.setState({login: e.target.value}); 123 | } 124 | 125 | handleSignUp() { 126 | alert(`Welcome aboard, ${this.state.login}!`); 127 | } 128 | } 129 | ``` 130 | 131 | [**在 CodePen 上尝试**](https://codepen.io/gaearon/pen/gwZbYa?editors=0010) 132 | 133 | ![image-20221025135929891](https://i0.hdslb.com/bfs/album/d343f27193258344b3ef4adf5b0f7f0f3f558a66.png) -------------------------------------------------------------------------------- /docs/front_end/front_end_framework/uniapp/02.md: -------------------------------------------------------------------------------- 1 | # 02 【uni-app起步】 2 | 3 | ## 1.什么是uni-app 4 | 5 | `uni-app` 是一个使用 [Vue.js (opens new window)](https://vuejs.org/)开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。 6 | 7 | > 翻译翻译就是:写一套代码就可以在多端运行 8 | 9 | `DCloud`公司拥有900万开发者、数百万应用、12亿手机端月活用户、数千款uni-app插件、70+微信/qq群。阿里小程序工具官方内置uni-app([详见 (opens new window)](https://opendocs.alipay.com/mini/ide/overview)),腾讯课堂官方为uni-app录制培训课程([详见 (opens new window)](https://ask.dcloud.net.cn/article/35640)),开发者可以放心选择。 10 | 11 | `uni-app`在手,做啥都不愁。即使不跨端,`uni-app`也是更好的小程序开发框架([详见 (opens new window)](https://ask.dcloud.net.cn/article/35947))、更好的App跨平台框架、更方便的H5开发框架。不管领导安排什么样的项目,你都可以快速交付,不需要转换开发思维、不需要更改开发习惯。 12 | 13 | ## 2.uni-app 环境搭建 14 | 15 | > `uni-app`支持通过 可视化界面、[`vue-cli`命令行 (opens new window)](https://uniapp.dcloud.io/quickstart-cli)两种方式快速创建项目。 16 | 17 | 可视化的方式比较简单,HBuilderX内置相关环境,开箱即用,无需配置nodejs。 18 | 19 | 开始之前,开发者需先下载安装如下工具: 20 | 21 | - HBuilderX:[官方IDE下载地址(opens new window)](https://www.dcloud.io/hbuilderx.html) 22 | 23 | HBuilderX是通用的前端开发工具,但为`uni-app`做了特别强化。 24 | 25 | ### 2.1 创建uni-app 26 | 27 | 在点击工具栏里的文件 -> 新建 -> 项目(快捷键`Ctrl+N`): 28 | 29 | ![image-20221012200152918](https://i0.hdslb.com/bfs/album/001a7e2797edb732ae2be49927272e8da7f4787d.png) 30 | 31 | 选择`uni-app`类型,输入工程名,选择模板,点击创建,即可成功创建。 32 | 33 | uni-app自带的模板有 默认的空项目模板、Hello uni-app 官方组件和API示例,还有一个重要模板是 uni ui项目模板,日常开发推荐使用该模板,已内置大量常用组件。 34 | 35 | ![image-20221012200227087](https://i0.hdslb.com/bfs/album/fc1ff9bfcbe771013e62c53b182b3be27499cea3.png) 36 | 37 | 开发者也可以使用`cli`方式创建项目,另见[文档 (opens new window)](https://uniapp.dcloud.io/quickstart-cli.html)。 38 | 39 | 差别是:HBuilderX创建的项目根目录就是源码,可直接编辑。uni-app的编译器在HBuilderX的插件目录下,跟随HBuilderX升级而一起升级。 40 | 41 | 如果开发者习惯于node模式的项目,对HBuilderX可视化方式感到困惑,可另行参考文档:[## cli创建项目和HBuilderX可视化界面创建项目的区别](https://uniapp.dcloud.net.cn/quickstart-cli#clidiff) 42 | 43 | ### 2.2 运行uni-app 44 | 45 | 1. 浏览器运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到浏览器 -> 选择浏览器,即可体验 uni-app 的 web 版。 46 | 47 | ![image-20221012200308031](https://i0.hdslb.com/bfs/album/0cdaef87ed51ef3f21d25a4535ca3ac673b3ccb9.png) 48 | 49 | 2. 运行App到手机或模拟器:使用电压足够的usb端口连接手机,设置中开启USB调试,手机上允许电脑设备调试手机,进入hello-uniapp项目,点击工具栏的运行 -> 运行App到手机或模拟器,即可在该设备里面体验uni-app。 50 | 51 | ![image-20221012200359605](https://i0.hdslb.com/bfs/album/91430d87d04bd3020fce08cf6ffb89d455e5a6d4.png) 52 | 53 | - 如手机或模拟器无法识别,请点击[常见故障排查指南 (opens new window)](https://uniapp.dcloud.net.cn/tutorial/run/run-app-faq.html)。 54 | 55 | - 如需运行在苹果手机真机上,注意需使用自定义基座。[详见](https://uniapp.dcloud.net.cn/tutorial/run/run-app.html#customplayground) 56 | 57 | 3. 在微信开发者工具里运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到小程序模拟器 -> 微信开发者工具,即可在微信开发者工具里面体验uni-app。 58 | 59 | ![image-20221012200437511](https://i0.hdslb.com/bfs/album/a8df3bf4fb45c4fdf1dd121269a7951fbd2792a7.png) 60 | 61 | **注意**:如果是第一次使用,需要先配置小程序ide的相关路径,才能运行成功。如下图,需在输入框输入微信开发者工具的安装路径。 62 | 63 | ![image-20221012200500652](https://i0.hdslb.com/bfs/album/6fcd39f14abdb550ac748127c668c0e10c8b513b.png) 64 | 65 | **注意**:微信开发者工具需要开启服务端口 在微信工具的设置->安全中。 66 | 67 | ![image-20221012200517918](https://i0.hdslb.com/bfs/album/6e08a0e6959e795eba2019eea81839ab663b1130.png) 68 | 69 | ## 3.uni-app的开发目录结构 70 | 71 | ### 3.1 官方 72 | 73 | 一个uni-app工程,默认包含如下目录及文件: 74 | 75 | ```markdown 76 | ┌─uniCloud 云空间目录,阿里云为uniCloud-aliyun,腾讯云为uniCloud-tcb(详见uniCloud) 77 | │─components 符合vue组件规范的uni-app组件目录 78 | │ └─comp-a.vue 可复用的a组件 79 | ├─utssdk 存放uts文件 80 | ├─pages 业务页面文件存放的目录 81 | │ ├─index 82 | │ │ └─index.vue index页面 83 | │ └─list 84 | │ └─list.vue list页面 85 | ├─static 存放应用引用的本地静态资源(如图片、视频等)的目录,注意:静态资源只能存放于此 86 | ├─uni_modules 存放[uni_module](/uni_modules)。 87 | ├─platforms 存放各平台专用页面的目录,详见 88 | ├─nativeplugins App原生语言插件 详见 89 | ├─nativeResources App端原生资源目录 90 | │ └─android Android原生资源目录 详见 91 | ├─hybrid App端存放本地html文件的目录,详见 92 | ├─wxcomponents 存放小程序组件的目录,详见 93 | ├─unpackage 非工程代码,一般存放运行或发行的编译结果 94 | ├─AndroidManifest.xml Android原生应用清单文件 详见 95 | ├─main.js Vue初始化入口文件 96 | ├─App.vue 应用配置,用来配置App全局样式以及监听 应用生命周期 97 | ├─manifest.json 配置应用名称、appid、logo、版本等打包信息,详见 98 | ├─pages.json 配置页面路由、导航条、选项卡等页面类信息,详见 99 | └─uni.scss 这里是uni-app内置的常用样式变量 100 | ``` 101 | 102 | **Tips** 103 | 104 | - 编译到任意平台时,`static` 目录下的文件均会被完整打包进去,且不会编译。非 `static` 目录下的文件(vue、js、css 等)只有被引用到才会被打包编译进去。 105 | - `static` 目录下的 `js` 文件不会被编译,如果里面有 `es6` 的代码,不经过转换直接运行,在手机设备上会报错。 106 | - `css`、`less/scss` 等资源不要放在 `static` 目录下,建议这些公用的资源放在自建的 `common` 目录下。 107 | - HbuilderX 1.9.0+ 支持在根目录创建 `ext.json`、`sitemap.json` 等小程序需要的文件。 108 | 109 | ### 3.2 基础项目 110 | 111 | ![image-20221012200922934](https://i0.hdslb.com/bfs/album/cdc77725add1d4fda236938df819eb6a4c60d10f.png) 112 | 113 | pages目录: 存放页面的。 114 | 115 | static目录:存放静态资源的。 116 | 117 | unpackage目录:存放最终打包的存放位置。 118 | 119 | App.vue文件:项目根组件。 120 | 121 | main.js文件:项目的入口文件,也就是项目加载时,先加载main.js文件。 122 | 123 | manifest.json文件:负责管理打包的一些配置,指定应用名称,图标,权限等。 124 | 125 | pages.json文件:页面路由,负责设置整个项目的页面(pages)存放路径以及窗口外观(globalStyle)的。 126 | 127 | uni.scss文件:配置一些颜色什么的。 128 | 129 | **uni-app的开发规范:(看起来就是Vue和小程序混合起来了)** 130 | 131 | 为了实现多端兼容,综合考虑编译速度、运行性能等因素,`uni-app` 约定了如下开发规范: 132 | 133 | - 页面文件遵循 [Vue 单文件组件 (SFC) 规范(opens new window)](https://vue-loader.vuejs.org/zh/spec.html) 134 | - 组件标签靠近小程序规范,详见[uni-app 组件规范](https://uniapp.dcloud.net.cn/component/) 135 | - 接口能力(JS API)靠近微信小程序规范,但需将前缀 `wx` 替换为 `uni`,详见[uni-app接口规范](https://uniapp.dcloud.net.cn/api/) 136 | - 数据绑定及事件处理同 `Vue.js` 规范,同时补充了App及页面的生命周期 137 | - 为兼容多端运行,建议使用flex布局进行开发 138 | 139 | -------------------------------------------------------------------------------- /docs/front_end/front_end_framework/uniapp/06.md: -------------------------------------------------------------------------------- 1 | # 06 【uniapp生命周期】 2 | 3 | 生命周期的概念:一个对象从创建、运行、销毁的整个过程被成为生命周期。 4 | 5 | 生命周期函数:在生命周期中每个阶段会伴随着每一个函数的触发,这些函数被称为生命周期函数。 6 | 7 | ## 1.应用生命周期 8 | 9 | [uni-app官网 (dcloud.net.cn)](https://uniapp.dcloud.net.cn/collocation/App.html#applifecycle) 10 | 11 | `uni-app` 支持如下应用生命周期函数: 12 | 13 | | 函数名 | 说明 | 14 | | :------- | :--------------------------------------------- | 15 | | onLaunch | 当`uni-app` 初始化完成时触发(全局只触发一次) | 16 | | onShow | 当 `uni-app` 启动,或从后台进入前台显示 | 17 | | onHide | 当 `uni-app` 从前台进入后台 | 18 | | onError | 当 `uni-app` 报错时触发 | 19 | 20 | **示例代码** 21 | 22 | ```html 23 | 40 | 41 | 44 | ``` 45 | 46 | **代码分析:** 47 | 48 | - 第一次加载页面时会调用`onLaunch` ,`onShow` 打印`App Launch`,`App Show` 49 | - 当你在浏览器离开页面,去查看其它页面,或者其它应用会触发`onHide`,在回来查看该页面时触发`onShow` ,打印`App Hide`,`App Show` 50 | - 我们手动把`onShow`方法里面的`console.log(‘App Show’) `改为`consol.log(‘App Show’) `去掉一个`e`字母,这样会导致报错,这个时候我们`onError`方法就可以监听到错误 51 | 52 | **注意** 53 | 54 | - **应用生命周期仅可在`App.vue`中监听,在其它页面监听无效**。 55 | - 应用启动参数,可以在API `uni.getLaunchOptionsSync`获取,[详见(opens new window)](https://uniapp.dcloud.net.cn/api/plugins/getLaunchOptionsSync.html#getlaunchoptionssync) 56 | - onlaunch里进行页面跳转,如遇白屏报错,请参考[https://ask.dcloud.net.cn/article/35942(opens new window)](https://ask.dcloud.net.cn/article/35942) 57 | - `App.vue` 不能写模板 58 | - onPageNotFound 页面实际上已经打开了(比如通过分享卡片、小程序码)且发现页面不存在,才会触发,api 跳转不存在的页面不会触发(如 uni.navigateTo) 59 | 60 | ## 2.页面生命周期 61 | 62 | [页面简介 | uni-app官网 (dcloud.net.cn)](https://uniapp.dcloud.net.cn/tutorial/page.html#lifecycle) 63 | 64 | `uni-app` 支持如下页面生命周期函数: 65 | 66 | | 函数名 | 说明 | 平台差异说明 | 最低版本 | 67 | | :------- | :----------------------------------------------------------- | :----------- | :------- | 68 | | onLoad | 监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参),参考[示例](https://uniapp.dcloud.net.cn/api/router#navigateto) | | | 69 | | onShow | 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面 | | | 70 | | onReady | 监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发 | | | 71 | | onHide | 监听页面隐藏 | | | 72 | | onUnload | 监听页面卸载 | | | 73 | 74 | `index.vue`页面里面定义的页面生命周期函数如下: 75 | 76 | 77 | ```js 78 | export default { 79 | data() { 80 | return { 81 | title: 'Hello' 82 | } 83 | }, 84 | onLoad(option) { 85 | console.log('页面加载了', option); 86 | }, 87 | onShow() { 88 | console.log('页面显示了'); 89 | }, 90 | onReady() { 91 | console.log('页面初次渲染完成了'); 92 | }, 93 | onHide() { 94 | console.log('页面隐藏了'); 95 | }, 96 | onUpload() { 97 | console.log('页面卸载了'); 98 | }, 99 | methods: { 100 | 101 | } 102 | } 103 | ``` 104 | **代码分析:** 105 | 106 | - 第一次加载首页,触发onLoad,onShow,onReady方法,依次打印页面加载了,页面显示了,页面初次渲染完成了 107 | - 当你在浏览器离开页面,去查看其它页面,或者其它应用,会触发onHide方法,打印页面隐藏了,在回来查看该页面时触发onShow方法,打印页面显示了。可以发现印页面加载了,页面初次渲染完成了都不在打印,证明onLoad,onReady方法只触发一次,而onShow,onHide方法多次触发 108 | 109 | 当我们取tabbr底部栏从首页切换到其它页面,会触发onHide方法,打印页面隐藏了。再次会到首页,触发onShow方法,打印页面显示了 110 | 111 |   tabbar的提示: 112 | 113 | ```tex 114 | tabbar 切换第一次加载时可能渲染不及时,可以在每个tabbar页面的onLoad生命周期里先弹出一个等待雪花(hello uni-app使用了此方式) 115 | tabbar 的页面展现过一次后就保留在内存中,再次切换 tabbar 页面,只会触发每个页面的onShow,不会再触发onLoad 116 | ``` 117 | 118 | ## 3.组件生命周期 119 | 120 | `uni-app` 组件支持的生命周期,与vue标准组件的生命周期相同。这里没有页面级的onLoad等生命周期: 121 | 122 | | 函数名 | 说明 | 平台差异说明 | 最低版本 | 123 | | :------------ | :----------------------------------------------------------- | :----------- | :------- | 124 | | beforeCreate | 在实例初始化之前被调用。[详见(opens new window)](https://cn.vuejs.org/v2/api/#beforeCreate) | | | 125 | | created | 在实例创建完成后被立即调用。[详见(opens new window)](https://cn.vuejs.org/v2/api/#created) | | | 126 | | beforeMount | 在挂载开始之前被调用。[详见(opens new window)](https://cn.vuejs.org/v2/api/#beforeMount) | | | 127 | | mounted | 挂载到实例上去之后调用。[详见 (opens new window)](https://cn.vuejs.org/v2/api/#mounted)注意:此处并不能确定子组件被全部挂载,如果需要子组件完全挂载之后在执行操作可以使用`$nextTick`[Vue官方文档(opens new window)](https://cn.vuejs.org/v2/api/#Vue-nextTick) | | | 128 | | beforeUpdate | 数据更新时调用,发生在虚拟 DOM 打补丁之前。[详见(opens new window)](https://cn.vuejs.org/v2/api/#beforeUpdate) | 仅H5平台支持 | | 129 | | updated | 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。[详见(opens new window)](https://cn.vuejs.org/v2/api/#updated) | 仅H5平台支持 | | 130 | | beforeDestroy | 实例销毁之前调用。在这一步,实例仍然完全可用。[详见(opens new window)](https://cn.vuejs.org/v2/api/#beforeDestroy) | | | 131 | | destroyed | Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。[详见](https://cn.vuejs.org/v2/api/#destroyed) | | | -------------------------------------------------------------------------------- /docs/front_end/front_end_framework/vue2/01.md: -------------------------------------------------------------------------------- 1 | # 01 【Vue简介 初识Vue 模板语法和数据绑定】 2 | 3 | ## 1.Vue简介 4 | 5 | ### 1.1官网 6 | 7 | - [英文官网](https://vuejs.org/) 8 | - [中文官网](https://cn.vuejs.org/) 9 | 10 | ### 1.2介绍与描述 11 | 12 | - Vue 是一套用来动态构建用户界面的渐进式JavaScript框架 13 | ○构建用户界面:把数据通过某种办法变成用户界面 14 | ○渐进式:Vue可以自底向上逐层的应用,简单应用只需要一个轻量小巧的核心库,复杂应用可以引入各式各样的Vue插件 15 | - 作者:尤雨溪 16 | 17 | ![image-20220627111824089](https://i0.hdslb.com/bfs/album/a480928cc5819344850462e511b11481f773c4e3.png) 18 | 19 | ### 1.3. Vue 的特点 20 | 21 | 1 遵循MVVM模式 22 | 2 编码简洁,体积小,运行效率高,适合移动/PC端开发 23 | 3 它本身只关注 UI,可以引入其它第三方库开发项目 24 | 4采用`组件化`模式,提高代码复用率、且让代码更好维护 25 | 26 | ![image-20220627112112058](https://i0.hdslb.com/bfs/album/911d5825fb775e5d72a180e14cf91cd4150b7d6f.png) 27 | 28 | 5 `声明式`编码,让编码人员无需直接操作DOM,提高开发效率 29 | 30 | ![image-20220627112141707](https://i0.hdslb.com/bfs/album/84f52ac120ac699f8e9e2d5b777359e90545dd3a.png) 31 | 32 | 使用`虚拟DOM` 和 `Diff算法`,尽量复用DOM节点 33 | 34 | ![image-20220627112235934](https://i0.hdslb.com/bfs/album/a28b2b5307e90c92fd36bbad151869b7dbc481ce.png) 35 | 36 | ### 1.4与其他 JS 框架的关联 37 | 38 | - 借鉴 angular 的 **模板** 和 **数据绑定** 技术 39 | - 借鉴 react 的 **组件化** 和 **虚拟DOM** 技术 40 | 41 | ### 1.5Vue 周边库 42 | 43 | - vue-cli:vue 脚手架 44 | - vue-router:路由 45 | - vuex:状态管理(它是 vue 的插件但是没有用 vue-xxx 的命名规则) 46 | - vue-lazyload:图片懒加载 47 | - vue-scroller:页面滑动相关 48 | - mint-ui:基于 vue 的 UI 组件库(移动端) 49 | - element-ui:基于 vue 的 UI 组件库(PC 端) 50 | 51 | ## 2.初识Vue 52 | 53 | **前置工作** 54 | 55 | 1. 给浏览器安装 [Vue Devtools](https://cn.vuejs.org/v2/guide/installation.html#Vue-Devtools) 插件 56 | 2. 标签引入Vue包 57 | 3. (可选)阻止vue在启动时生成生产提示`Vue.config.productionTip = false` 58 | 4. favicon 需要将页签图标放在项目根路径,重新打开就有了(shfit+F5 强制刷新) 59 | 60 | **初识Vue** 61 | 62 | 1. 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象 63 | 2. root 容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法 64 | 3. root 容器里的代码被称为Vue模板 65 | 4. Vue 实例与容器是`一一对应`的 66 | 5. 真实开发中只有一个Vue实例,并且会配合着组件一起使用 67 | 6. `{{xxx}}`中的 xxx 要写` js 表达式`,且 xxx 可以自动读取到data中的所有属性 68 | **注意区分**:js 表达式 和 js代码(语句) 69 | 1. 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方 70 | a a+b demo(1) x === y ? 'a' : 'b' 71 | 2. js代码(语句) 72 | if(){} for(){} 73 | 7. 一旦data中的数据发生变化,那么模板中用到该数据的地方也会自动更新(Vue实现的响应式) 74 | 75 | > 初始示例代码 76 | 77 | ```html 78 | 79 | 80 | 81 |
82 |

Hello,{{name.toUpperCase()}},{{address}}

83 |
84 | 85 | 98 | ``` 99 | 100 | ## 3.模板语法和数据绑定 101 | 102 | ### 3.1模板语法 103 | 104 | `Vue`模板语法有2大类: 105 | 106 | * **插值语法:** 107 | 108 | 功能:用于解析标签体内容 109 | 110 | 写法:`{{xxx}}`,xxx是**js表达式**,且可以直接读取到data中的所有属性 111 | 112 | * **指令语法:** 113 | 114 | 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件.....) 115 | 116 | 举例:`v-bind:href="xxx"` 或 简写为 `:href="xxx"`,xxx同样要写`js表达式`,且可以直接读取到data中的所有属性 117 | 118 | 备注:Vue中有很多的指令,且形式都是 **v-xxx**,此处只是拿v-bind举例 119 | 120 | > 代码 121 | 122 | ```html 123 |
124 |

插值语法

125 |

你好,{{ name }}

126 |
127 |

指令语法

128 | 点我去看{{ tencent.name }}1 129 | 点我去看{{ tencent.name }}2 130 |
131 | 132 | 144 | ``` 145 | 146 | ![image-20220627113847858](https://i0.hdslb.com/bfs/album/39acee45f25c6e31959ae833c1f9d55cb08bc896.png) 147 | 148 | ### 3.2数据绑定 149 | 150 | Vue中有2种数据绑定的方式: 151 | 152 | * 单向绑定`(v-bind)`:数据只能从data流向页面 153 | 154 | * 双向绑定`(v-model)`:数据不仅能从data流向页面,还可以从页面流向data 155 | 156 | > tips: 157 | > 158 | > 1.双向绑定一般都应用在**表单类元素**上(如:`input`、`select`等) 159 | > 160 | > 2.**v-model:value** 可以简写为` v-model`,因为v-model默认收集的就是value值 161 | 162 | > 代码 163 | 164 | ```html 165 |
166 | 167 | 单向数据绑定:
168 | 双向数据绑定:
169 | 170 | 171 | 单向数据绑定:
172 | 双向数据绑定:
173 | 174 | 175 | 176 |
177 | 178 | 186 | ``` 187 | 188 | -------------------------------------------------------------------------------- /docs/front_end/front_end_framework/vue2/02.md: -------------------------------------------------------------------------------- 1 | # 02 【el和data的两种写法 MVVM模型】 2 | 3 | ## 1.el和data的两种写法 4 | 5 | **el**有2种写法 6 | 7 | - 创建Vue实例对象的时候配置el属性 8 | 9 | - 先创建Vue实例,随后再通过vm.$mount('#root')指定el的值 10 | 11 | **data**有2种写法 12 | 13 | - 对象式:data: { } 14 | - 函数式:data() { return { } } 15 | - 如何选择:目前哪种写法都可以,以后到组件时,data必须使用函数,否则会报错 16 | 一个重要的原则 17 | - 由Vue管理的函数,一定不要写箭头函数,否则 this 就不再是Vue实例了 18 | 19 | ```html 20 | 21 |
22 |

你好,{{name}}

23 |
24 | 25 | 53 | ``` 54 | 55 | ## 2.MVVM模型 56 | 57 | ![image-20220627114527315](https://i0.hdslb.com/bfs/album/16a3c9896eb5b087c5c8e8cfa276f89b76b9732e.png) 58 | 59 | MVVM模型 60 | 61 | - M:模型 `Model`,data中的数据 62 | - V:视图 `View`,模板代码 63 | - VM:视图模型 `ViewModel`,Vue实例(相当于数据和页面的连接桥梁) 64 | 65 | 观察发现 66 | 67 | - `data`中所有的属性,最后都出现在了`vm`身上 68 | - `vm`身上所有的属性 及Vue原型身上所有的属性,在 Vue模板中都可以直接使用 69 | 70 | ```html 71 |
72 |

名称:{{ name }}

73 |

战队:{{ team }}

74 |

测试:{{ $options }}

75 |
76 | 77 | 87 | ``` 88 | 89 | ![image-20220627114825918](https://i0.hdslb.com/bfs/album/a58c057f9f09939e3c77bcb11c1dc8743354607f.png) -------------------------------------------------------------------------------- /docs/front_end/front_end_framework/vue2/12.md: -------------------------------------------------------------------------------- 1 | # 12 【nextTick 过渡与动画】 2 | 3 | ## 1.nextTick 4 | 5 | **这是一个生命周期钩子** 6 | 7 | 1. 语法:```this.$nextTick(回调函数)``` 8 | 2. 作用:在下一次 DOM 更新结束后执行其指定的回调。 9 | 3. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。 10 | 11 | > 比如编辑按钮使文本变成表单且自动获取焦点 12 | > 13 | > 点击表单时会用一个布尔值配合v-show使表单显示,可是改变布尔值的时候,后面的focus方法会跟着执行,然后再渲染模板 14 | 15 | ```html 16 | 29 | 30 | 49 | ``` 50 | 51 | ## 2.过渡与动画 52 | 53 | ### 2.1 基本介绍 54 | 55 | Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。 56 | 包括以下工具: 57 | 1、在 CSS 过渡和动画中自动应用 class; 58 | 2、配合使用第三方 CSS 动画库,如 Animate.css; 59 | 3、在过渡钩子函数中使用 JavaScript 直接操作 DOM; 60 | 4、配合使用第三方 JavaScript 动画库,如 Velocity.js。 61 | 62 | ![image-20220702200614775](https://i0.hdslb.com/bfs/album/211e5bf27c639a3f962a7a9d76cf3b9dab20ea1b.png) 63 | 64 | 1. 作用:Vue封装的在插入、更新或移除` DOM`元素时,在合适的时候给元素添加样式类名。 65 | 66 | 2. 写法: 67 | 68 | 1. 准备好样式: 69 | 70 | - 元素进入的样式: 71 | 1. v-enter:进入的起点 72 | 2. v-enter-active:进入过程中 73 | 3. v-enter-to:进入的终点 74 | - 元素离开的样式: 75 | 1. v-leave:离开的起点 76 | 2. v-leave-active:离开过程中 77 | 3. v-leave-to:离开的终点 78 | 79 | 2. 使用``包裹要过度的元素,并配置`name`属性,此时需要将上面样式名的`v`换为`name` 80 | 81 | ```vue 82 | 83 |

你好啊!

84 |
85 | ``` 86 | 87 | 3. 要让页面一开始就显示动画,需要添加`appear` 88 | 89 | 4. 备注:若有多个元素需要过度,则需要使用:``````,且每个元素都要指定```key```值。 90 | 91 | ```vue 92 | 93 |

你好啊!

94 |

尚硅谷!

95 |
96 | ``` 97 | 98 | 5. 第三方动画库`Animate.css` 99 | 100 | ```vue 101 | 115 | 116 | 127 | ``` 128 | 129 | ### 2.2 动画的使用 130 | 131 | ```vue 132 | 133 |

你好啊!

134 |
135 | 136 | 154 | ``` 155 | 156 | ### 2.3 过渡的使用 157 | 158 | ```vue 159 | 168 | 169 | 175 | 176 | 193 | ``` 194 | 195 | -------------------------------------------------------------------------------- /docs/front_end/front_end_framework/vue2/16.md: -------------------------------------------------------------------------------- 1 | # 16 【打包 图片懒加载】 2 | 3 | ## 1.打包 4 | 5 | `vue.config.js` 6 | 7 | ```javascript 8 | module.exports = { 9 | //打包时不生成map文件(用来进行错误提示的文件,很占用空间) 10 | productionSourceMap: false, 11 | // 关闭ESLINT校验工具 12 | lintOnSave: false, 13 | } 14 | ``` 15 | 16 | ```shell 17 | pnpm run build 18 | ``` 19 | 20 | ## 2.图片懒加载 21 | 22 | [懒加载vue-lazyload插件官网](https://www.npmjs.com/package/vue-lazyload) 23 | 插件的使用直接参考官方教程,很简单。 24 | 25 | **安装vue-lazyload插件** 26 | 27 | ```shell 28 | pnpm add vue-lazyload@1.3.3 --save-dev 29 | ``` 30 | 31 | **在main.js中进行引用** 32 | 33 | ```js 34 | import VueLazyload from "vue-lazyload"; 35 | 36 | //或者自定义配置插件 37 | Vue.use(VueLazyload, { 38 | preLoad: 1.3, 39 | error: require('@/assets/image/error.png'), 40 | loading: require('@/assets/image/loading.gif'), 41 | attempt: 1 42 | }) 43 | 44 | ``` 45 | 46 | **各个自定义配置属性含义:** 47 | 48 | ![image-20220720143240479](https://i0.hdslb.com/bfs/album/4f3788e8fd79ec4841143a5824982956f983d9a2.png) 49 | 50 | **使用(将图片设置为[懒加载](https://so.csdn.net/so/search?q=懒加载&spm=1001.2101.3001.7020))** 51 | 52 | ```html 53 | 54 | ``` 55 | 56 | **注意:** 57 | 当遇到是v-for循环的时候,或者用div包裹着img的时候,需要在div上面添加 `v-lazy-container="{ selector: ‘img’ }"` 58 | 59 | ```html 60 |
61 | 62 | 63 | 64 |
65 | 66 | 67 | 68 |
69 |
70 | ``` 71 | 72 | 如果是这种情况的话,一定要使用 data-src 来指定路径,而不使用v-lazy。因为如果使用的是v-lazy的话,拿到了图片地址也会一直显示不出来。 73 | 74 | -------------------------------------------------------------------------------- /docs/front_end/front_end_framework/vue3/07.md: -------------------------------------------------------------------------------- 1 | # 07 【动态组件 组件注册】 2 | 3 | ## 1.动态组件 4 | 5 | ### 1.1 基本使用 6 | 7 | composition api写法:只适用于vue3 8 | 9 | - 在 ` 41 | ``` 42 | 43 | > **提示** 44 | > 45 | > 用 markRaw 也可以,但是不如shallwRef直观与方便。 46 | 47 | ### 1.2 官方案例 48 | 49 | 有些场景会需要在两个组件间来回切换,比如 Tab 界面: 50 | 51 | ```vue 52 | 66 | 67 | 80 | 85 | ``` 86 | 87 | ![image-20220808210314991](https://i0.hdslb.com/bfs/album/2ebb7dd5ec1d2e46080623849ad437d80f0ef230.png) 88 | 89 | 上面的例子是通过 Vue 的 `` 元素和特殊的 `is` attribute 实现的: 90 | 91 | ```vue 92 | 93 | 94 | ``` 95 | 96 | 在上面的例子中,被传给 `:is` 的值可以是以下几种: 97 | 98 | - 被注册的组件名 99 | - 导入的组件对象 100 | 101 | 你也可以使用 `is` attribute 来创建一般的 HTML 元素。 102 | 103 | 当使用 `` 来在多个组件间作切换时,被切换掉的组件会被卸载。我们可以通过 [`` 组件](https://staging-cn.vuejs.org/guide/built-ins/keep-alive.html)强制被切换掉的组件仍然保持“存活”的状态。 104 | 105 | ## 2.组件注册 106 | 107 | ### 2.1 全局注册[#](https://staging-cn.vuejs.org/guide/components/registration.html#global-registration) 108 | 109 | 例如组件使用频率非常高(table,Input,button,等)这些组件 几乎每个页面都在使用便可以封装成全局组件 110 | 111 | 我们可以使用 [Vue 应用实例](https://staging-cn.vuejs.org/guide/essentials/application.html)的 `app.component()` 方法,让组件在当前 Vue 应用中全局可用。 112 | 113 | ```js 114 | import { createApp } from 'vue' 115 | 116 | const app = createApp({}) 117 | 118 | app.component( 119 | // 注册的名字 120 | 'MyComponent', 121 | // 组件的实现 122 | { 123 | /* ... */ 124 | } 125 | ) 126 | ``` 127 | 128 | 如果使用单文件组件,你可以注册被导入的 `.vue` 文件: 129 | 130 | ```js 131 | import MyComponent from './test.vue' 132 | 133 | app.component('MyComponent', MyComponent) 134 | ``` 135 | 136 | `app.component()` 方法可以被链式调用: 137 | 138 | ```js 139 | app 140 | .component('ComponentA', ComponentA) 141 | .component('ComponentB', ComponentB) 142 | .component('ComponentC', ComponentC) 143 | ``` 144 | 145 | 全局注册的组件可以在此应用的任意组件的模板中使用: 146 | 147 | ```vue 148 | 149 | 150 | 151 | 152 | ``` 153 | 154 | 所有的子组件也可以使用全局注册的组件,这意味着这三个组件也都可以在*彼此内部*使用。 155 | 156 | ### 2.2 局部注册[#](https://staging-cn.vuejs.org/guide/components/registration.html#local-registration) 157 | 158 | 全局注册虽然很方便,但有以下几个问题: 159 | 160 | 1. 全局注册,但并没有被使用的组件无法在生产打包时被自动移除 (也叫“tree-shaking”)。如果你全局注册了一个组件,即使它并没有被实际使用,它仍然会出现在打包后的 JS 文件中。 161 | 2. 全局注册在大型项目中使项目的依赖关系变得不那么明确。在父组件中使用子组件时,不太容易定位子组件的实现。和使用过多的全局变量一样,这可能会影响应用长期的可维护性。 162 | 163 | 相比之下,局部注册的组件需要在使用它的父组件中显式导入,并且只能在该父组件中使用。它的优点是使组件之间的依赖关系更加明确,并且对 tree-shaking 更加友好。 164 | 165 | 在使用 ` 171 | 172 | 175 | ``` 176 | 177 | 如果没有使用 ` 68 | 69 | 70 | ``` 71 | 72 | 这里点击按钮,就又可以创建一个新的窗口了 73 | 74 | ## 2.electron14.0版本API修改 75 | 76 | ![image-20230109191550834](https://i0.hdslb.com/bfs/album/f3e24468d08568375545e2735c7b7dff08e47edf.png) 77 | 78 | > 1.还得自行安装 `remote` 79 | 80 | ```bash 81 | npm i -D @electron/remote 82 | ``` 83 | 84 | > 2.主进程中导入 85 | 86 | ```js 87 | app.on('ready',function(){ 88 | require('@electron/remote/main').initialize() 89 | }) 90 | ``` 91 | 92 | > 3.渲染进程中 93 | 94 | ```js 95 | //这样来引入remote 96 | const { BrowserWindow, app } = require('@electron/remote') 97 | ``` 98 | 99 | **完整代码:** 100 | 101 | `main.js` 102 | 103 | ```js 104 | const { app, BrowserWindow } = require('electron') 105 | 106 | const createWindow = () => { 107 | const win = new BrowserWindow({ 108 | width: 800, 109 | height: 600, 110 | webPreferences: { 111 | nodeIntegration: true, 112 | contextIsolation: false, 113 | }, 114 | }) 115 | 116 | win.loadFile('index.html') 117 | win.webContents.openDevTools() 118 | 119 | require('@electron/remote/main').initialize() 120 | require('@electron/remote/main').enable(win.webContents) 121 | } 122 | 123 | app.whenReady().then(() => { 124 | createWindow() 125 | 126 | app.on('activate', () => { 127 | if (BrowserWindow.getAllWindows().length === 0) { 128 | createWindow() 129 | } 130 | }) 131 | }) 132 | 133 | app.on('window-all-closed', () => { 134 | if (process.platform !== 'darwin') { 135 | app.quit() 136 | } 137 | }) 138 | 139 | ``` 140 | 141 | `index.html` 142 | 143 | ```html 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | Hello from Electron renderer! 152 | 153 | 154 |

Hello from Electron renderer!

155 |

👋

156 | 157 | 158 | 159 | 160 | 161 | ``` 162 | 163 | `render.js` 164 | 165 | ```js 166 | const { BrowserWindow } = require('@electron/remote') 167 | 168 | document.querySelector('#btn').addEventListener('click', () => { 169 | let newWin = new BrowserWindow({ 170 | width: 300, 171 | height: 200, 172 | }) 173 | 174 | newWin.loadFile('index2.html') 175 | 176 | newWin.on('closed', () => (newWin = null)) 177 | }) 178 | ``` 179 | 180 | 效果图: 181 | 182 | ![image-20230109193710284](https://i0.hdslb.com/bfs/album/8d42b1db9c154a94c7204d91708d35a9bbddf824.png) -------------------------------------------------------------------------------- /docs/front_end/other/electron/05.md: -------------------------------------------------------------------------------- 1 | # 05 【electron的一些渲染进程Api】 2 | 3 | ## 1.clipboard 4 | 5 | > 在系统剪贴板上进行复制和粘贴操作。 6 | > 7 | > 在主进程(main process)和渲染进程(renderer process)上均可用。 8 | 9 | ### 1.1 `readText()` 10 | 11 | 返回字符串 - 剪贴板中的内容为纯文本。 12 | 13 | ```js 14 | const { clipboard } = require('electron') 15 | 16 | clipboard.writeText('千锋教育HTML5大前端!') 17 | 18 | const text = clipboard.readText() 19 | console.log(text) 20 | // hello i am a bit of text!' 21 | ``` 22 | 23 | ### 1.2 `writeText(text)` 24 | 25 | 将文本作为纯文本写进剪贴板。 26 | 27 | ## 2.contextBridge 28 | 29 | > 创建一个安全的、双向的、跨越隔离情境的同步桥梁。 30 | > 31 | > 只在渲染进程(renderer pocess)中可用。 32 | 33 | ## 3.desktopCapturer 34 | 35 | >使用 navigator.mediaDevices.getUserMedia API 访问可用于从桌面捕获音频和视频的媒体源信息。 36 | > 37 | >只在主进程(main process)可用。 38 | 39 | 下面的例子显示了如何从一个标题为Electron的桌面窗口捕捉图像: 40 | 41 | - 在主进程里 42 | 43 | ```js 44 | // ./controller/getSource.js 45 | const { desktopCapturer, ipcMain } = require('electron') 46 | 47 | const getSource = (mainWindow) => { 48 | ipcMain.handle('desktop-capturer', async (event) => { 49 | desktopCapturer.getSources({ 50 | types: ['window', 'screen'], 51 | thumbnailSize: { 52 | width: 1728, 53 | height: 1117 54 | } 55 | }).then(async sources => { 56 | for (const source of sources) { 57 | if (source.name === 'Entire Screen') { 58 | mainWindow.webContents.send('SET_SOURCE', source) 59 | return 60 | } 61 | } 62 | }) 63 | }) 64 | } 65 | 66 | module.exports = getSource 67 | 68 | // ./main.js 69 | getSource(win) 70 | ``` 71 | 72 | - 在预处理JS里 73 | 74 | ```js 75 | // ./preload-js/setSource.js 76 | const { ipcRenderer } = require('electron') 77 | 78 | const setSource = () => { 79 | return new Promise((resolve) => { 80 | ipcRenderer.on('SET_SOURCE', async (event, source) => { 81 | let str = source.thumbnail.crop({ x: 0, y: 30, width: 1200, height: 1170 }) 82 | resolve(str.toDataURL()) 83 | }) 84 | }) 85 | } 86 | 87 | const invokeCaptureEvent = async () => { 88 | const result = await ipcRenderer.invoke('desktop-capturer') 89 | return result 90 | } 91 | 92 | module.exports = { 93 | setSource, 94 | invokeCaptureEvent 95 | } 96 | 97 | // ./preload-js/index.js 98 | const { setSource, invokeCaptureEvent } = require('./setSource') 99 | contextBridge.exposeInMainWorld('myAPI', { 100 | setSource, 101 | invokeCaptureEvent 102 | }) 103 | ``` 104 | 105 | - 在渲染进程页面里 106 | 107 | ```js 108 | const app = Vue.createApp({ 109 | template: ` 110 |
111 | 112 |
113 |
114 | 115 |
116 | `, 117 | 118 | data() { 119 | return { 120 | imgSrc: '' 121 | } 122 | }, 123 | 124 | methods: { 125 | async captureDesk() { 126 | const result = await myAPI.invokeCaptureEvent() 127 | } 128 | }, 129 | 130 | async beforeCreate() { 131 | let imgDataUrl = await myAPI.setSource() 132 | this.imgSrc = imgDataUrl 133 | }, 134 | }) 135 | 136 | app.mount('#root') 137 | ``` 138 | 139 | ## 4.ipcRenderer 140 | 141 | >从一个渲染器进程到主进程的异步通信。 142 | > 143 | >只在渲染进程(renderer pocess)中可用。 144 | 145 | `详情见 09 【进程间通信】` 146 | 147 | ## 5.nativeImage 148 | 149 | >使用PNG或JPG文件创建托盘、停靠区和应用程序图标。 150 | > 151 | >在主进程(main process)和渲染进程(renderer process)上均可用。 152 | 153 | 在Electron中,对于接受图像的API,你可以传递文件路径或NativeImage实例。当传递null时,将使用一个空的图像。 154 | 155 | 例如,在创建一个托盘或设置一个窗口的图标时,你可以把图像文件路径作为一个字符串传递。 156 | 157 | ```js 158 | const { BrowserWindow, Tray } = require('electron') 159 | 160 | const appIcon = new Tray('/Users/somebody/images/icon.png') 161 | const win = new BrowserWindow({ icon: '/Users/somebody/images/window.png' }) 162 | console.log(appIcon, win) 163 | ``` 164 | 165 | 或者从剪贴板上读取图像,返回一个NativeImage。 166 | 167 | ```js 168 | const { clipboard, Tray } = require('electron') 169 | const image = clipboard.readImage() 170 | const appIcon = new Tray(image) 171 | console.log(appIcon) 172 | ``` 173 | 174 | ### 5.1 支持的格式 175 | 176 | 目前支持PNG和JPEG图像格式。建议使用PNG,因为它支持透明度和无损压缩。 177 | 178 | 在Windows上,你也可以从文件路径加载ICO图标。为了获得最佳的视觉质量,建议至少包括以下尺寸的文件。 179 | 180 | - Small icon 181 | - 16x16 (100% DPI scale) 182 | - 20x20 (125% DPI scale) 183 | - 24x24 (150% DPI scale) 184 | - 32x32 (200% DPI scale) 185 | - Large icon 186 | - 32x32 (100% DPI scale) 187 | - 40x40 (125% DPI scale) 188 | - 48x48 (150% DPI scale) 189 | - 64x64 (200% DPI scale) 190 | - 256x256 191 | 192 | ### 5.2 高分辨率图像 193 | 194 | 在支持高DPI的平台上,如苹果Retina显示器,你可以在图像的基本文件名后附加@2x来标记它为高分辨率的图像。 195 | 196 | 例如,如果icon.png是一个具有标准分辨率的普通图像,那么icon@2x.png,将被视为具有双倍DPI密度的高分辨率图像。 197 | 198 | 如果你想同时支持不同DPI密度的显示器,你可以把不同尺寸的图像放在同一个文件夹里,使用不带DPI后缀的文件名。例如: 199 | 200 | ```js 201 | images/ 202 | ├── icon.png 203 | ├── icon@2x.png 204 | └── icon@3x.png 205 | ``` 206 | 207 | ```js 208 | const { Tray } = require('electron') 209 | const appIcon = new Tray('/Users/somebody/images/icon.png') 210 | console.log(appIcon) 211 | ``` 212 | 213 | 还支持以下DPI的后缀: 214 | 215 | ```js 216 | @1x 217 | @1.25x 218 | @1.33x 219 | @1.4x 220 | @1.5x 221 | @1.8x 222 | @2x 223 | @2.5x 224 | @3x 225 | @4x 226 | @5x 227 | ``` 228 | 229 | ### 5.3 方法 230 | 231 | - ## `nativeImage.createEmpty()` 232 | 233 | - ## `nativeImage.createFromPath(path)` 234 | 235 | 返回 `NativeImage` 236 | 237 | 从位于路径的文件中创建一个新的NativeImage实例。如果路径不存在,不能被读取,或者不是一个有效的图像,该方法将返回一个空图像。 238 | 239 | ```js 240 | const nativeImage = require('electron').nativeImage 241 | 242 | const image = nativeImage.createFromPath('/Users/somebody/images/icon.png') 243 | console.log(image) 244 | ``` 245 | 246 | - ## `nativeImage.createFromDataURL(dataURL)` 247 | 248 | ### 5.4 Class: NativeImage 249 | 250 | 自然地包裹图像,如托盘、停靠区和应用程序图标。 251 | 252 | 253 | 在主进程(main process)和渲染进程(renderer process)上均可用。 254 | 255 | 实例方法: 256 | 257 | - ### `image.toPNG([options])` 258 | 259 | - ### `image.toJPEG(quality)` 260 | 261 | - ### `image.toDataURL([options])` 262 | 263 | - ### `image.getSize([scaleFactor])` 264 | 265 | - ### `image.crop(rect)` -------------------------------------------------------------------------------- /docs/front_end/other/electron/08.md: -------------------------------------------------------------------------------- 1 | # 08 【electron系统托盘 】 2 | 3 | 当我们关闭一个应用程序的时候,它其实关闭了,但是没有完全关闭,只是隐藏了,有的就存在系统托盘中,那么如何在`electron` 设置系统托盘呢 4 | 5 | [官方文档:Tray](https://link.juejin.cn/?target=https%3A%2F%2Fwww.electronjs.org%2Fdocs%2Ftutorial%2Ftray) 6 | 7 | ## 1.概览 8 | 9 | 当前指南将带领你创建 [Tray](https://www.electronjs.org/docs/api/tray) 图标, 并且其拥有系统通知区域的独立上下文菜单 10 | 11 | 在 MacOS 和 Ubuntu, 托盘将位于屏幕右上角上,靠近你的电池和 wifi 图标。 在 Windows 上,托盘通常位于右下角。 12 | 13 | ## 2.示例 14 | 15 | 首先,我们需要从 `electron` 导入 `app`, `Tray`, `Menu`, `nativeImage` 16 | 17 | ```js 18 | const { app, Tray, Menu, nativeImage } = require('electron') 19 | ``` 20 | 21 | 下一步我们将创建托盘。 要做到这一点,我们将使用一个 [`NativeImage`](https://www.electronjs.org/docs/api/native-image) 图标, 可以通过其中任一方法创建 [methods](https://www.electronjs.org/docs/api/native-image#methods)。 请注意,我们将托盘创建代码包装在一个 [`app.whenReady`](https://www.electronjs.org/docs/api/app#appwhenready) ,因为我们需要等待 electron 应用完成初始化 22 | 23 | `main.js` 24 | 25 | ```js 26 | let tray 27 | 28 | app.whenReady().then(() => { 29 | const icon = nativeImage.createFromPath('path/to/asset.png') 30 | tray = new Tray(icon) 31 | 32 | // 注意: 你的 contextMenu, Tooltip 和 Title 代码需要写在这里! 33 | }) 34 | ``` 35 | 36 | 现在我们可以开始将上下文菜单附加到我们的托盘上,就像这样: 37 | 38 | ```js 39 | const contextMenu = Menu.buildFromTemplate([ 40 | { label: 'Item1', type: 'radio' }, 41 | { label: 'Item2', type: 'radio' }, 42 | { label: 'Item3', type: 'radio', checked: true }, 43 | { label: 'Item4', type: 'radio' }, 44 | { 45 | label: '退出', 46 | click: app.quit, 47 | }, 48 | ]) 49 | 50 | tray.setContextMenu(contextMenu) 51 | ``` 52 | 53 | 上面的代码将在上下文菜单中创建4个单独的 radio-type 单选类型项。 要阅读更多关于构建原生菜单的信息,请点击 [这里](https://www.electronjs.org/docs/api/menu#menubuildfromtemplatetemplate) 54 | 55 | 最后,让我们给我们的托盘一个工具提示和标题。 56 | 57 | ```js 58 | // 移动到托盘上的提示 59 | tray.setToolTip('electron demo is running') 60 | // 还可以设置 titlle 61 | tray.setTitle('electron demo') 62 | ``` 63 | 64 | ## 3.完整代码 65 | 66 | ```js 67 | // 引入托盘 Tray,和 Menu 等下要创建菜单,nativeImage创建 icon图标 68 | const { app, BrowserWindow, Tray, Menu, nativeImage } = require('electron') 69 | 70 | let win, tray 71 | const createWindow = () => { 72 | win = new BrowserWindow({ 73 | width: 800, 74 | height: 600, 75 | }) 76 | 77 | win.loadFile('index.html') 78 | } 79 | 80 | app.whenReady().then(() => { 81 | // 创建图片图标 82 | const icon = nativeImage.createFromPath('icon.ico') 83 | // 实例化一个 托盘对象,传入的是托盘的图标 84 | tray = new Tray(icon) 85 | // 移动到托盘上的提示 86 | tray.setToolTip('electron demo is running') 87 | // 还可以设置 titlle 88 | tray.setTitle('electron demo') 89 | 90 | // 监听托盘右键事件 91 | tray.on('right-click', () => { 92 | // 右键菜单模板 93 | const contextMenu = Menu.buildFromTemplate([ 94 | { label: 'Item1', type: 'radio' }, 95 | { label: 'Item2', type: 'radio' }, 96 | { label: 'Item3', type: 'radio', checked: true }, 97 | { label: 'Item4', type: 'radio' }, 98 | { 99 | label: '退出', 100 | click: app.quit, 101 | }, 102 | ]) 103 | // 让我们的写的托盘右键的菜单替代原来的 104 | tray.setContextMenu(contextMenu) 105 | }) 106 | 107 | //监听点击托盘的事件 108 | tray.on('click', () => { 109 | // 这里来控制窗口的显示和隐藏 110 | if (win.isVisible()) { 111 | win.hide() 112 | } else { 113 | win.show() 114 | } 115 | }) 116 | 117 | createWindow() 118 | }) 119 | 120 | // 监听所有的窗口都关闭了 121 | app.on('window-all-closed', () => { 122 | if (process.platform !== 'darwin') { 123 | app.quit() 124 | } 125 | }) 126 | ``` 127 | 128 | **效果图** 129 | 130 | ![image-20230109213555028](https://i0.hdslb.com/bfs/album/35ed3a71aa95ba3f0c511bfca3f9cdf49a15191b.png) -------------------------------------------------------------------------------- /docs/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | title: 个人介绍 4 | icon: any 5 | --- 6 | 7 | 互联网广告人, 8 | 9 | 迷信新工具、新方法, 10 | 11 | 坚持批评与自我批评,对每一个机遇保持开放的态度,勇于尝试新鲜事物, 12 | 13 | 热衷于研究开源软件,定期分享探索成果。 14 | -------------------------------------------------------------------------------- /docs/professional_knowledge/software_engineer/03.md: -------------------------------------------------------------------------------- 1 | # 03 【需求分析】 2 | 3 | 为了开发出真正满足用户需求的软件产品,首先必须知道用户的需求。对软件需求的深入理解是软件开发工作获得成功的前提条件,不论人们把设计和编码工作做得如何出色,不能真正满足用户需求的程序只会令用户失望,给开发者带来烦恼。 4 | 5 | 需求分析是软件定义时期的最后一个阶段,它的基本任务是准确地回答“系统必须做什么?”这个问题,对目标系统提出完整、准确、清晰、具体的要求。 系统分析员应该写出**软件需求规格说明书**,以书面形式准确地描述软件需求。 6 | 7 | ## 1.需求分析的任务 8 | 9 | ### 1.1 确定对系统的综合要求 10 | 11 | 虽然功能需求是对软件系统的一项基本需求,但却并不是唯一的需求。通常对软件系统有下述几方面的综合要求。 12 | 13 | ![image-20230126221725410](https://i0.hdslb.com/bfs/album/d336da3a6ae5338e6ff68b1dabfb1a46edb1ba94.png) 14 | 15 | **功能性需求** 16 | 17 | 这方面的需求指定系统必须提供的服务。通过需求分析应该划分出系统必须完成的所有功能 18 | 19 | **性能需求** 20 | 21 | 性能需求指定系统必须满足的定时约束或容量约束,通常包括速度(响应时间)、信息量速率、主存容量、磁盘容量、安全性等方面的需求。 22 | 23 | **可靠性和可用性需求** 24 | 25 | 可靠性需求定量地指定系统的可靠性,可用性与可靠性密切相关,它量化了用户可以使用系统的程度。 26 | 27 | **出错处理需求** 28 | 29 | 这类需求说明系统对环境错误应该怎样响应。例如,如果它接收到从另一个系统发来的违反协议格式的消息,应该做什么?注意,上述这类错误并不是由该应用系统本身造成的。 30 | 31 | **接口需求** 32 | 33 | 接口需求描述应用系统与它的环境通信的格式。常见的接口需求有:用户接口需求;硬件接口需求;软件接口需求;通信接口需求。 34 | 35 | **约束** 36 | 37 | 设计约束或实现约束描述在设计或实现应用系统时应遵守的限制条件。常见的约束有:精度;工具和语言约束;设计约束;应该使用的标准;应该使用的硬件平台。 38 | 39 | **逆向需求** 40 | 41 | 逆向需求说明软件系统不应该做什么。理论上有无限多个逆向需求,人们应该仅选取能澄清真实需求且可消除可能发生的误解的那些逆向需求。 42 | 43 | **将来可能提出的要求** 44 | 45 | 应该明确地列出那些虽然不属于当前系统开发范畴,但是据分析将来很可能会提出来的要求。这样做的目的是,在设计过程中对系统将来可能的扩充和修改预做准备,以便一旦确实需要时能比较容易地进行这种扩充和修改。 46 | 47 | ### 1.2 分析系统的数据要求 48 | 49 | 任何一个软件系统本质上都是信息处理系统,系统必须处理的信息和系统应该产生的信息在很大程度上决定了系统的面貌,对软件设计有深远影响,因此,必须分析系统的数据要求,这是软件需求分析的一个重要任务。 50 | 51 | 复杂的数据由许多基本的数据元素组成,数据结构表示数据元素之间的逻辑关系。利用数据字典可以全面准确地定义数据,但是数据字典的缺点是不够形象直观。为了提高可理解性,常常利用图形工具辅助描绘数据结构。 52 | 53 | ### 1.3 导出系统的逻辑模型 54 | 55 | 综合上述两项分析的结果可以导出系统的详细的逻辑模型,通常用数据流图、实体联系图、状态转换图、数据字典和主要的处理算法描述这个逻辑模型。 56 | 57 | ### 1.4 修正系统开发计划 58 | 59 | 根据在分析过程中获得的对系统的更深入更具体的了解,可以比较准确地估计系统的成本和进度,修正以前制定的开发计划。 60 | 61 | ## 2.分析建模与规格说明(重要) 62 | 63 | ### 2.1 分析建模 64 | 65 | 模型,就是为了理解事物而对事物作出的一种抽象,是对事物的一种无歧义的书面描述。 66 | 67 | 为了开发复杂的系统,应从不同角度(模型)抽象出目标系统的特性(数据模型、功能模型、行为模型) 68 | 69 | ![image-20230126223449383](https://i0.hdslb.com/bfs/album/7d4221ef7f36e4686a3e212220205c90704bb138.png) 70 | 71 | - 实体联系图,描绘数据对象及数据对象之间的关系,是用于建立数据模型的图形。 72 | - 数据流图是建立功能模型的基础。 73 | - 状态转换图描绘了系统的各种行为模式和在不同状态间转换的方式。 74 | 75 | ### 2.2 软件需求规格说明 76 | 77 | 软件需求规格说明是需求分析阶段得出的最主要的文档。 78 | 79 | 通常用自然语言完整、准确、具体地描述系统的数据要求、功能需求、性能需求、可靠性和可用性要求、出错处理需求、接口需求、约束、逆向需求以及将来可能提出的要求。 80 | 81 | ## 3.实体-联系图 82 | 83 | 数据模型中包含3种相互关联的信息:数据对象、数据对象的属性及数据对象彼此间相互连接的关系。 84 | 85 | ### 3.1 数据对象 86 | 87 | **数据对象是对软件必须理解的复合信息的抽象。** 88 | 89 | 数据对象可以是外部实体、事物、行为、事件、角色、单位、地点或结构等。总之,可以由一组属性来定义的实体都可以被认为是数据对象。 90 | 91 | ### 3.2 属性 92 | 93 | **属性定义了数据对象的性质**。 94 | 95 | 必须把一个或多个属性定义为“标识符”,也就是说,当人们希望找到数据对象的一个实例时,用标识符属性作为“关键字”(通常简称为“键”)。 96 | 97 | ### 3.3 联系 98 | 99 | **客观世界中的事物彼此间往往是有联系的**。 100 | 101 | 数据对象彼此之间相互连接的方式称为联系,也称为关系。联系可分为以下3种类型。 102 | 103 | - 一对一联系(1∶1) 104 | - 一对多联系(1∶N) 105 | - 多对多联系(M∶N) 106 | 107 | ![image-20230127223243074](https://i0.hdslb.com/bfs/album/644d4026f5c62a3de2091e5138f6f9933be88bbd.png) 108 | 109 | ![image-20230127223250799](https://i0.hdslb.com/bfs/album/055f5a7108f92f0e8a6b509401eb601f08f375d6.png) 110 | 111 | ### 3.4 实体-联系图的符号 112 | 113 | 通常,使用实体联系图(entityrelationship diagram)来建立数据模型。可以把实体联系图简称为ER图,相应地可把用ER图描绘的数据模型称为ER模型。 114 | 115 | ER图中包含了实体(即数据对象)、关系和属性3种基本成分,通常用矩形框代表实体,用连接相关实体的菱形框表示关系,用椭圆形或圆角矩形表示实体(或关系)的属性,并用直线把实体(或关系)与其属性连接起来。 116 | 117 | ER模型可以作为用户与分析员之间有效的交流工具。 118 | 119 | ## 4.状态转换图 120 | 121 | 状态转换图(简称为状态图)通过描绘系统的状态及引起系统状态转换的事件,来表示系统的行为。此外,状态图还指明了作为特定事件的结果系统将做哪些动作。 122 | 123 | ### 4.1 状态 124 | 125 | 状态是任何可以被观察到的系统行为模式,一个状态代表系统的一种行为模式。状态规定了系统对事件的响应方式。 126 | 127 | 在状态图中定义的状态主要有:初态(即初始状态)、终态(即最终状态)和中间状态。在一张状态图中只能有一个初态,而终态则可以有0至多个。 128 | 129 | 状态图既可以表示系统循环运行过程,也可以表示系统单程生命期。 130 | 131 | ### 4.2 事件 132 | 133 | 事件是在某个特定时刻发生的事情,它是对引起系统做动作或(和)从一个状态转换到另一个状态的外界事件的抽象。 134 | 135 | 事件就是引起系统做动作或(和)转换状态的控制信息。 136 | 137 | ### 4.3 符号 138 | 139 | 状态图中两个状态之间带箭头的连线称为状态转换,箭头指明了转换方向。状态变迁通常是由事件触发的,在这种情况下应在表示状态转换的箭头线上标出触发转换的事件表达式;如果在箭头线上未标明事件,则表示在源状态的内部活动执行完之后自动触发转换。 140 | 141 | 事件表达式的语法如下: 142 | 143 | 事件说明[守卫条件]/动作表达式其中,事件说明的语法为:事件名(参数表)。 144 | 145 | ![image-20230127225650921](https://i0.hdslb.com/bfs/album/bed92b1f6dd9981f2e45e16bedbe872e39c92ee7.png) 146 | 147 | ### 4.4 例子 148 | 149 | 为了具体说明怎样用状态图建立系统的行为模型,下面举一个例子 150 | 151 | 下图是人们非常熟悉的电话系统的状态图。 152 | 153 | image-20230127225722348 154 | 155 | ## 5.其他图形工具 156 | 157 | ### 5.1 层次方框图 158 | 159 | 层次方框图用树形结构的一系列多层次的矩形框描绘数据的层次结构。 160 | 161 | 例如,描绘一家计算机公司全部产品的数据结构可以用下图层次方框图表示。 162 | 163 | 这家公司的产品由硬件、软件和服务3类产品组成,软件产品又分为系统软件和应用软件,系统软件又进一步分为操作系统、编译程序和软件工具等。 164 | 165 | image-20230127225905396 166 | 167 | ### 5.2 Warnier图 168 | 169 | 和层次方框图类似,Warnier图也用树形结构描绘信息,但是这种图形工具比层次方框图提供了更丰富的描绘手段。 170 | 171 | 用Warnier图可以表明信息的逻辑组织,也就是说,它可以指出一类信息或一个信息元素是重复出现的,也可以表示特定信息在某一类信息中是有条件地出现的。 172 | 173 | ![image-20230127225959364](https://i0.hdslb.com/bfs/album/0d7db7fbd91b2bf1e30532ddeb74cbd1366f23e0.png) 174 | 175 | ### 5.3 IPO图 176 | 177 | IPO图是输入、处理、输出图的简称,它是由美国IBM公司发展完善起来的一种图形工具,能够方便地描绘输入数据、对数据的处理和输出数据之间的关系。 178 | 179 | 下图是主文件更新的例子,通过这个例子不难了解IPO图的用法 180 | 181 | image-20230127230124219 182 | 183 | 改进的IPO图 184 | 185 | image-20230127230129596 186 | 187 | ## 6.本章小结 188 | 189 | 1. 本章讲解了需求分析的重要性,以及如何与用户交谈获取需求 190 | 191 | 2. 讲述建立模型的方法,在需求分析阶段建立数据模型、功能模型和行为模型。 192 | 193 | 3. 讲述如何使用实体联系图建立数据模型,使用数据流图建立功能模型,使用状态图建立行为模型。 194 | 195 | 4. 详细阐述状态转换图 196 | 197 | 5. 最后讲解如何验证软件需求。 -------------------------------------------------------------------------------- /docs/professional_knowledge/software_engineer/09.md: -------------------------------------------------------------------------------- 1 | # 09 【面向对象设计】 -------------------------------------------------------------------------------- /docs/professional_knowledge/software_engineer/10.md: -------------------------------------------------------------------------------- 1 | # 10 【面向对象实现】 -------------------------------------------------------------------------------- /docs/tool/efficiency/bookmark-scripts.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: '收录一些实用的书签脚本,没想到书签还能这么玩' 3 | --- 4 | 5 | # 书签脚本 6 | 7 | ## 回到顶部 8 | 9 | 只支持窗口滚动,不支持内联滚动 10 | 11 | ```js 12 | javascript: void (function () { 13 | document.scrollingElement.scrollIntoView({ behavior: 'smooth' }) 14 | })() 15 | ``` 16 | 17 | 回到顶部 18 | 19 | ## 显示密码 20 | 21 | ```js 22 | javascript: void (function () { 23 | document.querySelectorAll('input[type=password]').forEach(function (dom) { 24 | dom.setAttribute('type', 'text') 25 | }) 26 | })() 27 | ``` 28 | 29 | 显示密码 30 | -------------------------------------------------------------------------------- /docs/tool/efficiency/online-tools.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: '收录一些实用的在线工具,免去下载软件的烦恼' 3 | --- 4 | 5 | # 在线工具 6 | 7 | ## 开发相关 8 | 9 | - [Can I use](https://caniuse.com) 兼容性查询 10 | - [carbon](https://carbon.now.sh) 代码图片生成 11 | - [npm trends](https://www.npmtrends.com/) 比较 npm package 的下载情况 12 | - [Bundlephobia](https://bundlephobia.com/) 分析 npm package 的依赖、bundle 后的大小、下载速度预估 13 | - [Package Phobia](https://packagephobia.com/) 查询 npm package 的安装体积(磁盘大小) 14 | 15 | ### 沙箱 16 | 17 | - [CodeSandbox](https://codesandbox.io) 18 | - [Codepen](https://codepen.io) 19 | 20 | ### 正则 21 | 22 | - 正则可视化工具 23 | - [regulex](https://jex.im/regulex) 24 | - [regexper](https://regexper.com) 25 | - [正则可视化](https://wangwl.net/r/vr) 26 | - [regex101](https://regex101.com) 在线正则测试工具 27 | - [regexgen](https://npm.runkit.com/regexgen) 生成与一组字符串匹配的正则表达式 28 | - [any-rule](https://any86.github.io/any-rule) 正则大全 29 | 30 | ### 代码编译 31 | 32 | - [ast 生成器](https://astexplorer.net) 33 | - [rollup](http://rollupjs.org/repl) 34 | 35 | #### JS 相关 36 | 37 | - [Babel](https://www.babeljs.cn/repl) 38 | - [TypeScript](https://www.typescriptlang.org/play) 39 | 40 | #### Vue 41 | 42 | - [Vue Template Explorer](https://template-explorer.vuejs.org/) 43 | - [Vue 3 Template Explorer](https://vue-next-template-explorer.netlify.app/) 44 | - [Vue SFC Playground](https://sfc.vuejs.org/) 45 | 46 | #### CSS 预处理器 47 | 48 | - [Sass Playground](https://www.sassmeister.com) 49 | - [Less-To-CSS Playground](https://lesscss.org/less-preview) 50 | - Stylus Playground 51 | - [英文官网](https://stylus-lang.com/try.html) 52 | - [中文站点](https://www.stylus-lang.cn/try.html) 53 | 54 | ### 代码生成 55 | 56 | - [webcode.tools](https://webcode.tools) Web 代码生成工具 (CSS、HTML、meta 信息、JSON 等) 57 | - [nginx 配置可视化生成](https://do.co/nginxconfig) [(github)](https://github.com/digitalocean/nginxconfig.io) 58 | 59 | #### CSS 相关 60 | 61 | - [CSS Grid Generator](https://cssgrid-generator.netlify.app) grid 布局 62 | - [FANCY-BORDER-RADIUS](https://9elements.github.io/fancy-border-radius) border-radius 圆角 63 | - [CSS Shadows Generator](https://shadows.brumm.af) box-shadow 阴影 64 | - [Cubic-Bezier](https://cubic-bezier.com) 贝塞尔曲线 65 | - [Easing Gradients](https://larsenwork.com/easing-gradients) 渐变 66 | - [Clippy — CSS clip-path maker](https://bennettfeely.com/clippy) clip-path 67 | - [Neumorphism/Soft UI generator](https://neumorphism.io) `border-radius / background / box-shadow` 68 | 69 | #### SVG 相关 70 | 71 | - [Get Waves](https://getwaves.io) SVG 波浪生成器 72 | 73 | ### CDN 74 | 75 | - [jsDelivr](https://www.jsdelivr.com) 76 | - [esm.sh](https://esm.sh/) 77 | 78 | ## 图片处理 79 | 80 | ### 图片底色去除 81 | 82 | - [remove.bg](https://www.remove.bg) 83 | - [BgRemover](https://www.aigei.com/bgremover) 84 | 85 | ### 图片压缩 86 | 87 | - [TinyPNG](https://tinypng.com) 88 | - [docsmall](https://docsmall.com) 89 | - [squoosh](https://squoosh.app) [Google 开源](https://github.com/GoogleChromeLabs/squoosh)的图片压缩工具 90 | 91 | ### 图片生成 92 | 93 | - [Shields.io](https://shields.io/) 绘制小徽章 94 | 95 | - 生成 Github 仓库 Star 增长图 96 | 97 | - [Star Charts](https://starchart.cc/) 数据更详细 98 | - [Star history](https://star-history.t9t.io/) 手绘风格 99 | 100 | - [Notion 风格头像制作](https://notion-avatar.vercel.app/zh) 101 | 102 | ## 作图工具 103 | 104 | - [ProcessOn](https://www.processon.com/) 免费在线流程图思维导图 105 | - [Draw.io](https://app.diagrams.net/) 流程图 106 | - [Excalidraw](https://excalidraw.com/) 手绘风格流程图 107 | 108 | ## 文件处理 109 | 110 | - 在线格式转换 111 | - [CloudConvert](https://cloudconvert.com/) 在线文件转换器,支持 200+ 种格式、支持自定义设置、图片可在线预览(英文界面) 112 | - [Convertio](https://convertio.co/zh/) 在线转换文件的简单工具,支持 300+ 种格式、支持自定义设置(最大 100M) 113 | 114 | ## 休闲娱乐 115 | 116 | [yikm 小霸王在线游戏机](https://www.yikm.net/) 117 | -------------------------------------------------------------------------------- /docs/tool/efficiency/software/browser.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: '收录一些能提升使用体验的浏览器扩展、油猴脚本、实用小技巧' 3 | --- 4 | 5 | # 浏览器设置与扩展 6 | 7 | - [Chrome 插件开发全攻略](https://github.com/sxei/chrome-plugin-demo) 8 | 9 | ## 扩展商店 10 | 11 | - [Chrome 网上应用店](https://chrome.google.com/webstore/category/extensions) 12 | 13 | - [CrxDL - Chrome 浏览器扩展插件 CRX 下载网](https://crxdl.com/) 更新及时,可下载历史版本 14 | 15 | - [Chrome 插件扩展下载网 (免翻墙)](https://www.extfans.com/) 16 | 17 | ## 体验优化 18 | 19 | - 自定义你的新标签页 20 | 21 | - [Infinity 新标签页 (Pro)](https://chrome.google.com/webstore/detail/infinity-new-tab-pro/nnnkddnnlpamobajfibfdgfnbcnkgngh) 功能强大,更符合用户习惯 22 | 23 | - [Momentum](https://chrome.google.com/webstore/detail/momentum/laookkfknpbbblfpciffpaejjkokdgca) 设计更加简洁 24 | 25 | - [MONKNOW 新标签页 - 个性化面板](https://www.monknow.com/zh-CN) 支持网站网址 URL 分组管理,数据实时云同步,黑暗深色夜间主题模式。 26 | 27 | - [二维码生成器](https://chrome.google.com/webstore/detail/quick-qr-code-generator/afpbjjgbdimpioenaedcjgkaigggcdpp/) 为当前网页链接或任意内容生成二维码 28 | 29 | - [uBlock Origin](https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm) 广告拦截工具 30 | 31 | - [过滤广告 为 Youtube™](https://chrome.google.com/webstore/detail/adblock-for-youtube/cmedhionkhpnakcndndgjdbohmhepckk) 移除 Youtube 中的视频广告。 32 | 33 | - [哔哩哔哩助手](https://chrome.google.com/webstore/detail/%E5%93%94%E5%93%A9%E5%93%94%E5%93%A9%E5%8A%A9%E6%89%8B%EF%BC%9Abilibilicom-%E7%BB%BC%E5%90%88%E8%BE%85%E5%8A%A9%E6%89%A9%E5%B1%95/kpbnombpnpcffllnianjibmpadjolanh) 哔哩哔哩弹幕网辅助扩展,拥有视频区和直播区的人性化功能 34 | 35 | - [The Marvellous Suspender](https://chrome.google.com/webstore/detail/the-marvellous-suspender/noogafoofpebimajpfpamcfhoaifemoa) 冻结暂时用不到的标签页,以释放系统资源 36 | 37 | - [OneTab](https://chrome.google.com/webstore/detail/the-great-suspender/klbibkeccnjlkjkiokjodocebajanakg) 点击 OneTab 可将标签页转换成一个列表以释放系统资源,当您需要再次访问这些标签页时,可以单独或全部恢复它们。 38 | 39 | - [彩云小译](https://chrome.google.com/webstore/detail/lingocloud-web-translatio/jmpepeebcbihafjjadogphmbgiffiajh) 全文翻译(中英对照) 40 | 41 | - [划词翻译](https://chrome.google.com/webstore/detail/%E5%88%92%E8%AF%8D%E7%BF%BB%E8%AF%91/ikhdkkncnoglghljlkmcimlnlhkeamad) 划词翻译 42 | 43 | - [沙拉查词](https://chrome.google.com/webstore/detail/%E6%B2%99%E6%8B%89%E6%9F%A5%E8%AF%8D-%E8%81%9A%E5%90%88%E8%AF%8D%E5%85%B8%E5%88%92%E8%AF%8D%E7%BF%BB%E8%AF%91/cdonnmffkdaoajfknoeeecmchibpmkmg) Saladict 沙拉查词是一款专业划词翻译扩展,为交叉阅读而生。大量权威词典涵盖中英日韩法德西语,支持复杂的划词操作、网页翻译、生词本与 PDF 浏览。 44 | 45 | - [Video Speed Controller](https://chrome.google.com/webstore/detail/video-speed-controller/nffaoalbilbmmfgbnbgppjihopabppdk) 视频倍速播放,支持使用快捷键加快,减慢,推进和回放任何 HTML5 视频 46 | 47 | - [medium-unlimited](https://github.com/manojVivek/medium-unlimited) 免费读取 `medium.com` 文章 48 | 49 | ## 开发常用 50 | 51 | - [Vue.js devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) 用于调试 `Vue.js` 应用程序 52 | 53 | - [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) 用于调试 `React` 应用程序 54 | 55 | - [Redux DevTools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd) 用于调试应用程序 `Redux` 状态更改 56 | 57 | - [掘金](https://chrome.google.com/webstore/detail/%E6%8E%98%E9%87%91/lecdifefmmfjnjjinhaennhdlmcaeeeb) 在新标签页展示聚合内容,包含前端、Android、iOS、后端、产品、设计六大频道,每个频道内都有一到多个内容源 58 | 59 | - [WEB 前端助手(FeHelper)](https://chrome.google.com/webstore/detail/fehelperjson/pkgccpejnmalmdinmhkkfafefagiiiad) 包括字符串编解码、图片 `base64` 编码、代码压缩、美化、`JSON` 格式化、正则表达式、时间转换工具、二维码生成器、编码规范检测、页面性能检测、栅格检测、`JS` 运行效率分析 60 | 61 | - [Lighthouse](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk) 网站性能测评工具 62 | 63 | - [JSON Formatter](https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa) `JSON` 格式化 64 | 65 | ## GitHub 相关 66 | 67 | - [Octotree](https://chrome.google.com/webstore/detail/octotree/bkhaagjahfmjljalopjnoealnfndnagc) 显示文件树形目,在线浏览 Github 代码更便捷 68 | 69 | - [Refined GitHub](https://chrome.google.com/webstore/detail/refined-github/hlepfoohegkhhmjieoechaddaejaokhf) 优化 GitHub 默认功能和样式 70 | 71 | - [OctoLinker](https://chrome.google.com/webstore/detail/octolinker/jlmafbaeoofdegohdhinkhilhclaklkp) 根据 `require/import` 或 `package.json` 中的 `dependencies` 进行快速跳转 72 | 73 | - [File Icon for GitHub and GitLab](https://chrome.google.com/webstore/detail/file-icon-for-github-and/ficfmibkjjnpogdcfhfokmihanoldbfe) 文件 `icon` 美化 74 | 75 | - [Github Hovercard](https://chrome.google.com/webstore/detail/github-hovercard/mmoahbbnojgkclgceahhakhnccimnplk) GitHub 的悬浮卡,可快速浏览量用户/仓库/问题/提交信息 76 | 77 | - [Enhanced GitHub](https://chrome.google.com/webstore/detail/enhanced-github/anlikcnbgdeidpacdbdljnabclhahhmd) 显示仓库大小、每个文件的大小、下载链接和复制文件内容的选项 78 | 79 | ## 油猴 80 | 81 | - [油猴管理器](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo) 可以通过脚本修改网页 82 | 83 | - [油猴脚本市场](https://greasyfork.org/zh-CN) 84 | 85 | - [油猴 API 文档](https://www.tampermonkey.net/documentation.php?ext=dhdg&locale=zh) 86 | 87 | - 脚本推荐 88 | 89 | - [access-link](https://greasyfork.org/zh-CN/scripts/395970)修复跳转链接为站外直链(移除重定向),免去拦截页面点击步骤可直达站外;拦截页面自动跳转 90 | 91 | - [解除 B 站区域限制](https://greasyfork.org/zh-CN/scripts/25718) 实现解除 B 站区域限制,只对 `HTML5` 播放器生效 92 | 93 | - [imooc-tools](https://greasyfork.org/zh-CN/scripts/396378) 慕课网问答区快速查看问答详情、自动播放下一节视频 94 | 95 | - [115 转存助手 ui 优化版](https://gist.github.com/Nerver4Ever/953447c9ecd330ffc0861d4cbb839369) 115 网盘重要资源的备份复制转移 96 | 97 | ## 其他工具 98 | 99 | - [微信读书自动阅读器](https://github.com/DoooReyn/WxRead-WebAutoReader) 全自动刷阅读时长,轻轻松松冲顶霸榜,您的微读挂机好帮手 100 | 101 | ## 技巧 102 | 103 | ### 打开不安全网页 104 | 105 | 在当前页面任意地方点击,直接输入 `thisisunsafe` 后回车就能访问 106 | -------------------------------------------------------------------------------- /docs/tool/efficiency/software/cross-platform.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: '收录那些支持多个平台(Mac、Windows)的实用软件,提升使用体验' 3 | --- 4 | 5 | # 多平台软件 6 | 7 | ## 效率神器 uTools 8 | 9 | 1. 强大的插件化 10 | 2. 多功能输入框,支持文本、截图、图片、文件、文件夹 11 | 3. 自动识别 / 粘贴 12 | 4. 全局快捷键 13 | 5. 云端数据同步 14 | 6. 支持 Windows、Mac、Linux 15 | 16 | [软件官网](https://u.tools/) 17 | 18 | ## 下载神器 Motrix 19 | 20 | 1. 界面清爽简洁 21 | 2. 支持 BT 和磁力链任务 22 | 3. 支持选择性下载 BT 部分文件 23 | 4. 基于 Aria2 24 | 5. 自动更新 Tracker 服务器列表 25 | 26 | [Github](https://github.com/agalwood/Motrix) 27 | [软件官网](https://motrix.app/zh-CN) 28 | 29 | ## SwitchHosts 30 | 31 | Hosts 管理工具 32 | 33 | 1. Hosts 文件语法高亮 34 | 2. 快速切换 Hosts 35 | 3. 在线 Hosts 方案 36 | 4. 系统托盘图标快速切换 37 | 38 | [Github](https://github.com/oldj/SwitchHosts) 39 | 40 | ## QtScrcpy 41 | 42 | 通过 USB 或 TCP/IP 连接 Android 设备,并进行显示和控制 43 | 44 | 1. 不需要 root 权限 45 | 2. 最多支持 16 个安卓设备同时连接 46 | 3. 支持自定义按键映射 47 | 4. 可同时控制所有连接设备 48 | 49 | [Github](https://github.com/barry-ran/QtScrcpy) 50 | 51 | ## 图床工具 PicGo 52 | 53 | 一个用于快速上传图片并获取图片 URL 链接的工具 54 | 55 | 1. 支持 GitHub、七牛云、腾讯云、又拍云、阿里云 OSS、SM.MS V2、Imgur 56 | 2. 支持拖拽图片上传 57 | 3. 支持快捷键上传剪贴板里第一张图片 58 | 4. 支持右键图片文件通过菜单上传 59 | 5. 支持自定义复制到剪贴板的链接格式、 60 | 6. 丰富的[插件系统](https://github.com/PicGo/Awesome-PicGo) 61 | 62 | [Github](https://github.com/Molunerfinn/PicGo) 63 | [软件官网](https://molunerfinn.com/PicGo/) 64 | 65 | ## Sourcetree 66 | 67 | 1. 界面简洁、美观 68 | 2. 简化 Git 日常操作,对新人友好易上手 69 | 3. 支持 Git 工作流,规范开发流程 70 | 4. 支持 Git 和 Mercurial 两种 VCS 71 | 5. 支持自定义脚本执行 72 | 73 | ### 性能优化设置 74 | 75 | 1. 打开 `设置 => Diff` 76 | 2. 在 `忽略文件模式` 中添加 `package-lock.json, yarn.lock` 77 | 78 | [软件官网](https://www.sourcetreeapp.com/) 79 | -------------------------------------------------------------------------------- /docs/tool/efficiency/software/images/instasll.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dselegent/dselegent-blog/39b171793b69ed8b3bc914bd88d42174e534fd3c/docs/tool/efficiency/software/images/instasll.jpg -------------------------------------------------------------------------------- /docs/tool/efficiency/software/webstorm.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: '茂茂的 WebStorm 配置,记录扩展插件、使用小技巧' 3 | --- 4 | 5 | # WebStorm 配置 6 | 7 | ## 获取许可证 8 | 9 | [使用开源项目免费申请 JetBrains 全家桶开源许可证](https://www.jetbrains.com/shop/eform/opensource) 10 | 11 | ## 汉化 12 | 13 | - 方案一 14 | - 进入 `文件 - 设置 - Plugins - Marketplace` 15 | - 搜索 `Chinese ​(Simplified)​ Language Pack EAP` 下载安装 16 | - 方案二 17 | - 打开 [Chinese ​(Simplified)​ Language Pack EAP](https://plugins.jetbrains.com/plugin/13710-chinese-simplified-language-pack-eap) 18 | - 点击 `Install to IDE` 按钮再选择对应编辑器 19 | - 方案三 20 | - 查看本地 `WebStorm` 版本 21 | - 进入 `帮助 - 关于` 22 | - 找到 `Build #WS-` 后面的数字 23 | - 打开 [Chinese ​(Simplified)​ Language Pack EAP](https://plugins.jetbrains.com/plugin/13710-chinese-simplified-language-pack-eap) 24 | - 点击 `Versions` 选择对应编辑器再搜索对应版本下载(当找不到一样的版本时,可以看列表的第二栏版本范围,找包含你编辑器的版本下载就行) 25 | - 通过磁盘安装刚下载的文件 26 | 27 | ![磁盘安装](./images/instasll.jpg) 28 | 29 | ## 编辑器美化 30 | 31 | - 主题(进入 `文件 - 设置 - Plugins - Marketplace` 安装如下插件) 32 | - [Atom Material Icons](https://plugins.jetbrains.com/plugin/10044-atom-material-icons/) 图标美化 33 | - [Atom OneDark Theme](https://plugins.jetbrains.com/plugin/12178-atom-onedark-theme) Atom OneDark 主题 34 | - [Material Theme UI](https://plugins.jetbrains.com/plugin/8006-material-theme-ui) Material Design 主题 35 | - [One Dark theme](https://plugins.jetbrains.com/plugin/index?xmlId=com.markskelton.one-dark-theme) 黑色主题 36 | - 配色方案 37 | - [bluloco 方案](https://github.com/uloco/webstorm-bluloco-scheme) 38 | - [Dark 下载](https://cdn.jsdelivr.net/gh/uloco/webstorm-bluloco-scheme/Bluloco%20Dark.icls) 39 | - [Light 下载](https://cdn.jsdelivr.net/gh/uloco/webstorm-bluloco-scheme/Bluloco%20Light.icls) 40 | - 自定义背景图 41 | - 进入 `文件 - 设置 - 外观和行为 - Appearance` 42 | - 点击 `BACKGROUND IMAGE` 43 | - 其他 44 | - [.env files support](https://plugins.jetbrains.com/plugin/9525--env-files-support) `.env` 文件键值字符串高亮 45 | 46 | ## 插件市场 47 | 48 | - [官方](https://plugins.jetbrains.com/) 49 | 50 | ## 保存格式化 51 | 52 | 1. 进入 `文件 - 设置 - 工具 - File Watchers` 53 | 2. 点击 `+` 选择 `Prettier` 54 | 3. 将 `File type` 修改为你需要的文件类型,通用可选 `Any` 55 | 56 | ## webpack 项目识别 alias 57 | 58 | 1. 进入 `文件 - 设置 - 框架和语言 - JavaScript - Webpack` 59 | 2. 将 webpack 配置文件地址修改为对应地址 60 | 1. vue-cli2: 项目地址 + `\build\webpack.base.conf.js` 61 | 2. vue-cli3: 项目地址 + `\node_modules\@vue\cli-service\webpack.config.js` 62 | -------------------------------------------------------------------------------- /docs/tool/efficiency/software/windows.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: '收录 Windows 平台下的实用软件,提升使用体验' 3 | --- 4 | 5 | # Windows 平台 6 | 7 | ## 终端神器 Cmder 8 | 9 | 1. 便携,解压即可用 10 | 2. 支持子窗口 11 | 3. 自带 `git`、`ls` 等命令 12 | 4. 自定义配置项 13 | 14 | [Github](https://github.com/cmderdev/cmder) 15 | [软件官网](https://cmder.net/) 16 | 17 | ## 搜索神器 Everything 18 | 19 | 1. Windows 平台最快的文件搜索软件 20 | 2. 支持整词、路经匹配搜索 21 | 3. 支持正则表达式搜索 22 | 23 | [软件官网](https://www.voidtools.com/zh-cn/) 24 | 25 | ## 效率神器 Wox 26 | 27 | 1. 可以搜索安装的程序,支持中文拼音模糊搜索 28 | 2. 搜索浏览器书签 29 | 3. 可以调用 Everything 进行快速全局搜索 30 | 4. 网页搜索功能 31 | 5. 支持插件扩展 32 | 6. 支持自定义主题 33 | 34 | [Github](https://github.com/Wox-launcher/Wox) 35 | [软件官网](https://wox.one/) 36 | 37 | ## 视频播放神器 PotPlayer 38 | 39 | 1. 界面简洁,可自定义皮肤 40 | 2. 功能强大,设置以播放体验为中心 41 | 3. 纯粹的本地播放器 42 | 4. 视频/音频格式支持非常全面 43 | 44 | [软件官网](https://potplayer.daum.net/?lang=zh_CN) 45 | [最新版直链下载](https://t1.daumcdn.net/potplayer/PotPlayer/Version/Latest/PotPlayerSetup64.exe) 46 | 47 | ## 压缩/解压神器 bandizip 48 | 49 | 1. 界面简洁、清新 50 | 2. 集 压缩/解压/浏览/编辑 为一体 51 | 3. 支持处理乱码 52 | 4. 支持通过对文件完整性的检查来判断压缩包是否受损 53 | 54 | - 最新版存在广告,需要无广告的可下载 [6.x 版本](https://cn.bandisoft.com/bandizip/old/6/) 55 | 56 | [软件官网](https://www.bandisoft.com/bandizip/) 57 | 58 | ## 音量管理神器 EarTrumpet 59 | 60 | 1. 基于 Microsoft Store 托管的 UWP 应用程序,可自动更新,性能影响小 61 | 2. 默认播放设备管理 62 | 3. 支持明 / 暗模式和所有强调色 63 | 4. 支持快捷键设置 64 | 5. 在播放设备之间移动应用 65 | 66 | [Github](https://github.com/File-New-Project/EarTrumpet) 67 | [Microsoft Store](https://www.microsoft.com/en-us/p/eartrumpet/9nblggh516xp) 68 | 69 | ## 看图神器 Honeyview 70 | 71 | 1. 支持众多图片格式,如 PSD 文件预览 72 | 2. 对图像格式进行批量转换和调整 73 | 3. 可以显示包括 GPS 信息在内的 JPEG 格式的 EXIF 信息 74 | 75 | [软件官网](https://www.bandisoft.com/honeyview) 76 | 77 | ## 壁纸神器 Wallpaper Engine 78 | 79 | 1. 内存占用低 80 | 2. 支持视频、网页、2D、3D、GIF 等类型壁纸 81 | 3. 强大的创意工坊拥有海量壁纸可供选择 82 | 83 | [Steam 商店地址](https://store.steampowered.com/app/431960/Wallpaper_Engine/) 84 | [创意工坊](https://steamcommunity.com/app/431960/workshop/) 85 | 86 | ## 系统优化工具 Dism++ 87 | 88 | 1. 基于 Windows 系统原生功能 Dism 开发的增强工具 89 | 2. 体积小,解压即用,方便快捷 90 | 3. 集成空间清理、系统管理/优化、热备份还原等功能于一体 91 | 92 | [Github](https://github.com/Chuyu-Team/Dism-Multi-language) 93 | [软件官网](https://www.chuyu.me/zh-Hans/index.html) 94 | 95 | ## 隐私优化 WPD 96 | 97 | 1. 隐私管理 98 | 2. 预装应用卸载 99 | 3. 绿色免费、支持中文 100 | 101 | [软件官网](https://wpd.app) 102 | 103 | ## 防撤回补丁 104 | 105 | 1. 支持微信/QQ/TIM 防撤回 106 | 2. 支持微信多开 107 | 108 | [Github](https://github.com/huiyadanli/RevokeMsgPatcher) 109 | 110 | ## 任务栏透明 TranslucentTB 111 | 112 | 1. 支持亚克力、模糊、透明、主题色、不透明效果 113 | 2. 支持自定义颜色 114 | 3. 只支持 Windows 10 115 | 116 | [Github](https://github.com/TranslucentTB/TranslucentTB) 117 | [Microsoft Store](https://www.microsoft.com/zh-cn/p/translucenttb/9pf4kz2vn4w9) 118 | [Microsoft Store 汉化版](https://www.microsoft.com/zh-cn/p/translucenttb-%E6%B1%89%E5%8C%96-by-tpxxn/9n5w18jc9bg2) 119 | 120 | ## 查重神器 Duplicate Cleaner 121 | 122 | 1. 快速查找重复文件、支持多目录 123 | 2. 灵活的搜索设置 124 | 3. 在详细列表中查看所有文件信息 125 | 4. 删除重复文件至回收站 126 | 5. 移动重复文件到新位置 127 | 128 | [软件官网](https://www.duplicatecleaner.com) 129 | [绿色汉化版](https://www.52pojie.cn/forum.php?mod=viewthread&tid=1224420) 130 | 131 | ## 电子书格式转换器 NeatConverter 132 | 133 | 1. 完全免费,简单易用 134 | 2. 支持 ePub、Azw3、Mobi、Doc、PDF、TXT 文件的互转 135 | 136 | [软件官网](https://www.neat-reader.cn/downloads/converter) 137 | 138 | ## 系统增强工具 PowerToys 139 | 140 | - [Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) 颜色选择器 141 | 142 | - 默认启动快捷键: `Win` + `Shift` + `C` 143 | 144 | - [FancyZones](https://aka.ms/PowerToysOverview_FancyZones) 窗口管理器 145 | 146 | - 自定义窗口布局 147 | - 默认启动快捷键: `Win` + `~` 148 | 149 | - [File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) 文件资源管理器 150 | 151 | - 快速预览 SVG 和 Markdown 文件 152 | 153 | - [Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) 图像大小调整器 154 | 155 | - 修改图片大小、旋转方向、图片格式 156 | - 支持批量修改 157 | 158 | - [Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) 键盘管理器 159 | 160 | - 修改键位映射 161 | 162 | - [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) 批量重命名工具 163 | 164 | - 添加文件名前缀、后缀 165 | - 支持搜索、替换、正则表达式匹配 166 | - 排除指定的文件、文件夹 167 | - 预览重命名结果 168 | 169 | - [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) 快速启动程序 170 | - 搜索应用程序、文件夹或文件 171 | - 使用计算器执行简单计算 172 | - 默认启动快捷键: `Alt` + `Space` 173 | 174 | [Github](https://github.com/microsoft/PowerToys) 175 | [安装文档](https://docs.microsoft.com/zh-cn/windows/powertoys/install) 176 | 177 | ## 网速监控悬浮窗 TrafficMonitor 178 | 179 | 1. 显示当前实现网络传输速率、CPU 和内存占用率 180 | 2. 支持嵌入到任务栏显示 181 | 3. 支持更换皮肤和自定义皮肤 182 | 4. 历史流量统计 183 | 184 | [Github](https://github.com/zhongyang219/TrafficMonitor) 185 | 186 | ## GIF 录制神器 ScreenToGif 187 | 188 | 1. 支持屏幕、摄像头、画板录制 189 | 2. 可对 Gif 进行压缩、裁剪、涂鸦、模糊、添加字幕、添加水印、添加进度条等操作 190 | 3. 免费无广告支持免安装使用 191 | 192 | [Github](https://github.com/NickeManarin/ScreenToGif) 193 | [软件官网](https://www.screentogif.com/) 194 | 195 | ## 按键精灵 KeymouseGo 196 | 197 | 录制鼠标键盘操作进行自动化操作 198 | 199 | [Github](https://github.com/taojy123/KeymouseGo) 200 | 201 | ## 截图神器 Snipaste 202 | 203 | 1. 免费、无广告 204 | 2. 自动检测界面元素区域、像素级的鼠标移动控制、截图范围控制、截图历史记录回放 205 | 3. 标注(矩形、椭圆、线条、箭头、铅笔、马克笔、文字、马赛克、高斯模糊等) 206 | 4. 支持剪贴板中的图像、纯文本、HTML 文本、颜色信息、图像文件转化成图片 207 | 5. 贴图、取色 208 | 6. 支持自定义设置 209 | 210 | [软件官网](https://zh.snipaste.com/) 211 | [使用文档](https://docs.snipaste.com/zh-cn/getting-started) 212 | 213 | ## 卸载神器 HiBit Uninstaller 214 | 215 | 1. 强制卸载、批量卸载 216 | 2. 安全的清理注册表和垃圾文件 217 | 3. 快捷方式修复 218 | 4. 空文件夹删除 219 | 5. 系统更新补丁管理 220 | 221 | [软件官网](https://www.hibitsoft.ir/Uninstaller.html) 222 | 223 | ## 硬盘分析工具 WizTree 224 | 225 | 1. 分析速度极快 226 | 2. 可视化显示空间占用 227 | 3. 支持数据导出 228 | 4. 免费无广告支持免安装使用 229 | 230 | [软件官网](https://www.diskanalyzer.com) 231 | -------------------------------------------------------------------------------- /docs/tool/git/01.md: -------------------------------------------------------------------------------- 1 | # 01 【版本控制和Git的安装介绍】 2 | 3 | 工程设计领域中,使用“版本控制”管理工程蓝图的设计过程。在 IT 开发中也可以使用版本控制思想管理代码的版本迭代。 4 | 5 | ## 1.目的 6 | 7 | 协同修改:支持在服务器对同一个文件多人协同地修改; 8 | 数据备份:同时保存目录及文件的当前状态与每次提交时的历史状态; 9 | 版本管理:不保存版本间的重复数据以节约存储空间; 10 | 11 | > 为此,SVN 和 Git 分别采用增量式管理 和文件系统快照 的方式。 12 | 13 | 权限控制:对团队协作者进行权限控制(SVN 和 Git 共有);审核团队外开发者贡献的代码(Git 独有); 14 | 历史记录:查看修改者、修改时间、修改内容、日志信息等项目;将本地文件恢复到某一指定的历史状态; 15 | 分支管理:允许开发团队同时优雅地推进多条生产线任务,提高效率。 16 | 17 | ## 2. 工具 18 | 19 | 版本控制工具是版本控制思想的实现。 20 | 21 | ### 2.1 集中式版本控制工具 22 | 23 | 如:CVS、SVN、VSS 等。 24 | 25 | - 仅云端库有版本历史记录,本地库仅有最新的版本; 26 | - 无法完全避免单点故障的问题。 27 | 28 | > 单点故障:一个主机连接多个处理节点,主节点负责分发任务,而子节点负责处理业务,当主节点发生故障时,会导致整个系统发故障。 29 | 30 | ![image-20220827211244519](https://i0.hdslb.com/bfs/album/7b0bdd27704c333af32efeced9bcb98f2ed3b889.png) 31 | 32 | ![image-20220827211204909](https://i0.hdslb.com/bfs/album/0f5f0cd17c6e8a48f0ff991aa7bc64ea0211f6c6.png) 33 | 34 | ### 2.2 分布式版本控制工具 35 | 36 | 如:Git、Mercurial、Bazaar、Darcs 等。 37 | 38 | - 云端库和本地库都会为各个版本历史记录存档; 39 | - 从根本上避免了单点故障。 40 | 41 | ![image-20220827211230657](https://i0.hdslb.com/bfs/album/9fceda60db8eceea9503ea8b0ff6a35fd0970a97.png) 42 | 43 | ## 3.Git 简介 44 | 45 | ### 3.2 Git:分布式版本控制系统 46 | 47 | Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。既然每个人的电脑都有一个完整的版本库,那多个人如何协作呢?比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。 48 | 49 | 下图就是分布式版本控制工具管理方式: 50 | 51 | ![image-20221006131925125](https://i0.hdslb.com/bfs/album/33e8eb98bed3beea624278acba725b3d6c9889b1.png) 52 | 53 | 仓库(版本库):相当于一个专门用来存放代码的目录。这个目录里面的所有文件都可以Git管理,每个文件的增删改查都能被Git跟踪到 54 | 55 | ### 3.2 发展史 56 | 57 | ![image-20220827211720552](https://i0.hdslb.com/bfs/album/f90f771ae3d0f2c874feae9418df19974c4424bf.png) 58 | 59 | ### 3.3 优势 60 | 61 | - 大部分操作在本地完成,不需要联网; 62 | - 完整性保证; 63 | - 尽可能添加数据,而不是删除或修改数据; 64 | - 分支操作非常快捷流畅; 65 | - 与 Linux 命令全面兼容。 66 | 67 | ## 4.Git 软件的安装 68 | 69 | 从 https://git-scm.com/downloads 下载对应操作系统的二进制可执行文件。 70 | 71 | > 直接下一步的过程就不介绍了 72 | 73 | 1.安装到无空格的英文路径下(这是软件安装过程中的规范,防止因程序的不健壮而引发未知错误); 74 | 75 | ![image-20220827211905363](https://i0.hdslb.com/bfs/album/4e00c1fac6315adf8f38f0d996d4a91d92c8a1b5.png) 76 | 77 | 2.选择需要安装的组件; 78 | 79 | ![image-20220827211916721](https://i0.hdslb.com/bfs/album/682ee9b628eae1dd15042730df38fb75cea0a951.png) 80 | 81 | 3.选择 [Visual Studio Code](https://code.visualstudio.com/) 用于 Git 的默认文本编辑器; 82 | 83 | ![image-20220827212000737](https://i0.hdslb.com/bfs/album/c519001a28231c5941aad78f7f4b89bbca08ed1a.png) 84 | 85 | 4.设置在执行`git init`命令后,由 Git 自行定义新存储库的初始分支名称——`master`; 86 | 87 | ![image-20220827212024257](https://i0.hdslb.com/bfs/album/703320786d402e2f5e32a844b644343d834fd6b4.png) 88 | 89 | 5.设置PATH环境变量——保持默认; 90 | 91 | ![image-20220827212111362](https://i0.hdslb.com/bfs/album/01aec4a2ff2caef58f88b6c7fbbd22a4c11fa848.png) 92 | 93 | 6.选用内置的 OpenSSH 作为 SSH 可执行文件; 94 | 95 | ![image-20220827212130586](https://i0.hdslb.com/bfs/album/02727881e69d9626d359a0e5b3861cc5ff56e063.png) 96 | 97 | 7.选择 OpenSSL 库作为 HTTPS 传输端; 98 | 99 | ![image-20220827212142376](https://i0.hdslb.com/bfs/album/8435ebc111356ab3be7bc4d83e76621befd337ce.png) 100 | 101 | 8.使用默认配置转换文本文件中的行尾; 102 | 103 | ![image-20220827212154165](https://i0.hdslb.com/bfs/album/b6a3afb46bc1a7a04d50580c67de349149a30bfd.png) 104 | 105 | 9.使用默认配置,选用 MinTTY 作为 Git Bash 的终端; 106 | 107 | ![image-20220827212206242](https://i0.hdslb.com/bfs/album/d20c764070c38076bfd48dcddc3cf07f559b1c4f.png) 108 | 109 | 10.对于执行git pull命令后的行为保持默认; 110 | 111 | ![image-20220827212223848](https://i0.hdslb.com/bfs/album/4d6fe391e7919077107073080c80764b2fd67497.png) 112 | 113 | 11.选用默认的授权助手; 114 | 115 | ![image-20220827212233762](https://i0.hdslb.com/bfs/album/b434fe096bc937099a157a40e25296232804f0d0.png) 116 | 117 | 12.其他杂项设置; 118 | 119 | ![image-20220827212247326](https://i0.hdslb.com/bfs/album/c0b932915cc0d02c04a8ca63de4f179e70829351.png) 120 | 121 | 13.保持对实验性选项的禁用后安装 (Install); 122 | 123 | ![image-20220827212312589](https://i0.hdslb.com/bfs/album/14eb73fb460fd69bd4381c57ccde48daa9c650cd.png) -------------------------------------------------------------------------------- /docs/tool/git/04.md: -------------------------------------------------------------------------------- 1 | # 04 【忽略某些文件】 2 | 3 | 在push给远程仓库时需要忽略某些文件时,需要在本地仓库新建`.gitignore`的文件,注意在windows下无法直接创建该文件,只能通过`Git Bash`来`touch .gitignore `来生`gitignore`文件 4 | 5 | 然后在`.gitignore`中书写规则如下: 6 | 7 | 常见规则写法 8 | 9 | ```markdown 10 | /mtk/ 过滤整个文件夹 11 | 12 | *.zip 过滤所有.zip文件 13 | 14 | /mtk/do.java 过滤某个具体文件 15 | 16 | !do.java 不过滤某个文件 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /docs/web/Comments.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | title: 评论插件 4 | icon: comment 5 | order: 3 6 | --- 7 | 8 | LearnData 使用的是 Waline 评论插件,部署简单,有后端管理。评论插件推荐次序为 Waline > Valine > giscus > Gitalk > Gitter。 9 | 10 | ## 评论插件 11 | 12 | - [Waline](https://waline.js.org/guide/get-started.html):基于 Valine 衍生的简洁、安全的评论系统,部署到 Vercel,可匿名互动,导出评论内容,支持文章表情互动。 13 | - [Valine](https://github.com/xCss/Valine):快速、简洁且高效的无后端评论系统,可匿名互动。 14 | - [giscus](https://github.com/giscus/giscus):基于 github discussion,近似于论坛。查看 [配置方法](https://blog.csdn.net/duninet/article/details/125280107)。 15 | - [Gitalk](https://github.com/gitalk/gitalk):基于 github commit,需配置独立库用于存储评论。 16 | - [Gitter](https://gitter.im/):要登录的公共聊天室。样例如:[boardgame](https://boardgame.io/documentation/#/),[regauge](https://itchef.github.io/regauge/#/)。 17 | 18 | ## Waline 19 | 20 | Waline 支持 Akismet 反垃圾评论和免注册留言,不过匿名留言会带来安全隐患,建议开启评论通知,避免极端情况。Waline 的评论通知支持多种方式,包括 QQ、微信、邮件等,回复评论作者仅支持邮件通知。 21 | 22 | Vercel 项目中选择「Overview」>「Settings」>「Environment Variables」,然后按照 [Waline 评论通知](https://waline.js.org/guide/server/notification.html)配置所需环境变量。如果需要 Webhook 等更多通知方式,则查看 [Waline 服务端配置](https://waline.js.org/reference/server.html)。配置成功后,选择「Overview」>「Deployments」,进行 Redeploy,重新部署后环境变量和评论通知方会生效。 23 | 24 | 目前 `*.vercel.app` 域名已经被 DNS 污染,会出现「无法加载评论」,国内使用建议绑定自定义域名,域名对备案暂无硬性要求。 25 | 26 | ## Gitalk 27 | 28 | Gitalk 是轻量化的评论组件,用户必须登录 github 才能评论,适合项目类使用。 29 | 30 | `https://github.com/settings/developers` 页面管理已建的应用,获取 Client ID 和 Client secrets,修改应用链接。^[[超 Nice 的评论组件 —— Gitalk](https://blog.csdn.net/qq_39052513/article/details/108291272)] 31 | 32 | 将以下代码放入 docsify 页面中,即可启动 Gitalk: 33 | 34 | ```HTML 35 | 36 | 37 | 38 | 39 | 51 | ``` 52 | 53 | Gitalk 缺点: 54 | 55 | - 每次有新页面时,都需要登录 github 初始化评论区。 56 | - 域名不能改变,Homepage URL 和 Authorization callback URL 需与你的 Gitalk 页面一致,否则页面会报错,提示初始化,无法登录 github。 57 | -------------------------------------------------------------------------------- /docs/web/docsify.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | title: docsify 4 | icon: edit 5 | order: 2 6 | --- 7 | 8 | [docsify](https://docsify.js.org/#/zh-cn/) 是一个神奇的文档网站生成器,可以快速帮你将 .md 文档生成为网站。docsify 入门简单且无需服务器,非常适合个人笔记的简单整理分享。 9 | 10 | 本页集中了我使用 docsify 中遇到的问题,新手先看 [docsify 入门文档](https://docsify.js.org/#/zh-cn/)。 11 | 12 | ## 插件 13 | 14 | [docsify 插件列表](https://github.com/docsifyjs/awesome-docsify#plugins): 15 | 16 | - [x] [docsify 笔记类参考](https://notebook.js.org/#/README):看板娘,多级页面,页面点击效果,网站运行时间。 17 | - [x] [docsify-count](https://github.com/827652549/docsify-count):docsify 的字数和阅读时长插件。 18 | - [x] [docsify-waline](https://github.com/cxcn/docsify-waline/blob/main/README.zh-CN.md):提供评论功能的同时,借用 docsify-count 接口展示阅读量。暂时停止 1300 宽度的 waline 显示,避免页面显示异常。 19 | - [x] [docsify-toc](https://github.com/mrpotatoes/docsify-toc):给笔记页内部添加目录。不过本插件与 gitalk、waline 冲突,页面宽于 1300px 时出现 toc 目录,评论区位置也跟着挤到页面顶部,需手动修改。参考链接:[Tainacan Wiki](https://tainacan.github.io/tainacan-wiki/#/general-concepts),[Sureness](https://github.com/dromara/sureness/blob/master/docs/index.html),[lifeupapp](https://wiki.lifeupapp.fun/zh-cn/#/features/174)。 20 | - [x] [docsify-pdf-converter](https://github.com/meff34/docsify-to-pdf-converter):将 docsify 转为 pdf,不带书签目录。 21 | - `illegal operation on a directory` 报错:sidebar 中不要使用简写地址,将 `main/` 改为 `main/README.md`,否则将读取到目录而报错。 22 | - `'node_modules' 不是内部或外部命令` 报错:将 package.json 的设置修改为 `"convert": "node_modules\\.bin\\docsify-pdf-converter"`。这问题多发生在 Windows,是由 Windows 与 Linux 路径规则不同而引起的。 23 | 24 | ## 配置 25 | 26 | ### docsify emoji 27 | 28 | [emoji 插件](https://docsify.js.org/#/zh-cn/plugins?id=emoji)在标题中使用容易出错,建议使用 `:`。例如,原本是 `:100:`,替换为 `:100:`。 29 | 30 | 实际使用中,我直接复制 emoji,都能正常显示。 31 | 32 | ## 本地命令 33 | 34 | [docsify 本地命令](https://github.com/docsifyjs/docsify-cli): 35 | 36 | `` 默认为当前路径,可使用子文件夹指定路径,如 `./docs` 或 `docs`。 37 | 38 | `[]` 为可省略命令区,无实际作用,输出时需要去除。 39 | 40 | ### Serve 启动 41 | 42 | 若要在电脑上查看 docsify 页面,可执行 serve 架构命令,在本地主机上运行服务。默认本地端口为 3000,可以指定端口。 43 | 44 | ```shell 45 | docsify serve [--open false] [--port 3000] 46 | ``` 47 | 48 | 使用时不要关闭命令终端,否则 serve 也会停止。 49 | 50 | ### 生成侧边栏 51 | 52 | ```shell 53 | docsify generate [--sidebar _sidebar.md] 54 | ``` 55 | 56 | generate 命令会遍历指定目录及其子目录的所有 markdown 文件,并生成全路径的 \_sidebar.md。`` 不能省略,需指定子文件夹路径。 57 | 58 | 如果路径中存在 \_sidebar.md,则会报错。 59 | 60 | ## 常见问题 61 | 62 | ### 引用路径 63 | 64 | docsify 引用内部文件时,路径会自带添加域名。 65 | 66 | 例如:指向子文档时,链接是 `子文件夹/文档名.md`;指向子文档的小标题时,链接是 `子文件夹/文档名?id=小标题`。 67 | 68 | ### 页面未同步更新 69 | 70 | > CDN 默认是有缓存的,如果文件更新,访问的可能不是最新的文件。 71 | > 72 | > 我设置了 routerMode 为 history,使用 CDN 访问非首页,再次刷新会找不到文件。 73 | > 74 | > 如果开启了 `relativePath: true`,文件可以找到,但是侧栏上边的标题点击又有点问题。 75 | 76 | ### GitHub Pages 报错 77 | 78 | 如果 SSL 链接 404 报错,显示「There isn't a GitHub Pages site here」,则目录中加入 `CNAME` 文件。 79 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learn-data", 3 | "version": "1.1.9", 4 | "license": "MIT", 5 | "scripts": { 6 | "docs:dev": "vuepress dev docs", 7 | "dev": "vuepress dev docs", 8 | "docs:build": "vuepress build docs", 9 | "docs:clean-dev": "vuepress dev docs --clean-cache" 10 | }, 11 | "dependencies": { 12 | "@vuepress/client": "2.0.0-beta.62", 13 | "@vuepress/plugin-google-analytics": "2.0.0-beta.62", 14 | "@vuepress/utils": "2.0.0-beta.62", 15 | "vue": "^3.2.45", 16 | "vuepress": "2.0.0-beta.62", 17 | "vuepress-theme-hope": "2.0.0-beta.216" 18 | }, 19 | "devDependencies": { 20 | "@commitlint/cli": "^17.4.2", 21 | "@commitlint/config-conventional": "^17.4.2", 22 | "@vuepress/plugin-docsearch": "2.0.0-beta.62", 23 | "husky": "^8.0.3", 24 | "vuepress-plugin-sitemap2": "2.0.0-beta.216" 25 | } 26 | } 27 | --------------------------------------------------------------------------------