VuePress 由两部分组成:一部分是支持用 Vue 开发主题的极简静态网站生成器,另外一个部分是为书写技术文档而优化的默认主题。它的诞生初衷是为了支持 Vue 及其子项目的文档需求。javascript
每个由 VuePress 生成的页面都带有预渲染好的 HTML,也所以具备很是好的加载性能和搜索引擎优化(SEO)。同时,一旦页面被加载,Vue 将接管这些静态内容,并将其转换成一个完整的单页应用(SPA),其余的页面则会只在用户浏览到的时候才按需加载。html
若是没有安装node,可在node官网选择对应操做系统下载安装:https://nodejs.org/zh-cn/
可在终端使用node -v
命令来查看node版本,如:v8.12.0
。
若是你的node版本低,请把node版本升级到8.0以上。
如何升级node:https://segmentfault.com/a/11...vue
全局安装,打开终端,输入以下命令:java
~ npm install -g vuepress http fetch GET 200 https://registry.npm.taobao.org/caniuse-db/download/caniuse-db-1.0.30000909.tgz 3993ms /usr/local/bin/vuepress -> /usr/local/lib/node_modules/vuepress/bin/vuepress.js + vuepress@0.14.5 removed 1 package and updated 13 packages in 68.944s
安装结束后,可在终端使用vuepress --version
来查看vuepress版本node
首先在终端建立一个文件夹,做为项目目录,而后建立一个md文件:webpack
~ mkdir press ~ cd press # 新建一个 markdown 文件 ~ echo '# Hello VuePress!' > README.md
而后终端输入以下命令来启动vuepress服务:git
~ vuepress dev . WAIT Extracting site metadata... DONE [00:34:16] Build 94707d finished in 5175 ms! > VuePress dev server listening at http://localhost:8080/
此时在浏览器中输入http://localhost:8080/
就能浏览效果了。github
配置须要在文档目录下建立一个.vuepress
目录,全部 VuePress 相关的文件都将会被放在这里。
终端建立一个文件夹:web
mkdir .vuepress
其中有一个最重要的文件.vuepress/config.js
,网站的全部文件的配置都在这个文件里面,
须要建立该文件touch .vuepress/config.js
,该文件要导出一个JavaScript 对象:算法
module.exports = { title: '我的文档', description: '练习文档' }
如今的目录结构:
. ├── .vuepress │ └── config.js └── README.md
在vuepress里面,一个md文件就是一个页面,如在下面的目录结构中:
./ ├── .vuepress │ └── config.js ├── README.md ├── home1.md └── page-a ├── README.md ├── a.md ├── b.md └── 你好.md
因为服务是在./
启动的,因此路径以./
为服务根路径。
./README.md
文件,也就是http://localhost:8080/
./home1.md
http://localhost:8080/home1.html
。/home1
./page-a/README.md
http://localhost:8080/page-a/
时默认找的文件。/
不能少,不然会去找./page-a.md
文件。./page-a/a.md
http://localhost:8080/page-a/a.html
。注: md文件的文件名能够是中文,可是文件夹名字必定要是英文的。
vuepress内置了一个主页样式,是Front-matter格式的,
Front-matter教程:https://hexo.io/zh-cn/docs/fr...
首页的文件是根级README.md文件,在文件中写入以下配置:
--- home: true heroImage: actionText: 快速上手 → actionLink: /zh/guide/ features: - title: 简洁至上 details: 以 Markdown 为中心的项目结构,以最少的配置帮助你专一于写做。 - title: Vue驱动 details: 享受 Vue + webpack 的开发体验,在 Markdown 中使用 Vue 组件,同时可使用 Vue 来开发自定义主题。 - title: 高性能 details: VuePress 为每一个页面预渲染生成静态的 HTML,同时在页面被加载的时候,将做为 SPA 运行。 footer: MIT Licensed | Copyright © 2018-present Evan You --- # Hello VuePress!
保存文件后页面效果以下图所示:
注意Front-matter必定要在md文件的顶部,不然不会生效。
导航栏可能包含你的页面标题、搜索框、 导航栏连接、多语言切换、仓库连接,它们均取决于你的配置。
导航栏经过.vuepress/config.js
文件的themeConfig.nav
来配置:
// .vuepress/config.js module.exports = { themeConfig: { nav: [ { text: 'Home', link: '/' }, // 根路径 { text: 'Guide', link: '/guide/' }, { text: 'External', link: 'https://google.com' }, // 外部连接 // 显示下拉列表 { text: 'Languages', items: [ { text: 'Chinese', link: '/language/chinese' }, { text: 'Japanese', link: '/language/japanese' } ] }, // 下拉列表显示分组 { text: '高级', items: [ { text: '算法', items: [ { text: '冒泡', link: '/language/chinese' }, { text: '快速', link: '/language/japanese' } ] }, { text: '设计模式', items: [ { text: '工厂', link: '/language/chinese' }, { text: '单例', link: '/language/chinese'}, ] }, ] } ] } }
文件保存后,页面导航效果:
vuepress官方文档中关于导航栏的介绍:https://v0.vuepress.vuejs.org...
若是你什么也不作,那么一个页面是没有侧边栏的,以下图所示:
若是想要配置侧边栏,须要用到sidebar
参数,该参数能够在配置文件中配置,也能够在每一个md文件中配置。
两种方法:
在md文件的顶部写上下面代码:
--- sidebar: auto ---
此配置之针对当前md文件生效。
注:此格式是YAML front matter,必定要在md文件的顶部才会生效。
在.vuepress/config.js
中配置
// .vuepress/config.js module.exports = { themeConfig: { sidebar: 'auto' } }
在配置文件中设置这句话后,全部页面都会生效。
配置后页面效果:
默认状况下,侧边栏会自动显示当前页面的标题(h2~h3)组成的连接,按照页面自己的结构进行嵌套。
侧边栏不会显示h1
标题,从h2
开始显示,最多显示到h3
。
能够经过在配置文件中配置themeConfig.sidebarDepth
来设置嵌套层级
// .vuepress/config.js module.exports = { themeConfig: { sidebarDepth: 2, } }
或者在md文件的顶部使用YAML front matter
来为某个页面重写此值:
--- sidebarDepth: 2 ---
sidebarDepth可设置的值:
值 | 说明 |
---|---|
0 | 禁用标题(headers)连接 |
1 | 默认值,只显示h2 的标题 |
2 | 可设置的最大值,再大无效, 同时提取h2 和h3 标题 |
注:若是设置了 sidebar: 'auto'
,侧边栏会显示h2
和h3
标题,此时sidebarDepth的值只有0是生效的(仅显示h2
的标题),这里须要注意一下。
在md文件中标题的写法:
# 这是一级标题,对应HTML中<h1>标签 ## 这是二级标题,对应HTML中<h2>标签 ### 这是三级标题,对应HTML中<h3>标签 ....
若是想要全部页面显示一个侧边栏,那么须要在配置文件中添加sidebar字段:
// .vuepress/config.js module.exports = { themeConfig: { sidebar: [ '/', '/home1', ['/home2', 'home2自定义标题'], '/home3', '中文', ] } }
说明:
- 能够省略 .md 拓展名
- 以
/
结尾的路径将会被视为*/README.md
- 页面的连接文字自动获取(页面的第一个header),若是明确地在 YAML front matter 中指定页面的标题,则
显示front matter中的标题。- 也能够指定连接的文字,使用一个格式为 [link, text] 的数组。
md文件顶部使用front matter
设置标题的方法:
--- title: 自定义标题 ---
配置好后页面效果:
你能够经过使用对象来将侧边栏划分红多个组
// .vuepress/config.js module.exports = { themeConfig: { sidebar: [ { title: '一组题目', collapsable: false, children: [ '/', '/home1', ] }, { title: '二组题目', children: [ ['/home2', 'home2自定义题目'], '/home3', '/中文', ] } ] } }
侧边栏的每一个子组默认是可折叠的,你能够设置 collapsable: false 来让一个组永远都是展开状态。
设置后页面效果,其中二组题目是能够折叠的:
若是你想为不一样的页面组来显示不一样的侧边栏,须要把一个侧边栏下的多个文件放在一个目录下,一个侧边栏一个目录,以下面的文件结构:
. ├── README.md ├── home1.md ├── home2.md ├── home3.md ├── bar │ ├── README.md │ ├── one.md │ └── two.md └── page-a ├── README.md ├── a.md └── b.md
配置文件中的sidebar
作以下设置:
// .vuepress/config.js module.exports = { themeConfig: { sidebar: { // /bar/ 一个侧边栏,里面的三个页面共用一个侧边栏 '/bar/': [ '', // ./bar/README.md文件,对应页面上/bar/路径 'one', // ./bar/one.md文件,对应页面上/bar/one.html 'two', // ./bar/two.md文件,对应页面上/bar/two.html ], '/page-a/': [ '', 'a', 'b', ], // 确保'/'侧边栏被最后定义。VuePress 会按顺序遍历侧边栏配置来寻找匹配的配置。 '/': [ '', 'home1', 'home2', 'home3', ], }, } }
侧边栏每一个页面的标题可从以下三个地方获取,三种方式选一个配置就能够了。
一、 YAML front matter 中指定页面的标题:
--- title: 自定义标题 ---
二、在配置文件中配置的路径,如:
// .vuepress/config.js module.exports = { themeConfig: { sidebar: [ '/', ['/page-b', '自定义的标题'] ] } }
三、若是上面方法没有设置,那么页面将会取页面中第一个header做为标题。
若是想要在md文件中引入图片,一种是使用图片的相对地址,这种方式有的时候路径会很长,并且文件移动到另一个文件夹后,还须要修改图片的引用路径。
若是你有这个烦恼,那么能够经过给图片路径配置别名的方式来直接使用别名代替路径,使用方式以下:
// .vuepress/config.js const path = require('path'); module.exports = { configureWebpack: { resolve: { alias: { '@vuepress': path.join(__dirname, '../images/vuepress'), } } } }
上面../images/vuepress
路径是相对于config.js
文件的路径。
而后就能够在MD文件中使用以下方式引入图片了:

