【前端学习笔记】VitePress 项目构建 以及 基础使用汇总(config.js、themeConfig、frontmatter 块、预定义变量)
VitePress 可以快速创建一个简单的文档站点。使用的时候我们只需要了解一些简单的配置项,然后在项目里分结构存储 md 文档即可。这样一来,我们可以在除了要写一些必要的 Vue 之外,不用额外写 Vue 代码、不用写任何的样式,使用 VitePress 自带的页面架构和主题,进行文档的存储管理和文档展示。...
由于在自己的工作和学习过程中,只查看某个大佬的教程或文章无法满足自己的学习需求和解决遇到的问题,所以自己在追赶大佬们步伐的基础上,又自己总结、整理、汇总了一些资料,方便自己理解和后续回顾,同时也希望给大家带来帮助,所以才写下该篇文章。在本文中,所有参考或引用大佬们文章内容的位置,都附上了原文章链接,您可以直接前往查阅观看。在原文章内容的基础上,若无任何补充内容,同时避免直接大段摘抄大佬们的文章,该情况下也只附上了原文章链接供大家学习。本文旨在总结归纳,并希望给大家提供帮助,未用作任何商用用途。文章内容如有错误之处,望各位大佬指出。如果涉及侵权行为,将会第一时间对文章进行删除。
👉 个人博客主页 👈
📝 一个努力学习的程序猿
VitePress 介绍
笔者在最近发现了一个很好用的工具,又或者说是一个网站框架,迫不及待要跟大家分享。它就是 VitePress。
首先先阐述一下基于 VitePress 的特点,VitePress 能给大家带来什么,能做什么,有什么用(以下内容仅为个人观点,观点不同请轻喷):
相信各位在工作或学习过程中,肯定或多或少写过文档,常用的可能就是 Word、Markdown 等格式的文档。如果是学生的话,可能就是找一个合适的目录存放文档。如果是工作的话,写文档的数量可能就会很多了,而且通常需要满足多人预览或修改的需求,所以通常会借助一些其他应用,比如:SVN、xx笔记、某在线文档等。
使用上述应用很正常,大家平常也习惯用这些应用。但是这些毕竟都是别人开发好的应用,其中可能会有很多不需要的功能,比如广告等。而且它的样式也就不是我们能决定的了。如果想要自己开发一个前端项目去展示和管理这些文档是否可行?答案就是 VitePress。
VitePress 就是这样的一个所谓的网站框架,使用它可以快速创建一个简单的文档站点。使用的时候我们只需要了解一些简单的配置项,然后在项目里分结构存储 md 文档即可。这样一来,我们可以在除了要写一些必要的 Vue 之外,不用额外写 Vue 代码、不用写任何的样式,使用 VitePress 自带的页面架构和主题,进行文档的存储管理和文档展示(不过和其他应用在页面使用富文本编辑器不同,想要使用 VitePress 需要有基础的开发工具,比如 VSCode、Webstorm 等。然后在这个前端项目里,写基础配置项和 md 文档。也可以通过写代码,调整默认主题、给 md 文档加样式以及满足一些其他的需求)。换句话说,之前用各种应用管理文档,现在使用前端项目提交到 Git 仓库管理,和平常的开发很类似。
总结来说,使用 VitePress 可以快速创建一个简单的文档站点,且整个项目十分轻量,使用起来不繁琐。但是和其他应用对比就会衍生一些需要考虑的问题:首先,如果作为前端开发者来说其实没什么,但写文档的人不一定会 Vue,也可能没接触过 Markdown,这对写文档的人来说就需要上手时间,也需要学习相关用法。就算以上内容不由写文档的人考虑,那么将 Word 文档转成 Markdown 再放到项目中做处理,再提交到 Git 仓库,也无形中增大了管理文档站点人员的工作量,相比于使用现成的应用来说。但是如果真的有展示所有文档的需求,比如你的团队需要整理很多平台相关文档,需要汇报或者给团队内外展示,那么相比于使用其他应用来说,有一个属于自己团队的前端项目,进行页面展示,这显然看起来更有水平,不过确实可能会更费时。也会有些其他场景,比如可以在面试中利用该项目展示自己的技术栈;用该项目建一个自己的个人博客站点等等。所以,如果不考虑费时费力的因素,且确实需要存储并展示文档内容,只考虑最终效果的话,相比于使用其他应用,使用 VitePress 绝对是相对亮眼的选择。如下所示,快速创建站点的页面简单效果:
简单明确了它的用途后,现在说回到 VitePress 本身:
首先,它和普通的 Vue 项目不同,从名字上也可以看出来,它使用的是 Vite,而不是老熟人 Webpack。在我的 Vue3 专栏 其实有简单提到过 Vite,Vite 是尤大大开发的一款意图取代 Webpack 的工具。而通过对 Vite 的了解,最后整个项目一定是很轻的。当然 VitePress 必然也不是横空出世的,它的前身就是 VuePress。而推荐 VitePress,就是因为我们的项目可能就是想展示几个文档,基于 Webpack 的项目启动往往就要多出几秒。而 Vite 显然会很好的解决了这些问题:立即启动、按需编译、快速的热更新。
如果您对 Vite 感兴趣,建议您前往官网查看:
https://vitejs.cn/
如果您对 VuePress 感兴趣,建议您前往官网查看:
https://vuepress.vuejs.org/guide/#how-it-works
如果您对 VitePress 感兴趣,建议您前往官网查看:
https://vitejs.cn/vitepress/
其次更关注的就是使用方面。通过这一段时间对 VitePress 的使用,笔者发现 VitePress 真的很简单。它会有多种使用方式,这些用法在文章下方会有相关的使用示例。现在简单来说就是,我们可以直接引用写好的 Markdown 文档,也可以在 Markdown 文档中自由的混合 Vue 组件。它能实现这样操作的核心简述就是(详细原理可前往官网查看):
每个 Markdown 文档都会使用 markdown-it
(https://github.com/markdown-it/markdown-it),涉及到 YAML 的部分还会使用 gray-matter
(https://github.com/jonschlinkert/gray-matter)作处理,从而将其编译成 HTML ,然后作为 Vue 组件的模板处理。这就允许我们在 Markdown 文件中直接使用 Vue。在样式方面,我们也可以不做设置,VitePress 中会有一套默认的主题。
最后需要补充的是,在官网中的提示如下:如果使用 VitePress 的情景比较简单,比如只是展示文档那还好。如果想要用于更正式的环境(比如想要商用或大型项目),由于 Vite 仍需要稳定和持续完善,所以不建议使用在任何正式的环境(您也可以选择使用 VuePress,参照上文给出的官方文档)。
【图片截取自 VitePress 中文网】
话不多说,接下来创建 VitePress 项目。
创建 VitePress 项目
如果您已经有了一个本地项目,那么可以直接查看第四步。
第一步:找一个合适的位置,创建并进入目录
第二步:在目录中打开终端,输入 npm install -g yarn
(如果已经安装 yarn 请看第三步):
第三步:初始化项目,输入 yarn init
,然后输入一些项目基本信息:
第四步:本地安装 VitePress,输入 yarn add --dev vitepress
:
第五步:运行项目。输入yarn vitepress dev docs
:
也可以在 package.json中添加 scripts 便捷启动,比如:
"scripts": {
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs",
"docs:serve": "vitepress serve docs"
}}
添加之后,就可以通过输入 yarn docs:dev
运行项目:
第六步:运行后,VitePress 就会在 http://localhost:3000 启动一个热重载的开发服务器,可以前往查看。只不过我们现在没有写任何内容,所以它是 404:
现在,就可以正式开始 VitePress 之旅了!
VitePress 基础项目结构
通过前文的内容,我们已经创建了一个VitePress的空项目:
为了更好的使用,在 VitePress 的官方文档中为我们设计了基础的项目结构,只不过需要我们手动创建:
【图片转自 VitePress 中文网】
参照上图,创建完成:
在这里简单说一下文件的功能,关于每个文件更详细的内容将在下文总结。
1、config.js
该文件存储在 .vitepress 目录中,是必要的配置文件。比如可以配置站点的标题、描述、整个站点的页头(页眉)、首页的页脚、跳转其他页面的路由链接,甚至可以配置广告。其中具体的配置项将在下文总结。
2、index.md
该文件就是整个站点的首页。在没有该文件的时候就会像最开始创建项目一样直接进入一个 404 的页面。(其中内容具体怎么使用,将在下文的使用示例中展示)
在这里做一个十分简单的示例,给大家体验一下:
index.md:
# 测试
测试首页
config.js
export default {
title: 'Hello VitePress', // 站点的标题
description: '第一个 VitePress' // 站点的描述
}
效果:
此时启动项目,就可以发现首页不再是 404 了,而是 index.md 中的内容。且首页的 title 确实已经做了修改。此时可以注意页面导航栏中的页面标签,它的规则是:页面从上到下检索到的第一个h1标题 + | + config.js 中的 title。除此以外,页面标签也有其他的设置方式,而其他方式将在下文预定义变量中着重表述。
config.js
config.js 中的内容就像在基础项目结构里展示的那样,需要导出一个 JavaScript 对象。其中它的一些常用配置项总结如下:
【表格总结自 VitePress 和 VuePress 中文网】
配置 | 说明 | 类型 | 默认值 |
---|---|---|---|
title | 站点的标题,显示在导航栏中,如上例一样 | string | VitePress |
description | 站点的描述。这将作为<meta> 标记渲染在页面HTML中 | string | A VitePress site |
base | 站点的base URL | string | / |
举个例子,如果我们做了以下设置(做了该设置需要重启项目查看效果):
export default {
base: '/csdn/'
}
那么当我们再次启动项目的时候,它的路径就会是:
在使用的时候需要注意,在配置 base 的时候,需要像上例一样,必须以 /
开头,以 /
结尾。因为 base 会自动的被插入到其他配置中所有以 /
开始的路径之前,所以只需要在 config.js 中指定一次。
最重要的是:一旦设置了 base,就一定需要注意对静态资源的处理。在这里简单提一下,详细内容在下文 静态资源处理 标题说明。
配置 | 说明 | 类型 | 默认值 |
---|---|---|---|
lang | 站点的 lang 属性 | string | en-US |
export default {
lang: 'zh-CN'
}
对于这个配置,大家应该不陌生了。它就是来设置页面的语言类型。比如,这个属性将作为 <html lang="zh-CN">
标记渲染到页面HTML中。
注意,lang 属性只会通过 vitepress build 构建站点时添加,通过 vitepress dev 渲染时不会出现。
配置 | 说明 | 类型 | 默认值 |
---|---|---|---|
head | 浏览器页面标签图标设置 | array | - |
关于该配置,笔者也是在网上找了好久,就是浏览器当前页面标签前面的这个小图标。
后来通过查找找到了设置方式,尊重原作者,您需要前往原文章查看:
https://blog.csdn.net/qq_42460209/article/details/125647447
配置 | 说明 | 类型 | 默认值 |
---|---|---|---|
outDir | 打包目录设置 | string | - |
如果需要打包的话,我们先可以使用 vitepress build docs 或 yarn docs:build 试一下。此时我们可以发现,它被打包在了 docs 》 .vitepress 目录中,打包文件名叫 dist。
如果要调整它,我们可以用这样的方式:
export default {
outDir: './.vitepress/document', // 打包文件从dist改成document
}
配置 | 说明 | 类型 | 默认值 |
---|---|---|---|
themeConfig | 主题配置 | object | - |
themeConfig 中有很多配置,如下所示。
themeConfig的配置
themeConfig的常用配置:
配置 | 说明 |
---|---|
siteTitle | 顶部导航栏的标题 |
logo | 顶部导航栏标题前的图标 |
nav | 顶部导航栏的路由 |
socialLinks | 顶部导航栏右侧关联社交平台或代码仓库等的路由 |
sidebar | 左侧边导航栏的路由 |
outlineTitle | 右侧边导航栏的标题 |
footer | 首页最底部的配置(主要用来设置版权) |
接下来对 themeConfig 的配置进行一个演示和说明。首先先从顶部导航栏说起。
themeConfig使用示例一:顶部导航栏
使用示例:
config.js
export default {
title: 'CSDN', // 所有文档的浏览器标签title
description: 'CSDN只爭朝夕不負韶華', // 会渲染成<meta>标签
lang: 'zh-CN',
themeConfig: {
siteTitle: 'CSDN只爭朝夕不負韶華',
logo: '/logo.jpg',
nav: [
{ text: '菜单1', link: '/menu1/', activeMatch: '/menu1/' },
{ text: '菜单2', link: '/menu2/', activeMatch: '/menu2/' }
],
socialLinks: [
{ icon: 'github', link: 'https://blog.csdn.net/qq_45613931' }
],
footer: {
message: 'CSDN只爭朝夕不負韶華',
copyright: 'Copyright © 2022-present CSDN'
}
}
}
效果:
相信各位看到效果之后,根据之前表格的介绍,应该能理解各自的使用了,和用例一样使用即可。不过在这里还需要说明一下:nav 、socialLinks、logo(静态资源处理)。
themeConfig:nav
对于 nav,其实就是在给顶部导航栏配置一个路由:
{ text: '菜单1', link: '/menu1/', activeMatch: '/menu1/' }
比如上例中,
http://localhost:3000/menu1/
就会跳转到菜单1的页面里;
http://localhost:3000/menu2/
就会跳转到菜单2的页面里。
其中,这个路由是由 link
决定的。而 activeMatch
将会决定在什么路由下,对应的菜单会亮起。比如点击菜单1,因为此时的路由是:http://localhost:3000/menu1/
,匹配到了 activeMatch ,所以菜单1亮起。
如果你将 activeMatch 改的和 link 不一样,那么你就会发现,当你点击菜单1,菜单1就不会高亮了,但是会进入页面。因此通常 activeMatch 和 link 是一致的。
而点击 菜单1 会进入什么页面呢,这将会从当前项目的目录中寻找。比如这么设置之后:
{ text: '菜单1', link: '/menu1/', activeMatch: '/menu1/' }
那就会在 docs 目录下,找 menu1 的目录,然后默认进入目录下的 index.md。所以我们要像下图这样创建目录:
这样一来,点击 菜单1 就不会是 404 了。
而为什么 /menu1/
的路径会在 docs 目录下查找,估计是 VitePress 进行了根目录设置。笔者在这里也未进行深究,之后也还会遇到类似的用法,后续再进行说明。但是静态资源的路径需要额外注意,在下文的静态资源处理中有相关说明。
themeConfig:socialLinks
然后说一下 socialLinks,比如在上面的使用示例中是这样的。
socialLinks: [
{ icon: 'github', link: 'https://blog.csdn.net/qq_45613931' }
]
我们可以发现,在使用上就是写上了指定的 icon 就会展示对应的图标,点击图标就会跳转进 link 的链接。但这个 icon 明显不是个相对路径或绝对路径,显然是内部组件设定好的,笔者也进行了尝试,试图写入一个相对路径或绝对路径,但不会展示想要的图标。那比如我想把这个图标改成 csdn 的,该怎么做呢?笔者找了好久,百度没有、VuePress没有、VitePress也没有,官方文档中根本找不到答案。那没办法了,只能使用出杀手锏了,直接看源码。
我们从图标入手,找到关键信息:
然后全局搜索肯定能找到这个 github 图标。果不其然,找到了:
我们可以发现,这个图标是个 svg 图标,同时被存储在 VPIconGitHub
组件中。然后再找哪里使用到了 VPIconGitHub
。果不其然,找到了:
到了这就发现问题该如何解决了。我们可以看到,socialLinks中有很多的默认图标,比如:facebook、Twitter、YouTube 等等。那我们只需要在这里补充一个想要的图标就行了(svg格式)。
顺便再总结一下,如何在这里使用 svg 格式图片:
首先,我们找到一个可用的 png 或 svg 格式图片。笔者一直都在 iconfont 网站中找,在这里也推荐给大家:https://www.iconfont.cn/search/index?searchType=icon&q=csdn
在这里随便下载个想要的图片就OK了(如何下载应该不用详细总结了吧)。
如果用 png 图片也可以,我们找好 png 图片后,随便在网上找一个 png 转 svg 的网站https://www.aconvert.com/cn/image/png-to-svg/ 进行转换就可以了。
当我们拿到 svg 格式的图片后,具体是这样的:
在这个路径下,创建并引入图标的 Vue 组件:
VPIconCSDN 中的 svg 内容,就是把刚才下载的 svg 图片用文本工具打开,将其中 svg 标签的部分拿出来就OK了。
看一下效果:
socialLinks: [
{ icon: 'csdn', link: 'https://blog.csdn.net/qq_45613931' }
]
成功。那么通过源码,我们也就看出来为什么这里的 icon 不能写相对路径、绝对路径了,因为它就是个传参字段,根据传参来展示不同的图标。
静态资源处理
之前已经提到过几次需要注意静态资源处理的情况,一次是使用路由 nav 时提到,一次是 config.js 中 base 的配置提到,比如使用路由 /menu1/
会以 docs 目录为根目录寻找。
而对于如果要使用图片的话,这个路径就需要注意了。比如在 themeConfig 中,对 logo 有这样的设置:
logo: '/logo.jpg',
那么它的根目录还会是 docs 目录吗?这个时候,它会去 public 中寻找。也就是说,你需要有这样的一个 public 目录:
如果在 md 文档中引入 public 中的图片,方式是这样的:
![pic](/logo.jpg)
因为之前提到过,VitePress 支持在 md 文档中写 Vue,所以最后无论是用 img 标签的方式,还是 md 的方式,一定会碰到相对路径和绝对路径。如果是用相对路径,那肯定没问题。如果是用绝对路径,那就需要注意下面的问题了:
在上文提到了一个关于 base 的配置,比如:
export default {
base: '/csdn/'
}
这样写的时候,它的路径会是:
那么有过经历的开发者应该发现了,因为路径发生了改变,所以最后部署成功后,就会导致使用绝对路径的图片获取不到。也就是说,此时在文档中使用的绝对路径的图片,现在应该调整成这样:
![pic](/csdn/logo.jpg)
需要补充的是:config.js 中使用的绝对路径是不需要加上 base 设定的前缀的。其原因笔者未进行深究。也就是说,在其他地方使用 public 的图片要改成:
![pic](/csdn/logo.jpg)
但是在 config.js 中,不需要进行调整:
logo: '/logo.jpg',
themeConfig 使用示例二:侧边导航栏
使用示例:
config.js (只引入 menu1Siderbar 举例)
import menu1Sidebar from "./menu1Sidebar";
export default {
title: 'CSDN',
description: 'CSDN只爭朝夕不負韶華',
lang: 'zh-CN',
themeConfig: {
siteTitle: 'CSDN只爭朝夕不負韶華',
logo: '/logo.jpg',
outlineTitle: '当前页面',
nav: [
{ text: '菜单1', link: '/menu1/', activeMatch: '/menu1/' },
{ text: '菜单2', link: '/menu2/', activeMatch: '/menu2/' }
],
sidebar: {
'/menu1/': menu1Sidebar
},
socialLinks: [
{ icon: 'csdn', link: 'https://blog.csdn.net/qq_45613931' }
],
footer: {
message: 'CSDN只爭朝夕不負韶華',
copyright: 'Copyright © 2022-present CSDN'
}
}
}
menu1Sidebar.js
const commonPath = '/menu1';
export default [
{
text: '侧边栏1',
collapsible: true,
collapsed: false,
items: [
{ text: '文档1', link: `${commonPath}/a.md` },
{ text: '文档2', link: `${commonPath}/b.md` }
]
},
{
text: '侧边栏2',
collapsible: true,
collapsed: true,
items: [
{ text: '文档3', link: `${commonPath}/c.md` },
{ text: '文档4', link: `${commonPath}/d.md` }
]
}
]
目录结构:
效果:
相信各位看到示例后,应该也能理解各自的使用了,和用例一样使用即可。再补充几点就是:参照好用例,创建好目录,然后点击顶部导航栏后,页面就将默认进入对应目录下的 index.md。然后因为设置了 sidebar,所以页面就出现了左侧边栏(不配置 sidebar 的页面就会和普通的页面一样)。
sidebar 的配置也很简单:text 就是侧边栏一级标题;collapsible 就是当前侧边栏是否允许折叠,collapsed 就是当前侧边栏是否在进入页面时默认展开,items 就是侧边栏二级标题和对应的路由。
{
text: '侧边栏1',
collapsible: true,
collapsed: false,
items: [
{ text: '文档1', link: `${commonPath}/a.md` },
{ text: '文档2', link: `${commonPath}/b.md` }
]
},
不过在这里其实没看到右侧边栏,接下来说一下 outlineTitle。
themeConfig:outlineTitle
右侧边栏其实不需要配置,它将会根据当前 md 文档的二级标题进行自动设置:
a.md
# 文档1
a.md
## 二级标题1
## 二级标题2
outlineTitle: '当前页面'
outlineTitle 就是用来设置右侧边栏的大标题,从上图中可以看到。如果不设置 outlineTitle 的话,它的默认值是 on this page。
补充说明
最后还是要补充说明一些内容,显然的是 config 和 themeConfig 的配置肯定远远不止以上内容,以上仅为笔者在使用 VitePress 过程中留意到的常用内容,更多的配置项需要各位参考百度、VuePress、VitePress官网查看。
VitePress
https://vitejs.cn/vitepress/
VuePress
https://v2.vuepress.vuejs.org/zh/reference/default-theme/config.html
不过需要说明的是,之所以这里也推荐查阅 VuePress,是因为 VitePress 的官网给的配置项少的可怜,如上文内容一样,可能需要查源码才能找到该如何配置。而 VitePress 的前身是 VuePress,所以还是有些可以共通的配置项,但是需要自己尝试才能知道在 VitePress 中能不能用。所以如果出现了找不到的配置项,建议大家翻翻源码,是能够发现一些使用方法的,比如全局搜索 outlineTitle 就可以找到默认主题(themeConfig)的配置项:
在默认主题的方法里,甚至还有广告的配置项。感兴趣的话,大家可以查源码查阅。
再比如全局搜索 themeConfig 就可以找到 config 的配置项:
VitePress 中 md 文档的基本使用
上文总结了很多配置项,现在终于来到该如何使用的说明上。不过还是先说一些题外话。
首先在文章的开头提到过,这其实是个 Vue 项目,无论是 VuePress 还是 VitePress,它本质上就还是 Vue、Vue Router、Webpack(Vite)驱动的单页应用。不过我们在使用时,创建的文件将是以 .md 为后缀,而不是像 Vue 项目里那样的 .vue,也就是说我们会在 md 文档中编辑我们想要的内容。而它的转换原理在文章的开头和官方文档中都有说明,没注意到的话可以回到顶部查看。其次,在前文的叙述中,提到了使用 VitePress 会有多种使用方式:
1、纯 Vue 用法(但是和写 Vue 还是有区别,详细内容在下文说明)
2、纯 Markdown 文档用法(推荐)
3、YAML + Vue
4、YAML + Markdown(推荐)
5、YAML + Vue + Markdown(推荐)
其中相关的用法,在文章下方会有相关的使用示例。其中笔者个人推荐的方式是 2、4、5。在这里想简单说明一下:首先,我们可以看到部分方式里有使用到 YAML,而 YAML 的作用就是用来给对应文档做一些配置,当然你也可以用 JSON 来做配置,相关的使用在文中下方有相关说明。所以 YAML 并不是一个必选项。而各个方式的优劣性,将在使用示例后总结。
在本文中将不会介绍 Vue 和 Markdown 本身的基础用法,主要是总结在 VitePress 中该如何使用这些内容。其中 3,4,5 使用示例将在下文说明。
由于在 VitePress 用法中,YAML 是比较重要的内容,在其中可以对页面进行相关的配置和主题设定,所以在下文先简单总结一下 YAML 的基本使用方式。如果不想了解 YAML 也没关系,它也可以用 JSON 来替代,您可以直接跳到关于 frontmatter 块的说明部分。
如果想了解关于更多 Vue 的内容,您可以前往我的以下专栏查阅:
Vue 专栏: https://blog.csdn.net/qq_45613931/category_9941207.html
Vue3 专栏:https://blog.csdn.net/qq_45613931/category_10525285.html
如果想了解关于 Markdown 基础使用的内容,由于网上总结的文章有很多,感兴趣的话建议您自行查阅。
除此以外,VitePress 官网还有自己总结的扩展用法,为了避免大篇幅说明和引用,建议您自行前往查阅: https://vitejs.cn/vitepress/guide/markdown.html
YAML说明
在本小节将只总结后续需要的用法,更详细全面的内容,为了避免大篇幅引用,您可以前往以下文章查阅:https://www.runoob.com/w3cnote/yaml-intro.html
对于 YAML,可以把它理解成类似于 XML、JSON 文件的一种,通常用作配置文件,配置文件后缀为 .yml。不过 YAML 相比于它们来说会有更精简的语法。在 VitePress 中,通常将使用 YAML 的这部分内容叫做 YAML frontmatter 块。我们将会使用 YAML 精简的语法,以一种紧凑且可读的格式,在 md 文档中存储数据。
YAML 的基本语法如下:
(1)大小写敏感
(2)使用缩进表示层级关系
(3)缩进不允许使用tab,只允许空格
(4)缩进的空格数不重要,只要相同层级的元素左对齐即可
(5)‘#’ 表示注释
YAML 的数据类型如下:
(1)对象:键值对的集合
(2)数组:一组按次序排列的值
(3)纯量:单个的、不可再分的值
1、YAML对象
上文提到过 YAML 的语法是很精简的,我们可以简单做个比对。比如我们在 Vue 中写个对象:
form: {
name: 'csdn',
test: 'test'
}
现在在 YAML 中,我们只需要用缩进表示层级关系即可。比如在以下代码中,它就会将上下行中处于相同缩进层级的行(直到碰到不是一个层级的行为止),作为对象中的数据(下文的相关用法同理,不再赘述):
form:
name: csdn
test: test
在上文的基本语法中提到过,我们还需要注意:缩进不允许使用 tab,只允许空格。缩进的空格数不重要,只要相同层级的元素左对齐即可。
2、YAML数组
在使用数组的时候,以 -
开头的行,将会和上下文处于相同缩进层级的行(直到碰到不是一个层级的行),构成一个数组,比如:
list:
- A
- B
- C
就相当于:list: ['A', 'B', 'C']
如果是多维数组,那就是:
list:
-
- A
-
- B
就相当于:list: [['A'], ['B']]
而我们通常都会从接口获得这样的数据:
tableData: [
{
name: 'csdn',
test: 'test'
},
{
name: 'csdn',
test: 'test'
}
]
我们现在只要将 YAML 对象和 YAML 数组组合在一起就可以了:
tableData:
- name: csdn
test: test
- name: csdn
test: test
这就是在 VitePress 中最常用的用法。
3、纯量
纯量就是最基本的值,而对于值大家也知道,肯定有所谓的数据类型。在 YAML 中将会包括:
字符串
布尔值
整数
浮点数
Null
时间
日期
不过我们在 YAML 中使用的时候不用像其他语言那样定义数据类型,也不用太关注数据类型,我们只需要使用即可。简单例子如下(根据类型把它们放在不同的数组、对象中):
【代码选自菜鸟教程】
boolean:
- TRUE #true,True都可以
- FALSE #false,False都可以
float:
- 3.14
- 6.8523015e+5 #可以使用科学计数法
int:
- 123
- 0b1010_0111_0100_1010_1110 #二进制表示
null:
parent: ~ #使用~表示null
string:
- 哈哈
- 'Hello world' #可以使用双引号或者单引号包裹特殊字符
- newline
newline2 #字符串可以拆成多行,每一行会被转化成一个空格
date:
- 2018-02-17 #日期必须使用ISO 8601格式,即yyyy-MM-dd
datetime:
- 2018-02-17T15:02:31+08:00 #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
4、引用
在平常,可能多个对象、数组要复用相同的数据,那就可以使用引用。&
用来建立锚点,<<
表示合并到当前数据,*
用来引用锚点。比如:
defaults: &defaults
name: csdn
list:
num: 1
<<: *defaults
test:
num: 2
<<: *defaults
它相当于:
defaults:
name: csdn
list:
num: 1
name: csdn
test:
num: 2
name: csdn
另一个例子:
- &showell Steve
- Clark
- Brian
- Oren
- *showell
它相当于:
[ 'Steve', 'Clark', 'Brian', 'Oren', 'Steve' ]
以上就是需要了解的 YAML 使用内容。
frontmatter 块的说明
在了解了 YAML 的基础用法之后,就可以在每个 Markdown 文档中使用 YAML 了。在每个 Markdown 文档中包含了 YAML 这部分内容的区块就是 YAML frontmatter 块。这个 frontmatter 块将是一个由三个点划线包裹的区块,且这个区块必须位于当前 Markdown 文件的顶部,如果使用 YAML 那么其中必须是有效的 YAML 格式。比如需要这样用(放在 md 文档的顶部):
---
title: VitePress
titleTemplate: Test VitePress
---
在 frontmatter 块中,可以分为三种变量:预定义变量、自定义变量、主题组件变量。
预定义变量就是 VitePress 帮我们设定好的变量,只要在 frontmatter 块中使用,就会带来特定的效果;
主题组件变量就是我们想要使用的某个 VitePress 主题帮我们设定好的变量,只要在frontmatter 块中使用,就会带来特定的效果;
而自定义变量就是没有任何含义和效果,完全是我们自己创建的用于使用的变量。
其中关于预定义变量和主题组件变量的具体说明和使用将在下文展示。
而在上文说明 YAML 的时候也提到了,frontmatter 块主要是存储这些数据的。如果我们想要使用的话,以上的这些变量都可以通过 $frontmatter
调用。这个调用的演示将在下面的使用示例中展示。
除此以外,VitePress 也支持 JSON 格式的 frontmatter,那就需要注意以花括号开始和结尾。比如:
---
{
"title": "VitePress",
"titleTemplate": Test VitePress
}
---
而在本文将只使用 YAML frontmatter。
使用示例一:YAML frontmatter + Markdown
对于这种方式就很简单了,您依然可以像使用 Markdown 那样,在 YAML frontmatter 的下方书写。如果需要使用预定义变量、自定义变量、主题组件变量时,写入 YAML frontmatter 中即可(具体变量下文说明)。示例如下:
index.md
---
title: VitePress
titleTemplate: Test VitePress
---
# {{ $frontmatter.title }}
首页内容
运行效果如下:
使用示例二:YAML frontmatter + Vue
在 md 文档中如果要使用 Vue,和我们平常使用 Vue 会有一点点区别,感兴趣的话可以查看以下内容。您也可以直接查看使用示例三,没有任何区别的,完全的使用 Vue。
使用示例:
index.md
---
title: VitePress
titleTemplate: Test VitePress
---
<style>
.testTitle {
border: 1px solid black;
}
</style>
<script setup>
const tableData = [
{
test: 'test',
name: 'csdn'
}
]
const testList = ['1','2','3']
</script>
<div class="testTitle">
<h1>{{ $frontmatter.title }}</h1>
<h1>{{ tableData[0].name }}</h1>
<div v-for="(item, index) in testList" :key="index">
<h1>{{ item }}</h1>
</div>
</div>
运行效果如下:
需要说明的是:style、script、页面主体内容,可以放在 YAML frontmatter 下的任意位置,它们没有先后排列顺序。而在使用上,其实只有 style 和之前用法一样,所以在这里需要额外说明 script 部分和之前Vue的页面 template 部分。
首先说页面的主体内容,也就是平常我们在使用 Vue 时,用 template 包裹的标签部分。在 VitePress 使用时需要注意,此时我们不需要用 template 包裹这些标签,使用的话是会报错的。同时也不需要让这些标签,都在当前 md 文档的一个标签内部。比如这样也是可以的:
<div class="testTitle">
<h1>{{ $frontmatter.title }}</h1>
<h1>{{ tableData[0].name }}</h1>
<div v-for="(item, index) in testList" :key="index">
<h1>{{ item }}</h1>
</div>
</div>
<div>不用在一个标签内</div>
能这样做的原因是:就像文章最开始的时候说到,md 文档最终会在 VitePress 的转换下,变成 Vue 的内容。而查看源码可以发现,它在外层帮我们加好了一层 template,随后利用插槽将转换好的内容,插入到了不同的情况中。在其中也可以看到帮我们设置的 404 页面以及可以根据主题变量 layout ,出现不同的页面效果。具体的 layout 使用会在下文说明,这里只是告诉大家可以不用在乎是否被 template 标签包裹。
除此以外就需要注意,script 要使用 <script setup>
。setup 不写的话,页面就会报错。对 Vue3 有了解的话就知道,setup 其实是 Vue3 中的内容。所以笔者在这里推测(以下内容笔者未真实考证,不保证正确):在这里写 setup 应该是去告知 script 中的内容用 Vue3 来解析,然后放进 setup 函数里。只不过我们不用定义响应式对象?(不确定)
所以看到这您应该明白了,如果 script 中的内容只想使用数据,且您只使用过 Vue2 ,那么像上例一样使用就可以了,也不用了解更多使用内容。不过,笔者还是测试了一下,其中是否能够使用 Vue3、Vue2 的其他用法。浅试了一下事件,发现可以是可以,但是页面数据不会更新。或许需要其他操作吧,笔者在这里也就不进行测试了。因为在 md 文档中完全使用 Vue 并不是笔者推荐的方式(不过仍有必须要写 Vue 的情况,这主要取决于主题变量 layout,这将在下文说明),而且如果真要使用其他用法可以直接像下文的使用示例三那样使用,省去很多麻烦,且要用 Vue 展示文档也完全用不到其他复杂操作,同时这些方式的使用也没有官方文档的说明。
通过以上的使用可以发现:在 md 文档中写的 Vue 和平常写的显然不一样,而且会有不少的限制。所以,如果不想用以上的使用方式也是可以的,还有另一种方式能够让我们更舒适的使用 Vue 来替代上面说的一切内容。那就是直接引入 Vue 组件。
使用示例三:在 Markdown 中引入 Vue 组件
使用示例如下:
test.vue
<template>
<div class="test">
<div>测试 test 组件</div>
<button @click="addOne">测试按钮</button>
<div>{{ age }}</div>
</div>
</template>
<script>
export default {
data() {
return {
age: 17
}
},
methods: {
addOne() {
this.age++;
}
}
}
</script>
<style scoped>
.test {
border: 1px solid darkgrey;
}
</style>
index.md
---
title: VitePress
titleTemplate: Test VitePress
---
# {{ $frontmatter.title }}
<test />
<script setup>
import test from './test.vue'
</script>
直接引入 Vue 组件相比于使用示例二要舒服的多,和平常写 Vue 一样使用就可以了,在 md 文档中引入 Vue 参照示例即可。在官网中还有很多关于在 Markdown 中使用 Vue 的内容,感兴趣的话可以前往查阅:https://vitejs.cn/vitepress/guide/using-vue.html
使用示例四:YAML frontmatter + Vue + Markdown
示例如下:
index.md
---
title: VitePress
titleTemplate: Test VitePress
---
# 测试1
<style>
.testTitle {
border: 1px solid black;
}
</style>
# {{ $frontmatter.title }}
<div class="testTitle">
<h1>{{ $frontmatter.title }}</h1>
<h1>{{ tableData[0].name }}</h1>
<div v-for="(item, index) in testList" :key="index">
<h1>{{ item }}</h1>
</div>
</div>
# 测试3
# 测试4
<script setup>
const tableData = [
{
test: 'test',
name: 'csdn'
}
]
const testList = ['1','2','3']
</script>
# 测试5
运行效果如下:
需要注意的是:md 的用法不能在 script、style 以及其他标签的内部,否则会被当作 js、css、html 来看待,且 md 用法也不能写在 html 标签的下一行,否则就会像上例一样,被当作 html 来看待。除此以外,md 的用法可以混杂在 YAML frontmatter 下的任何一个地方。当然,您也可以参照使用示例三,直接引入 Vue 组件。这样就不用考虑以上需要注意的事项。
最后仍然需要提示,存在一种情况,让 md 文档中只能写 Vue,这取决于 YAML frontmatter 中的主题变量 layout。该用法在下文说明。
多种使用示例的对比总结
在展示过所有的使用示例后,最后阐述一下相关用法的优劣点以及笔者推荐哪个用法。
先说一下使用 Vue 的优势:
1、展示文档时,我们很可能会想要改变 md 文档中固定的一些样式,比如表格的样式、某个文本的样式。而这样的操作,用 css 来设置显然对笔者来说是更方便的;
2、我们在写 md 文档时,可能会遇到一些大篇幅重复的内容,比如样式完全相同的 N 多行类似的内容,那么在文档中肯定是要对应写 N 多行的。但是利用 Vue 的话,我们就可以用 v-for 来解决了。当然效率上的差异本身没那么大,它的效果可能就是少写了几行代码。即可以利用 Vue 特性。
而使用 Vue 的劣势笔者认为会比 Vue 的优势更突出,这也是笔者先前不推荐完全用 Vue 的原因:
1、要是只在 Markdown 文档中写 Vue 难免是有些繁琐的,会有上文使用示例中演示的一些限制。当然,你可以用 Vue 组件引入的方式来解决以上繁琐的麻烦。
2、但是只要使用 Vue,最关键的问题就是,该 md 文档在除了 VitePress 的其他工具中,完全用不了,因为别的工具不会解析 Vue。所以只要是个工作团队,你不可能强求写文档的同事会写 Vue ,而且如果写文档的同事已经把 md 文档写好,那就可能稍微改一些内容,直接放入项目中就可以展示了。完全没有必要再将其转成 Vue,从而增加自己的工作量。如果用纯 md 文档写,或者混着写,在别的工具中想要查看时,至少改动都会小一些。
3、其次,如果不需要改变样式的情况下,很多的文本类标签,比如 <h1>、<i>、<b>、<strong>
等等,再带上其他的功能类标签,比如 <a>、<img>
等等,在 md 文档中都会有对应的用法,比如:#、*、**、![]()
等等。所以也不需要担心基础的功能在 md 中没有。笔者觉得相比于写标签,不如使用 md 用法或者VitePress md 扩展用法。
所以综上所述,如果没有样式的调整或者其他需求,建议用纯 md 文档写,配合 YAML 写一些 VitePress 配置。这样一来在别的工具也能直接查看,其他同事也只需要写 md 文档就可以了,不需要写文档的同事学习 Vue。如果真的需要写 Vue(layout 变量下文说明),或者做一些功能调整和样式优化,稍微写一点 Vue 即可。此时的 Vue 也建议用组件去写,然后在 md 引入,这样如果要删除也方便一些。所以这也就是为什么,笔者推荐以下这三个用法,当然最推荐的就是方法 2,因为在任意支持 md 的工具中都能直接用或者修改程度极小:
2、纯 Markdown 文档用法(推荐)
4、YAML + Markdown(推荐)
5、YAML + Vue + Markdown(推荐)
当然以上用法的取舍最后还是要靠各位自行决定。
预定义变量
预定义变量就是 VitePress 帮我们设定好的变量,只要在 frontmatter 块中使用,就会带来特定的效果。
接下来就来看一些常用预定义变量:
【表格总结自 VitePress 中文网】
配置 | 说明 | 类型 | 默认值 |
---|---|---|---|
title | 当前页面的标题 | string | h1_title |
titleTemplate | 当前页面的副标题 | string | - |
在文章前面的 VitePress 基础项目结构中,曾经演示过在 config.js 中设置的 title 的效果以及页面导航栏中的页面标签的设定规则。在这里将进行总结:
首先 config.js 的 title 设置为 config
export default {
title: 'config'
}
1、如果页面中没有设定 title 和 titleTemplate:
index.md
测试
# 测试2
此时页面标签将展示为:页面从上到下检索到的第一个 h1 标题 + | + config.js 中的 title
如果此时页面中没有 h1 标题:
index.md
测试
测试2
此时页面标签将展示为:config.js 中的 title + | + config.js 中的 title
2、如果页面中仅设定 title:
---
title: index
---
测试
#测试2
此时页面标签将展示为:页面中的 title + | + config.js 中的 title
3、如果页面中仅设定 titleTemplate:
---
titleTemplate: indexTemplate
---
测试
#测试2
此时页面标签将展示为:config.js 中的 title + | + 页面中的 titleTemplate
4、如果页面中设定 title 和 titleTemplate:
---
title: index
titleTemplate: indexTemplate
---
测试
#测试2
此时页面标签将展示为:页面中的 title + | + 页面中的 titleTemplate
总结来说就是,页面中设置了就拿页面的,页面没有就去拿 config 的。为了避免考虑这么多情况,有需要的话,通常会给每个页面设置 title 和 titleTemplate。
配置 | 说明 | 类型 | 默认值 |
---|---|---|---|
sidebar | 是否显示左侧边栏 | boolean | undefined |
navbar | 是否禁用导航 | boolean | undefined |
更多预定义变量,您可以通过百度查阅或前往官网查看。
而为什么只有这么几个预定义变量,而且还需要查阅 VuePress,在介绍 config.js 时就有了说明,在这里再说明一次:因为 VitePress 的官网给的配置项极其少,而 VitePress 的前身是 VuePress,所以还是有些可以共通的配置项,但是需要自己尝试才能知道在 VitePress 中能不能用。如上文内容一样,您也可以通过查源码找到寻找该如何配置。所以如果出现了找不到的配置项,建议大家翻翻源码,是能够发现一些使用方法的,比如全局搜索 frontmatter 就可以顺着找到所有配置项:
主题组件变量
主题组件变量就是我们想要使用的某个 VitePress 主题帮我们设定好的变量,只要在 frontmatter 块中使用,就会带来特定的效果。也就是说,主题组件变量其实就相当于预定义变量,只不过是专门用来调整主页布局的。
您可以前往官网查看:https://vitejs.cn/vitepress/config/homepage.html
不过目前官网没有详细说明,且笔者也没有像官网给的示例那样用。
先说一下,主题组件变量其实主要是用来快速配置主页的,其他的位置不推荐使用,详细的原因可以特别留意 layout 参数。
使用示例如下:
config.js
import menu1Sidebar from "./menu1Sidebar";
import menu2Sidebar from "./menu2Sidebar";
export default {
title: 'config', // 所有文档的浏览器标签title
description: 'CSDN只爭朝夕不負韶華', // 会渲染成<meta>标签,SEO用
lang: 'zh-CN',
head:[ // 页面标签图标
['link', { rel: 'icon', href: '/logo.jpg' }]
],
themeConfig: {
siteTitle: 'CSDN只爭朝夕不負韶華',
logo: '/logo.jpg',
outlineTitle: '当前页面', // on this page
nav: [
{ text: 'Vue', link: '/menu1/', activeMatch: '/menu1/' },
{ text: 'React', link: '/menu2/', activeMatch: '/menu2/' }
],
sidebar: {
'/menu1/': menu1Sidebar,
'/menu2/': menu2Sidebar
},
socialLinks: [
{ icon: 'csdn', link: 'https://blog.csdn.net/qq_45613931' }
],
footer: {
message: 'CSDN只爭朝夕不負韶華',
copyright: 'Copyright © 2022-present CSDN'
}
}
}
index.md
---
layout: home
title: index
titleTemplate: indexTemplate
hero:
image: /logo.jpg
alt: logo image
name: 只爭朝夕不負韶華
text: CSDN演示
tagline: 努力学习的程序猿
actions:
- theme: brand
text: CSDN个人主页
link: https://blog.csdn.net/qq_45613931
- theme: alt
text: VitePress中文网
link: https://vitejs.cn/vitepress/
features:
- title: HTML和CSS
details: HTML和CSS说明。
- title: JavaScript
details: JavaScript说明。
- title: jQuery
details: jQuery说明。
- title: Vue
details: Vue说明。
- title: React
details: React说明。
- title: Webpack和Vite
details: Webpack和Vite说明。
---
<script setup>
import { VPTeamPage, VPTeamPageTitle, VPTeamMembers } from 'vitepress/theme'
const members = [
{
avatar: 'https://www.github.com/yyx990803.png',
name: '只爭朝夕不負韶華',
title: '负责人'
}
]
</script>
<VPTeamPage>
<VPTeamPageTitle>
<template #title>
前端参与开发人员
</template>
<template #lead>
CSDN
</template>
</VPTeamPageTitle>
<VPTeamMembers
size="small"
:members="members"
/>
</VPTeamPage>
页面效果如下:
在上例 index.md 中已经使用了所有笔者常用的参数,在这里就不全部展开说明了。frontmatter 块中的参数,相信大家看一下例子,知道它是对应什么标题,会展示什么内容就可以了。通过以上的配置,您就可以快速的创建出这样一个默认主题的主页。如果您要添加内容,只要自己写 Vue 补充一下就可以了。而如何查看它们的更多参数,就像上文一直说的那样,查看源码就可以了,比如全局搜索 hero,您就可以找到它的组件和它的传参:
其他的组件都是同理,您可以通过查找源码的方式,找到它们的传参,也就可以不用找官网了,因为官网真的没有全面的文档。比如在上例中,笔者使用了VPTeamPage, VPTeamPageTitle, VPTeamMembers
组件。但是官网中没有提及 VitePress 可使用的组件及其使用方式,也没啥好办法,找源码吧。看看源码的话,能用的组件和它们的传参,您也就可以发现了。同时您也能更好的了解到 VitePress 的原理。
对于其他参数笔者就不多赘述了,主要想详细说一下 layout 这个参数,笔者在这上面踩了坑。
layout
在这里借助源码来进行相关的说明:
通过源码我们可以发现,layout 的传参无非就是 3 种:home、page、其他。在这里就不贴更详细的源码了,直接说结论:这三种不同的传参,可想而知,它们的样式已经在这几个组件内部设定好了,而我们最好也不要改它默认的样式(除非真的想让所有同类型页面的样式做调整),所以我们就要遵循这几种传参带来的样式效果。而笔者就在这方面踩了一下坑。在这里总结如下:
1、如果我们将 layout 设置成 home:
像上例一样,我们使用官方给的组件、预定义变量、主题组件变量达成了一个基础的效果。但此时在 index.md 中,将无法再使用 md 的用法,即此时只能使用 Vue。同时也需要注意到,此时的页面 width: 100%,不包含左右侧边栏。
2、如果我们将 layout 设置成 page:
此时,该页面就相当于是个极其普通的页面,我们依然只能使用 Vue。同时也需要注意到,此时的页面 width: 100%,不包含左右侧边栏。
且此时无法使用主题组件变量。它的原因可通过源码查明。
VPHome
也就是 layout 为 home 的组件中,引入了 hero、features
的组件,所以能使用主题组件变量:
但是 VPPage 中什么都没引入,所以就是个极其普通的 Vue 页面:
3、如果我们将 layout 不设置或传除了 home、page 以外的其他参数:
就比如上文的:themeConfig 使用示例二,此时的页面效果是这样的:
也就是说,无论你在 themeConfig 中有没有给当前页面设置左侧边栏或者有没有出现右侧边栏,那么页面的 width 不会是 100%,会预留出左右侧的空间。
总结一下就是:
能否支持主题组件变量 | 是否必须使用 Vue 用法 | 是否包含左右侧边栏 | |
---|---|---|---|
home | √ | √ | × |
page | × | √ | × |
其他 | × | × | √ |
笔者踩到的坑就在这个关系上。首先如果 layout 传了 home 和 page 的参数,那就代表着你不需要展示左右侧边栏,而这样的页面主要用于首页及其包含页面去使用,它们的区别就是你用 home 来代表它是主页以及能使用主题组件变量,用 page 来代表它是一个普通 Vue 页面。而如果不传或者传其他的话,就代表着该页面你应该想展示 md 文档,从而帮你给出左右侧边栏。比如:
点击顶部导航栏链接,跳转的路由都是在 config.js 中配置的,按常理来说,里面配置的都应该是要展示的 md 文档,此时你当然需要展示左右侧边栏,所以跳转到的页面都应该不写 layout。而如果你不想这么干,点击顶部导航栏仍然跳转到一个 layout 为 page 的 index.md 页面也可以,只不过需要注意此时没有左右侧边栏。
点击首页中任何的按钮,跳转的路由都是在当前页面配置的,比如上例的按钮改成:
hero:
actions:
- theme: brand
text: CSDN个人主页
link: /guide/index
那点击按钮后就会跳转到 docs 下的 guide 目录中的 index.md 中。而笔者遇到的坑就在这里。笔者希望点击首页的按钮,进入到一个其他页面中,也不需要侧边栏,同时仍然希望用 md 文档的写法那样写一个页面,所以就没写 layout。但是会发现,它的 width 不是 100%,而我又没给它配置左右侧边栏,所以左右就出现了大片空白。
而为了解决问题,笔者就给它改成了 layout 为 page,但是此时 md 的用法就失效了。后来就还是在 layout 为 page 的页面中写了一个 Vue 组件,完成了需求。所以大家需要注意 layout 的不同情况。
除了给定的主题组件变量外,VitePress 也允许我们自定义主题。笔者对自定义就不进行叙述了,感兴趣的话可以前往官网查看:https://vitejs.cn/vitepress/guide/customization.html。主要是官网描述的很少,而且在笔者看来,官网给的自定义主题方式,和引入 Vue 组件的方式也差不多,同时我们自己引入还能确保功能正确性。总之感兴趣的话,还是前往官网查看吧。
至此,基本的使用已经全部总结完毕。
由于在自己的工作和学习过程中,只查看某个大佬的教程或文章无法满足自己的学习需求和解决遇到的问题,所以自己在追赶大佬们步伐的基础上,又自己总结、整理、汇总了一些资料,方便自己理解和后续回顾,同时也希望给大家带来帮助,所以才写下该篇文章。在本文中,所有参考或引用大佬们文章内容的位置,都附上了原文章链接,您可以直接前往查阅观看。在原文章内容的基础上,若无任何补充内容,同时避免直接大段摘抄大佬们的文章,该情况下也只附上了原文章链接供大家学习。本文旨在总结归纳,并希望给大家提供帮助,未用作任何商用用途。文章内容如有错误之处,望各位大佬指出。如果涉及侵权行为,将会第一时间对文章进行删除。
👉 个人博客主页 👈
📝 一个努力学习的程序猿
更多推荐
所有评论(0)