资讯专栏INFORMATION COLUMN

riotjs 2.2.4

yuanzhanghu / 2949人阅读

摘要:目前进化至版本了。该路由模块是自动启动的。此时该缓存并没有被使用,的实例并没有建立。所有的实例都是由内部构造器实例化而来的。三混合其他数据和属性到当前上四更新视图,删除传导属性,重置事件。另外,注意是很特殊的,在混入时会自动执行。

riotjs

riotjs一款小型的10000star mvp框架。目前进化至3.x版本了。读者注意,本篇文章介绍的是2.2.4哦。为啥介绍这款啊,是因为那个啥,preact面向现代浏览器,对我来说不咋好使。

riotjs从出生到现在总共经历了3个大版本,基本上每个都不一样,1.x最为简陋,可以视之就一个简单的mvc框架哦,模板引擎也是简单的不要不要的,2.x版本完善了各项功能,并且强化了controller的作用,使之成为一个真正的MVP框架。3.x版本使用了大量es6,es5新增方法进行重构,对svg支持,模板引擎,事件系统,内存使用等进行了一定程度的优化。(实际从2.3开始就往现代浏览器上靠了)

为何选用

由于riotjs小,容易和其他框架混合使用

特点

小,但经不起强渲染

支持ie8吗

riotjs 2.2.4是最后一个支持ie8的版本。(然而事实上,代码中使用了一些es5新增的方法,这些方法要ie9才支持,以至于我们不得不使用es5shiv/es5sham来进行兼容);

静态方法 riot.observable

riot的事件系统,所有事件通知方式都基于该模块,可全局使用

// 发送全局事件

var window.eventBus = riot.observable();

eventBus.on("test", function (e) {
    console.log(e);
});

eventBus.trigger("test", 123);

包含方法

on(events, fn)

off(events, fn)

trigger(name[,arguments])

one(name, fn)

riot.mixin

作用是向内部对象mixins添加属性或方法,该对象无保护,所以必须要人为保证命名时不冲突.

// 在外部使用
riot.mixin("testfunction", function () { console.log(2) });

var c = riot.mixin("testfunction");

c() // print 2

该方法一般提供给riot tag初始化实例的时候使用。当在tag类中使用this.mixin混入方法的时候,会将内部对象mixins上的方法或属性混合到tag类上

riot.route

2.2.4版本的riot.route是一个功能超弱的路由管理器,通过监听hashchange事件来触发注册的路由回调。该路由模块是自动启动的。而且它的实现上是有缺陷的。它本质上是个事件分发器。

// 使用示例

riot.route(function (path, module, action, params) {
    console.log(path, module, action, params)
});

riot.route("search/index/search/1234");

包含方法

riot.route(arg)

2.2.4版本里arg接受2种类型,字符串和function,上面已经给出示例。需要自己去分出路径,模块,行为和参数。你没看错,就是这么弱

riot.route.exec(fn)

解释当前哈希路径,并把参数传递到fn里

riot.route.parser(fn)

指定哈希路径解释器,如果未调用该方法,固定解释方法是 path.split("/");如示例所示

riot.route.stop()

销毁监听hashchange事件,销毁路由事件

riot.route.start()

监听。默认是开启的

riot.util

包含两个内容,brackets和tmpl, brackets是tmpl的辅助函数,多带带使用意义不大,该辅助函数可以通过正则或者索引制造我们需要匹配的部分。tmpl是riotjs的模板引擎核心,html字符串拼接完全通过该引擎,可独立使用(在npm上有独立维护的模块名为riot-tmpl)