内置搜索只会为页面的标题、h2 和 h3 构建搜索索引,若是你须要全文搜索,你可使用 Algolia 搜索。
在algolia网站来注册而后本身上传网站很是麻烦。
algolia提供了简化的方式Algolia DocSearch ,只须要提交本身的网站,而后加入少许的脚本,就能使用了。
具体使用方法:
一、打开Algolia DocSearch,大约在最下面,输入本身的文档地址和邮箱。
二、Algolia DocSearch会发送确认邮件,收到后须要回复一下这个网站是你本身的,而且能够修改网站代码:
三、Algolia DocSearch会发送一封使用邮件,里面有apiKey
和indexName
:
四、在配置文件中添加以下内容, apiKey和indexName就是上面邮件中的内容:
module.exports = { themeConfig: { algolia: { apiKey: '<API_KEY>', indexName: '<INDEX_NAME>' } } }
最终页面效果:
目前服务启动的只是本地服务,vuepress还能够把文档生成静态html文件项目,部署到服务器或第三方托管网站上。
生成最终静态文件命令:
vuepress build .
该命令执行完毕后会在.vuepress
文件夹下生成dist
目录:
该目录里面的文件就是生成的最终静态HTML文件,可把该目录复制到服务器或第三方托管网站部署成本身的文档网站。
若是你打算发布到https://<USERNAME>.github.io/
,则能够省略这一步,由于 base 默认便是 "/"
。
若是你打算发布到https://<USERNAME>.github.io/<REPO>/
(也就是说你的仓库在 https://github.com/<USERNAME>/<REPO>
),则将base
设置为"/<REPO>/"
。
设置base的值:
// .vuepress/config.js module.exports = { base: '/press/', // 仓库名字是press themeConfig: {} }
为了方便部署,可建立一个自动部署脚本文件deploy.sh
,文件内容以下:
#!/usr/bin/env sh echo '开始执行命令' # 生成静态文件 echo '执行命令:vuepress build .' vuepress build . # 进入生成的文件夹 echo "执行命令:cd ./.vuepress/dist\n" cd ./.vuepress/dist # 初始化一个仓库,仅仅是作了一个初始化的操做,项目里的文件尚未被跟踪 echo "执行命令:git init\n" git init # 保存全部的修改 echo "执行命令:git add -A" git add -A # 把修改的文件提交 echo "执行命令:commit -m 'deploy'" git commit -m 'deploy' # 若是发布到 https://<USERNAME>.github.io # git push -f git@github.com:<USERNAME>/<USERNAME>.github.io.git master # 若是发布到 https://<USERNAME>.github.io/<REPO> # git push -f https://github.com/<USERNAME>/<REPO>.git master:gh-pages # 返回到上一次的工做目录 echo "回到刚才工做目录" cd -
而后在终端执行以下命令来运行脚本:
bash deploy.sh
还可使用./deploy.sh
命令,不过该命令须要deploy.sh
文件是可执行文件,在终端输入以下命令可把文件变成可执行文件:
chmod +x deploy.sh
注意:
dist
目录,而后重新打包的,全部git都是重新添加在提交。gh-pages
分支上,这样就能够源码跟打包后静态文件在一个仓库上。注意:若是GitHub Pages绑定域名,那么配置文件中的base
参数则须要删除,不然域名访问会失败。
一、 首先须要购买一个域名,好比在阿里云购买域名。
二、 域名须要实名认证,若是域名不是解析到IP地址则不须要备案,如域名指向github Pages就不须要备案。
三、在域名设置里面设置解析记录(以阿里云域名为例):
3.1 记录类型:CNAME - 将域名指向另一个域名
3.2 主机记录: 按提示输入,通常填@
(直接解析成yuming.com)或*
(泛解析,匹配其余全部域名 *.yuming.com)
3.3 记录值:github帐户的本身域名,如:user.github.io
3.4 解析线路:默认
3.5 TTL:默认
四、在项目里面建立一个CNAME
文件,里面放入域名。
在上面的deploy.sh
部署脚本中加入echo 'yuming.' > CNAME
:
# 生成静态文件 vuepress build . # 发布到自定义域名 echo "把域名放到CNAME文件中" echo 'yuming.com' > CNAME # 进入生成的文件夹 cd ./.vuepress/dist
vuepress 0.14版本能够把默认主题使用以下命令复制出来。
若是你的项目名称是press
,在press
同级目录下,终端输入以下命令:
vuepress eject press DONE Copied default theme into /Users/用户名/tmp/press/.vuepress/theme.
这个命令来将默认主题的源码复制到press
目录下的.vuepress/theme
文件夹下,从而能够对默认主题进行任意的修改。须要注意的是一旦 eject,即便升级 VuePress 你也没法再得到 VuePress 对默认主题的更新。
最终效果:
修改的代码以下:
一、在导出的主题目录中(.vuepress/theme/
)找到Sidebar.vue
文件,修改以下对应内容;
<template> <ul class="sidebar-links" v-if="items.length"> <!-- 这里修改了 --> <li v-for="(item, i) in items" :key="i" v-on:click="fileName($event.target)"> <!-- SidebarGroup里面加一个属性chapter --> <SidebarGroup v-if="item.type === 'group'" @toggle="toggleGroup(i)" :chapter="chapter" /> <!-- 这里修改了 --> <SidebarLink v-else :item="item" :chapter="chapter"/> </li> </ul> </template> <script> export default { // data方法修改为以下 data () { let h = ''; if (typeof window !== 'undefined') { h = window.location.href } return { openGroupIndex: 0, href: h, chapter: true, // 菜单栏是否展开, true:展开, false:收起 oneLevelkey: null, // 页面菜单的key } }, // created方法里面添加一行代码 created () { this.refreshIndex() // 设置当前的页面菜单key,用于菜单的展开、收缩 this.setOneLevelkey(); }, // 在methods里面添加4个新方法 methods: { // 设置当前的页面菜单key,用于菜单的展开、收缩 setOneLevelkey () { let urlPath = ''; // vuepress编译项目的时候找不到location, 加个判断 if (typeof window !== 'undefined') { urlPath = decodeURIComponent(window.location.pathname); } this.items.forEach(element => { if (urlPath === element.path) { this.oneLevelkey = element.key; } else if (element.type === 'group') { element.children.forEach( e => { if (urlPath === e.path) { this.oneLevelkey = e.key; } }) } }); }, // 点击侧边栏标题连接 fileName (a, time = 50) { // 延迟执行的目的是为了把菜单渲染结束后在操做 setTimeout(this.fileName2,time, a, time); }, fileName2 (a, time) { var nextSibling = a.nextSibling; // 为了防止在操做dom前ul尚未渲染,多进行几回重试 if (!a.nextSibling && time === 50) { this.fileName(a, 100) } else if (!a.nextSibling && time === 100) { this.fileName(a, 300) } else if (!a.nextSibling && time === 300) { this.fileName(a, 600) } else if (!a.nextSibling) { // 确实没有子菜单,试了这么多遍了, 若是卡了那没办法 // 设置当前的页面菜单key,用于菜单的展开、收缩 this.setOneLevelkey(); } // 点击没有子标题时 nextSibling === null,点击的是分组侧边栏时 nextSibling === #text // 当点击的标题有子标题时,才收缩标题 if (nextSibling && nextSibling.tagName === 'UL') { // setTimeout(this.changeStyle,5, a.nextSibling, a.innerText); this.changeStyle(a.nextSibling, a.innerText); } }, // 切换二级菜单 changeStyle (b, aInnerText) { if (b.offsetHeight && b.offsetHeight > 0) { // 展开状态, 收起菜单 b.style.height = '0'; b.style.overflow = 'hidden'; this.items.forEach(element => { // 若是点击的是页面菜单标题 if (aInnerText === element.title) { this.isOneLevel(b, element, false); } else if (element.type === 'group') { element.children.forEach( e => { if (aInnerText === e.title) { this.isOneLevel(b, e, false); } }) } }); } else { // 收起状态,展开菜单 b.style.height = 'auto'; b.style.overflow = 'inherit'; // 点击的是页面标题菜单 才展开 this.items.forEach(element => { if (element.title === aInnerText) { this.chapter = true; } else if (element.type === 'group') { element.children.forEach( e => { if (e.title === aInnerText) { this.chapter = true; } }) } }); } }, // 判断点击的是不是页面标题菜单 isOneLevel (b, element, chapter) { if (this.oneLevelkey !== element.key) { // 点击的是不一样页面标题, 应该展开菜单 b.style.height = 'auto'; b.style.overflow = 'inherit'; // 设置箭头为展开状态 this.chapter = true; // 设置选中的页面标题的key this.oneLevelkey = element.key; } else if (this.oneLevelkey === element.key) { // 点击的是同一个页面标题,则收起菜单 this.chapter = false; } }, } } </script>
二、在导出的主题目录中(.vuepress/theme/
)找到SidebarLink.vue
文件,修改以下对应内容;
<script> export default { // props里面添加一个chapter属性 props: ['item', 'chapter'], // render里面的props添加一个chapter render (h, { parent: { $page, $site, $route }, props: { item, chapter }}) { // use custom active class matching logic // due to edge case of paths ending with / + hash const selfActive = isActive($route, item.path) // for sidebar: auto pages, a hash link should be active if one of its child // matches // item.type === 'auto' 是配置文件中设置themeConfig.sidebar = 'auto' // 打开的是当前的页面标题 const active = item.type === 'auto' ? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug)) : selfActive // renderLink方法添加chapter, true两个参数 const link = renderLink(h, item.path, item.title || item.path, active, chapter, true) const configDepth = $page.frontmatter.sidebarDepth != null ? $page.frontmatter.sidebarDepth : $site.themeConfig.sidebarDepth const maxDepth = configDepth == null ? 1 : configDepth // 是否在配置文件中设置themeConfig.displayAllHeaders = true const displayAllHeaders = !!$site.themeConfig.displayAllHeaders if (item.type === 'auto') { // item.type === 'auto' 是配置文件中设置themeConfig.sidebar = 'auto' return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)] } else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) { // 侧边栏展开的状态 const children = groupHeaders(item.headers) return [link, renderChildren(h, children, item.path, $route, maxDepth)] } else { return link } } } // renderLink方法添加两个参数:chapter, oneLevel function renderLink (h, to, text, active, chapter, oneLevel) { return h('router-link', { props: { to, activeClass: '', exactActiveClass: '' }, class: { // 可收缩菜单左边的指示箭头 'one-level': oneLevel, // 箭头样式 'one-level-active': active && chapter && oneLevel, // 箭头向下样式 active, 'sidebar-link': true } }, text) } </script> <style lang="stylus"> // 在样式末尾添加以下样式 .one-level position relative &:before content '' border-top 1px solid border-right 1px solid position absolute left: 0px; top: 10px; height: 9px; width: 9px; transform: rotate(45deg); .sidebar-group & &:before left: 8px; .one-level-active &:before left: 4px; transform: rotate(135deg); .sidebar-group & &:before left: 12px; </style>
三、在导出的主题目录中(.vuepress/theme/
)找到SidebarGroup.vue
文件,修改以下对应内容;
<template> <div :class="{ first, collapsable }" > <DropdownTransition> <ul v-if="open || !collapsable" > <li v-for="child in item.children"> // 这一行添加一个chapter参数, 大约在26行 <SidebarLink :item="child" :chapter="chapter"/> </li> </ul> </DropdownTransition> </div> </template> <script> export default { // props里面添加一个chapter属性, 大约第39行 props: ['item', 'first', 'open', 'collapsable', 'chapter'], } </script>
保存后,重启vuepress服务便可。
最终效果以下图:
修改的代码以下:
一、在导出的主题目录中(.vuepress/theme/
)找到SidebarButton.vue
文件,修改以下对应内容;
<style lang="stylus"> // sidebar-button中,删除 display none, 添加cursor pointer .sidebar-button // display none cursor pointer </style>
修改此文件的目的是在页面左上角显示展开、收缩的按钮。
二、在导出的主题目录中(.vuepress/theme/
)找到Navbar.vue
文件,修改以下对应内容;
<style lang="stylus"> // 在.navbar中添加padding-left 4rem .navbar position relative padding-left 4rem </style>
修改此文件的目的是在页面左上角给侧边栏按钮添加位置。
三、
在导出的主题目录中(.vuepress/theme/
)找到Layout.vue
文件,修改以下对应内容;
<script> export default { methods: { // 在toggleSidebar方法里面添加一行代码 toggleSidebar (to) { // 这里加一行代码 this.switchSidebar(); }, // 添加一个新方法: 显示隐藏侧边栏 switchSidebar() { // 侧边栏 let sidebar = document.querySelector('#app .sidebar'); // 内容区域 let page = document.querySelector('#app .page'); if (!sidebar || !page) { // 没获取到元素不执行方法 return; } if (window.screen.width < 719) { // 手机屏幕,把样式恢复 sidebar.style.width = ''; page.style.paddingLeft = ''; return; } if (sidebar.offsetWidth > 100) { // 侧边栏是展开状态, 收起侧边栏 sidebar.style.width = '0'; page.style.paddingLeft = '0'; } else { // 侧边栏是收起状态,展开侧边栏 sidebar.style.width = '20rem'; page.style.paddingLeft = '20rem'; } }, } } </script>
这里主要是添加了一个新方法,并在toggleSidebar方法里面执行这个方法, 这里的代码主要是实现侧边栏按钮的切换功能
vuepress 0.4版本官方文档:https://v0.vuepress.vuejs.org...
Front-matter 教程:https://hexo.io/zh-cn/docs/fr...
vuepress中实现代码折叠、高亮