API Reference

命名约定

  • Component 此接口同时属于Regular及其子类.
  • Regular 此接口只属于Regular本身
  • component: 代表Regular及其子类的实例

1. 静态接口

1.1. Component.extend( options )

创建一个继承自Component的组件,参数 options 中的所有属性都会成为 原型属性.

Usage:

const Component = Regular.extend({
  template: `
  <div>
    <h2 >{count}</h2>
    <button on-click={this.tick( 'a' )} >点击加a</button>
  </div>
  `,
  tick: function(posfix) {
    this.data.count += posfix;
  }
})

Arguments

Param Type Detail
options Object 组件定义和配置,见 options

Return

Component

注意 extend 是原型继承的一个语法糖,options是实例共享的

1.2. Component.implement(options)

扩展Component的原型属性与方法optionsComponent.extend一致. 

Arguments

Param Type Detail
options Object 组件定义和配置,见 options

Return

Component

小技巧: 通过 implementextend 扩展的方法,都可以通过this.supr(arg1, arg2..)调用父类同名函数

"Regular的类式继承体系来源于著名的ded/klass."

Example

Component.extend({
  init: function(){
    this.supr() // call the super init
  }
}).implement({
  hello: function( msg ){
    this.supr( msg ) // call the super hello
  }
})

1.3. new Component(options)

Example

var component = new Component({
  // ...other options 
  data: {
    username: "leeluolee"
  }
})

component.$inject('#container');

Arguments

Param Type Detail
options Object 组件定义和配置,见 options

Return

Component的实例: 查看实例接口

通过实例化传入的 options 将成为实例属性, 意味它将覆盖 extend 与 implement 的定义.并且方法中无法使用 this.supr()

1.4. Component.directive(name, definition)

定义指令

Arguments

param type detail
name String 指令名
definition.link Function[required] 链接函数,指令编译时会被调用
definition.update Function[optional] 更新函数,指令绑定的表达式变更时会被调用
definition.params Array[optional] 指令参数,指定指令参数列表

如果 definition 是一个 Function,则视为成为link函数

