做者博客地址: 管鮑切思世所稀的博客... , 移動端和PC端有差異哦~前幾天看到掘金上有人用Vuepress搭建博客,知道vuepress的我,卻歷來沒有親自上手過,因而乎瞎琢磨一下。總結:vuepress仍是很強的,操做簡單,沒有那麼難,只要你認真閱讀了文章,你能夠作vuepress的爸爸了。這篇文章通俗易懂,從起步到結束,按順序講解,認真看完你就是最靚的仔~css
本博客是基於vuepress搭建而成,什麼是vuepress? => vuepress是以Vue驅動的靜態網站生成器。VuePress 由兩部分組成:第一部分是一個極簡靜態網站生成器,它包含由 Vue 驅動的主題系統和插件 API,另外一個部分是爲書寫技術文檔而優化的默認主題,它的誕生初衷是爲了支持 Vue 及其子項目的文檔需求。html
你可能須要30-50分鐘時間讀完它,才能勝任vuepress
# 安裝 yarn global add vuepress # 或者:npm install -g vuepress # 新建一個 markdown 文件 echo '# Hello VuePress!' > README.md # 開始寫做 vuepress dev . # 構建靜態文件 vuepress build .
注意:請確保你的 Node.js 版本 >= 8.6。
事實上,一個 VuePress 網站是一個由 Vue、Vue Router 和 webpack 驅動的單頁應用。若是你之前使用過 Vue 的話,當你在開發一個自定義主題的時候,你會感覺到很是熟悉的開發體驗,你甚至可使用 Vue DevTools 去調試你的自定義主題。前端
在構建時,咱們會爲應用建立一個服務端渲染(SSR)的版本,而後經過虛擬訪問每一條路徑來渲染對應的HTML。這種作法的靈感來源於 Nuxt 的 nuxt generate
命令,以及其餘的一些項目,好比 Gatsbyvue
官方話就不扯了,更多官方術語詳情請移步 官方
請確保你的 Node.js 版本 >= 8。
若是你只是想嘗試一下 VuePress,你能夠全局安裝它:java
# 安裝 yarn global add vuepress # 或者:npm install -g vuepress # 新建一個 markdown 文件 echo '# Hello VuePress!' > README.md # 開始寫做 vuepress dev . # 構建靜態文件 vuepress build .
若是你想在一個現有項目中使用 VuePress,同時想要在該項目中管理文檔,則應該將 VuePress 安裝爲本地依賴。做爲本地依賴安裝讓你可使用持續集成工具,或者一些其餘服務(好比 Netlify)來幫助你在每次提交代碼時自動部署。webpack
# 將 VuePress 做爲一個本地依賴安裝 yarn add -D vuepress # 或者:npm install -D vuepress # 新建一個 docs 文件夾 mkdir docs # 新建一個 markdown 文件 echo '# Hello VuePress!' > docs/README.md # 開始寫做 npx vuepress dev docs
注意若是你的現有項目依賴了 webpack 3.x,推薦使用 Yarn 而不是 npm 來安裝 VuePress。由於在這種情形下,npm 會生成錯誤的依賴樹。
接着,在 package.json
里加一些腳本:ios
{ "scripts": { "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs" } }
而後就能夠開始寫做了:git
yarn docs:dev # 或者:npm run docs:dev
要生成靜態的 HTML 文件,運行:es6
yarn docs:build # 或者:npm run docs:build
默認狀況下,文件將會被生成在 .vuepress/dist
,固然,你也能夠經過 .vuepress/config.js
中的 dest
字段來修改,生成的文件能夠部署到任意的靜態文件服務器上,參考 部署 來了解更多。github
VuePress 遵循 「約定優於配置」 的原則,推薦的目錄結構以下:
注意vuepress約定入口目錄必須是 docs ,務必根目錄是docs
. ├── docs │ ├── .vuepress (可選的) → 官方標註可選,不過通常都會用這個文件夾,核心文件夾 │ │ ├── components (可選的) → 這個文件夾一些以.vue結尾的vue組件,能夠在markdown文件裏使用 │ │ ├── theme (可選的) → 能夠配置本身的博客 │ │ │ └── Layout.vue │ │ ├── public (可選的) → 放一些公共靜態資源 使用方式 /xxx, 請必須以 `/` 開始表示根 │ │ ├── styles (可選的) → 樣式 │ │ │ ├── index.styl → 自定義樣式 │ │ │ └── palette.styl → 用於重寫默認顏色常量,或者設置新的 stylus 顏色常量 │ │ ├── templates (可選的, 謹慎配置) │ │ │ ├── dev.html → 用於開發環境的 HTML 模板文件 │ │ │ └── ssr.html → 構建時基於 Vue SSR 的 HTML 模板文件 │ │ ├── config.js (可選的) → 配置文件的入口文件,也能夠是 YML 或 toml │ │ └── enhanceApp.js (可選的) → 客戶端應用的加強 │ │ │ ├── README.md │ ├── guide │ │ └── README.md │ └── config.md │ └── package.json
注意當你想要去自定義 templates/ssr.html 或 templates/dev.html 時,最好基於 默認的模板文件 來修改,不然可能會致使構建出錯。
此外,對於上述的目錄結構,默認頁面路由地址以下:
文件的相對路徑 | 頁面路由地址 |
---|---|
/README.md | / |
/guide/README.md | /guide/ |
/config.md | /config.html |
// dcos/.vuepress/config.js module.exports = { title:"取捨", // HTML的title description:"管鮑切思世所稀博客", // 描述 keywords:"管鮑切思世所稀博客", // 關鍵字 head:[ // 配置頭部 [ ['link', {rel:'icon', href:"/icon.png"}], ['meta', {'name':'viewport', content:"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;"}] ] ], markdown: { lineNumbers: true, // 代碼顯示行號 }, dest:"./outer", // 設置打包路徑 lastUpdated: 'Last Updated', // 顯示更新時間 themeConfig:{ logo:"/icon.png", // 導航欄左邊logo,不寫就不顯示 sidebarDepth: 2, // 側邊欄顯示2級 nav:[ // 導航欄配置 { text: 'vue', link: '/' }, { text: 'css', link: '/blog/' }, { text: 'js', // 這裏是下拉列表展示形式。 items能夠一直嵌套下去 items:[ text:"ES5", link:"/js/es5/", text:"ES6", link:"/js/es6/", ] }, {text: 'github', link:"https://github.com/1046224544"} ], // 爲如下路由添加側邊欄 sidebar: ['/', '/git', '/vue'] // 嵌套側邊欄 以對象的方式嵌套下去 // sidebar: { // '/2019/': [ // ['','前言(2019)'], // { // title:"10月份", // collapsable:false, // sidebarDepth:2, // children:[ // ["Nginx部署Vue項目", "Nginx部署Vue項目"], // ["NVM自由切換Node版本", "NVM自由切換Node版本小筆記"], // ["KTV點歌系統", "KTV點歌系統"], // ] // }, // { // title:"9月份", // collapsable:false, // sidebarDepth:2, // children:[ // ["綜合性博客網站", "綜合性博客網站"] // ] // } // ], // ... // } }, plugins:[ // 'axios' // 配置插件 ] } }
注意以上就是完整的基本config.js
配置文件,有強迫症的同窗確定會以爲文件大了,很差維護。的確,當咱們的路有文件變多了,文件會變得很長。筆者在這裏推薦,將導航欄
和側邊欄
單獨拆分兩個文件,以文件加載的方式引入,這樣路由導航欄
和側邊欄
就能夠無限嵌套,你也能夠無限往下分級,建文件夾等等達到分類效果。
以下:
// docs/.vuepress/config.js module.exports = { ...部分(同上) themeConfig:{ nav: require('./nav'), // 引入導航欄 sidebar:require('./sidebar'), // 引入側邊欄 }, ... } // docs/.vuepress/sidebar.js module.exports = { "/api/front/2019/": require('../.vuepress/frontbar/2019'), // 繼續分類 "/api/front/2020/": require('../.vuepress/frontbar/2020'), "/api/end/2019/": require('../.vuepress/endbar/2019'), "/api/learn/koa/": require('../.vuepress/learnbar/koabar'), "/api/learn/express/": require('../.vuepress/learnbar/expressbar'), "/api/learn/java/": require('../.vuepress/learnbar/javabar'), "/api/learn/es6/": require('../.vuepress/learnbar/es6bar'), "/api/learn/vue/": require('../.vuepress/learnbar/vuebar'), } // docs/.vuepress/nav.js module.exports = [ {text:"首頁", link:"/"}, { text:"技術API", ariLabel:"技術API", items:[ {text:"koa", link:"/api/learn/koa/"}, {text:"vue", link:"/api/learn/vue/"}, {text:"es6", link:"/api/learn/es6/"}, {text:"java", link:"/api/learn/java/"}, {text:"express", link:"/api/learn/express/"}, ] }, { text:"平常博客", ariLabel:"平常博客", items:[ {text:"前端",link:"/api/front/"}, {text:"後端",link:"/api/end/"}, {text:"其餘",link:"/api/orther/1.md"}, ] }, {text:"關於博客", link:"/api/builog/"}, {text:"關於做者", link:"/api/author/"}, { text:"其餘小站", ariLabel:"其餘小站", items:[ {text:"掘金", link:'https://juejin.im/user/5d1079ab6fb9a07ed4410cc0'}, {text:"SegmentFault", link:'https://segmentfault.com/u/98kk'}, {text:"CSDN", link:'https://blog.csdn.net/weixin_43374176'}, ] }, { text:"聯繫", ariLabel:"聯繫", items:[ {text:"郵箱", link:"mailto:wsm_1105@163.com", target:"_blank"}, {text:"其餘", link:"/api/contact/"} ] }, {text:"GitHub", link:"http://github.com/1046224544"} ]
筆者目錄截圖:
注意只要是本身配置的目錄,都必須在docs目錄下有對應的目錄結構, 若是你的路徑是/api/aboutme/
, 那麼對象的文件目錄就是/docs/api/aboutme/readme.md
,默認根路徑就是readme.md
文件。 若是你的路徑是/api/aboutme/ktv點歌系統
, 那麼對象的文件目錄就是/docs/api/aboutme/ktv點歌系統.md
單文件
的方式一致,有些時候咱們有可能須要使用 Vue 的 UI 組件庫。例如 Element
, Mint
等,一般咱們在項目中使用這些 UI 組件庫的時候,咱們都會在 main.js
或 botostrap.js
文件中統一註冊。好在 VuePress 中也支持這種功能,咱們能夠經過建立一個 .vuepress/enhanceApp.js
文件來作一些應用級別的配置,這個文件 exprot default 一個鉤子函數
,在這個鉤子中你能夠作一些特殊處理,例如添加全局路由鉤子,註冊外部組件庫。// .vuepress/enhanceApp.js // 全局註冊 Element 組件庫 import Vue from 'vue' import Element from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' export default ({ Vue, options, router }) => { Vue.use(Element) } // 在vue中使用第三方庫 // 定義一個vue組件 /docs/.vuepress/componets/demo.vue <template> <div class="demo"> {{ msg }} <my-hello></my-hello> <el-button>button</el-button> // 使用了el-button </div> </template> <script> export default { data () { return { msg: 'Hello VuePress!' } } } </script>
請確保只在 beforeMount 或者 mounted 訪問瀏覽器 / DOM 的 API。
若是你正在使用,或者須要展現一個對於 SSR 不怎麼友好的組件(好比包含了自定義指令),你能夠將它們包裹在內置的 <ClientOnly>
組件中:
<ClientOnly> <demo /> </ClientOnly>
請注意,這並不能解決一些組件或庫在導入
時就試圖訪問瀏覽器 API 的問題 —— 若是須要使用這樣的組件或庫,你須要在合適的生命週期鉤子中動態導入
它們:
<script> export default { mounted () { import('./lib-that-access-window-on-import').then(module => { // use code }) } } </script>
若是你的模塊經過 export default 導出一個 Vue 組件,那麼你能夠動態註冊它:
<template> <component v-if="dynamicComponent" :is="dynamicComponent"></component> </template> <script> export default { data() { return { dynamicComponent: null } }, mounted () { import('./lib-that-access-window-on-import').then(module => { this.dynamicComponent = module.default }) } } </script>
參考:
網站內部的連接,將會被轉換成 <router-link>
用於 SPA 導航。同時,站內的每個文件夾下的 README.md
或者 index.md
文件都會被自動編譯爲 index.html
,對應的連接將被視爲 /
。
以以下的文件結構爲例:
. ├─ README.md ├─ foo │ ├─ README.md │ ├─ one.md │ └─ two.md └─ bar ├─ README.md ├─ three.md └─ four.md
假設你如今在 foo/one.md
中:
[Home](/) <!-- 跳轉到根部的 README.md --> [foo](/foo/) <!-- 跳轉到 foo 文件夾的 index.html --> [foo heading](./#heading) <!-- 跳轉到 foo/index.html 的特定標題位置 --> [bar - three](../bar/three.md) <!-- 具體文件可使用 .md 結尾(推薦) --> [bar - four](../bar/four.html) <!-- 也能夠用 .html -->
VuePress 支持重定向到乾淨連接。若是一個連接 /foo
找不到,VuePress 會自行尋找一個可用的 /foo/
或 /foo.html
。反過來,當 /foo/
或 /foo.html
中的一個找不到時,VuePress 也會嘗試尋找另外一個。藉助這種特性,咱們能夠經過官方插件 vuepress-plugin-clean-urls 定製你的網站路徑。
注意不管是否使用了 permalink 和 clean-urls 插件,你的相對路徑都應該依賴於當前的文件結構來定義。在上面的例子中,即便你將/foo/one.md
的路徑設爲了/foo/one/
,你依然應該經過./two.md
來訪問/foo/two.md
。
外部的連接將會被自動地設置爲 target="_blank" rel="noopener noreferrer":
你能夠自定義經過配置 config.markdown.externalLinks 來自定義外部連接的特性
VuePress 提供了對 YAML front matter 開箱即用的支持:
--- title: Blogging Like a Hacker lang: en-US ---
這些數據能夠在當前 markdown 的正文,或者是任意的自定義或主題組件中使用。
想了解更多,請移步 Front Matter
輸入
| Tables | Are | Cool | | ------------- |:-------------:| -----:| | col 3 is | right-aligned | $1600 | | col 2 is | centered | $12 | | zebra stripes | are neat | $1 |
輸出
Tables | Are | Cool |
---|---|---|
col 3 is | right-aligned | $1600 |
col 2 is | centered | $12 |
zebra stripes | are neat | $1 |
輸入
:tada: :100:
輸出
你能夠在這個列表找到全部可用的 Emoji。
輸入
[[toc]]
輸出
目錄(Table of Contents)的渲染能夠經過 markdown.toc
選項來配置。
輸入
::: tip This is a tip ::: ::: warning This is a warning ::: ::: danger This is a dangerous warning :::
輸出
::: tip
This is a tip
:::
::: warning
This is a warning
:::
::: danger
This is a dangerous warning
:::
你也能夠自定義塊中的標題:
::: danger STOP Danger zone, do not proceed :::
::: danger STOP
Danger zone, do not proceed
:::
參考:
VuePress 使用了 Prism 來爲 markdown 中的代碼塊實現語法高亮。Prism 支持大量的編程語言,你須要作的只是在代碼塊的開始倒勾中附加一個有效的語言別名:
輸入
export default { name: 'MyComponent', // ... } ```
**輸出**
export default {
name: 'MyComponent',
// ...
}
**輸入**
<ul> <li v-for="todo in todos" :key="todo.id" > {{ todo.text }} </li> </ul>
**輸出**
<ul>
<li
v-for="todo in todos" :key="todo.id"
{{ todo.text }}
</li>
</ul>
## 代碼塊中的行高亮 **輸入**
export default { data () { return { msg: 'Highlighted!' } } }
**輸出**
export default {
data () {
return { msg: 'Highlighted!' }
}
}
## 行號 你能夠經過配置來爲每一個代碼塊顯示行號:
module.exports = {
markdown: {
lineNumbers: true
}
}
## 導入代碼段 你能夠經過下述的語法導入已經存在的文件中的代碼段:
<<< @/filepath
它也支持 行高亮:
<<< @/filepath{highlightLines}
>**注意**因爲代碼段的導入將在 webpack 編譯以前執行,所以你沒法使用 webpack 中的路徑別名,此處的 `@` 默認值是 `process.cwd()`。 ## 進階配置 VuePress 使用 [markdown-it](https://github.com/markdown-it/markdown-it) 來渲染 Markdown,上述大多數的拓展也都是經過自定義的插件實現的。想要進一步的話,你能夠經過 `.vuepress/config.js` 的` markdown` 選項,來對當前的 `markdown-it` 實例作一些自定義的配置:
module.exports = {
markdown: {
// markdown-it-anchor 的選項 anchor: { permalink: false }, // markdown-it-toc 的選項 toc: { includeLevel: [1, 2] }, extendMarkdown: md => { // 使用更多的 markdown-it 插件! md.use(require('markdown-it-xxx')) }
}
}
## 評論系統 Valine >看完本節內容,你就能夠勝任Valine了,今後網站不在寂靜,本評論系統通俗易懂,徹底能夠解決其餘做者講解此部分留下的後遺症,趕忙收藏吧! - 須要安裝leancloud-storage和valine - [valine官網](https://valine.js.org/quickstart.html) - appid和appkey的獲取須要註冊[leancloud](https://leancloud.cn/),而後能夠新建應用並在`設置>應用 key`能夠查看 ### 安裝
npm install leancloud-storage --save
npm install valine --save
### 配置 Components.vue組件
// 新建Components.vue組件
<template>
<div class="vcomment" v-if="data.comments === true"> <div id="vcomments"></div> </div>
</template>
<script>
import { isActive, hashRE, groupHeaders } from '../util'
export default {
computed: {
data () { return this.$page.frontmatter },
},
mounted: function(){
this.createValine()
},
methods: {
createValine() { const Valine = require('valine'); window.AV = require('leancloud-storage'); const valine = new Valine({ el: '#vcomments', appId: 'your ID', appKey: 'your Key', notify: false, verify: false, avatar: 'monsterid', path: window.location.pathname, placeholder: '同道中人,文明留言...', }); this.valineRefresh = false }
},
watch: {
'$route' (to, from) { if(to.path !== from.path){ setTimeout(() => { //從新刷新valine this.createValine() }, 180) } }
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
max-width 740px
padding 10px
display block;
margin-left auto;
margin-right auto;
}
</style>
Page.vue
// Page.vue
<template>
<main class="page">
<slot name="top" /> <Content class="theme-default-content" /> <PageEdit /> <PageNav v-bind="{ sidebarItems }" /> <slot name="bottom" /> <Comments v-bind:is="viewComments"></Comments>
</main>
</template>
<script>
import PageEdit from '@theme/components/PageEdit.vue'
import PageNav from '@theme/components/PageNav.vue'
import { resolvePage, normalize, outboundRE, endingSlashRE } from '../util'
import Comments from './Comments.vue'
export default {
components: { PageEdit, PageNav , Comments},
props: ['sidebarItems'],
data(){
return{ viewComments: 'Comments', }
}
}
</script>
<style lang="stylus">
@require '../styles/wrapper.styl'
.page
padding-bottom 2rem
display block
</style>
### 使用(按需使用) 好比你想在china.md 文件中使用, 你就在頭部 貼入一下代碼 評論系統不是每一個頁面都同樣的,根據不一樣的頁面,加載不一樣的評論, 看了不少小編說什麼評論的亂七八糟,看完這篇文章,對Valine再也不那麼恐慌,讓你玩轉第三方評論
**截圖** ![](https://user-gold-cdn.xitu.io/2019/11/23/16e974512e5203a8?w=1736&h=919&f=png&s=125627) ![](https://user-gold-cdn.xitu.io/2019/11/23/16e974657170e175?w=1914&h=1078&f=png&s=161457) >Valine實例與leancloud-storage實例 在每次頁面加載時會向服務器發起帶當前url參數的請求以獲取評論數據,而這個url參數每次都是同樣。首先Valine 實例與 leancloud-storage 實例都在 mounted 鉤子中初始化或掛載至 window 對象上了。當頁面 url 變化時,Page.vue 自己並無變化,但mounted會從新觸發。 ## 關於其餘插件 你能夠移步到官網查看,插件就是給咱們用的,若是難的話,還叫什麼插件,只要認真看,你總會看懂的 ## 部署到 Github pages 當咱們將文檔寫好後就到了咱們最關心的地方了,怎麼將打包後的代碼推送到遠程倉庫的 `gh-pages` 分支上,網上應該有不少文章描述怎麼作,可是不少方法比較麻煩,還好有工具已經爲咱們解決了這個麻煩了。 ### 建立一個deploy.sh
touch deploy.sh
### 編寫腳本
set -e
npm run docs:build
cd docs/.vuepress/dist
git init
git add -A
git commit -m 'deploy'
cd -
### 設置package.json
{
"scripts": { "deploy": "bash deploy.sh" },
}
### 發佈
npm run deploy // 便可自動構建部署到github上。
**詳情移步官網** - [vuepress.vuejs.org](https://vuepress.vuejs.org/zh/guide/deploy.html) ## 總結 相比較 Hexo 而言 VuePress 上手更加容易,功能也更強大,例如在 VuePress 能夠註冊自定義組件,並且 VuePress 中編寫 Vue 和平時同樣學習成本幾乎爲零。因此若是您正在開源一款 Vue 相關的庫或是其餘項目,您均可以使用 VuePress 做爲您的文檔編輯工具。雖然並無徹底將 VuePress 內容講完,學完該篇文章相信你能夠對 VuePress 有個大概的瞭解,您至少能夠快速搭建一個博客,若是您想對 VuePress 有更多瞭解,請參考 [Vuepress 中文 API](https://vuepress.vuejs.org/zh/) ## 在線查看 [管鮑切思世所稀的博客...](https://blog.usword.cn/api/builog/) >移動端和PC端有差異哦~ ## 博客部分截圖 ![](https://user-gold-cdn.xitu.io/2019/11/23/16e9748ca35656c7?w=1738&h=920&f=png&s=112208) ![](https://user-gold-cdn.xitu.io/2019/11/23/16e97497621d5dc1?w=1741&h=918&f=png&s=117851) ![](https://user-gold-cdn.xitu.io/2019/11/23/16e974a11bfd972d?w=1739&h=919&f=png&s=137144) ## 其餘 - [完整的綜合性網站](https://juejin.im/post/5da2a8ed6fb9a04de818eeff) - [KTV點歌系統](https://juejin.im/post/5dac3b4351882576534d33d7) - [Nginx部署Vue項目](https://juejin.im/post/5dbbb4df51882522c14f81a8) - [NVM的使用小技巧](https://juejin.im/post/5dae55b75188257d8936be94) ## 聯繫 若是你們有興趣,歡迎關注公衆號:_facebook(web技術進階),查看更多優質文章,歡迎你們加入個人前端交流羣:[866068198](https://qm.qq.com/cgi-bin/qm/qr?k=m8asYpHTs_cw3lJVLVv4U6wbF4ep2Ny5&authKey=OknnnniiEOFaIZNhEl2dUIhSrKPB8wGrEYu1AGyS01Y6XXz7doQl7v%2FitvPRr3ii) ,一塊兒交流學習前端技術。博主目前一直在自學Node中,技術有限,若是能夠,會盡力給你們提供一些幫助,或是一些學習方法. - 公衆號 ![](https://user-gold-cdn.xitu.io/2019/11/23/16e974db11404fe7?w=748&h=776&f=jpeg&s=54595) - QQ羣 <a href="https://qm.qq.com/cgi-bin/qm/qr?k=m8asYpHTs_cw3lJVLVv4U6wbF4ep2Ny5&authKey=OknnnniiEOFaIZNhEl2dUIhSrKPB8wGrEYu1AGyS01Y6XXz7doQl7v%2FitvPRr3ii" style="display:flex;align-items:center;justify-content:center;"> <img src="https://user-gold-cdn.xitu.io/2019/11/23/16e974e0f084ca30?w=540&h=740&f=jpeg&s=125975"> </a> ## 福利 有須要刷鑽,刷會員,刷騰訊視頻會員,漲粉絲等等相關意向的小夥伴們,能夠訪問做者推薦的超值代刷網站:[qq.usword.cn](http://qq.usword.cn), 也能夠掃描下方二維碼 ![](https://user-gold-cdn.xitu.io/2019/11/23/16e974ec2da5a31f?w=300&h=390&f=png&s=12507) ## 最後 >若是老闆以爲這篇文章有幫助,就大方的點個贊吧,老闆大氣,老闆最帥~ If you have some questions after you see this article, you can contact me or you can find some info by clicking these links. - [juejin@wsm's juejin](https://juejin.im/user/5d1079ab6fb9a07ed4410cc0) - Gi[tHub@1046224544](https://github.com/1046224544) - [Segmentfault@wsm](https://segmentfault.com/u/98kk)