├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ └── feature_request.md ├── .gitignore ├── .npmrc ├── .travis.yml ├── README.md ├── build ├── addComment.js ├── delComment.js └── findMarkdown.js ├── config.js ├── docs ├── .vuepress │ ├── components │ │ ├── demos │ │ │ ├── ex.vue │ │ │ ├── line-height.vue │ │ │ ├── line-height2.vue │ │ │ └── trafficLight.vue │ │ ├── images │ │ │ └── arrow-down.png │ │ ├── odometer │ │ │ └── demo1.vue │ │ └── svg │ │ │ ├── animate1.vue │ │ │ ├── animate2.vue │ │ │ ├── animate3.vue │ │ │ ├── bse1.vue │ │ │ ├── bse2.vue │ │ │ ├── bse3.vue │ │ │ ├── bse4.vue │ │ │ ├── circle1.vue │ │ │ ├── defs1.vue │ │ │ ├── filter1.vue │ │ │ ├── g1.vue │ │ │ ├── line1.vue │ │ │ ├── line2.vue │ │ │ ├── lineargradient1.vue │ │ │ ├── polygon1.vue │ │ │ ├── polyline1.vue │ │ │ ├── preserveAspectRatio.vue │ │ │ ├── radialGradient1.vue │ │ │ ├── rect1.vue │ │ │ ├── rect2.vue │ │ │ ├── rect3.vue │ │ │ ├── rect4.vue │ │ │ ├── stroke1.vue │ │ │ ├── stroke2.vue │ │ │ ├── stroke3.vue │ │ │ ├── stroke4.vue │ │ │ ├── tcircle1.vue │ │ │ ├── text1.vue │ │ │ ├── text2.vue │ │ │ ├── text3.vue │ │ │ ├── text4.vue │ │ │ ├── text5.vue │ │ │ └── viewbox1.vue │ ├── config.js │ ├── enhanceApp.js │ ├── plugins │ │ ├── comment │ │ │ ├── comment.vue │ │ │ ├── enhanceAppFile.js │ │ │ ├── index.js │ │ │ └── initComment.js │ │ └── copy │ │ │ ├── copy.vue │ │ │ ├── enhanceAppFile.js │ │ │ └── index.js │ ├── public │ │ ├── images │ │ │ └── favicon.png │ │ └── styles │ │ │ ├── basic.scss │ │ │ ├── element-variables.scss │ │ │ ├── overide.scss │ │ │ └── reset.css │ ├── styles │ │ └── palette.styl │ └── theme │ │ ├── LICENSE │ │ ├── components │ │ ├── AlgoliaSearchBox.vue │ │ ├── DropdownLink.vue │ │ ├── DropdownTransition.vue │ │ ├── Home.vue │ │ ├── NavLink.vue │ │ ├── NavLinks.vue │ │ ├── Navbar.vue │ │ ├── Page.vue │ │ ├── PageEdit.vue │ │ ├── PageNav.vue │ │ ├── Sidebar.vue │ │ ├── SidebarButton.vue │ │ ├── SidebarGroup.vue │ │ ├── SidebarLink.vue │ │ ├── SidebarLinks.vue │ │ └── Statistic.vue │ │ ├── global-components │ │ └── Badge.vue │ │ ├── index.js │ │ ├── layouts │ │ ├── 404.vue │ │ └── Layout.vue │ │ ├── noopModule.js │ │ ├── styles │ │ ├── arrow.styl │ │ ├── code.styl │ │ ├── config.styl │ │ ├── custom-blocks.styl │ │ ├── index.styl │ │ ├── mobile.styl │ │ ├── toc.styl │ │ └── wrapper.styl │ │ └── util │ │ ├── index.js │ │ └── mo.min.js ├── README.md ├── algorithm │ └── cacheLRU.md ├── bff │ └── README.md ├── bom │ └── README.md ├── browser │ ├── cors.md │ ├── extension.md │ └── knowledge.md ├── css │ ├── animate.md │ ├── base.md │ ├── display.md │ ├── fix.md │ ├── higher.md │ ├── img.md │ └── interview.md ├── dom │ └── README.md ├── electron │ ├── build.md │ └── update.md ├── es │ └── README.md ├── extend │ └── number.md ├── git │ ├── base.md │ ├── list.md │ ├── rebase.md │ └── standant.md ├── http │ └── README.md ├── im │ ├── base.md │ └── tcent.md ├── javascript │ ├── ajax.md │ ├── array.md │ ├── assignment.md │ ├── asyncCatch.md │ ├── canvans.md │ ├── copy.md │ ├── cros.md │ ├── empty.md │ ├── env.md │ ├── eventloop.md │ ├── eventsEmitter.md │ ├── for-in.md │ ├── form.md │ ├── function.md │ ├── html5.md │ ├── improve.md │ ├── json.md │ ├── macro.md │ ├── math.md │ ├── noscript.md │ ├── not.md │ ├── null.md │ ├── number.md │ ├── object.md │ ├── oop.md │ ├── prototype.md │ ├── regexp.md │ ├── rubbish.md │ ├── script.md │ ├── scriptsort.md │ ├── strict.md │ ├── target.md │ ├── throtte.md │ ├── tostring.md │ ├── try-catch.md │ ├── type.md │ ├── typeChange.md │ ├── url.md │ ├── var.md │ ├── webgl.md │ └── with.md ├── javascriptHigh │ ├── createTypes.md │ ├── mutationObserver.md │ ├── queue.md │ └── tips.md ├── leetcode │ ├── addOfTwoNum.md │ ├── sameTree.md │ └── sumOfTwoNum.md ├── mobile │ ├── h5live.md │ ├── h5liveProblems.md │ ├── hybrid.md │ ├── live.md │ ├── meta.md │ ├── rtc.md │ ├── tips.md │ ├── videojs.md │ └── wxShare.md ├── mysql │ ├── base.md │ ├── delete.md │ ├── faq.md │ ├── insert.md │ ├── select.md │ └── update.md ├── nginx │ ├── base.md │ └── https.md ├── node │ ├── async.md │ ├── childProcess.md │ ├── egg.md │ ├── jwt.md │ ├── koaMiddleware.md │ ├── puppeteer.md │ ├── schedule.md │ ├── socket.md │ └── uploadQiNiu.md ├── open │ ├── deepClone.md │ ├── font.md │ ├── highList.md │ ├── module.md │ ├── pageVisualization.md │ ├── performance.md │ ├── px.md │ ├── rtv.md │ ├── semicolon.md │ └── system.md ├── project │ ├── autoTryCatch.md │ ├── autobuild.md │ ├── babel.md │ ├── docker.md │ ├── err.md │ ├── gitlabCI.md │ ├── immer.md │ ├── middleWare.md │ ├── mock.md │ ├── module.md │ ├── standards.md │ ├── vscode.md │ └── webpack.md ├── ps │ └── quick.md ├── python │ ├── autoRenameImgs.md │ ├── base.md │ ├── django.md │ ├── downloadImgs.md │ ├── jsonToCsv.md │ ├── numpy.md │ ├── os.md │ ├── pandas.md │ ├── pillow.md │ ├── pip.md │ ├── readPdf.md │ ├── selenium.md │ ├── tinyPng.md │ └── utils.md ├── react │ ├── aria.md │ ├── codesplit.md │ ├── com.md │ ├── component.md │ ├── componentWillUnMount.md │ ├── design.md │ ├── diff.md │ ├── dom.md │ ├── fiber.md │ ├── hoc.md │ ├── hooks.md │ ├── hooksRedux.md │ ├── jsx.md │ ├── key.md │ ├── lifestyle.md │ ├── mobx.md │ ├── optimization.md │ ├── plugin.md │ ├── portal.md │ ├── problems.md │ ├── recompose.md │ ├── redux.md │ ├── reduxSaga.md │ ├── ref.md │ ├── setState.md │ ├── syntheticEvent.md │ ├── upgrade.md │ └── webpack.md ├── redis │ ├── base.md │ ├── multy.md │ └── notification.md ├── safe │ ├── README.md │ ├── base.md │ ├── csrf.md │ ├── javascript.md │ └── xss.md ├── svg │ ├── animation.md │ ├── base.md │ ├── example.md │ ├── high.md │ └── path.md ├── tool │ ├── charles.md │ └── emoji.md ├── typescript │ ├── base.md │ ├── enum.md │ ├── expirence.md │ ├── fan.md │ ├── func.md │ ├── interface.md │ ├── prefer.md │ └── start.md ├── vue │ ├── lifestyle.md │ └── scoped.md └── wechat │ ├── h5share.md │ ├── miniprogram.md │ ├── miniprogramComponent.md │ ├── plugin.md │ └── vscode.md ├── index.js ├── package-lock.json ├── package.json ├── private-config.js └── yarn.lock /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.log 4 | .temp 5 | vuepress 6 | TODOs.md 7 | .idea 8 | .vscode 9 | dist 10 | ./private-config -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | sass_binary_site=https://npm.taobao.org/mirrors/node-sass/ 2 | registry=https://registry.npmjs.org -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - lts/* 4 | install: 5 | - npm ci # npm ci 6 | script: 7 | - npm run build # npm run build 8 | deploy: 9 | provider: pages 10 | skip_cleanup: true 11 | local_dir: dist 12 | github_token: $GITHUB_TOKEN 13 | keep_history: true 14 | on: 15 | branch: master -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 关于项目 2 | 3 | 此项目是使用VuePress搭建的一个博客类型的指南,记录了一些前后端相关的基础知识以及各类在世界项目中遇到的一些问题以及工作的一些总结。欢迎大家关注与star。 4 | 5 | 6 | ## 克隆 7 | git clone https://github.com/xjl271314/docs.git 8 | 9 | ## 安装 10 | npm install 或者 yarn install 11 | 12 | ## 启动 13 | npm run dev 14 | 15 | ## 打包 16 | npm run docs:build 17 | 18 | ## 直接访问 19 | 20 | https://xjl271314.github.io/docs/ 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /build/addComment.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const findMarkdown = require('./findMarkdown') 3 | const rootDir = './docs' 4 | 5 | findMarkdown(rootDir, writeComment) 6 | 7 | function writeComment(dir) { 8 | fs.appendFile(dir, `\n \n `, (err) => { 9 | if (err) throw err 10 | console.log(`add comment component to ${dir}`) 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /build/delComment.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const findMarkdown = require('./findMarkdown') 3 | const rootDir = './docs' 4 | 5 | findMarkdown(rootDir,delComment) 6 | 7 | // delComment('./docs/index.md') 8 | function delComment(dir){ 9 | fs.readFile(dir,'utf-8', (err, content) => { 10 | if (err) throw err 11 | 12 | fs.writeFile(dir, content.replace(/\n \n /g,''), (err) => { 13 | if (err) throw err 14 | console.log(`del comment component from ${dir}`) 15 | }) 16 | }) 17 | } -------------------------------------------------------------------------------- /build/findMarkdown.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | 3 | function findMarkdown(dir, callback) { 4 | fs.readdir(dir, function (err, files) { 5 | if (err) throw err 6 | 7 | files.forEach((fileName) => { 8 | let innerDir = `${dir}/${fileName}` 9 | 10 | if (fileName.indexOf('.') !== 0) { 11 | fs.stat(innerDir, function (err, stat) { 12 | 13 | if (stat.isDirectory()) { 14 | findMarkdown(innerDir, callback) 15 | } else { 16 | callback(innerDir) 17 | } 18 | }) 19 | } 20 | 21 | }) 22 | }) 23 | } 24 | 25 | module.exports = findMarkdown 26 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | const chalk = require("chalk"); 2 | const config = require('./private-config'); 3 | 4 | try{ 5 | console.log('config success!') 6 | } 7 | catch (e) { 8 | console.log(chalk.red('You are not owner of this project')); 9 | console.log(chalk.red('If you want use gitalk or google analysis,write configuration options in project-path/private-config.js ')); 10 | } 11 | 12 | module.exports = config; -------------------------------------------------------------------------------- /docs/.vuepress/components/demos/ex.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 显示全部内容 4 | 5 | 6 | 7 | 8 | 22 | 23 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/.vuepress/components/demos/line-height.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 我的line-height为0,font-size为18px; 4 | 我的line-height为18px,font-size为0; 5 | 6 | 7 | 8 | 33 | 34 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /docs/.vuepress/components/demos/line-height2.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 基于行高实现的内联元素垂直居中,需要使用 vertical-align 辅助实现。 5 | 6 | 7 | 8 | 9 | 23 | 24 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/.vuepress/components/demos/trafficLight.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 35 | 36 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/.vuepress/components/images/arrow-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjl271314/docs/8ed7561fb5da0d09ba64ea5192220987229b8dc4/docs/.vuepress/components/images/arrow-down.png -------------------------------------------------------------------------------- /docs/.vuepress/components/odometer/demo1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ defaultNum }} 4 | 5 | 点我更新 6 | 点我重置 7 | 8 | 9 | 10 | 11 | 19 | 46 | 47 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/animate1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 25 | 26 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/animate2.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 21 | 22 | 23 | 24 | 25 | 26 | 41 | 42 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/animate3.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | 36 | 37 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/bse1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 26 | 27 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/bse2.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 34 | 35 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/bse3.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 27 | 28 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/bse4.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 33 | 34 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/circle1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 17 | 18 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/defs1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 24 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/filter1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/g1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Audi 11 | 12 | 13 | 14 | 15 | 23 | 24 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/line1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 20 | 21 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/line2.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 20 | 21 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/lineargradient1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 26 | 27 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/polygon1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 23 | 24 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/polyline1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 21 | 22 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/preserveAspectRatio.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 无preserveAspectRatio 10 | 11 | 12 | 13 | meet 14 | 15 | 16 | 17 | slice 18 | 19 | 20 | 21 | none 22 | 23 | 24 | 25 | 26 | 27 | 41 | 42 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/radialGradient1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 24 | 25 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/rect1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/rect2.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 15 | 16 | 27 | 28 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/rect3.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 16 | 17 | 18 | 29 | 30 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/rect4.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 20 | 21 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/stroke1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/stroke2.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/stroke3.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/stroke4.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/tcircle1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 15 | 16 | 24 | 25 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/text1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | I am svg text 5 | 6 | 7 | 8 | 9 | 17 | 18 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/text2.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | I am transform svg text 5 | 6 | 7 | 8 | 9 | 17 | 18 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/text3.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | I am magic svg path text 9 | 10 | 11 | 12 | 13 | 14 | 22 | 23 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/text4.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Several lines: 6 | First line 7 | Second line 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/text5.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | I am superLink text 6 | 7 | 8 | 9 | 10 | 11 | 19 | 20 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/.vuepress/components/svg/viewbox1.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 点击下一步,显示viewBox区域 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 29 | 30 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /docs/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | import ElementUI from "element-ui"; 2 | // import ViLike from 'vilike'; 3 | // import Bmob from "hydrogen-js-sdk"; 4 | import "./public/styles/element-variables.scss"; 5 | import "./public/styles/overide.scss"; 6 | 7 | export default ({ 8 | Vue, // VuePress 正在使用的 Vue 构造函数 9 | options, // 附加到根实例的一些选项 10 | router, // 当前应用的路由实例 11 | siteData // 站点元数据 12 | }) => { 13 | Vue.use(ElementUI); 14 | // Vue.use(ViLike); 15 | // Vue.prototype.Bmob = Bmob; 16 | }; 17 | 18 | // 请自行修改相关配置信息 19 | // ViLike.configure({ 20 | // secretKey: 'cfba00864a7da46d', 21 | // safeKey: '331023', 22 | // table: 'statistic', 23 | // key: 'skey', 24 | // visit: 'visit', 25 | // like: 'like' 26 | // }); 27 | 28 | // // 初始化 29 | // ViLike.init(); 30 | 31 | -------------------------------------------------------------------------------- /docs/.vuepress/plugins/comment/enhanceAppFile.js: -------------------------------------------------------------------------------- 1 | import Comment from "./comment.vue"; 2 | export default ({ Vue }) => { 3 | Vue.component("Comment", Comment); 4 | }; -------------------------------------------------------------------------------- /docs/.vuepress/plugins/comment/index.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require("path"); 2 | module.exports = (options, ctx) => { 3 | return { 4 | enhanceAppFiles: resolve(__dirname, "enhanceAppFile.js"), 5 | globalUIComponents: "Comment" 6 | }; 7 | }; -------------------------------------------------------------------------------- /docs/.vuepress/plugins/comment/initComment.js: -------------------------------------------------------------------------------- 1 | const CONFIG = require("../../../../config.js"); 2 | 3 | export default function initComment() { 4 | const body = document.querySelector(".gitalk-container"); 5 | const script = document.createElement("script"); 6 | 7 | script.src = "https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"; 8 | body.appendChild(script); 9 | script.onload = () => { 10 | const commentConfig = Object.assign(CONFIG.gitalk, { 11 | // id: `/my-blogs${location.pathname}` 12 | }); 13 | console.log('commentConfig', commentConfig) 14 | const gitalk = new Gitalk(commentConfig); 15 | gitalk.render("gitalk-container"); 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /docs/.vuepress/plugins/copy/copy.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 24 | 25 | 103 | -------------------------------------------------------------------------------- /docs/.vuepress/plugins/copy/enhanceAppFile.js: -------------------------------------------------------------------------------- 1 | import Copy from "./copy.vue"; 2 | 3 | export default ({ Vue }) => { 4 | Vue.component("Copy", Copy); 5 | }; 6 | -------------------------------------------------------------------------------- /docs/.vuepress/plugins/copy/index.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require("path"); 2 | 3 | 4 | module.exports = { 5 | enhanceAppFiles: resolve(__dirname, "enhanceAppFile.js"), 6 | globalUIComponents: "Copy" 7 | }; 8 | -------------------------------------------------------------------------------- /docs/.vuepress/public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjl271314/docs/8ed7561fb5da0d09ba64ea5192220987229b8dc4/docs/.vuepress/public/images/favicon.png -------------------------------------------------------------------------------- /docs/.vuepress/public/styles/basic.scss: -------------------------------------------------------------------------------- 1 | $blue :#00adb5; 2 | $green:#3eaf7c; 3 | $red:#F56C6C; 4 | $black:#303133; 5 | $gray:#606266; 6 | $border:#DCDFE6; 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/.vuepress/public/styles/element-variables.scss: -------------------------------------------------------------------------------- 1 | $--color-primary: #00adb5; 2 | $--color-success: #67c23a !default; 3 | $--color-warning: #e6a23c !default; 4 | $--color-danger: #f56c6c !default; 5 | $--color-info: #909399 !default; 6 | 7 | $--font-path: '~element-ui/lib/theme-chalk/fonts'; 8 | 9 | @import "~element-ui/packages/theme-chalk/src/index"; 10 | -------------------------------------------------------------------------------- /docs/.vuepress/public/styles/overide.scss: -------------------------------------------------------------------------------- 1 | @media (max-width: 959px) { 2 | .global-ui { 3 | padding-left: 2rem; 4 | } 5 | } 6 | 7 | @media (max-width: 419px) { 8 | .global-ui { 9 | padding-left: 1.5rem; 10 | } 11 | } 12 | 13 | .page-edit{ 14 | display: flex; 15 | flex-direction: row; 16 | align-items: center; 17 | justify-content: space-between; 18 | } -------------------------------------------------------------------------------- /docs/.vuepress/public/styles/reset.css: -------------------------------------------------------------------------------- 1 | html,body,h1,h2,h3,h4,h5,h6,div,dl,dt,dd,ul,ol,li,p,blockquote,pre,hr,figure,table,caption,th,td,form,fieldset,legend,input,button,textarea,menu{margin:0;padding:0;} 2 | header,footer,section,article,aside,nav,hgroup,address,figure,figcaption,menu,details{display:block;} 3 | table{border-collapse:collapse;border-spacing:0;} 4 | caption,th{text-align:left;font-weight:normal;} 5 | html,body,fieldset,img,iframe,abbr{border:0;} 6 | i,cite,em,var,address,dfn{font-style:normal;} 7 | [hidefocus],summary{outline:0;} 8 | li{list-style:none;} 9 | h1,h2,h3,h4,h5,h6,small{font-size:100%;} 10 | sup,sub{font-size:83%;} 11 | pre,code,kbd,samp{font-family:inherit;} 12 | q:before,q:after{content:none;} 13 | textarea{overflow:auto;resize:none;} 14 | label,summary{cursor:default;} 15 | a,button{cursor:pointer;} 16 | h1,h2,h3,h4,h5,h6,em,strong,b{font-weight:bold;} 17 | del,ins,u,s,a,a:hover{text-decoration:none;} 18 | body,textarea,input,button,select,keygen,legend{font:12px/1.14 arial,\5b8b\4f53;color:#333;outline:0;} 19 | body{background:#fff;} 20 | a,a:hover{color:#333;} 21 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/palette.styl: -------------------------------------------------------------------------------- 1 | $accentColor = #00adb5 2 | $textColor = #222831 3 | $borderColor = #eeeeee 4 | $codeBgColor = #282c34 5 | 6 | // 修改2级目录透明度 7 | .sidebar-group.is-sub-group > .sidebar-heading:not(.clickable){ 8 | opacity :1 9 | } 10 | 11 | // 修改内容最大宽度 12 | .theme-default-content{ 13 | max-width: 1020px!important; 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/DropdownTransition.vue: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 28 | 29 | 34 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/NavLink.vue: -------------------------------------------------------------------------------- 1 | 2 | 9 | {{ item.text }} 10 | 11 | 19 | {{ item.text }} 20 | 21 | 22 | 23 | 24 | 88 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Page.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 23 | 24 | 32 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 27 | 28 | 65 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/SidebarButton.vue: -------------------------------------------------------------------------------- 1 | 2 | 6 | 13 | 18 | 19 | 20 | 21 | 22 | 41 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/SidebarLinks.vue: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 18 | 23 | 24 | 25 | 26 | 27 | 103 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/global-components/Badge.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | // Theme API. 4 | module.exports = (options, ctx) => { 5 | const { themeConfig, siteConfig } = ctx 6 | 7 | // resolve algolia 8 | const isAlgoliaSearch = ( 9 | themeConfig.algolia 10 | || Object 11 | .keys(siteConfig.locales && themeConfig.locales || {}) 12 | .some(base => themeConfig.locales[base].algolia) 13 | ) 14 | 15 | const enableSmoothScroll = themeConfig.smoothScroll === true 16 | 17 | return { 18 | alias () { 19 | return { 20 | '@AlgoliaSearchBox': isAlgoliaSearch 21 | ? path.resolve(__dirname, 'components/AlgoliaSearchBox.vue') 22 | : path.resolve(__dirname, 'noopModule.js') 23 | } 24 | }, 25 | 26 | plugins: [ 27 | ['@vuepress/active-header-links', options.activeHeaderLinks], 28 | '@vuepress/search', 29 | '@vuepress/plugin-nprogress', 30 | ['container', { 31 | type: 'tip', 32 | defaultTitle: { 33 | '/': 'TIP', 34 | '/zh/': '提示' 35 | } 36 | }], 37 | ['container', { 38 | type: 'warning', 39 | defaultTitle: { 40 | '/': 'WARNING', 41 | '/zh/': '注意' 42 | } 43 | }], 44 | ['container', { 45 | type: 'danger', 46 | defaultTitle: { 47 | '/': 'WARNING', 48 | '/zh/': '警告' 49 | } 50 | }], 51 | ['container', { 52 | type: 'details', 53 | before: info => `${info ? `${info}` : ''}\n`, 54 | after: () => '\n' 55 | }], 56 | ['smooth-scroll', enableSmoothScroll] 57 | ] 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/layouts/404.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 404 5 | 6 | {{ getMsg() }} 7 | 8 | 9 | Take me home. 10 | 11 | 12 | 13 | 14 | 15 | 31 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/noopModule.js: -------------------------------------------------------------------------------- 1 | export default {} 2 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/arrow.styl: -------------------------------------------------------------------------------- 1 | @require './config' 2 | 3 | .arrow 4 | display inline-block 5 | width 0 6 | height 0 7 | &.up 8 | border-left 4px solid transparent 9 | border-right 4px solid transparent 10 | border-bottom 6px solid $arrowBgColor 11 | &.down 12 | border-left 4px solid transparent 13 | border-right 4px solid transparent 14 | border-top 6px solid $arrowBgColor 15 | &.right 16 | border-top 4px solid transparent 17 | border-bottom 4px solid transparent 18 | border-left 6px solid $arrowBgColor 19 | &.left 20 | border-top 4px solid transparent 21 | border-bottom 4px solid transparent 22 | border-right 6px solid $arrowBgColor 23 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/config.styl: -------------------------------------------------------------------------------- 1 | $contentClass = '.theme-default-content' 2 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/custom-blocks.styl: -------------------------------------------------------------------------------- 1 | .custom-block 2 | .custom-block-title 3 | font-weight 600 4 | margin-bottom -0.4rem 5 | &.tip, &.warning, &.danger 6 | padding .1rem 1.5rem 7 | border-left-width .5rem 8 | border-left-style solid 9 | margin 1rem 0 10 | &.tip 11 | background-color #f3f5f7 12 | border-color #42b983 13 | &.warning 14 | background-color rgba(255,229,100,.3) 15 | border-color darken(#ffe564, 35%) 16 | color darken(#ffe564, 70%) 17 | .custom-block-title 18 | color darken(#ffe564, 50%) 19 | a 20 | color $textColor 21 | &.danger 22 | background-color #ffe6e6 23 | border-color darken(red, 20%) 24 | color darken(red, 70%) 25 | .custom-block-title 26 | color darken(red, 40%) 27 | a 28 | color $textColor 29 | &.details 30 | display block 31 | position relative 32 | border-radius 2px 33 | margin 1.6em 0 34 | padding 1.6em 35 | background-color #eee 36 | h4 37 | margin-top 0 38 | figure, p 39 | &:last-child 40 | margin-bottom 0 41 | padding-bottom 0 42 | summary 43 | outline none 44 | cursor pointer 45 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/mobile.styl: -------------------------------------------------------------------------------- 1 | @require './config' 2 | 3 | $mobileSidebarWidth = $sidebarWidth * 0.82 4 | 5 | // narrow desktop / iPad 6 | @media (max-width: $MQNarrow) 7 | .sidebar 8 | font-size 15px 9 | width $mobileSidebarWidth 10 | .page 11 | padding-left $mobileSidebarWidth 12 | 13 | // wide mobile 14 | @media (max-width: $MQMobile) 15 | .sidebar 16 | top 0 17 | padding-top $navbarHeight 18 | transform translateX(-100%) 19 | transition transform .2s ease 20 | .page 21 | padding-left 0 22 | .theme-container 23 | &.sidebar-open 24 | .sidebar 25 | transform translateX(0) 26 | &.no-navbar 27 | .sidebar 28 | padding-top: 0 29 | 30 | // narrow mobile 31 | @media (max-width: $MQMobileNarrow) 32 | h1 33 | font-size 1.9rem 34 | {$contentClass} 35 | div[class*="language-"] 36 | margin 0.85rem -1.5rem 37 | border-radius 0 38 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/toc.styl: -------------------------------------------------------------------------------- 1 | .table-of-contents 2 | .badge 3 | vertical-align middle 4 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/wrapper.styl: -------------------------------------------------------------------------------- 1 | $wrapper 2 | max-width $contentWidth 3 | margin 0 auto 4 | padding 2rem 2.5rem 5 | @media (max-width: $MQNarrow) 6 | padding 2rem 7 | @media (max-width: $MQMobileNarrow) 8 | padding 1.5rem 9 | 10 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # 关于本人 2 | 3 | 信息管理与信息系统专业毕业,从事前端工作3年+时间,主要技术栈涉及React、Vue、React Native、Node.js、微信小程序和微信公众号相关开发,辅修Python与PHP。 4 | 5 | # 关于项目 About Project 6 | 7 | 前端从事了一段时间,之前的积累大部分都是以项目内部的文档以及写了好几本手记和一些零散的博客为主,现在想把工作中碰到的以及一些常用的知识系统性的整理出来,一是对知识体系的回顾和总结,二是对以后查阅与复习的方便。 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/algorithm/cacheLRU.md: -------------------------------------------------------------------------------- 1 | # 缓存算法(页面置换算法)之LRU算法 2 | 3 | - 2020.04.27 4 | 5 | > LRU(Least Recently Used:最近最少使用).假设我们有一个缓存数组,数量为5,里面存放了5个最近被访问的页面。当我们又去访问一个页面的时候,根据此类算法会将最近最少被访问到的页面移除缓存。 6 | 7 | ## 一道leetCode的原题 8 | 9 | :::tip 10 | 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 `get` 和 写入数据 `put` 。 11 | 12 | 获取数据 `get(key)` - 如果`密钥 (key)` 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。 13 | 14 | 写入数据 `put(key, value)` - 如果密钥已经存在,则变更其数据值;如果密钥不存在,则插入该组「密钥/数据值」。 15 | 16 | 当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。 17 | ::: 18 | 19 | ### 示例: 20 | 21 | ```js 22 | LRUCache cache = new LRUCache( 2 /* 缓存容量 */ ); 23 | 24 | cache.put(1, 1); 25 | cache.put(2, 2); 26 | cache.get(1); // 返回 1 27 | cache.put(3, 3); // 该操作会使得密钥 2 作废 28 | cache.get(2); // 返回 -1 (未找到) 29 | cache.put(4, 4); // 该操作会使得密钥 1 作废 30 | cache.get(1); // 返回 -1 (未找到) 31 | cache.get(3); // 返回 3 32 | cache.get(4); // 返回 4 33 | ``` 34 | 35 | ### 思路: 36 | 37 | 1. 维护一个堆栈,最近访问的在最底层,最近最少访问的在最上层。 38 | 2. 当堆栈满了,有新的元素进栈时,将最上层的元素出栈,将新元素放到栈尾。 39 | 3. 当访问已经存在于堆栈的中的老元素,将老元素放到堆栈的最后一位,其他元素往前补位。 40 | 41 | 42 | ```JS 43 | /** 44 | * LRUCache类 45 | * @param {number} capacity 46 | */ 47 | const LRUCache = function(capacity) { 48 | // 维护一个堆栈来进行缓存,最近使用的在最后面,最久没使用的在第一个 49 | this.cacheMap = new Map(); 50 | this.capacity = capacity; 51 | }; 52 | 53 | /** 54 | * get方法 55 | * @param {number} key 56 | * @return {number} 57 | */ 58 | LRUCache.prototype.get = function(key) { 59 | if(this.cacheMap.has(key)){ 60 | // 有命中,更改该值在堆栈中的顺序 61 | let temp = this.cacheMap.get(key); 62 | this.cacheMap.delete(key); 63 | this.cacheMap.set(key, temp); 64 | return temp; 65 | } 66 | return -1; 67 | }; 68 | 69 | /** 70 | * put方法 71 | * @param {number} key 72 | * @param {number} value 73 | * @return {void} 74 | */ 75 | LRUCache.prototype.put = function(key, value) { 76 | if(this.cacheMap.has(key)){ 77 | // 命中,改变顺序即可 78 | this.cacheMap.delete(key); 79 | this.cacheMap.set(key, value) 80 | } 81 | else{ 82 | // 没命中 83 | if(this.cacheMap.size >= this.capacity){ 84 | // 堆栈已满,清除第一个数据 85 | // map的keys函数返回一个迭代器,然后用一次next就能获取第一个元素 86 | let firstKey = this.cacheMap.keys().next().value; 87 | this.cacheMap.delete(firstKey); 88 | this.cacheMap.set(key, value) 89 | } 90 | else{ 91 | // 堆栈未满,存数据 92 | this.cacheMap.set(key, value) 93 | } 94 | } 95 | }; 96 | ``` -------------------------------------------------------------------------------- /docs/bff/README.md: -------------------------------------------------------------------------------- 1 | # BFF 2 | 3 | - 2020.03.16 4 | 5 | > `BFF(Backend For Frontend(服务于前端的后端))`,也就是服务器设计 API 时会考虑前端的使用,并在服务端直接进行业务逻辑的处理,又称为`用户体验适配器`。`BFF` 只是一种逻辑分层,而非一种技术,虽然 `BFF` 是一个新名词,但它的理念由来已久。 6 | 7 |  8 | 9 | 在我们的前端页面时常存在,某个页面需要向 `backend A`、`backend B` 以及 `backend C`...... 发送请求,不同服务的返回值用于渲染页面中不同的 `component`,即一个页面存在很多请求的场景。 10 | 11 |  12 | 13 | 此时,每次访问该页面都需要发送 3 个请求。同时为了保障 `Android`,`iOS`,以及 `Web` 端的不同需求,需要为不同的平台写不同的 `API` 接口,而每当值发生一些变化时,需要 `Android`,`iOS`,`Web` 做出修改。 14 | 15 | 与此同时,当我们需要对一个字符串进行处理,如限定 `140` 个字符的时候,我们需要在每一个客户端`(Android,iOS,Web)`分别实现一遍,这样的代价显然相当大。 16 | 17 | **于是,我们就需要 `BFF` 作为中间件。在这个中间件上我们将做一些业务逻辑处理:** 18 | 19 |  20 | 21 | 例如,我们加入 `BFF` 层,原本每次访问发送 3 请求页面,变成一个请求。 22 | 23 |  24 | 25 | ## 使用 BFF 的正确姿势 26 | 27 | **- 多端应用** 28 | 29 | 我们在设计 API 时会考虑到不同设备的需求,也就是为不同的设备提供不同的 API,虽然它们可能是实现相同的功能,但因为不同设备的特殊性,它们对服务端的 API 访问也各有其特点,需要区别处理。 30 | 31 | **- 服务聚合** 32 | 33 | 随着微服务的兴起,原本在同一个进程内运行的业务流程被拆分到了不同的服务中。这在增加业务灵活性的同时,也让前端的调用变得更复杂。BFF 的出现为前端应用提供了一个对业务服务调用的聚合点,它屏蔽了复杂的服务调用链,让前端可以聚焦在所需要的数据上,而不用关注底层提供这些数据的服务。 34 | 35 | **- 非必要,莫新增** 36 | 37 | 我们在看到 BFF 带来的各种好处的同时,也要注意到它所带来的代码重复和工作量增加方面的问题。如果与已有 BFF 功能类似,且展现数据的要求也相近的话,一定要谨慎对待新增 BFF 的行为。因此,建议非必要,莫新增。 38 | 39 | 40 | ## 实战中的玩法 41 | 42 | **- 访问控制** 43 | 例如,服务中的权限控制,将所有服务中的权限控制集中在 BFF 层,使下层服务更加纯粹和独立。 44 | 45 | **- 应用缓存** 46 | 项目中时常存在一些需要缓存的临时数据,此时 BFF 作为业务的汇聚点,距离用户请求最近,遂将该缓存操作放在 BFF 层。 47 | 48 | **- 第三方入口** 49 | 在业务中需要与第三交互时,将该交互放在 BFF 层,这样可以只暴露必要信息给第三方,从而便于控制第三方的访问。 50 | 51 | 52 | -------------------------------------------------------------------------------- /docs/css/animate.md: -------------------------------------------------------------------------------- 1 | # 动画技巧 2 | 3 | ## 如何实现类似gif效果一直循环的css动画 4 | 5 | - 2020.08.24 6 | 7 | > 实际开发场景中,使用gif图片的方式能够快速实现一些动图,但是由于gif的实现在某些设备上可能会产生毛边的效果。针对某一些动画效果实现起来并不复杂(css3动画就能支持)的循环动画,我们也可以通过css的方式来进行实现。 8 | 9 | 比如说有以下这么一个场景,产品想实现一个每隔10s,动画执行时间为1s的无限循环摇摆动画(css:transform:rotate(30deg))。 10 | 11 | ```css 12 | /* 13 | * 动画计算属性说明 14 | * 不断执行 时间间隔为3s 每次执行2次 15 | * 之前的动画时长为0.2s 所以总时间为3.2s 0.2s内执行2次 0.2s占总时长的6.25% 0.1s执行一次 占3.125% 16 | * 0.1s内抖动4次 每次占0.78125% 17 | */ 18 | @basePercent:0.78125; 19 | @percents: @basePercent, @basePercent*2,@basePercent*3, @basePercent*4,@basePercent*5,@basePercent*6,@basePercent*7,@basePercent*8,100; 20 | @fk: '{transform: rotate(0deg);}','{transform: rotate(-10deg);}','{transform: rotate(0deg);}','{transform: rotate(10deg);}','{transform: rotate(0deg);}','{transform: rotate(-10deg);}','{transform: rotate(0deg);}','{transform: rotate(10deg);}','{transform: rotate(0deg);}','{transform: rotate(0deg);})'; 21 | 22 | .generickeyframe(@name; @framelist; @frameprops){ 23 | @keyframes @name{ 24 | .loop-framelist(@index) when (@index <= length(@framelist)){ 25 | @framepos: extract(@framelist, @index) * 1%; 26 | @{framepos}{ 27 | @props: extract(@frameprops, @index); 28 | @props(); 29 | } 30 | .loop-framelist(@index + 1); 31 | } 32 | .loop-framelist(1); 33 | } 34 | } 35 | 36 | .generickeyframe(huangDong; 0, @basePercent, @basePercent*2,@basePercent*3, @basePercent*4,@basePercent*5,@basePercent*6,@basePercent*7,@basePercent*8,100; 37 | {transform: rotate(0deg);}, 38 | {transform: rotate(-10deg);}, 39 | {transform: rotate(0deg);}, 40 | {transform: rotate(10deg);}, 41 | {transform: rotate(0deg);}, 42 | {transform: rotate(-10deg);}, 43 | {transform: rotate(0deg);}, 44 | {transform: rotate(10deg);}, 45 | {transform: rotate(0deg);}, 46 | {transform: rotate(0deg);} 47 | ); 48 | ``` -------------------------------------------------------------------------------- /docs/css/display.md: -------------------------------------------------------------------------------- 1 | # 布局技巧 2 | 3 | ## CSS 多列等高如何实现? 4 | 5 | 1. 利用`padding-bottom|margin-bottom`正负值相抵,不会影响页面布局的特点。父容器设置超出隐藏(overflow: 6 | hidden),这样父容器的高度就还是它里面的列没有设定`padding-bottom`时的高度,当它里面的任一列高度增加了,则 7 | 父容器的高度被撑到里面最高那列的高度,其他比这列矮的列会用它们的padding-bottom补偿这部分高度差。 8 | 9 | 2. 利用`table-cell`所有单元格高度都相等的特性,来实现多列等高。 10 | 11 | 3. 利用`flex布局`中项目`align-items`属性默认为`stretch`,如果项目未设置高度或设为`auto`,将占满整个容器的高度 12 | 的特性,来实现多列等高。 13 | 14 | ## `width:auto` 和 `width:100%`的区别? 15 | 16 | - `width:100%`会使元素box的宽度等于父元素的contentbox的宽度。 17 | 18 | - `width:auto`会使元素撑满整个父元素,margin、border、padding、content区域会自动分配水平空间。 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/css/fix.md: -------------------------------------------------------------------------------- 1 | # 适配相关 2 | 3 | - 2020.05.18 4 | 5 | ## iPhone X系列安全区域适配问题 6 | 7 | `iPhone X` 以及它以上的系列,都采用刘海屏设计和全面屏手势。头部、底部、侧边都需要做特殊处理。才能适配 `iPhone X` 的特殊情况。 8 | 9 | 10 | ### 1. 设置安全区域,填充危险区域,危险区域不做操作和内容展示。 11 | 12 | :::tip 13 | 危险区域指头部不规则区域,底部横条区域,左右触发区域。 14 | ::: 15 | 16 | 具体操作为:`viewport-fit meta` 标签设置为 `cover`,获取所有区域填充。判断设备是否属于 `iPhone X`,给头部底部增加适配层 17 | 18 | :::tip 19 | `viewport-fit` 有 3 个值分别为: 20 | 21 | - `auto`:此值不影响初始布局视图端口,并且整个web页面都是可查看的。 22 | - `contain`:视图端口按比例缩放,以适合显示内嵌的最大矩形。 23 | - `cover`:视图端口被缩放以填充设备显示。强烈建议使用 `safe area inset` 变量,以确保重要内容不会出现在显示之外。 24 | 25 | ::: 26 | 27 | **设置 viewport-fit 为 cover** 28 | 29 | ```html 30 | 31 | ``` 32 | 33 | **增加适配层** 34 | 35 | 使用 `safe area inset` 变量 36 | 37 | ```css 38 | /* 适配 iPhone X 顶部填充*/ 39 | @supports (top: env(safe-area-inset-top)){ 40 | body, 41 | .header{ 42 | padding-top: constant(safe-area-inset-top, 40px); 43 | padding-top: env(safe-area-inset-top, 40px); 44 | padding-top: var(safe-area-inset-top, 40px); 45 | } 46 | } 47 | /* 判断iPhoneX 将 footer 的 padding-bottom 填充到最底部 */ 48 | @supports (bottom: env(safe-area-inset-bottom)){ 49 | body, 50 | .footer{ 51 | padding-bottom: constant(safe-area-inset-bottom, 20px); 52 | padding-bottom: env(safe-area-inset-bottom, 20px); 53 | padding-top: var(safe-area-inset-bottom, 20px); 54 | } 55 | } 56 | ``` 57 | 58 | :::tip 59 | `safe-area-inset-top`, `safe-area-inset-right`, `safe-area-inset-bottom`, `safe-area-inset-left` `safe-area-inset-*`由四个定义了视口边缘内矩形的 top, right, bottom 和 left 的环境变量组成,这样可以安全地放入内容,而不会有被非矩形的显示切断的风险。 60 | 61 | 对于矩形视口,例如普通的笔记本电脑显示器,其值等于零。对于非矩形显示器(如圆形表盘,iPhoneX 屏幕),在用户代理设置的四个值形成的矩形内,所有内容均可见。 62 | ::: 63 | 64 | 65 | - 其中 `env()` 用法为 `env( , ? )`,第一个参数为自定义的区域,第二个为备用值。 66 | 67 | - 其中 `var()` 用法为 `var( , ? )`,作用是在 `env()` 不生效的情况下,给出一个备用值。 68 | 69 | - `constant(`) 被 css 2017-2018 年为草稿阶段,是否已被标准化未知。而其他iOS 浏览器版本中是否有此函数未知,作为兼容处理而添加进去。 -------------------------------------------------------------------------------- /docs/css/img.md: -------------------------------------------------------------------------------- 1 | # 实现div中图片高度自适应并与父级div宽度一致 2 | 3 | ```html 4 | 5 | 6 | 7 | ``` 8 | 9 | ```scss 10 | // 图片宽高比例自适应或者固定比例 11 | // 装图片的盒子imgbox,设置的padding-bottom,当该值为百分比属性时,是基于父元素宽度的百分比,所以这里设置100%的时候,就相当于形成了一个正方形。 12 | // 宽高比16:9 (100%*9)/16 13 | @mixin imgFixPercent($percent:100%) { 14 | position: relative; 15 | overflow: hidden; 16 | padding-bottom: $percent+%; 17 | >img { 18 | position: absolute; 19 | left: 0; 20 | top: 0; 21 | width:100%; 22 | } 23 | } 24 | ``` -------------------------------------------------------------------------------- /docs/electron/build.md: -------------------------------------------------------------------------------- 1 | # 从开发到打包 2 | 3 | **本文将分以下小节和大家分享「从本地的代码到云端可下载的安装包」这一路的风景,带你领略一路上的美(jian)好(nan)风(cuo)光(zhe):** 4 | 5 | - 第一节是关于目录结构的讨论,合适的目录结构会是一个良好的开端 6 | - 第二节是之后几个小节的概述,阐述了怎么把这一整个过程分成多个环节,每个环节又大要做什么事 7 | - 第三到七节分别详细描述了「配置」、「打包」、「代码签名」、「构建安装包」、「发行安装包」这几个环节要做哪些事,有什么讲究 8 | - 第八节是简述一些可进一步研究或优化的点 9 | - 附:这样设计的 `gulpfile` 文件结构 10 | 11 | ## 目录结构 12 | 13 | 以下目录结构供参考,没有很详细地展开,因为每个应用可能不同,最想表达的是这是一个「双 package.json 结构」,你可以看到根目录下有一个`package.json`,app目录下还有一个`package.json`。 14 | 15 |  16 | 17 | 这是因为,我们的应用在运行时需要一些第三方依赖,这些依赖我们需要打包到应用内,也就是说`/app/node_modules`目录内的内容是要被打包到应用内的,用户使用的时候才不会缺失「运行时依赖」,而如果我们只有一个`package.json`,那么所有的依赖都被下载和安装到同一个`node_modules`文件夹下,我们没法把我们需要打包进去的依赖树提取出来。 18 | 19 | 所以这样双 `package.json`的结构最清晰明了和简单易用,`dependencies`和`devDependencies`有了明确划分。 20 | 21 | 暂定待续.... 22 | -------------------------------------------------------------------------------- /docs/electron/update.md: -------------------------------------------------------------------------------- 1 | # 热更新方案 2 | 3 | ### 自动更新的基本需求 4 | 5 | **不管每个应用的自动更新有多少的细节差别,有一些基本的需求(也可以说环节)是必须要实现的。** 6 | 7 | - 检查更新 :检查是否有新版本可用,什么时候检查,有哪些方式触发检查,可以自定。 8 | - 通知用户 :当有更新可用的时候需要通知用户,可以检查到有更新就通知,也可以在更新文件下载好了后再通知,前者用户可以见到下载过程,后者用户感受不到下载过程。 9 | - 下载更新 :应用有能力下载更新,并且保证下载的完整性,可以后台下载,也可以前台下载。 10 | - 安装更新 :应用能唤起下载好的新版应用安装程序,然后自身退出,至于什么时候唤起安装,可以根据需要做设计。 11 | 12 | ### 区分强弱更新 13 | 14 | **我们把自动更新划分成了强弱两种更新方式,背后的出发点是,我们对某次更新的定性。** 15 | 16 | - 如果某次更新只是功能特性的改进、小功能的上线、普通 BUG 的修复,总之是一次让你「 情绪保持稳定 」的更新,那么这被定性为一次弱更新,我们对于这次更新的期待是,希望用户更新,但是不强制。 17 | 18 | - 如果某次更新包含了杀手级功能的上线、重大 BUG 的修复、大的改版,总之是一次让你「 无法保持平静 」的更新,那么这被定性为一次强更新,我们对于强更新的期待是,强烈推荐用户更新,具有强制性。 19 | 20 | ### 设计自动更新的产品逻辑 21 | 22 | 检查更新有两个问题,第一个问题是我们检查什么?这里我们可以不依赖后端接口去实现检查,我们把各次版本发行记录在一个 json 文件中,然后部署这个 json 文件到服务器,检查更新就是去服务器请求这个 json 文件,然后解析,对比里面的最新版和当前使用的客户端版本,知道有没有更新。 23 | 24 | 第二个问题是,依据什么判断是强升级还是弱更新?基于上面的需求拆分,我们需要划分出强弱更新,强弱更新的逻辑是不一样的,那么在检查更新阶段如何判定该进入哪个更新逻辑呢? 25 | 26 | 第一个办法,在 json 文件中对于每个版本标明相比于上一个版本是一次强升级还是弱更新,比如有一个 `updateType` 字段。这个方式的优点是简单明了,就算用户当前的版本和最新版相隔了好几个版本, 只要满足这其中跨越的有任何一个版本是强升级,那么这次的更新就是一次强升级 ,否则是一次弱更新。 27 | 28 | 第二个办法,一切根据版本号而来,`「X.Y.Z」` 这样的版本号,对比当前客户端的版本和最新版,我们可以把 `X、Y` 不变,仅仅 `Z `(修订版本号)改变的当做一次`弱更新`,如果对比发现,`X` 或 `Y` 有任何一个比当前的高了,那么就定义为一次`强升级`。这种方式不用额外的字段,也不用比对中间跨越的版本,仅仅需要对比当前的版本和最新的版本。 29 | 30 | 推荐采用第二种方式,那么检查更新的流程是以下这样的: 31 | 32 |  33 | 34 | ### 强升级逻辑 35 | 36 |  37 | 38 | 强升级下,一旦发行有可用的更新,在下载前就直接通知用户,而通知的方式是新建一个通知窗口,在 `Electron` 中也就是新建一个渲染进程。 39 | 40 | ### 弱更新逻辑 41 | 42 |  43 | 44 | ### 代码实现 45 | 46 | 本文的思路是采用`electron-builder` 和 `electron-update`两个插件来实现自动更新 -------------------------------------------------------------------------------- /docs/extend/number.md: -------------------------------------------------------------------------------- 1 | # 数字相关插件 2 | 3 | 4 | ## 数字滚轴效果 [odometer](https://github.hubspot.com/odometer/) 5 | 6 | - 2020.10.21 7 | 8 | > `odometer`是一款使用`javascript`和`css`构建的数字滚轴插件,可以平滑的展示数字的变化动画效果。 9 | 10 | ### 安装 11 | 12 | ``` 13 | npm i odometer 14 | ``` 15 | 16 | 17 | 18 | ```vue 19 | 20 | 21 | {{ defaultNum }} 22 | 23 | 24 | ``` 25 | 26 | ```js 27 | const od = new Odometer({ 28 | el: this.$refs.demo, 29 | value: 0, 30 | duration: 2000, 31 | dot: 0, 32 | animation: "count", 33 | format: "", 34 | theme: "coin-animate-defualt", 35 | }); 36 | 37 | od.update(8888); 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/git/standant.md: -------------------------------------------------------------------------------- 1 | 2 | # 代码规范部分参照 3 | 4 | - 2020.07.27 5 | 6 | ## 提交格式要求 7 | 8 | ```xml 9 | (): 10 | 11 | 12 | 13 |
8 | 9 | 无preserveAspectRatio 10 |
12 | 13 | meet 14 |
16 | 17 | slice 18 |
20 | 21 | none 22 |
4 | 点击下一步,显示viewBox区域 5 |
13 | 14 |
{{ getMsg() }}