definition.link(elem, value)

  • elem 绑定的元素节点
  • value 属性值(可能是字符串或是一个[Expression];
  • this 这里的this指向component组件本身

definition.update(elem, value)

  • elem 绑定的元素节点
  • value 属性值(可能是字符串或是一个[Expression];
  • this 这里的this指向component组件本身

definition.params

Example (source code of builtin r-html )


Regular.directive('r-html', function(elem, value){
  this.$watch(value, function(newValue){
    elem.innerHTML = newValue
  })
})

这里由于$watch同时接受字符串或者Expression, 所以我们可以在模板里传字符串或插值, 最终r-html的效果是一样的

  <div class='preview' r-html='content'></div>
  <!-- or -->
  <div class='preview' r-html={content}></div>

如果必要你也可以在函数返回一个destroy函数做指令的销毁工作(比如绑定了节点事件). 需要注意的是, regular中watch数据是不需要进行销毁的, regular会自动清理对应的数据绑定

Example


Regular.directive('some-directive', function(elem, value){

  return function destroy(){
    ... destroy logic
  }
})

1.5. Component.filter

regularjs 当然也支持普遍存在于模板中的过滤器,过滤器支持链式的多重调用.

regularjs也支持双向过滤, 来帮助你解决双向数据流的需求

Usage

Component.filter(name, factory)

Syntax

{Expression|filter1: args.. | filter2: args...}

Arguments

param type detail
name string 过滤器名称
factory function object 创建新的自定义过滤器

factory

  • factory.get(origin, args...) [Function]:

    数据从终点到源的处理函数.

  • factory.set(dest, args...) [Function]:

    从最终结果反推到源头的处理函数. .

如果传入的factory是函数类型,则自动成为factory.get

Example1 >

一个简单的日期格式化过滤器

// simplest date format
var filter = function(){
  function fix(str){
    str = "" + (str || "");
    return str.length <= 1? "0" + str : str;
  }
  var maps = {
    'yyyy': function(date){return date.getFullYear()},
    'MM': function(date){return fix(date.getMonth() + 1); },
    'dd': function(date){ return fix(date.getDate()) },
    'HH': function(date){ return fix(date.getHours()) },
    'mm': function(date){ return fix(date.getMinutes())}
  }

  var trunk = new RegExp(Object.keys(maps).join('|'),'g');
  return function(value, format){
    format = format || "yyyy-MM-dd HH:mm";
    value = new Date(value);

    return format.replace(trunk, function(capture){
      return maps[capture]? maps[capture](value): "";
    });
  }
}();
Regular.filter("format", filter)

然后在模板中使用

<p>{time| format: 'yyyy-MM-dd HH:mm'}</p>

输出

<p>2014-12-31 12:30</p>

双向过滤器

双向过滤器主要是帮助我们实现数据的对流, 对任意数据读或写操作时可以进行过滤操作, 与计算属性不同的是,双向过滤器定义是不与具体的数据进行绑定,它是一种可复用的抽象.

双向过滤器如其名,经常会用在双向绑定上, 由于这个特性, r-model 得以与一个数组类型实现双向绑定。 当然你也可以使用它在其它可能有“数据回流”场合,比如内嵌组件

take {[1,2,3]|join: '-'} for example

过滤器定义

Regular.filter('join', {
  //["1","2","3"] - > '1-2-3'
  get: function(origin, split ){
    return origin.join( split || "-" );
  },
  // **Important **
  // "1"-"2"-"3" - > ["1","2","3"]
  set: function(dest, split ){
    return dest.split( split || "-" );
  }
})

{array|json}
<input r-model={array|join:'-'} >

【 DEMO : two-way filter】

内建过滤器

json

这是一个双向过滤器

example


var component = new Regular({
  template: "<h2>{user|json}</h2>"
})

component.$update("user|json", "{'name': 'leeluolee', 'age': 10}")
//console.log(user) --> {'user':'leeluolee', 'age': 10}

Only Browser that support JSON API can get the json filter

last

获得数组最后一个元素, 这是一个单向过滤器

{[1,2,3]|last}  ===>  3

1.6. Component.event

Usage

Component.event(name, factory)

设置自定义dom事件

Argument

Param Type Detail
name String the custom event name
factory Function Factory function for creating event type

1.7. Component.animation

自定义一个动画command. animation接口完全是为r-animation指令服务的.

查看 指南: animation 了解更多

Usage

Component.animation(name, factory)

Arguments

Param Type Detail
name String the custom animation name
factory Function Factory function for creating command

Example

1.8. Component.component

注册一个组件,使其可以被, 这里类似与在options中声明name

Usage

Component.component(name, factory)

Arguments

Param Type Detail
name String the name used to insert Component in template
factory Component A Component to be register

Example >


var Pager = Regular.extend({
  // other options
})

Component.component('pager', Pager)

// you can use pager as nested component
Component2 = Component.extend({
  template: "<pager></pager>"
})

1.9. Component.use

Usage

Component.use(factory)

著名的angular中模块化的解决方案是angular.module()和依赖注入, 一个模块可以有factory可以有filter可以有directive等等.

在regular中不可能照搬这种方式, 这是因为

  • regular中没有$rootScope.$digest()这种全局性的解药无脑的促使所有绑定进入数据检查阶段,regular组件的生命周期都是独立的, 这就决定了必须让扩展建立与组件的关系.

    比如angular的$timeout之类的实现只需在定时器完成后$rootScope.$digest()即可进入全局的数据检查, 而regular中timeout之后必须调用组件的$update()才进入组件本身的数据检查阶段,即需建立与组件的关系.

  • 模块插件应该是与组件无关的, 绑定只应该在被使用时发生, 这样才是可复用的模块插件.

所以一个典型的插件的写法应该是这样的


function FooPlugin(Componenet){
  Component.implement()// implement method
    .filter()          // define filter
    .directive()       // define directive
    .event()           // define custom event
}

var YourComponent = Regular.extend();

FooPlugin(YourComponent);   // lazy bind
FooPlugin(Regular);         // lazy bind to globals

为了更统一, 所有Component都有一个use函数来统一'使用'插件, 如上例可以写成


YourComponent.use(FooPlugin);

// global
Regular.use(FooPlugin);

2. options

new ComponentComponent.extend, Component.implement 都接受同一种 options 参数

没有提及的配置项都会自动成为Component的原型属性( 或实例属性 )

2.1. template

  • type: String | AST

模板字符串需要遵循模板语法,模板只会在首次实例化时被编译一次

你可以选择在构建时通过 Regular.parse 将模板先处理成 AST

2.2. name

注册组件到父组件的命名空间内,使其可以被声明式调用。

注意通过name注册,是全局的

const Component = SuperComponent.extend({
  //other options
  name: 'foo1'
})

const Component2 = SuperComponent.extend({
  template: "<foo1></foo1>"
})

也可使用Component.component 注册, 上例实际上等同于


const Component = SuperComponent.extend({});

Regular.component('foo1', Component)

2.3. events

  • type: Object

批量定义绑定事件,__这个在需要绑定一些内置事件时格外有用。


Regular.extend({
  events: {
    "$init": function(){
      // same in component.init
    },
    "$destroy": function(){
      // same in component.destroy
    }
  }
})

2.4. data

  • type: Object

⚠️不要在 extend 或 implement 时定义data属性 !!! ,这会导致所有实例共享数据。

永远只在 new Componentconfig 中定义初始化函数

2.5. computed

  • Type: Object

计算属性定义为键值对

  • key: 表达式名
  • value: 表达式定义

Example

comuted: {
  title: 
}

表达式定义支持几种类型

3. 生命周期钩子

options 中还可以定义如下生命周期钩子

3.1. config( data )

  • type: Function

在模板编译 之前 被调用,config一般是用来初始化参数,它接受的 data 即你在new Component() 时传入的 data属性。

3.2. init()

  • type: Function

会在模板编译 之后( 即DOM结构已产生 )被调用. 你可以在这里处理一些与DOM相关的逻辑 

3.3. destory()

  • type: Function

如果你需要有额外的回收逻辑, 你可以重写destroy方法

记得调用this.supr()来运行默认的回收逻辑 !!!!, 否则会回收失败

var Component = Regular.extend({
//.....
  destroy: function(){
    this.supr(); // call the super destroy 
    ...other logic
  }
})

var component = new Component();

component.destory();

3.4. modifyBodyComponent( component, next )

4. 实例接口

component即代表组件实例, 注意这些公有都有$前缀 意味不建议进行重写

4.1. component.$inject

插入组件到指定位置

Usage

component.$inject(element[, direction])

Arguments

Param Type Detail
element Node false 被插入节点,如果传入false则代表将此组件从dom中移除
direction(optional default:'bottom') String 组件的位置插入目标的位置. 可以是 'top', 'bottom', 'after', or 'before'.

Example >

假设你已经有这样一个组件

var component = new Component({
  template: "<h2>{title}</h2>",
  data: { title : "Example" }
})
var div = document.getElementById("#div");

和一段html片段

<div id="div">
  <div class='child'></div>
</div>
  • compnent.$inject( div ) or component.$inject( div, 'bottom' )

    resulting html

    <div id="div">
      <div class='child'></div>
      <h2>Example</h2>
    </div>
    
  • compnent.$inject( div, 'top' )

    resulting html

    <div id="div">
      <h2>Example</h2>
      <div class='child'></div>
    </div>
    
  • compnent.$inject( div, 'after' )

    resulting html

    <div id="div">
      <div class='child'></div>
    </div>
    <h2>Example</h2>
    
  • or component.$inject( div, 'before' )

    resulting html

    <h2>Example</h2>
    <div id="div">
      <div class='child'></div>
    </div>
    
  • component.$inject( false )(假设我们已经调用了以上方法插入了本组件)

    完全从原插入位置移除它(但是没有销毁,你仍然可以再次$inject它)

    resulting html

    <div id="div">
      <div class='child'></div>
    </div>
    

Tips

你通过多次调用$inject 将组件有一个位置移动到另外一个位置

4.2. component.$watch

注册一个监听回调,一旦绑定的表达式的值发生改变,它将会被调用

Usage

component.$watch(expression, callback [, options])

Arguments

Param Type Detail
expression Expression 一旦表达式求值发生改变,回调会被触发
callback(newValue, oldValue) Function 回调接受两个参数.
1. newValue: 表达式的新值.
2.oldValue: 表达式的原值

Return

watchid [Number]: 监听id,用于方法 $unwatch

  • expression 会在每次脏检查时被调用,并比较之前的值
  • 当值与上次求值发生变化的判断依据是严格不相等即!==. 一种例外就是当求值为数组时,Regularjs会使用莱文斯坦距离计算数组差异
component.$watch("user.name", function(newValue, oldValue){
  alert("user.name changed from " + oldValue + " to " + newValue) ; 
})

4.3. component.$unwatch

利用watchid解绑一个数据监听, 一般来讲你很少会用到它,因为所有regularjs中的数据绑定会被自动回收,除非你想在模板回收之前清除某个绑定.

Usage


var component = new Regular();

component.$watch('b', function(b){
  alert('b watcher 1');
})

var id = component.$watch('b', function(){
  alert('b watcher 2');
})

component.$unwatch(id);
component.$update('b', 100); // only alert 'watcher 1'

4.4. component.$update

component.$update is used to synchronize data and view

由于regularjs是基于脏检查,所以当不是由regularjs本身控制的操作(如事件、指令)引起的数据操作,可能需要你手动的去同步data与view的数据. $update方法即帮助将你的data同步到view层.

Usage

component.$update([expr] [, value])

更新某个值,并强制进入digest阶段,即脏检查.

Arguments

  • expr(Optional) [Expression| Function | String] - expression可以有多种参数类型

    • String: 此字符串会先被Regular.expression处理为Expression
    • Expression: 此expression需要有set函数, 查看Expression
    • Object: 多重设值
  • value - 设置的值

Example >


var component = new Regular({
  template: "<h2 ref='h2' on-click={title=title.toLowerCase()}>{title}</h2>",
  data: {
    title: "REGULARJS"
  }
});

//=> log 'REGULARJS' , with no doubt
console.log( component.$refs.h2.innerHTML ) 

component.data.title = "LEELUOLEE";

//=> also log 'REGULARJS', regularjs don't know the value is changed.
console.log( component.$refs.h2.innerHTML ) //

// force synchronizing data and view 
component.$update()

//=> also 'REGULARJS'. synchronize now.
console.log( component.$refs.h2.innerHTML ) //


// trigger on-click event  
component.$refs.h2.click();


// should log leeluolee.
// the Expression `title=title.toLowerCase()` is actived.
// when listener is done, regularjs will enter digest phase
console.log( component.$refs.h2.innerHTML ) //

you may need check $refs first

Beacuse you may need to set a complex Expression, $update also accept optional params to set the property easily, for Example


// 1. simple
component.$update("user.name", 'leeluolee')

// is equals to

component.data.user.name = 'leeluolee'
component.$update()


// 2. multiple
component.$update({
  "user.name": "leeluolee",
  "user.age": 20
})
// is equlas to
component.data.user.name = 'leeluolee'
component.data.user.age = 20
component.$update()

你当然也可以使用更复杂的表达式,不过你必须保证你的表达式是可设值的, 不过由于会创建表达式,这显然是不高效的,作者强烈建议不怎么做, 除非你需要通过双向过滤器来设值.


// JSON.parse the title first.
component.$update('title|json', "{'title': 1}");

console.log(component.data.title) // => {title:1};

Warning: 无论传入什么参数,运行$update之后都会进行组件作用域内的dirty-check

4.5. component.$get

Usage

component.$get(Expression|String)

获得一个Expression的值,类似于angular的$eval函数

Example >

component.data.username = "leeluolee"
component.data.job = "developer"

component.$get('username + ":" + job') // => leeluolee:developer

Arguments

Param Type Detail
expression Expression String 表达式

4.6. component.$refs

  • type: Object

在模板中,你可以使用ref属性来标记一个节点或组件. 在实例化后,你可以通过component.$refs 来获取你标记的节点

Example >


component = new Regular({
  template: "<input ref=input> <pager ref=pager></pager>",
  init: function(){
    this.$refs.input // -> the input tag
    this.$refs.pager // -> the pager component
  }
})

The less reference the better

4.7. component.$on

Register an event handler fn.

Usage

component.$on(event, fn])

Arguments

Param Type Detail
eventName Object String 事件名
fn Function 监听器回调

如果你传入一个Object, 会成为一个多重事件绑定

Example >

component.$on("hello", fn1)

// multiple
component.$on({
  notify: fn2,
  message: fn3
})

4.8. component.$off

Usage

component.$off([event] [,fn])

Arguments

Param Type Detail
eventName Object String 事件名
fn Function 监听器回调
  • 如果同时传入 event和fn, 则移除指定event类型下的fn函数
  • 只传入event, 移除所有event对应的监听器
  • 什么都不传,移除所有

4.9. component.$emit

触发指定事件

Usage

component.$emit(eventName [, args...])

Arguments

Param Type Detail
eventName Object String 事件名
args Function 剩余的参数都会作为参数传入到监听器

Example >

var component = new Regular();

var clickhandler1 = function(arg1){ console.log('clickhandler1:' + arg1)}
var clickhandler2 = function(arg1){ console.log('clickhandler2:' + arg1)}
var clickhandler3 = function(arg1){ console.log('clickhandler3:' + arg1)}

component.$on('hello', clickhandler1);
component.$on('hello', clickhandler2);
component.$on({ 
  'other': clickhandler3 
});


component.$emit('hello', 1); // handler1 handler2 trigger

component.$off('hello', clickhandler1) // hello: handler1 removed

component.$emit('hello', 2); // handler1 handler2 trigger

component.$off('hello') // all hello handler removed

component.$off() // all component's handler removed

component.$emit('other');

4.10. component.$mute

你可以使用$mute(true)让组件失效,使其不参与到脏检查中. 后续使用 $mute(false) 来重新激活一个被失效的组件, 激活的同时,会自动进行一次数据与ui同步.

Usage

component.$mute( isMute )

Argument

Param Type Detail
mute Boolean 是否disable这个组件(可以后续重启它)

Example >


var component = new Regular({
  template: '<h2>{title}</h2>',
  data: {
    title: "hello"
  }
})

//resulting html

<h2>hello</h2>

component.$mute(true) // disable it

component.data.hello = 'title changed'
component.$update();

// resulting html

<h2>hello</h2>

4.11. component.$bind

创建组件之间的双向绑定.

这已是一个不推荐的方法. 由于$bind过于灵活的双向绑定,极可能不当使用带来难以维护的对象间关系. 请使用事件通讯来处理组件之间的消息同步。

Usage

component.$bind(component2, expr1[, expr2])

Arguments

  1. component2: 要绑定的组件
  2. expr1 : 此参数有多种参数类型
    • Expression|String: 本组件要绑定的表达式
    • Object: 同时绑定多个表达式对
    • Array: 表达式列表,同时实现多个同名表达式(即只传入expr1)
  3. expr2 : 目标组件要绑定的表达式, 缺省为expr1

WARN

  1. 如果两个表达式都是setable的,可实现双向绑定,否则只能实现单向绑定
  2. 如果连个组件在bind时是不同步的,component2数据会先同步到component

create binding between pager components.


 // insert
var pager = new Pager( {data: {total: 100, current:20}} ).$inject('#bind1');
var pager2 = new Pager( {data: {total: 50, current:2}} ).$inject('#bind1');

var pager3 = new Pager({data: {total: 100, current:20} }).$inject('#bind2');
var pager4 = new Pager({data: {total: 50, current:2}}).$inject('#bind2');

var pager5 = new Pager({data: {total: 100, current:2}}).$inject('#bind3');
var pager6 = new Pager({data: {total: 50, current:20}}).$inject('#bind3');


// style 1
pager.$bind(pager2, ['current', 'total']);


// style 2
pager3.$bind(pager4, 'current', 'current')
pager3.$bind(pager4, 'total') // the same as pager3.$bind(pager4, 'total', 'total')

// style 3
pager5.$bind(pager6, {current: "current", total: "total"});


// bind chain
var pager = new Pager({data:{total: 1000, current:1}}).$inject('#bind_chain');
for(var i = 0; i < 10; i++){
  var pager = new Pager({data:{total: 1000, current:1}})
    .$bind(pager, ['total', 'current'])
    .$inject('#bind_chain');
}

Demo here

you may want the source code of pager

5. 其它

5.1. Regular.dom

由于内部实现需要,Regular实现了部分常用的跨浏览器的dom方法,如果只是简单的dom处理,你可以直接使用Regular.dom.

Regular.dom.inject(element, refer, direction)

component.$inject 依赖于此方法

Arguments

Param Type Detail
element Node false 要被插入的节点
refer Node false 参考节点
direction(optional default:'bottom') String 组件的位置插入目标的位置. 可以是 'top', 'bottom', 'after', or 'before'.

Regular.dom.on(element, event, handle)

绑定节点事件, 下列事件对象中的属性已经被修正,你可以在IE6-8使用它们. 回调的this对象也修正为element本身.

  • event.target
  • event.which
  • event.pageX
  • event.pageY
  • event.stopPropagation();
  • event.preventDefault();

Example >

var dom = Regular.dom;

dom.on(element, 'click', function(ev){
  ev.preventDefault();
})

Regular.dom.off(node, event, handle)

移除一个事件监听器

Regular.dom.addClass(element, className)

添加节点className

Regular.dom.delClass(element, className)

移除节点的某段className

Regular.dom.hasClass(element, className)

判断节点是否拥有某个className

<div class='class1 class2'></div>

dom.hasClass(element, 'class1') // => true

Regular.dom.text(element[, value])

根据浏览器和节点, 设置节点的textContent 或 innerText

Regular.dom.html(element[, value])

设置或获取节点的innerHTML值

Regular.dom.attr(element, name [ , value])

设置或获取节点的指定属性

5.2. Regular.config

配置一些全局属性, 目前主要可以用来配置模板的自定义开关符号

Usage

Regular.config( settings )

Arguments

Param Type Detail
settings.BEGIN String OPEN_TAG (default: '{')
settings.END String END_TAG (default: '}')

Example >

将默认符号{}修改为 {{}}.


Regular.config({
  BEGIN: "{{", 
  END: "}}" 
})

5.3. Regular.parse

Usage

Regular.parse(templateString, setting)

解析模板字符串为AST, 基本上你不会使用此方法, 你可以使用此方法来预解析你得regularjs模板

Arguments

Param Type Detail
templateString String 要解析的模板字符串
settings.BEGIN String 开符号 (default: '{'
settings.END String 关符号 (default: '}')
settings.stringify Boolean 是否stringify 输出的AST (default: false)

Usage

Example >

Regular.parse("<h2>{{page.title + page.desc}}</h2>", {
  BEGIN: '{{',
  END: '}}'
})
// output
[
  {
    "type": "element",
    "tag": "h2",
    "attrs": [],
    "children": [
      {
        "type": "expression",
        "body": "_d_['page']['title']+'-'+_d_['page']['desc']",
        "constant": false,
        "setbody": false
      }
    ]
  }
]

6. 服务端渲染

results matching ""

    No results matching ""