44

VuePress 由两部分组成:一部分是支持用 Vue 开发主题的极简静态网站生成器,另一个部分是为书写技术文档而优化的默认主题。它的诞生初衷是为了支持 Vue 及其子项目的文档需求。

每一个由 VuePress 生成的页面都带有预渲染好的 HTML,也因此具有非常好的加载性能和搜索引擎优化(SEO)。同时,一旦页面被加载,Vue 将接管这些静态内容,并将其转换成一个完整的单页应用(SPA),其他的页面则会只在用户浏览到的时候才按需加载。

2020-07-14号更新:
本文档是基于vuepress的0.14.5版本编写的,目前vuepress版本已经到了1.5.2。
如果你安装了vuepress的最新版本,按照此教程操作有出入,请查看官方最新版本的教程。

本教程可以保证0.14.5版的操作正确,安装特定版本:
npm install -g vuepress@0.14.5

1. 安装

1.1 依赖环境:node8.0以上的版本

如果没有安装node,可在node官网选择对应操作系统下载安装:https://nodejs.org/zh-cn/
可在终端使用node -v命令来查看node版本,如:v8.12.0
如果你的node版本低,请把node版本升级到8.0以上。
如何升级node:https://segmentfault.com/a/1190000016956077

1.2 安装VuePress

全局安装,打开终端,输入如下命令:

~ 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版本

2. 启动一个服务

首先在终端创建一个文件夹,作为项目目录,然后创建一个md文件:

~ mkdir press
~ cd press
# 新建一个 markdown 文件
~ echo '# Hello VuePress!' > README.md

然后终端输入如下命令来启动vuepress服务:

~ vuepress dev .


 WAIT  Extracting site metadata...

 DONE  [00:34:16] Build 94707d finished in 5175 ms!

> VuePress dev server listening at http://localhost:8080/

clipboard.png

此时在浏览器中输入http://localhost:8080/就能浏览效果了。

图片描述

3. 配置文件说明

配置需要在文档目录下创建一个.vuepress目录,所有 VuePress 相关的文件都将会被放在这里。
终端创建一个文件夹:

mkdir .vuepress

其中有一个最重要的文件.vuepress/config.js,网站的所有文件的配置都在这个文件里面,
需要创建该文件touch .vuepress/config.js,该文件要导出一个JavaScript 对象:

module.exports = {
  title: '个人文档',
  description: '练习文档'
}

现在的目录结构:

.
├── .vuepress
│   └── config.js
└── README.md

4. 关于每个页面和路径说明

在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
    在vuepress中配置路径/home1
  • ./page-a/README.md
    该文件在服务路径:http://localhost:8080/page-a/时默认找的文件。
    注意URL最后的/不能少,否则会去找./page-a.md文件。
  • ./page-a/a.md
    该文件在服务的路径:http://localhost:8080/page-a/a.html

注: md文件的文件名可以是中文,但是文件夹名字一定要是英文的。

5. 首页设置

vuepress内置了一个主页样式,是Front-matter格式的,
Front-matter教程:https://hexo.io/zh-cn/docs/front-matter
首页的文件是根级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文件的顶部,否则不会生效。

6. 导航栏配置

导航栏可能包含你的页面标题、搜索框、 导航栏链接、多语言切换、仓库链接,它们均取决于你的配置。
导航栏通过.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'},
            ] 
          },
        ]
      }
    ]
  }
}

文件保存后,页面导航效果:
clipboard.png

vuepress官方文档中关于导航栏的介绍:https://v0.vuepress.vuejs.org/zh/default-theme-config/#%E9%A6...

7. 侧边栏设置

如果你什么也不做,那么一个页面是没有侧边栏的,如下图所示:

clipboard.png

如果想要配置侧边栏,需要用到sidebar参数,该参数可以在配置文件中配置,也可以在每个md文件中配置。

7.1 自动生成侧边栏(仅当前页面)

两种方法:

  1. 在md文件的顶部写上下面代码:

    ---
    sidebar: auto
    ---

    此配置只针对当前md文件生效。
    注:此格式是YAML front matter,一定要在md文件的顶部才会生效。

  2. .vuepress/config.js中配置

    // .vuepress/config.js
    module.exports = {
    themeConfig: {
     sidebar: 'auto'
    }
    }

    在配置文件中设置这句话后,所有页面都会生效。

配置后页面效果:

clipboard.png

7.2 设置侧边栏标题显示的层数