// 设置模板占位符(默认是{ })
riot.settings.brackets = "{{ }}";
// 使用
var html = riot.util.tmpl("
{{a}}
", { a:1 }); console.log(html); //print
1
riot.tag(name, html, css, attrs, fn)

全局注册一个riot标签, css attrs参数可省略。其实质是向一个内部对象tagImpl上创建了一个名为name的属性,其值是{name,html,css,attrs,fn}。此时该缓存并没有被使用,tag的实例并没有建立。

riot.tag(
    "ri-root",
    [
        "",
        ""
    ].join(""),
    function () {
        var self = this;
        this.showLogin = false;
        this.showError = false;
        this.on("mount", function () {
            var device_id = window.Qutils.getParams("device_id");
            if (!device_id) {
                alert("参数device_id缺失!");
            }
            else {
                setTimeout(function () {
                    bridge.isInApp(
                        function () {
                            self.showLogin = true;
                            self.tags["ri-login"].trigger("login-init", device_id);
                            self.update();
                        },
                        function () {
                            self.showError = true;
                            self.update();
                        }
                    )
                }, 100);
            }
        });
    }
);
riot.mount & riot.mountTo

riot.mountTo只是riot.mount的别名。该方法顾名思义,挂在riot标签(组件)。会返回一个tag的实例。

参数

selector

接受"*"(mount所有), string split with "," , string(使用原生的Selectors API,获取一个NodeList),或者接受一个NodeList,Element

tagName

接受"*"(mount所有), object(当为Object类型时,即为opts),string(等同mount所有selector上下文下的tagName匹配tag)

opts

Object,传入的参数对象,可直接混合在tag实体的opts对象上


riot.update

更新所有的tag实体,实质是调用每个实体的update方法。

riot的tag实例方法

上文说到riot中所用通过riot.tag声明的custom tag都只是缓存了,而没有立刻产生tag实例。实际上tag实例是在执行riot.mount的时候被创建的。所有的riot tag实例都是由内部构造器Tag实例化而来的。而对于一个多tag嵌套的组件,其实是递归先将子tag从底部实例化完,当实例化完成,会从根部到底部依次触发mount事件~

this.isMounted

true | false, 指示tag是否完成安装

this._id

一个自增的id,用于唯一代表该实例

this.parent

若一个tag实例有父实例,这个parent指向父实例

this.on("mount", function () {
    this.parent && this.parent.trigger("child-mounted");
}.bind(this))
this.root

该属性指向tag实例所表示的真实dom元素,另外root._tag同样挂载了tag实例的引用,所以当你的个自定义标签实例化以后,你还可以通过这样的姿势找到tag实例

var tag = riot.mount("custom-tag");

console.log(tag[0].root);
// print 

console.log(document.querySelector("custom-tag")._tag)
// print Tag {xxx}
this.opts

哦,这个的构造器是Child,不过特的原型指向你传入的opts的引用。所以如果不想自己配置被改动,请乖乖深度克隆

var tag = riot.mount("custom-tag", {a:1,b:2,c:3});

console.log(tag[0].opts.a);
// print 1

另外如果要在父子tag间传递参数也是很好玩的.

riot.tag(
    "hhh",
    "",
    function () {}
);
riot.tag(
    "zzz",
    "
{this.opts.myoptions}
", function () {} ); var new_custom_tag = document.createElement("hhh"); document.body.appendChild(new_custom_tag); var custom_tag = riot.mount("hhh", {test:1}); console.log(custom_tag[0].tags["zzz"].opts.myoptions); // print: 1

// 注: riot没有state机制,要通过attributes传值,小心undefined

需要注意的是,由于他遍历的是dom.attributes,你玩表单的时候小心一点。

this.tags

这里面放了子tag的实例的引用,上面的示例中有类似用法。多个同名子tag会放在数组里,我记不得在哪个版本里了,即使是一个子tag也会放在数组里。

this.update(data)

这个操作分为几个步骤:

一:源码里明确写到,执行该方法先判断data对象里有没有可能覆盖tag实例属性的属性,如果有,丢弃。注意,该处过滤数据使用的是浅复制,如果是对象套对象,你要小心了。

二:如果是循环产生的tag(注意,如果不是在custom-tag上使用each循环产生,不会去继承,因为此时isLoop为undefined),重新从父tag获取需要继承的值

riot.tag(
    "hhh",
    "",
    function () { this.eee = [{a:1,b:2},{a:1,b:2}]; this.eeeeeeeeee = 43214321; this.fdsafsdf = 3253425432 }
);
riot.tag(
    "zzz",
    "
{a} {b}
", function () { this.fffff = 4325345342543} ); var new_custom_tag = document.createElement("hhh"); document.body.appendChild(new_custom_tag); var custom_tag = riot.mount("hhh", {test:1}); console.log(custom_tag[0].tags.zzz[0].fdsafsdf) // print 3253425432
riot.tag(
    "hhh",
    "
", function () { this.eee = [{a:1,b:2},{a:1,b:2}]; this.eeeeeeeeee = 43214321; this.fdsafsdf = 3253425432 } ); riot.tag( "zzz", "
{a} {b}
", function () { this.fffff = 4325345342543} ); var new_custom_tag = document.createElement("hhh"); document.body.appendChild(new_custom_tag); var custom_tag = riot.mount("hhh", {test:1}); console.log(custom_tag[0].tags.zzz[0].fdsafsdf) // print undefined

该特性可能会对您造成困扰,啥时候误操作都可能一头雾水不造为什么。

三:混合其他数据和属性到当前tag上

四:更新视图,删除dom传导属性,重置事件。(所以说如果你浏览器在dom回收和事件回收上有问题,那你更新的时候就相当捉急了,在最新的版本里把这个泄漏点给堵上了)

this.mixin()

接受无数多个字符串参数,内部运行 riot.mixin[arguments[i]]将需要混入的属性或方法混入到实例上~~前面介绍过了。在2.2.4以前的版本没有使用.bind(this)来参入作用域,略蛋疼的说,2.2.4 对混入的方法都bind了当前作用域。另外,注意init是很特殊的,在混入时会自动执行。

riot.mixin({
    init: function () {
        this.a = 1;
        console.log("init")
    }
});

riot.tag("test", "
", function () { this.mixin("init"); }); var a = document.createElement("test"); document.body.appendChild(a); var custom_tag = riot.mount("test"); console.log(custom_tag[0].a) // print 1
this.mount()

将该实例强制重新装载一遍

this.unmount(keepRootTag)

传入参数,如果为true,会把初始化用的那个根节点也删球掉。该方法用于卸载实例,释放内存。

on, off, trigger, one

通过riot.observable混入的事件方法,然后我们可以在不同tag实例上到处传播事件了,建议使用一个集线器把事件管理起来,或者使用其他玩意,比如riot-flux什么的来玩。

生命周期

to be continue

后记

这个框架跟虚拟dom没撒关系,因为完全没有diff算法。。。在更新视图的时候用了文档碎片凑~,效果还凑合

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81816.html

相关文章

  • 列表的乐趣

    摘要:列表的乐趣标签空格分隔文章的原文是删除元素所有等于值的元素重复警告该方法不负责列表项的顺序。 列表的乐趣 标签(空格分隔): Python list 文章的原文是 Fun with Lists 1 删除元素 1.1 所有等于 X 值的元素 x = 4 a = [1, 2, 3, 4, 4, 5, 6, 1, 4] for i in range(a.count...

    littleGrow 评论0 收藏0
  • 简单易用的leetcode开发测试工具(npm)

    摘要:工具安装使用示例问题下面两部分的顺序不能交换第一个参数是空数组故意写错答案,展示测试失败输出效果测试用例编写说明要测试的都是函数,参数个数不定,但返回值是一个。上面例子的输入参数是,第一个参数是数组,第二个参数是数值返回值是一个数组。 描述 最近在用es6解leetcode,当问题比较复杂时,有可能修正了新的错误,却影响了前面的流程。要用通用的测试工具,却又有杀鸡用牛刀的感觉,所以就写...

    shusen 评论0 收藏0
  • PHP入门

    摘要:运行在浏览器端。未来软件的大趋势。相同点为语言结构,不是函数输出一个或者多个变量的类型,长度及值一般用于打印复杂变量结合标记格式化输出如数组对象等输出变量的值。一般用于打印变量。中认为变量的值为时,变量虽然定义了,但是无实际的意义。 PHP目录======== php介绍 2 基础 31 运算符 70 流程控制 77 函数 91 文件引入 100 ...

    abson 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<