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 [email protected]
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/11...
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
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/
此时在浏览器中输入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/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文件的顶部,否则不会生效。
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'},
]
},
]
}
]
}
}
文件保存后,页面导航效果:
7. 侧边栏设置
如果你什么也不做,那么一个页面是没有侧边栏的,如下图所示:
如果想要配置侧边栏,需要用到sidebar参数,该参数可以在配置文件中配置,也可以在每个md文件中配置。
7.1 自动生成侧边栏(仅当前页面)
两种方法:在md文件的顶部写上下面代码:---
sidebar: auto
---
此配置只针对当前md文件生效。
注:此格式是YAML front matter,一定要在md文件的顶部才会生效。
在.vuepress/config.js中配置// .vuepress/config.js
module.exports = {
themeConfig: {
sidebar: 'auto'
}
}
在配置文件中设置这句话后,所有页面都会生效。
配置后页面效果:
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可设置的最大值,再大无效, 同时提取h2和h3标题
注:如果设置了sidebar: 'auto',侧边栏会显示h2和h3标题,此时sidebarDepth的值只有0是生效的(仅显示h2的标题),这里需要注意一下。
在md文件中标题的写法:# 这是一级标题,对应HTML中
## 这是二级标题,对应HTML中
### 这是三级标题,对应HTML中
....
7.3 项目只显示一个侧边栏
如果想要所有页面显示一个侧边栏,那么需要在配置文件中添加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: 自定义标题
---
配置好后页面效果:
7.4 侧边栏分组
你可以通过使用对象来将侧边栏划分成多个组// .vuepress/config.js
module.exports = {
themeConfig: {
sidebar: [
{
title: '一组题目',
collapsable: false,
children: [
'/', '/home1',
]
},
{
title: '二组题目',
children: [
['/home2', 'home2自定义题目'],
'/home3',
'/中文',
]
}
]
}
}
侧边栏的每个子组默认是可折叠的,你可以设置 collapsable: false 来让一个组永远都是展开状态。
设置后页面效果,其中二组题目是可以折叠的:
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,大约在最下面,输入自己的文档地址和邮箱。
2、Algolia DocSearch会发送确认邮件,收到后需要回复一下这个网站是你自己的,并且可以修改网站代码:
3、Algolia DocSearch会发送一封使用邮件,里面有apiKey和indexName:
4、在配置文件中添加如下内容, apiKey和indexName就是上面邮件中的内容:module.exports = {
themeConfig: {
algolia: {
apiKey: '',
indexName: ''
}
}
}
最终页面效果:
9. 项目部署
目前服务启动的只是本地服务,vuepress还可以把文档生成静态html文件项目,部署到服务器或第三方托管网站上。
生成最终静态文件命令:vuepress build .
该命令执行完毕后会在.vuepress文件夹下生成dist目录:
该目录里面的文件就是生成的最终静态HTML文件,可把该目录复制到服务器或第三方托管网站部署成自己的文档网站。
9.1 部署到GitHub Pages
如果你打算发布到https://.github.io/,则可以省略这一步,因为 base 默认即是 "/"。
如果你打算发布到https://.github.io//(也就是说你的仓库在 https://github.com//),则将base设置为"//"。
设置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://.github.io
# git push -f [email protected]:/.github.io.git master
# 如果发布到 https://.github.io/
# git push -f https://github.com//.git master:gh-pages
# 返回到上一次的工作目录
echo "回到刚才工作目录"
cd -
然后在终端执行如下命令来运行脚本:bash deploy.sh
还可以使用./deploy.sh命令,不过该命令需要deploy.sh文件是可执行文件,在终端输入如下命令可把文件变成可执行文件:chmod +x deploy.sh
注意:vuepress每次执行后都会先删除dist目录,然后从新打包的,所有git都是从新添加在提交。
git推送是强制push的,所以github上仓库只会有一次提交。
推荐把打包后的文件传到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 对默认主题的更新。
10.2 设置侧边栏当前页面可收起、展开
最终效果:
修改的代码如下:
1、在导出的主题目录中(.vuepress/theme/)找到Sidebar.vue文件,修改如下对应内容;
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;
}
},
}
}
2、在导出的主题目录中(.vuepress/theme/)找到SidebarLink.vue文件,修改如下对应内容;
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)
}
// 在样式末尾添加如下样式
.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;
3、在导出的主题目录中(.vuepress/theme/)找到SidebarGroup.vue文件,修改如下对应内容;
:class="{ first, collapsable }"
>
v-if="open || !collapsable"
>
// 这一行添加一个chapter参数, 大约在26行
export default {
// props里面添加一个chapter属性, 大约第39行
props: ['item', 'first', 'open', 'collapsable', 'chapter'],
}
保存后,重启vuepress服务即可。
10.3 设置侧边栏可收起、展开
最终效果如下图:
修改的代码如下:
1、在导出的主题目录中(.vuepress/theme/)找到SidebarButton.vue文件,修改如下对应内容;
// sidebar-button中,删除 display none, 添加cursor pointer
.sidebar-button
// display none
cursor pointer
修改此文件的目的是在页面左上角显示展开、收缩的按钮。
2、在导出的主题目录中(.vuepress/theme/)找到Navbar.vue文件,修改如下对应内容;
// 在.navbar中添加padding-left 4rem
.navbar
position relative
padding-left 4rem
修改此文件的目的是在页面左上角给侧边栏按钮添加位置。
3、
在导出的主题目录中(.vuepress/theme/)找到Layout.vue文件,修改如下对应内容;
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';
}
},
}
}
这里主要是添加了一个新方法,并在toggleSidebar方法里面执行这个方法, 这里的代码主要是实现侧边栏按钮的切换功能
11. 一些插件
11.1 图片放大 fancybox
11.2 添加评论插件Gitalk
12. 静态文件添加
有时,你可能需要提供一个静态资源,比如网站favicons图标、插件库文件(比如Gitalk插件文件),在这种情形下,你可以将它们放在 .vuepress/public/ 文件夹中, 它们最终会被复制到生成的静态文件夹中。
比如.vuepress/public/logo.png文件:
在.vuepress/config.js配置文件中使用:/logo.png。
在vue代码文件中:location.href + 'logo.png'。
参考资料