前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >微型框架 Riot.js 特性一览

微型框架 Riot.js 特性一览

作者头像
逆葵
发布2019-04-24 18:27:51
8770
发布2019-04-24 18:27:51
举报
文章被收录于专栏:FECodingFECoding

注:本文基于Riot.js v2.5.0版本

Riot.js简介

  • 类似 React 的 微型 UI 库
  • 自定义标签/虚拟 DOM
  • 适合编写独立组件
  • MVP 架构
MVP 架构图
MVP 架构图
  • 支持 IE9+ ??

1.自定义标签

  1. 布局与逻辑耦合,可重用组件
  2. 实际上的语法糖—>编译为 JS
  3. 虚拟 DOM
    • 单向的数据传输: update 或 unmount 都是从 父亲->孩子
    • 预编译和缓存表达式,解析更加高效
    • 预处理器
    • 可用于服务器端
  4. 语法友好
    • 强大的属性缩写: class={enable: true, hidden: false}
    • 不需要额外的手动绑定,无需记忆 render,state,constructor 等
    • 可插值使用: Add #{items.length + 1} 或 class="item {selectd: true}"
    • 逻辑代码,可不放在 script 标签内
    • 可使用部分 ES6(完全使用需结合 Babel)

2.mixin

Mixin 可以将公共代码在不同标签之间方便地共享,可以混入 Object 和 new function(){}。

代码语言:javascript
复制
var OptsMixin = {
    init: function() {
      this.on('updated', function() { console.log('Updated!') })
    },

    getOpts: function() {
        return this.opts
    },

    setOpts: function(opts, update) {
        this.opts = opts

        if(!update) {
            this.update()
        }

        return this
    }
}

<my-tag>
    <h1>{ opts.title }</h1>

    this.mixin(OptsMixin)
</my-tag>

声明式 mixin 可在文件之间和项目之间共享 mixin:

代码语言:javascript
复制
riot.mixin("defaultData", {
    author: "ddfe",
    email: "shield@didichuxing.com"
});

// in custom tag
this.mixin("defaultData"); 

3.事件

  • 自定义标签创建过程:
    1. 创建标签实例
    2. 标签定义中的 JavaScript 被执行
    3. HTML 中的表达式被首次计算并首次触发 “update” 事件
    4. 标签被加载 (mount) 到页面上,触发 “mount” 事件
  • 监听生命周期事件
    • before-mount
    • mount
    • update(改写上下文数据)
    • updated(操作 DOM)
    • before-mount
    • unmount
  • 表达式更新方式:
    1. 当一个事件处理器被调用后自动更新。可以在事件处理器中设置 e.preventUpdate = true 来禁止这种行为。
    2. 当前标签实例的 this.update() 方法被调用时
    3. 当前标签的任何一个祖先的 this.update() 被调用时. 更新从父亲到儿子单向传播。
    4. 当 riot.update() 方法被调用时, 会更新页面上所有的表达式。

    ​ ​

4.表达式

100%纯 JavaScript:

代码语言:javascript
复制
{ title || 'Untitled' }
{ results ? 'ready' : 'loading' }
{ new Date() }
{ message.length > 140 && 'Message is too long' }
{ Math.round(rating) }

可放在 html 节点中,也可作为文本节点嵌入:

代码语言:javascript
复制
<h3 id={ /* 属性表达式 */ }>
  { /* 嵌入表达式 */ }
</h3>

注:可通过riot.settings.brackets自定义花括号

5.杂烩

  • 嵌套标签 <account> <subscription plan={ opts.plan } show_details="true" /> </account> <subscription> <h3>{ opts.plan.name }</h3> // 取得标签选项 var plan = opts.plan, show_details = opts.show_details // 访问父标签实例 var parent = this.parent </subscription> 父标签的参数通过 riot.mount 方法的参数设置,而子标签的选项通过标签属性来传递。 <script> riot.mount('account', { plan: { name: 'ddfe', age: '4' } }) </script> ​
  • 嵌套HTML <!--definition--> <my-tag> <p>Hello <yield/></p> this.text = 'world' </my-tag> <!--apply--> <my-tag> <b>{ text }</b> </my-tag> <!--result--> <my-tag> <p>Hello <b>world</b><p> </my-tag>
  • 带有 name 或 id 属性的 DOM 元素将自动被绑定到上下文中,可直接访问
  • 事件处理器 <login> <form onsubmit={ submit }> </form> // 上面的表单提交时调用此方法 submit(e) { } </login> //e.currentTarget 事件处理器的所属元素 //e.target 发起事件的元素 //e.which 键盘事件中的键值 //e.item 循环中的当前元素 ​
  • 渲染条件:if = {expression} show hide
  • 循环:each = {items}(对象数组)or each = {name, i in items}(非对象数组) or each = {name,value in items}(对象)(不建议使用) 循环中的每一项将建立一个新的上下文,子标签通过 parent 访问父标签定义的方法和属性。
  • 使用标准 HTML 元素作为标签 <ul riot-tag="my-tag"></ul> riot.mount('my-tag')
  • 服务端渲染 var riot = require('riot') var timer = require('timer.tag') var html = riot.render(timer, { start: 42 }) console.log(html) // <timer><p>Seconds Elapsed: 42</p></timer>

