• pug模板引擎(原jade)


    前面的话

      为什么要引入pug,pug有什么特别之处呢?有一些嵌套层次较深的页面,可能会出现巢状嵌套,如下图所示

      在后期维护和修改时,一不小心少了一个尖括号,或者某个标签的开始和闭合没有对应上,就会导致DOM结构的混乱甚至是错误。所以,有人发明了HAML,它最大的特色就是使用缩进排列来代替成对标签。受HAML的启发,pug进行了javascript的实现。

      Pug原名不叫Pug,是大名鼎鼎的jade,后来由于商标的原因,改为Pug,哈巴狗。其实只是换个名字,语法都与jade一样。丑话说在前面,Pug有它本身的缺点——可移植性差,调试困难,性能并不出色,但使用它可以加快开发效率。本文将详细介绍pug模板引擎

    安装

      使用npm安装pug

    $ npm install pug

      但运行pug命令时,提示pug命令未找到

      这时,需要安装pug命令行工具pug-cli

      [注意]一定要全局安装pug-cli,否则无法正常编译

    npm install  pug-cli -g

      再运行pug命令时,正常执行

    命令行

      在学习pug基础语法之前,首先要了解pug的命令行的使用

    【基础编译】

      将如下内容输入文件中,并命名为index.pug

    html
        head
            title aaa
        body

      在命令行中敲入pug index.pug即可实现基础编译

      在当前目录下生成一个index.html,是index.pug编译后的结果

    【sublime两列设置】

      但是,这样查看并不方便。下面将sublime设置为两列放置,将index.pug和index.html分别放置在左右两列,方便查看

    【自动编译】

      使用pug -w功能可以实现自动编译

      更改index.pug文件并保存后,index.html文件会实时更新为最新的编译的文件

    【标准版HTML】

      如上所示,默认地,pug编译出的HTML文件是压缩版的。如果要编译标准版的HTML文件,需要设置-P参数

    pug index.html -P

    【路径设置】

      如果并不希望在当前目录下输入编译后的HTML文件,而是有自定义目录的需求,则需要设置-o参数

      如下设置,index.html将输入到a目录下面,如果a目录不存在,则会新建a目录

    pug index.pug -o a

    【重命名】

      默认地,编译后的HTML与pug文件同名。如果需要重命名,则可以进行如下设置

      通过如下设置,可以同时设置路径和名称

      [注意]这里的路径必须提前建立好,否则不会成功

    pug <xx.pug> <xx/xx.html>

      最终,test.html文件被保存到templates目录下

    【批量编译】

      假设,编译href目录下所有的pug文件

    结构语法

      下面介绍关于结构的基础语法

    标签

    【树状】

      在默认情况下,在每行文本的开头(或者紧跟白字符的部分)书写这个 HTML 标签的名称。使用缩进来表示标签间的嵌套关系,这样可以构建一个 HTML 代码的树状结构  

    ul
      li Item A
      li Item B
      li Item C

    【内联】

      为了节省空间, Pug 嵌套标签提供了一种内联式语法

    a: img

    【自闭合】

      Pug知道哪些元素是自闭合的,也可以通过在标签后加上 / 来明确声明此标签是自闭合的

    img
    input
    img/
    input/

    【DOCTYPE】

       HTML5的DOCTYPE书写如下

    doctype html

      也可以自定义一个 doctype 字面值 

    doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"

    内容

       Pug 提供了三种常用的方式来放置内容

    【管道文本】

      这是最简单的向模板添加纯文本的方法。只需要在每行前面加一个 | 字符,这个字符在类 Unix 系统下常用作“管道”功能,因此得名

    | 纯文本当然也可以包括 <strong>HTML</strong> 内容。
    p
      | 但它必须单独起一行。

    【标签内文本】

      这实际上是最常见的情况,文本只需要和标签名隔开一个空格即可

    p 纯文本当然也可以包括 <strong>HTML</strong> 内容。

    【嵌入大段文本】

      有时可能想要写一个大段文本块。比如嵌入脚本或者样式。只需在标签后面接一个 .即可

      [注意]不要有空格

    script.
      if (usingPug)
        console.log('这是明智的选择。')
      else
        console.log('请用 Pug。')

    属性

      标签属性和 HTML 语法非常相似,它们的值就是普通的 JavaScript 表达式。可以用逗号作为属性分隔符,也可以不加逗号

    a(href='baidu.com') 百度
    = '
    '
    a(class='button' href='baidu.com') 百度
    = '
    '
    a(class='button', href='baidu.com') 百度

    【多行属性】

      如果有很多属性,可以把它们分几行写

    input(
      type='checkbox'
      name='agreement'
      checked
    )

    【长属性】

      如果有一个很长的属性,并且JavaScript运行时引擎支持ES2015模板字符串,可以使用它来写属性值

    复制代码
    input(data-json=`
      {
        "非常": "长的",
        "数据": true
      }
    `)
    复制代码

    【特殊字符】

      如果属性名称中含有某些奇怪的字符,可能会与 JavaScript 语法产生冲突的话,可以将它们使用 "" 或者 '' 括起来。还可以使用逗号来分割不同的属性

    div(class='div-class', (click)='play()')
    div(class='div-class' '(click)'='play()')

    【转义属性】

      默认情况下,所有的属性都经过转义(即把特殊字符转换成转义序列)来防止诸如跨站脚本攻击之类的攻击方式。如果要使用特殊符号,需要使用 != 而不是 =

      [注意]未经转义的缓存代码十分危险。必须正确处理和过滤用户的输入来避免跨站脚本攻击

    div(escaped="<code>")
    div(unescaped!="<code>")

    【布尔值】

      在Pug中,布尔值属性是经过映射的,这样布尔值(truefalse)就能接受了。没有指定值时,默认是true

    复制代码
    input(type='checkbox' checked)
    = '
    '
    input(type='checkbox' checked=true)
    = '
    '
    input(type='checkbox' checked=false)
    = '
    '
    input(type='checkbox' checked=true.toString())
    复制代码

    【行内样式】

      style(样式)属性可以是一个字符串(就像其他普通的属性一样)还可以是一个对象

    a(style={color: 'red', background: 'green'})

    【类和ID】

      类可以使用 .classname 语法来定义,ID 可以使用 #idname 语法来定义

      考虑到使用 div 作为标签名这种行为实在是太常见了,所以如果省略掉标签名称的话,它就是默认值

    a.button
    .content
    ="
    "
    a#main-link
    #content

    标签嵌入

      标签支持一种标签嵌入的写法,形式如下

    #[标签名(标签属性)  标签内容]

      对于内联标签来说,这种写法比较简单

    p.
      这是一个很长很长而且还很无聊的段落,还没有结束,是的,非常非常地长。
      突然出现了一个 #[strong 充满力量感的单词],这确实让人难以 #[em 忽视]。

    【空格调整】

      Pug 默认会去除一个标签前后的所有空格,而标签嵌入功能可以在需要嵌入的位置上处理前后空格

    复制代码
    p
      | 如果我不用嵌入功能来书写,一些标签比如
      strong strong
      | 和
      em em
      | 可能会产生意外的结果。
    p.
      如果用了嵌入,在 #[strong strong] 和 #[em em] 旁的空格就会让我舒服多了。
    复制代码

      

    注释

    【单行注释】

      单行注释和 JavaScript 类似,但是必须独立一行

    // 一些内容
    p foo
    p bar

    【不输出注释】

      只需要加上一个横杠,就可以使用不输出注释

    //- 这行不会出现在结果里
    p foo
    p bar

    【块注释】

    body
      //
        随便写多少字
        都没关系。

    【条件注释】

      Pug 没有特殊的语法来表示条件注释(conditional comments)。不过因为所有以 < 开头的行都会被当作纯文本,因此直接写一个 HTML 风格的条件注释也是没问题的

    复制代码
    <!--[if IE 8]>
    <html lang="en" class="lt-ie9">
    <![endif]-->
    <!--[if gt IE 8]><!-->
    <html lang="en">
    <!--<![endif]-->
    复制代码

    逻辑语法

      以下是关于模板逻辑的语法

    JS代码

    【不输出的代码】

      用 - 开始一段不直接进行输出的代码

    - for (var x = 0; x < 3; x++)
      li item

    【输出的代码】

      用=开始一段带有输出的代码,它应该是可以被求值的一个JavaScript表达式。为安全起见,它将被HTML转义

    p
      = '这个代码被 <转义> 了!'
    p= '这个代码被 <转义> 了!'

    【不转义的输出代码】

      用 != 开始一段不转义的,带有输出的代码。这将不会做任何转义,所以用于执行用户的输入将会不安全

    p
      != '这段文字 <strong>没有</strong> 被转义!'
    p!= '这段文字' + ' <strong>没有</strong> 被转义!'

    变量

    【内容变量】

      使用=或#{}来进行变量的真实值替换

    复制代码
    - var title = "On Dogs: Man's Best Friend";
    - var author = "enlore";
    - var theGreat = "<span>转义!</span>";
    
    h1= title
    p #{author} 笔下源于真情的创作。
    p 这是安全的:#{theGreat}
    复制代码

      在 #{ 和 } 里面的代码也会被求值、转义,并最终嵌入到模板的渲染输出中

    - var msg = "not my inside voice";
    p This is #{msg.toUpperCase()}

      Pug 足够聪明来分辨到底哪里才是嵌入表达式的结束,所以不用担心表达式中有 },也不需要额外的转义

    p 不要转义 #{'}'}!

      如果需要表示一个 #{ 文本,可以转义它,也可以用嵌入功能来生成

    p Escaping works with #{interpolation}
    p Interpolation works with #{'#{interpolation}'} too!

      使用!{}嵌入没有转义的文本进入模板中

    - var riskyBusiness = "<em>我希望通过外籍教师 Peter 找一位英语笔友。</em>";
    .quote
      p 李华:!{riskyBusiness}

      [注意]如果直接使用用户提供的数据,未进行转义的内容可能会带来安全风险

    【属性变量】

      如果要在属性当中使用变量的话,需要进行如下操作

    - var url = 'pug-test.html';
    a(href='/' + url) 链接
    = '
    '
    - url = 'https://example.com/'
    a(href=url) 另一个链接

      如果JavaScript运行时支持 ECMAScript 2015 模板字符串,还可以使用下列方式来简化属性值

    - var btnType = 'info'
    - var btnSize = 'lg'
    button(type='button' class='btn btn-' + btnType + ' btn-' + btnSize)
    = '
    '
    button(type='button' class=`btn btn-${btnType} btn-${btnSize}`)

      &attributes 语法可以将一个对象转化为一个元素的属性列表

    div#foo(data-bar="foo")&attributes({'data-foo': 'bar'})
    - var attributes = {};
    - attributes.class = 'baz';
    div#foo(data-bar="foo")&attributes(attributes)

    【变量来源】

      变量来源有三种,分别是pug文件内部、命令行参数和外部JSON文件

      1、pug文件内部

      2、命令行参数

      使用--obj参数,就可以跟随一个对象形式的参数

      3、外部JSON文件

      使用-O,跟随一个JSON文件的路径即可

      这三种方式,pug文件内部的变量优先级最多,而外部JSON文件和命令行传参优先级相同

      如下所示,外部JSON文件和命令行传参两种方式都存在,由于--obj写在-w后面,最终以命令行传参为准

    条件

      Pug 的条件判断的一般形式的括号是可选的,所以可以省略掉开头的 -,效果完全相同。类似一个常规的 JavaScript 语法形式

    【if else】

    复制代码
    - var user = { description: 'foo bar baz' }
    - var authorised = false
    #user
      if user.description
        h2.green 描述
        p.description= user.description
      else if authorised
        h2.blue 描述
        p.description.
          用户没有添加描述。
          不写点什么吗……
      else
        h2.red 描述
        p.description 用户没有描述
    复制代码

      Pug 同样也提供了它的反义版本 unless

    unless user.isAnonymous
      p 您已经以 #{user.name} 的身份登录。

    【switch】

      case 是 JavaScript 的 switch 指令的缩写,并且它接受如下的形式

    复制代码
    - var friends = 10
    case friends
      when 0
        p 您没有朋友
      when 1
        p 您有一个朋友
      default
        p 您有 #{friends} 个朋友
    复制代码

      在某些情况下,如果不想输出任何东西的话,可以明确地加上一个原生的 break 语句

    复制代码
    - var friends = 0
    case friends
      when 0
        - break
      when 1
        p 您的朋友很少
      default
        p 您有 #{friends} 个朋友
    复制代码

      也可以使用块展开的语法

    - var friends = 1
    case friends
      when 0: p 您没有朋友
      when 1: p 您有一个朋友
      default: p 您有 #{friends} 个朋友

    循环

      Pug 目前支持两种主要的迭代方式: each 和 while

    【each】

      这是 Pug 的首选迭代方式

    ul
      each val in [1, 2, 3, 4, 5]
        li= val

      可以在迭代时获得索引值

    ul
      each val, index in ['〇', '一', '二']
        li= index + ': ' + val

      能够迭代对象中的键值

    ul
      each val, index in {1:'一',2:'二',3:'三'}
        li= index + ': ' + val

      用于迭代的对象或数组仅仅是个 JavaScript 表达式,因此它可以是变量、函数调用的结果,又或者其他

    - var values = [];
    ul
      each val in values.length ? values : ['没有内容']
        li= val

      还能添加一个 else 块,这个语句块将会在数组与对象没有可供迭代的值时被执行

    复制代码
    - var values = [];
    ul
      each val in values
        li= val
      else
        li 没有内容
    复制代码

      [注意]也可以使用 for 作为 each 的别称

    【while】

      也可以使用 while 来创建一个循环

    - var n = 0;
    ul
      while n < 4
        li= n++

    混入

      混入是一种允许在 Pug 中重复使用一整个代码块的方法

    复制代码
    //- 定义
    mixin list
      ul
        li foo
        li bar
        li baz
    //- 使用
    +list
    +list
    复制代码

      混入可以被编译成函数形式,并传递一些参数

    复制代码
    mixin pet(name)
      li.pet= name
    ul
      +pet('猫')
      +pet('狗')
      +pet('猪')
    复制代码

      混入也可以把一整个代码块像内容一样传递进来

    复制代码
    mixin article(title)
      .article
        .article-wrapper
          h1= title
          if block
            block
          else
            p 没有提供任何内容。
    
    +article('Hello world')
    
    +article('Hello world')
      p 这是我
      p 随便写的文章
    复制代码

      混入也可以隐式地,从“标签属性”得到一个参数 attributes

      也可以直接用 &attributes 方法来传递 attributes 参数

    mixin link(href, name)
      a(class!=attributes.class href=href)= name
    
    +link('/foo', 'foo')(class="btn")

      [注意]+link(class="btn") 等价于 +link()(class="btn"),因为 Pug 会判断括号内的内容是属性还是参数。但最好使用后面的写法,明确地传递空的参数,确保第一对括号内始终都是参数列表

      可以用剩余参数(rest arguments)语法来表示参数列表最后传入若干个长度不定的参数

    复制代码
    mixin list(id, ...items)
      ul(id=id)
        each item in items
          li= item
    
    +list('my-list', 1, 2, 3, 4)
    复制代码

    文件包含

      包含(include)功能允许把另外的文件内容插入进来

    复制代码
    //- index.pug
    doctype html
    html
      include includes/head.pug
      body
        h1 我的网站
        p 欢迎来到我这简陋得不能再简陋的网站。
        include includes/foot.pug
    复制代码
    //- includes/head.pug
    head
      title 我的网站
      script(src='/javascripts/jquery.js')
      script(src='/javascripts/app.js')
    //- includes/foot.pug
    footer#footer
      p Copyright (c) foobar

      被包含的如果不是 Pug 文件,那么就只会当作文本内容来引入

    复制代码
    //- index.pug
    doctype html
    html
      head
        style
          include style.css
      body
        h1 我的网站
        p 欢迎来到我这简陋得不能再简陋的网站。
        script
          include script.js
    复制代码
    /* style.css */
    h1 {
      color: red;
    }
    // script.js
    console.log('真了不起!');

    文件继承

    【覆盖】

      Pug 支持使用 block 和 extends 关键字进行模板的继承。一个称之为“块”(block)的代码块,可以被子模板覆盖、替换。这个过程是递归的。

      Pug 的块可以提供一份默认内容,当然这是可选的

    复制代码
    //- layout.pug
    html
      head
       meta(charset="UTF-8") title 我的站点 - #{title} block scripts script(src='/jquery.js') body block content block foot #footer p 一些页脚的内容
    复制代码

      现在来扩展这个布局:只需要简单地创建一个新文件,并如下所示用一句 extends 来指出这个被继承的模板的路径。现在可以定义若干个新的块来覆盖父模板里对应的“父块”。值得注意的是,因为这里的 foot 块 没有 被重定义,所以会依然输出“一些页脚的内容”

    //- pet.pug
    p= petName
    复制代码
    //- page-a.pug
    extends layout.pug
    
    block scripts
      script(src='/jquery.js')
      script(src='/pets.js')
    
    block content
      h1= title
      - var pets = ['猫', '狗']
      each petName in pets
        include pet.pug
    复制代码

      同样,也可以覆盖一个块并在其中提供一些新的块。如下所示,content 块现在暴露出两个新的块 sidebar 和 primary 用来被扩展。当然,它的子模板也可以把整个 content 给覆盖掉

    复制代码
    //- sub-layout.pug
    extends layout.pug
    
    block content
      .sidebar
        block sidebar
          p 什么都没有
      .primary
        block primary
          p 什么都没有
    复制代码
    复制代码
    //- page-b.pug
    extends sub-layout.pug
    
    block content
      .sidebar
        block sidebar
          p 什么都没有
      .primary
        block primary
          p 什么都没有
    复制代码

    【扩展】

      Pug 允许去替换(默认的行为)、prepend(向头部添加内容),或者 append(向尾部添加内容)一个块。 假设有一份默认的脚本要放在 head 块中,而且希望将它应用到 每一个页面,可以进行如下操作

    复制代码
    //- layout.pug
    html
      head
        block head
          script(src='/vendor/jquery.js')
          script(src='/vendor/caustic.js')
      body
        block content
    复制代码

      现在假设有一个页面,那是一个 JavaScript 编写的游戏。希望把一些游戏相关的脚本也像默认的那些脚本一样放进去,那么只要简单地 append 这个块:

    复制代码
    //- page.pug
    extends layout.pug
    
    block prepend head
      script(src='/vendor/three.js')
    
    block append head
      script(src='/game.js')
    复制代码

      当使用 block append 或者 block prepend 时,block 关键字是可省略的:

    复制代码
    //- page.pug
    extends layout.pug
    
    prepend head
      script(src='/vendor/three.js')
    
    append head
      script(src='/game.js')
    复制代码

    简易模板

    复制代码
    //- index.pug
    doctype html
    html
        head
            meta(charset="UTF-8")
            title= documentTitle
            each val in srcStyles
                link(href= baseStyle +'/' + val)
        body
            header.hd
                nav.hd-navbar.m-navbar.m-navbar_primary
                    .hd-navbar-tel 联系方式: #{tel}
                ul.hd-navbar-nav
                    each val in mainNavItem
                        li.Hnn-item.m-btn.m-btn_info
                            a(href="#")= val
    
            section.main
                h1.main-title 我的文档
                p.main-content.
                    这是一个很长很长而且还很无聊的段落,还没有结束,是的,非常非常地长。
                    突然出现了一个 #[strong 充满力量感的单词],这确实让人难以 #[em 忽视]。
    
            footer.ft
                p Copyright (c) 小火柴的蓝色理想
    
            each val in srcScripts
                script(src=baseScript + '/' + val)
    复制代码
    复制代码
    //- data.json
    {
        "documentTitle":"测试文档",
        "tel":"400-888-8888",
        "mainNavItem":['登录','注册','关于','帮助'],
        "baseStyle":'style',
        "srcStyles":['bootstrap.css','main.css'],
        "baseScript":'/js',
        "srcScripts":['jquery.js','app.js']
    }
    复制代码
  • 相关阅读:
    费马小定理
    Codeforces Round #448
    [Offer收割]编程练习赛37
    Educational Codeforces Round 33
    Codeforces Round #447
    Codeforces Round #446
    A Great Alchemist 最详细的解题报告
    A Mountaineer 最详细的解题报告
    hihoCoder 1040 矩阵判断 最详细的解题报告
    hihoCoder 1039 字符消除 最详细的解题报告
  • 原文地址:https://www.cnblogs.com/yujihaia/p/7464952.html
Copyright © 2020-2023  润新知