ClosureTemplates(1-2):从Yaya说起

YayaTemplate

记得8个月前,我第一次在百度UED的网站上看到一篇关于前端模版的介绍。第一次并未一下就被吸引过去,而是辗转几日在项目前端复杂度逐渐增加的一个偶然机会,让我想起了一周前看到的“前端模版”这4个字眼。

那篇Blog上介绍的正是YayaTemplate这个由贵大师兄@王集鹄 所创作的优秀模版引擎,于是也会以它作为模版引擎的主要介绍对象。

yayaTemplate的github源码: https://github.com/yorkie/YayaTemplate/blob/master/yaya-template.js

yaya等许多模版系统其核心思想即:先向引擎传入模版字符串,然后yaya通过String.prototype.replace,转换为javascript编译器可以识别代码,利用Function将字符串转换为function对象的能力,将生成的匿名函数作为该编译过程的返回值。

作为一个轻量级的前端模版系统,以其不亚于artTemplate的速度上yaya做得相当出色,并且其源代码也足够轻,添加了注释的源代码也才122行。

具体的代码可能要等到翻译部分完成后,才能向大家贡献了,不过我想在这里提出我对于模版系统的至今不解的疑惑,或许是我自身的思考过程:

 

几个疑惑

1、最大的疑惑来自于Function,Function/setTimeout/eval等都具有根据字符串来执行js代码的能力,不过也带来了相当层度的性能问题(调试上由@糖饼哥哥 的artTemplate已得到了解决方案)。我在想是否可以通过向浏览器中添加script标签的方式来动态执行代码呢?下面的代码是我从Closure Library中的base.js摘录的:

其实这段代码来自于KIQ.js,是我对Google Library做了些许的改动。

/* customized EVAL method[by Google Closure Library] */
kiQ.globalEval = function (script) {
    if (kiQ.global.execScript) {
        kiQ.global.execScript(script);
    } else if (kiQ.global.eval) {
        if (kiQ.evalWorksForGlobals_ == null) {
            kiQ.global.eval("this.__test__=1;");
            if (typeof kiQ.global["__test__"] !== "undefined") {
                delete kiQ.global["__test__"];
                kiQ.evalWorksForGlobals_ = true;
            } else {
                kiQ.evalWorksForGlobals_ = false;
            }
        }
                     
        if (kiQ.evalWorksForGlobals_) {
            kiQ.global.eval(script);
        } else {
            var doc = kiQ.global.document;
            var scriptElem = doc.createElement('script');
            scriptElem.type = 'text/javascript';
            scriptElem.defer = false;
            scriptElem.appendChild(
                doc.createTextNode(script)
            );
            doc.body.appendChild(scriptElem);
            doc.body.removeChild(scriptElem);
        }
                     
    } else {
        kiQ.error("KIQ.globalEval not available");
    }
}

不过大致思路没有多少出入,19-27行即我上面提到的通过通过嵌入script的方式来执行Javascript脚本,需要注意的是在IE/Opera浏览器下,如果把23-25行改成scriptElem.innerHTML=script,将会报错,因此closure巧妙地用TextNode的方式来向script中填充js代码。

不过即使是Google,也是将这种方法作为eval不被ES环境支持的情况下的备选方案,现在的我所能想到这么做的原因即是:对于作用域的控制,eval上提供了很明确的用法,不过使用后者,我也能通过将要执行的js代码包装在一个function表达式中,然后向function传递作用域。不过对于此,我准备在翻译完Closure对模版系统有更深了解之后,写一个性能比对的测试再下定论。

2、这应该不算疑问了,算是领悟,与上一个问题紧密度很高,在上一篇做动静模版性能比对时,我将动态模版的性能消耗算在了编译期,现在仍然是编译期,不过涵盖了Function/eval函数,这也使得第一个问题最后提到的性能比对更加重要。

3、关于缓存,上面所提到的两个模版系统都提供缓存,但他们的缓存都是基于一个返回字符串的函数,而非一个灵活的DocumentFragment对象。我想说的是,如果在预编译时就将DOM生成的DOM节点转换为一个DocumentFragment的话,不是可以省去很多模版么?比如有时候我们仅仅需要改写一个ul中每个li的一个小元素,要么是将这个需要修改的节点作为参数,写入,要么是新建第一个模版。

还有更好的办法么?答案是有的,将这个模版生成的字符串转换为DocumentFragment,存储在一个Js对象中,在需要时更改,然后插入就行了。

不过为何我们不直接将其直接加入到系统的缓存中呢,直接返回DocumentFragment,也许性能上没有那么大的提升,但DOM在操作XML时永远比String要直观,不是吗?

这三个问题所提供得优化方法,都将在翻译完Closure的相关文档后,加入到我KIQ.js的动态模版库中,也会做出一系列性能比对第一时间分享给大家。

后记:很多时候真的身不由己,上一篇后记说是要在这篇写一些源码分析,不过看完yayaTemplate和artTemplate源码后,感觉我还没有能力在一个时间内将别人优秀的作品做一个现场解剖,不过提提意见总是可以的吧,这不就是"开源"的思想吗!好了,问题已经抛出来了,下周开始正式的翻译工作,相对于原创,会是比较简单的工作了吧。亲们,下周三见咯!

转载于:https://www.cnblogs.com/Mr-Jquery/articles/2795147.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值