Ruby's Louvre

每天学习一点点算法

导航

统计

迷你MVVM框架 avalonjs 0.82发布

本版本最大的改进是启用全新的parser。

parser是用于干什么的?在视图中,我们通过绑定属性实现双向绑定,比如ms-text="firstName", ms-html="sex + '士'", ms-visible="Math.abs(toggle + 2000) >= 20", 我们需要将它们转换为求值函数。我们通过ms-controller="vm"来绑定ViewModel,比如vm = { firstName: '司徒'}, 那么对于上面的第一个绑定,我们想让它变成函数,以前是这样实现的:

            function anonymous(vm1372575919386) {
                with (vm1372575919386) {
                    var ret1372575919386 = firstName
                }
                return ret1372575919386
            }

然后视图刷新函数会将vm传入此函数,var ret = anonymous(vm), 得到'司徒',然后node.value = ret(注,这里的node 为文本节点,它在扫描DOM树时被抽取出来),完成视图的最少化刷新。这个过程中如何将绑定属性的值转换为求值函数显然是重中之重。

之前的parser,正如大家看到的那样,非常简单,然后with表达式一包,然后返回结果。但with在ES5的严格模式下运行不了,也一直为性能洁癖人士所不齿。并且它存在一个问题,它的依赖收集并不完整。比如下面这种

     

aaa {{test1 && test2}}

上面的插值表达式是一个文本绑定,转换为求值函数时,为:

            function anonymous(vm1372575919386) {
                with (vm1372575919386) {
                    var ret1372575919386 = test1 && test2
                }
                return ret1372575919386
            }

当一开始test1为false, test2为true时,由于短路与的关系,我们并没有对test2进行取值。由于avalon只在求值函数的第一次执行时收集依赖,在依赖是通过求值赋值语句实现的,而这时,我们就肯定遗漏了test2了。因此一个全新的parser就迫在眉睫了。

新的parser的实现思路时,设法抽取到绑定值中的变量,然后转换为赋值语句,放到求值函数的最前面,这样就不会遗漏任何依赖了。问题是如何得到这些变量。比如上面三例,它们的变量依次是firstName, sex, toggle,我们要设法去掉所有杂质,首先要去掉注释,字符串,正则这些字面量,然后是加减乘除这些操作符,然后是if, while, for, undefined, void 等关键字,然后是作为某个对象的属性或方法存在的语句,如.prop,然后逗号这样用于断句用的符号。但即使这样,还会留下像Math, String等全局变量,这时我们就通过vm取hasOwnerProperty进行排除。

下面就是通过新的parser转换得到的求值函数。

            function anonymous(vm1372575919386) {
                var firstName =  vm1372575919386.firstName
              
                return firstName 
            }
            function anonymous(vm1372575919386) {
                var test1=  vm1372575919386.test1, test2 = vm1372575919386.test2
              
                return test1 && test2
            }

并且进一步,我们可以在里面塞进'use strict'来提高性能。

            function anonymous(vm1372575919386) {
                'use strict';
                var firstName =  vm1372575919386.firstName
              
                return firstName 
            }
            function anonymous(vm1372575919386) {
                'use strict';
                var test1=  vm1372575919386.test1, test2 = vm1372575919386.test2
              
                return test1 && test2
            }

如何存在过滤器

   
{{ new Date | date('dd MM yyyy') }}

            function anonymous(vm1372896828095_0, filters1372896828095) {
                'use strict';
                var ret1372896828095 = new Date
                if (filters1372896828095.date) {
                    try {
                        ret1372896828095 = filters1372896828095.date(ret1372896828095, 'dd MM yyyy')
                    } catch (e) {
                    }
                }
                return ret1372896828095
            }

凭借着此新parser,avalon又有了一个质的提高。有关的parser的实现,可以详看该issue

读者们也可以对比angular的parser实现, avalon的是非常小巧的。

迷你MVVM框架在github的仓库https://github.com/RubyLouvre/avalon

官网地址http://rubylouvre.github.io/mvvm/

大家可以加入QQ群:79641290进行讨论,此群为技术群,禁水!

posted on 2013-07-04 08:23  司徒正美  阅读(...)  评论(...编辑  收藏