6. 编译

自定义标签会被编译为 JavaScript

  • 浏览器内编译 <script src="todo.tag" type="riot/tag"></script> ​
  • 预编译:riot 命令 npm install riot -g # 编译到当前目录 riot some.tag # 编译到目标目录 riot some.tag some_folder # 编译到目标路径 riot some.tag some_folder/some.js # 将源目录下的所有文件编译至目的目录 riot some/folder path/to/dist # 将源目录下的所有文件编译(合并)到单个js文件 riot some/folder all-my-tags.js 参数: -w watch 目录 有变化自动编译 -ext html 指定后缀名 --config config 使用config.js作配置文件 --type 指定 js 处理器 --template 指定 HTML 模板 ​
  • 预处理器 <script type="coffee"></script> ​

7.观察者 Observable(事件触发器)

Riot 提供 Observable 以便组件间通信,实现模块化。

代码语言:javascript
复制
// 方法1,创建一个观察者,返回一个实例,之后该对象便可以触发和监听事件
var ddfe = riot.observable({
});

//方法2,使 ddfe 成为观察者
riot.observable(ddfe);


// 监听事件
ddfe.on("event1", function(data1, data2){
    // 监听event1事件
    // data1 和 data2 是trigger传入的参数
    // data1 = 1, data2 = 2
    console.log(data1, data2);
});

// 发布一个事件
// 该事件带有 1 和 2 作为参数
// 上面的on("event1")的回调fn将会执行
ddfe.trigger("event1", 1, 2);

// 解除 event1 的所有监听,第二个参数可选
// 如果有第二个参数 [function],则只解绑该函数
ddfe.off("event1");

// one 与 on 类似,只是 one 如果执行过一次,就自动解除绑定
ddfe.one("event1", function(data1){
    console.log(data1);
});
ddfe.trigger("event1", 1, 2);

//删除所有事件的所有监听器
ddfe.off('*')

//对所有的事件删除指定的回调函数
ddfe.off('*',fn)

8.路由

一个最小化的路由器实现

功能:

  1. 修改 URL 的 hash 部分
  2. hash 变化时进行通知
  3. 查看当前 hash

API:

  1. riot.route(callback) riot.route(function(collection, id, action) { }) //如果 url 变为 customers/987987/edit,则 //collection = 'customers' //id = '987987' //action = 'edit'
  2. riot.route(filter, callback) // 精确匹配 `/fruit` riot.route('/fruit', function(name) { console.log('The list of fruits') }) // 如果 url 变成 `/blog/2015-09/01`, // 回调的参数将被捕捉成 '2015', '09' 和 '01' riot.route('/blog/*-*/*', function(year, month, date) { console.log('The page of ' + year + '-' + month + '-' date) })
  3. riot.route.create() 返回一个新的路由上下文 <first-tag> <p>First tag</p> <script> var subRoute = riot.route.create() // 创建新的路由上下文 subRoute('/fruit/*', function(name) { /* 公用的部分 */ }) </script> </first-tag> <second-tag> <p>Second tag</p> <script> var subRoute = riot.route.create() // 创建新的路由上下文 subRoute('/fruit/apple', function(name) { /* 个别的部分 */ }) </script> </second-tag>
  4. riot.route(to[, title, shouldReplace]) 在内部实现中,
    • 如果没有 shouldReplace, 将使用 history.pushState().
    • 如果有 shouldReplace, 将使用history.replaceState().
  5. riot.route.start() 开始监听路由变化,需要手动调用
  6. riot.route.start(autoExec) riot.route.start(true) <=> riot.route.start()+riot.route.exec()
  7. riot.route.stop()
  8. riot.route.query() // 如果 url 变成 `/search?keyword=Apple&limit=30` 将会匹配 riot.route('/search..', function() { var q = riot.route.query() console.log('Search keyword: ' + q.keyword) console.log('Search limit: ' + q.limit) })
  9. riot.route.base(base)修改基础路径
  10. riot.route.parser(parser[, secondParser])
  11. 其他,路由优先级等
代码语言:javascript
复制
   riot.route('/fruit/apple', function() { /* */ }) // 路由-B (1)
   riot.route('/fruit/orange', function() { /* */ }) // 路由-C (2)
   riot.route('/fruit/*', function(name) { /* */ }) // 路由-A (3)

   riot.route(function() { /* */ }) // 路由-X (3)
   riot.route('/fruit/*', function() { /* */ }) // 路由-Y (1)
   riot.route('/sweet/*', function() { /* */ }) // 路由-Z (2)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Riot.js简介
  • 1.自定义标签
  • 2.mixin
  • 3.事件
  • 4.表达式
  • 5.杂烩
  • 6. 编译
  • 7.观察者 Observable(事件触发器)
  • 8.路由
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档