【前端从入门到入土系列】pug基础语法
Pug 模板引擎:学习与使用
在前端开发中,模板引擎的使用可以极大地提高代码的可读性和可维护性。Pug
(也称为 Jade
)是一个流行的 Node.js
模板引擎,它使用简洁的语法来创建 HTML 结构。由于在vue3
文档中看到了Pug
的影子,便决定学习体验一番。
官网:https://pugjs.org/zh-cn/api/getting-started.html
安装与配置
首先,确保你的项目中已经安装了 Node.js
和 npm
(Node 包管理器)。然后,可以通过 npm
来安装 Pug
。在命令行中执行以下命令:
1 | npm install pug |
基础语法
Pug 的语法非常简洁,它使用缩进来表示 HTML 元素的层级关系,而不是使用传统的尖括号和结束标签。以下是一些基础语法的示例:
文档类型与 HTML 元素
1 | doctype html |
编译执行
1 | pug index.pug |
vscode 安装插件Pug beautify
缩进
pug
对空格敏感,有点类似python
对制表符tab
敏感。pug
使用空格作为缩进符,当然用soft tab也可行。同一级标签需保证左对齐。
1 | div |
渲染结果如下:
1 | <div> |
注释
pug
使用//-
或//
对代码进行注释,前者注释内容不出现在渲染后的html
文件中,后者反之。
1 | //- html中不包含此行 |
属性和ID
pug
将标签属性存放于括号()
内,多个属性之间以逗号或空格分隔。
此外,对于标签的id
和class
,pug
使用#
紧跟标签id
,使用.
紧跟标签class
,可以同时设置多个class
。
1 | h1#title Test title |
会被编译为
1 | <h1 id="title">Test title</h1> |
包含
为了方便代码复用,pug
提供了include
包含功能,以下代码会将_partial
目录下的head.pug
文件内容包含到当前调用的位置。有点C/C++
中内联函数的意思。
1 | doctype html |
继承
下面是一个简单的base
模板,通过block
定义了页面头部head
和内容body
。块block
有点类似C/C++
的抽象函数,需要在继承者中完成定义,填充具体内容。
1 | //- base.pug |
变量与插值
pug
中通过- var name = value
的形式定义变量
1 | - var intData = 100 |
需注意的是,在引用变量时,需要在引用位置加上
=
号,否则会默认将变量名当成普通字符串使用。
如果想要将变量与其它字符串常量或是变量连接在一起,就不能用等号了,而是应该用#{}
,该符号会对大括号内的变量进行求值和转义,最终得到渲染输出的内容。
1 | - var girl = 'Lily' |
条件语句
pug
的条件语句与其它语言类似,均是如下这般:
1 | - var A = {value: 'Test'} |
循环
pug
中使用each
和while
实现循环迭代,each
可以返回当前所在项的索引值,默认从0开始计数。
1 | //- each |
混合
Pug 允许你创建可重用的代码块,称为混合(mixin),以及包含其他模板文件。
1 | mixin list |
hexo 相关
在hexo
主题中使用pug
时,可以通过使用hexo
提供的全局变量config
,theme
来分别调用博客根目录下_config.yml
文件中的参数以及主题根目录下_config.yml
文件中的参数。
1 | //- blog config |
当然,pug
中可以直接使用hexo
提供的其它全局变量及辅助函数,使用方法详见hexo
的文档
在 vue3 的 template 中使用 Pug
尽管 Pug 有自己的语法,可以定义变量,可以有 if 和 case-when 条件分支和 each-in 遍历,有自己的插值方式 #{} , 但如果在 template 里使用 Pug 语言,则不建议使用这些语法,而应该结合 Vue 的指令(如 v-if , v-for )和 mushache 插值方式。主要有以下原因:
一致性和可预测性:Vue 提供了自己的模板语法,该语法在 Vue 社区中广泛接受和使用。使用 Vue 的指令和插值方式可以确保代码的一致性和可预测性,这有助于其他 Vue 开发者更容易地理解和维护你的代码。
集成和兼容性:Vue 的指令和插值方式与 Vue 的响应式系统紧密集成。使用 Vue 的语法可以确保数据的变化能够正确地触发视图的更新。而使用 Pug 的原生语法可能会导致一些意料之外的行为或兼容性问题。
工具链支持:Vue 的模板语法在 Vue 的官方工具链(如 Vue CLI、Vite 等)中得到了很好的支持。这些工具可以帮助你进行代码拆分、热重载、静态分析等操作。相比之下,使用 Pug 可能会增加配置的复杂性,并可能减少与 Vue 工具链的集成度。
社区支持:Vue 的模板语法拥有庞大的社区支持,这意味着你可以更容易地找到相关的教程、文档和社区讨论。而 Pug 的社区虽然也很活跃,但可能与 Vue 社区不完全重合。
可读性和维护性:虽然 Pug 提供了一种简洁的语法来编写模板,但对于不熟悉 Pug 的开发者来说,它可能会增加阅读和维护的难度。使用 Vue 的模板语法可以使代码更加直观和易于理解。
安装对应插件
1 | npm i pug pug-plain-loader |
插值,属性和指令
mushache
插值
1 | <script setup lang="ts"> |
这段代码中使用 mushache
对 title
进行插值
- 属性 每个元素的属性都应该写在其后面的圆括号中,除了
id
和class
可以简写。(所有的 指定都是属性,都应写在括号中)
1 | <script setup lang="ts"> |
v-if
条件分支
1 | <script setup lang="ts"> |
v-for
遍历
1 | <script setup lang="ts"> |
v-bind
和v-on
1 | <script setup lang="ts"> |
v-model
双向绑定
1 | <script setup lang="ts"> |
插槽
- 创建子组件(ChildComponent.vue)
在子组件中,可以定义默认插槽或具名插槽。例如:
1 | <!-- ChildComponent.vue --> |
- 在父组件中使用子组件的插槽 (ParentComponent.vue)
在父组件中,可以使用 <template>
标签和 v-slot
指令来定义插槽内容
1 | <!-- ParentComponent.vue --> |
在上面的例子中,父组件 ParentComponent 使用了 ChildComponent,并通过 标签和 v-slot 或 v-slot:namedSlot 来定义插槽内容。
使用作用域插槽
对于作用域插槽,你可以在子组件的 slot 标签上绑定属性,然后在父组件的插槽模板中通过 v-slot 的值来接收这些属性。
子组件中定义作用域插槽:
1 | <!-- ChildComponent.vue --> |
父组件中使用作用域插槽:
1 | <!-- ParentComponent.vue --> |
在这个作用域插槽的例子中,子组件通过 slot 标签的 :item=”someItem” 传递了一个响应式对象 someItem 到作用域插槽。父组件通过v-slot:scopedSlot="{ item }"
来接收这个对象,并在模板中使用它。
总结
在 Vue 3 中使用 Pug(也称为 Jade)作为模板引擎,具有一些明显的优点和潜在的缺点。
- 优点:
简洁的语法:Pug 的语法非常简洁,通过缩进和换行来表示元素之间的层级关系,减少了模板中的冗余代码。这使得代码更加清晰易读,也更容易编写和维护。
提高开发效率:由于 Pug 的语法简洁,开发者可以更快地编写模板,提高开发效率。同时,Pug 还支持混合(mixin)功能,允许开发者定义可重用的代码块,进一步减少重复代码。
强大的功能:Pug 提供了丰富的功能,如条件语句、循环、过滤器等,使得开发者能够在模板中实现复杂的逻辑。这些功能使得 Pug 在处理复杂页面布局和交互时具有很大的灵活性。
与 Vue 3 的良好集成:Vue 3 支持使用不同的模板引擎,包括 Pug。Pug 可以与 Vue 3 的响应式系统、组件系统等无缝集成,使得开发者能够充分利用 Vue 3 的功能和特性。 - 缺点:
学习成本:对于没有使用过 Pug 的开发者来说,需要花费一定的时间来学习其语法和特性。虽然 Pug 的语法相对简洁,但与 HTML 相比仍有一定的差异,这可能会增加学习成本。
社区支持:虽然 Pug 是一个流行的模板引擎,但相对于 HTML 来说,其社区规模可能较小。这意味着在遇到问题时,可能难以找到足够的资源和支持。
浏览器兼容性:由于 Pug 在编译时会转换为 HTML,因此在浏览器兼容性方面通常不会有问题。但是,如果开发者在 Pug 中使用了某些非标准的特性或语法,可能会导致在某些浏览器中出现问题。
工具链集成:虽然 Vue 3 支持 Pug,但某些 Vue 生态中的工具链(如 Vue CLI 插件、构建工具等)可能不完全支持 Pug 或需要额外的配置。这可能会增加项目的复杂性和配置成本。
因此,在选择是否使用 Pug 时,需要根据项目的需求和团队的实际情况进行权衡。