默认情况下,侧边栏会自动显示当前页面的标题(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可设置的最大值,再大无效, 同时提取h2h3标题

注:如果设置了 sidebar: 'auto' ,侧边栏会显示h2h3标题,此时sidebarDepth的值只有0是生效的(仅显示h2的标题),这里需要注意一下。

在md文件中标题的写法:

# 这是一级标题,对应HTML中<h1>标签

## 这是二级标题,对应HTML中<h2>标签

### 这是三级标题,对应HTML中<h3>标签
....

7.3 项目只显示一个侧边栏

如果想要所有页面显示一个侧边栏,那么需要在配置文件中添加sidebar字段:

// .vuepress/config.js
module.exports = {
  themeConfig: {
    sidebar: [
      '/',
      '/home1',
      ['/home2', 'home2自定义标题'],
      '/home3',
      '中文',
    ]
  }
}

说明:

  1. 可以省略 .md 拓展名
  2. /结尾的路径将会被视为*/README.md
  3. 页面的链接文字自动获取(页面的第一个header),如果明确地在 YAML front matter 中指定页面的标题,则
    显示front matter中的标题。
  4. 也可以指定链接的文字,使用一个格式为 [link, text] 的数组。

md文件顶部使用front matter设置标题的方法:

---
title: 自定义标题
---

配置好后页面效果:

clipboard.png

7.4 侧边栏分组

你可以通过使用对象来将侧边栏划分成多个组

// .vuepress/config.js
module.exports = {
  themeConfig: {
    sidebar: [
      {
        title: '一组题目',
        collapsable: false,
        children: [
          '/', '/home1',
        ]
      },
      {
        title: '二组题目',
        children: [
          ['/home2', 'home2自定义题目'], 
          '/home3',
          '/中文',
        ]
      }
    ]
  }
}

侧边栏的每个子组默认是可折叠的,你可以设置 collapsable: false 来让一个组永远都是展开状态。

设置后页面效果,其中二组题目是可以折叠的:
clipboard.png

7.5 设置多个侧边栏

如果你想为不同的页面组来显示不同的侧边栏,需要把一个侧边栏下的多个文件放在一个目录下,一个侧边栏一个目录,如下面的文件结构:

.
├── 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',
      ],
    },
  }
}

7.6 一个目录下的子文件夹显示自己的侧边栏

// .vuepress/config.js
module.exports = {
  themeConfig: {
    sidebar: {
      '/doc/js/standardLibrary/': [
        '',           // 
        'one',        // 
        'two',        //
      ],
      '/doc/js/': [
        '',
        'a',
        'b',
      ],
    },
  }
}

注意子文件夹的侧边连配置要在父文件夹侧边栏匹配值的上边。

7.7 关于侧边栏每个页面显示的标题

侧边栏每个页面的标题可从如下三个地方获取,三种方式选一个配置就可以了。
1、 YAML front matter 中指定页面的标题:

---
title: 自定义标题
---

2、在配置文件中配置的路径,如:

// .vuepress/config.js
module.exports = {
  themeConfig: {
    sidebar: [
      '/',
      ['/page-b', '自定义的标题']
    ]
  }
}

3、如果上面方法没有设置,那么页面将会取页面中第一个header作为标题。

8. vuepress/config.js中其他配置

8.1 设置路径别名,解决引入图片路径问题

如果想要在md文件中引入图片,一种是使用图片的相对地址,这种方式有的时候路径会很长,而且文件移动到另外一个文件夹后,还需要修改图片的引用路径。
如果你有这个烦恼,那么可以通过给图片路径配置别名的方式来直接使用别名代替路径,使用方式如下:

// .vuepress/config.js
const path = require('path');

module.exports = {
  configureWebpack: {
    resolve: {
      alias: {
        '@vuepress': path.join(__dirname, '../images/vuepress'),
      }
    }
  }
}

上面../images/vuepress路径是相对于config.js文件的路径。
然后就可以在MD文件中使用如下方式引入图片了:

![](~@vuepress/003.png)

8.2 设置搜索使用Algolia搜索

内置搜索只会为页面的标题、h2 和 h3 构建搜索索引,如果你需要全文搜索,你可以使用 Algolia 搜索。
algolia网站来注册然后自己上传网站非常麻烦。
algolia提供了简化的方式Algolia DocSearch ,只需要提交自己的网站,然后加入少量的脚本,就能使用了。
具体使用方法:
1、打开Algolia DocSearch,大约在最下面,输入自己的文档地址和邮箱。

clipboard.png

2、Algolia DocSearch会发送确认邮件,收到后需要回复一下这个网站是你自己的,并且可以修改网站代码:

clipboard.png

3、Algolia DocSearch会发送一封使用邮件,里面有apiKeyindexName

clipboard.png

4、在配置文件中添加如下内容, apiKey和indexName就是上面邮件中的内容:

module.exports = {
  themeConfig: {
    algolia: {
      apiKey: '<API_KEY>',
      indexName: '<INDEX_NAME>'
    }
  }
}

最终页面效果:

clipboard.png

9. 项目部署

目前服务启动的只是本地服务,vuepress还可以把文档生成静态html文件项目,部署到服务器或第三方托管网站上。
生成最终静态文件命令:

vuepress build .

该命令执行完毕后会在.vuepress文件夹下生成dist目录:

该目录里面的文件就是生成的最终静态HTML文件,可把该目录复制到服务器或第三方托管网站部署成自己的文档网站。

9.1 部署到GitHub Pages

如果你打算发布到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: {}
}

9.1.2 创建一个自动执行脚本

为了方便部署,可创建一个自动部署脚本文件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

注意:

  1. vuepress每次执行后都会先删除dist目录,然后从新打包的,所有git都是从新添加在提交。
  2. git推送是强制push的,所以github上仓库只会有一次提交。
  3. 推荐把打包后的文件传到gh-pages分支上,这样就可以源码跟打包后静态文件在一个仓库上。

9.2 GitHub Pages绑定域名

注意:如果GitHub Pages绑定域名,那么配置文件中的base参数则需要删除,否则域名访问会失败。

1、 首先需要购买一个域名,比如在阿里云购买域名。
2、 域名需要实名认证,如果域名不是解析到IP地址则不需要备案,如域名指向github Pages就不需要备案。
3、在域名设置里面设置解析记录(以阿里云域名为例):

3.1 记录类型:CNAME - 将域名指向另外一个域名
3.2 主机记录: 按提示输入,一般填@(直接解析成yuming.com)或*(泛解析,匹配其他所有域名 *.yuming.com)
3.3 记录值:github账户的自己域名,如:user.github.io
3.4 解析线路:默认
3.5 TTL:默认

4、在项目里面创建一个CNAME文件,里面放入域名。
在上面的deploy.sh部署脚本中加入echo 'yuming.' > CNAME

# 生成静态文件
vuepress build .

# 发布到自定义域名
echo "把域名放到CNAME文件中"
echo 'yuming.com' > CNAME

# 进入生成的文件夹
cd ./.vuepress/dist

10. 在vuepress主题基础上修改主题功能

10.1 导出默认主题

vuepress 0.14版本可以把默认主题使用如下命令复制出来。
如果你的项目名称是press,在press同级目录下,终端输入如下命令:

vuepress eject press

 DONE  Copied default theme into /Users/用户名/tmp/press/.vuepress/theme.

这个命令来将默认主题的源码复制到press目录下的.vuepress/theme文件夹下,从而可以对默认主题进行任意的修改。需要注意的是一旦 eject,即使升级 VuePress 你也无法再获得 VuePress 对默认主题的更新。
clipboard.png

10.2 设置侧边栏当前页面可收起、展开

最终效果:

clipboard.png

修改的代码如下:

1、在导出的主题目录中(.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>

2、在导出的主题目录中(.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 link2 = renderLink(h, item.path, item.title || item.path, active, chapter)
    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)
      let linkResult = link;
      // 如果md文件配置了,不显示子标题,则显示 没有箭头的链接
      if (item.frontmatter && item.frontmatter.sidebarDepth === 0) {
        linkResult = link2;
      }
      return [linkResult, renderChildren(h, children, item.path, $route, maxDepth)]
    } else {
      return link2
    }
  }
}

// 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>

3、在导出的主题目录中(.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服务即可。

10.3 设置侧边栏可收起、展开

最终效果如下图:
clipboard.png

修改的代码如下:

1、在导出的主题目录中(.vuepress/theme/)找到SidebarButton.vue文件,修改如下对应内容;

<style lang="stylus">
// sidebar-button中,删除 display none, 添加cursor pointer
.sidebar-button
  // display none
  cursor pointer
</style>

修改此文件的目的是在页面左上角显示展开、收缩的按钮。

2、在导出的主题目录中(.vuepress/theme/)找到Navbar.vue文件,修改如下对应内容;

<style lang="stylus">
// 在.navbar中添加padding-left 4rem
.navbar
  position relative
  padding-left 4rem
</style>

修改此文件的目的是在页面左上角给侧边栏按钮添加位置。

3、
在导出的主题目录中(.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方法里面执行这个方法, 这里的代码主要是实现侧边栏按钮的切换功能

11. 一些插件

11.1 图片放大 fancybox

详情见链接:https://segmentfault.com/a/1190000021505365

11.2 添加评论插件Gitalk

详情见链接:https://segmentfault.com/a/1190000018072952

12. 静态文件添加

有时,你可能需要提供一个静态资源,比如网站favicons图标、插件库文件(比如Gitalk插件文件),在这种情形下,你可以将它们放在 .vuepress/public/ 文件夹中, 它们最终会被复制到生成的静态文件夹中。
比如.vuepress/public/logo.png文件:
.vuepress/config.js配置文件中使用:/logo.png
在vue代码文件中:location.href + 'logo.png'

参考资料

vuepress 0.4版本官方文档:https://v0.vuepress.vuejs.org/zh/
Front-matter 教程:https://hexo.io/zh-cn/docs/front-matter.html
vuepress中实现代码折叠、高亮


dragon
808 声望28 粉丝

一个前端页面开发者,用过react、vue前端框架