guide

模板语法

以下简称Regularjs的模板为__rgl__

表达式

ES5 表达式

Regular 支持几乎所有 ES5 表达式语法,下列都是合法的表达式

几个注意点

  1. 表达式中的this指向组件本身
  2. 数据根路径从 component.data 开始, 即user 其实获取的是component.data.user
  3. rgl不支持自增、自减(++,--)以及位操作符& |
  4. rgl不支持正则表达式的字面量
  5. rgl开放了部分JS内建对象:
    • Array Date JSON Math NaN RegExp Object String
    • decodeURI decodeURIComponent encodeURI encodeURIComponent
    • parseFloat parseInt

除了ES5的表达式,Regular还提供了以下几种表达式类型

一次性绑定

脏检查性能依赖于监听器的数量,Regular引入了@()预发提供了一次绑定功能: 监听器在一次变更后就会被移除。

syntax

@(Expression)

可以在任意的表达式环境使用@()(list, if… etc)

Example

<div>{ @(title) }</div> // the interpolation only trigger once

{#if @(test)}  // only test once
//...
{/if}

{#list @(items) as item}  // only trigger once
//...
{/list}


var component = new Regular({
  data: {
    user: {}
  }
});

var i = 0;
component.$watch("@(user.name)", function(){
    i++  // only trigger once
});
component.$update("user.name", 1);
component.$update("user.name", 2);

// update twice  but trigger once
alert(i === 1);

如上例所示,由于『脏了一次就被被抛弃』, 如果值后续继续变化,会导致UI与数据不同步。

###过滤器Filter {#filter}

syntax

Expression| fitlerName: arg1, arg2,... argN


Regular.filter({
  'last': function(obj){
    return obj[obj.length-1]; 
  },
  'lowercase': function(obj){
    return obj.toLowerCase(); 
  }
})

const Component = Regular.extend({
  template: `
    <div>{list|last|lowercase}</div>
  `
})

new Component({
  data: {
    list: ['Add', 'Update', 'Delete']
  }
}).$inject(document.body)

Regular 还支持一些过滤器的高阶玩法,比如双向过滤器

Range

Range 即数组的简写模式

Syntax:

start..end

Example

1..3 === [1,2,3]

错误抑制

在动态模板中,如果抛出所有JS中常见的 xx of undefined 的错误,整个系统会变得相当脆弱。Regular 抑制了这类错误中安全的部分,并使用undefined代替


new Regular({
  template: "<div>{blog.user.name}</div>"
})

// => <div></div>

如果是方法不存在产生的错误,Regular 仍然会抛出,这属于「非安全」的错误


new Regular({
  template: "<div>{this.methodNoFound(blog.user.name)}</div>"
})

其中blog.user.name错误被抑制,而this.methodNoFound的未定义错误会被抛出

插值

插值是rgl中最常用模板元素

Syntax

{Expression}

###文本插值

针对文本插值,Regular会创建一个textNode,并建立表达式到textContent单向数据绑定

Example


var app = new Regular({
  template: "<div>{username}</div>",
  data: {username: 'leeluolee'}
});

app.$inject('#app');


上面的例子会输出<div>leeluolee</div>,并且一旦数据发生改变,文本节点内容也会发生改变

属性插值

Regular 目前仅允许属性值可以被插值。

几个注意点

  1. 如果文本内部具有插值符号{}, Regular会解释成组合表达式,如.modal-{klass} z-{state} 就相当于是 '.modal-' + klass + 'z-' + state

  2. 对于非指令类的的属性, Regular会在值变化时, 修改对应属性, 即一般属性(class, styletitle等)是天生可插值的。

  3. 对于指令类的属性, Regular会将具体处理逻辑交由指令的link方法处理。

Example


<input
  type='radio'
  class={klass}
  r-model={checked}
  style="left: {10 + offsetX}px; top: {10 + offsetY}px"
  > 

上述几个属性结果如下

  1. r-model: 参考内置指令
  2. style: 即上述的字符串组合插值
  3. class: 简单属性插值
  4. type: 没有插值

Body 插值

body param 只能用于组件

功能语句

rgl 除了插值和表达式之外的语法元素就只有语句了

Syntax

{#NAME ...}Block..{/NAME}

或者自闭合语句

{#NAME /}

目前 rgl 中只有三类语句: list, if/else/elseifinclude,未来也会通过相同的语法来进行扩展

⚠️ Regular中 语句和XML标签是不能被相互打断的

__错误 __

<div>
{#if true}
  <p>True</p>
</div>
{#else}
  <p>False</p>
</div>
{/if}

正确


<div>
{#if true}
  <p>True</p>
{#else}
  <p>False</p>
{/if}
</div>

循环控制 - list语句

list指令用来遍历某个sequence来循环的处理某些重复性的结构

Syntax >:

{#list sequence as item}
  ...block...
{/list}

where

在每次循环都会创建一个临时变量代表当前下标

Example >

var component = new Regular({
  template: 
    "{#list items as item}\
     <span class='index'>{item_index}:{item}</span>\
     {/list}",
  data: {
    items: ["a", "b", "c", "d"]
  }
})

component.$inject(document.body);

resulting html

<span class="index">0:a</span>
<span class="index">1:b</span>
<span class="index">2:c</span>
<span class="index">3:d</span>

list 可以使用 #else语句

你可以在list 中嵌入#else语句来展现当list__不存在__ 或__为空__的情况

Example

如果list 是一个空数组或空值 ([], null, undefined )

The template

{#list list as item }
  <div class='item'>{item}</div>
{#else}
  <div class='altnate'> no result here  </div>
{/list}

will output ` <div class='altnate'> no result here </div> `

使用 track by 特性加速你的list语句

使用#list 去遍历数组 (until v0.4.3)

在遍历对象时, 除了item_index, item , 还额外提供一个循环变量item_key(同样取决于item的命名)

{#list ageMap as age }
<div class='age'>{age_key}:{age}</div>
{/list}

with data.ageMap = {'jack': 11 , 'tommy': 22 } will output

<div class='age'>jack:11</div>
<div class='age'>tommy:22</div>

逻辑控制 - if/else/elseif

与其它模板引擎(如freemarker)一样, regular也提供了if,elseif,else等语法元素提供对逻辑控制的支持

Syntax

{#if condition}
...
{#elseif condition2}
...
{#else}
...
{#if}

where:

Example


{#if user.age >= 80 }
  you are too old
{#elseif user.age <= 10}
  you are too young
{#else}
  Welcome, Friend
{/if}

引入控制 - include

include 用来标准引入一些内容,这些内容可能需要在初始化后指定,或可能发生变动。

syntax

{#include template}

where

动态引入会监听传入表达式template的数据变动, 每当变化时会重新编译template,并插入到制定位置, 它带来几个好处

  1. 可以配置部分模板内容
  2. 可以动态修改展现

其中1的意义要远大于2, 比如你实现一个modal弹窗组件,通常modal结构是固定的, 而内容区通常需后续指定, 这时候include就可以大展伸手了

<div id="app"></div>

<!-- Templates -->
<script id="modal" type="text/regular">
  <div class="modal show {clazz}">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" on-click={this.close()}>×</button>
          <h4 class="modal-title">{title}</h4>
        </div>
        <div class="modal-body">
          {#include content }
        </div>
        <div class="modal-footer">
          <button 
            type="button" 
            class="btn btn-default" 
            on-click={this.close()} >Close</button>
          <button 
            type="button" 
            class="btn btn-primary" 
            on-click={this.confirm()}>Confirm</button>
        </div>
      </div>
    </div>
  </div>
</script>

<script>

var Modal = Regular.extend({
  template: '#modal',
  init: function(){
    if(!this.parent) this.$inject(document.body)
  },
  close: function(){
    this.$emit('close');
    this.destroy();
  },
  confirm: function(){
    this.$emit('confirm', this.data);
    this.destroy();
  }
});

var modal = new Modal({
  data: {
    content: '<input type="email" class="form-control" r-model={email}>',
    title: 'please confirm your email'
  }
});

modal.$on('confirm', function(data){
  console.log(data.email)
});
</script>



【DEMO】

##注释

直接使用XML注释即可

<!-- you comment -->