迷你MVVM框架avalon在兼容旧式IE做的努力
很多时候,写代码就像砌砖头,只要我们不关心盖楼的原因、建筑的原理、土木工程基础和工程经验,就算我们砌了100栋高楼,我们也就只是一个砌砖工人,永远也成为不了一个工程师,更别说建筑师了。而那些包工头也只会把我们当成劳动力罢了。——左耳朵耗子
![](https://images.cnblogs.com/cnblogs_com/rubylouvre/506305/o_02456266.jpg)
avalon在兼容旧式IE上做了大量工作,从而让它更接地气,完美地运行于国内的各种奇葩浏览器中。
首先是Object.defineProperties的模拟,正因为有这东西,才能让avalon是纯事件驱动地同步视图,而不用脏检测,从而获得更高的性能。
//IE6-8使用VBScript类的set get语句实现
if (!defineProperties && window.VBArray) {
window.execScript([
"Function parseVB(code)",
"\tExecuteGlobal(code)",
"End Function"
].join("\n"), "VBScript") function VBMediator(accessingProperties, name, value) {
var accessor = accessingProperties[name]
if (arguments.length === 3) {
accessor(value)
} else {
return accessor()
}
}
defineProperties = function(name, accessingProperties, normalProperties) {
var className = "VBClass" + setTimeout("1"),
buffer = []
buffer.push(
"Class " + className,
"\tPrivate [__data__], [__proxy__]",
"\tPublic Default Function [__const__](d, p)",
"\t\tSet [__data__] = d: set [__proxy__] = p",
"\t\tSet [__const__] = Me", //链式调用
"\tEnd Function")
//添加普通属性,因为VBScript对象不能像JS那样随意增删属性,必须在这里预先定义好
for (name in normalProperties) {
buffer.push("\tPublic [" + name + "]")
}
buffer.push("\tPublic [" + 'hasOwnProperty' + "]")
//添加访问器属性
for (name in accessingProperties) {
if (!(name in normalProperties)) { //防止重复定义
buffer.push(
//由于不知对方会传入什么,因此set, let都用上
"\tPublic Property Let [" + name + "](val" + expose + ")", //setter
"\t\tCall [__proxy__]([__data__], \"" + name + "\", val" + expose + ")",
"\tEnd Property",
"\tPublic Property Set [" + name + "](val" + expose + ")", //setter
"\t\tCall [__proxy__]([__data__], \"" + name + "\", val" + expose + ")",
"\tEnd Property",
"\tPublic Property Get [" + name + "]", //getter
"\tOn Error Resume Next", //必须优先使用set语句,否则它会误将数组当字符串返回
"\t\tSet[" + name + "] = [__proxy__]([__data__],\"" + name + "\")",
"\tIf Err.Number 0 Then",
"\t\t[" + name + "] = [__proxy__]([__data__],\"" + name + "\")",
"\tEnd If",
"\tOn Error Goto 0",
"\tEnd Property")
}
}
buffer.push("End Class") //类定义完毕
buffer.push(
"Function " + className + "Factory(a, b)", //创建实例并传入两个关键的参数
"\tDim o",
"\tSet o = (New " + className + ")(a, b)",
"\tSet " + className + "Factory = o",
"End Function")
window.parseVB(buffer.join("\r\n")) //先创建一个VB类工厂
return window[className + "Factory"](accessingProperties, VBMediator) //得到其产品
}
option元素的value值的提取。在规范中,如果用户没有显式定义value,则会对其innerHTML进行两边对空白操作,作为value值。但如何判定用户是否显示定义value值呢,IE67是没有hasAttribute方法,此外还有其他兼容问题,而jQuery的做法太罗索。看avalon的实现:
var roption = /^<option(?:\s+\w+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?)*\s+value[\s=]/i
var valHooks = {
"option:get": function(node) {
//在IE11及W3C,如果没有指定value,那么node.value默认为node.text(存在trim作),但IE9-10则是取innerHTML(没trim操作)
if (node.hasAttribute) {
return node.hasAttribute("value") ? node.value : node.text
}
//specified并不可靠,因此通过分析outerHTML判定用户有没有显示定义value
return roption.test(node.outerHTML) ? node.value : node.text
},
//.....
}
旧式IE下高性能获对所有绑定属性:
//IE67下,在循环绑定中,一个节点如果是通过cloneNode得到,自定义属性的specified为false,无法进入里面的分支,
//但如果我们去掉scanAttr中的attr.specified检测,一个元素会有80+个特性节点(因为它不区分固有属性与自定义属性),很容易卡死页面
if (!"1" [0]) {
var cacheAttr = createCache(512)
var rattrs = /\s+(ms-[^=\s]+)(?:=("[^"]*"|'[^']*'|[^\s>]+))?/g,
rquote = /^['"]/,
rtag = /])*>/i
var getAttributes = function(elem) {
if (elem.outerHTML.slice(0, 2) == "</") {//处理旧式IE模拟HTML5新元素带来的伪标签
return []
}
var str = elem.outerHTML.match(rtag)[0]
var attributes = [],
match,
k, v;
if (cacheAttr[str]) {
return cacheAttr[str]
}
while (k = rattrs.exec(str)) {
v = k[2]
var name = k[1].toLowerCase()
match = name.match(rmsAttr)
var binding = {
name: name,
specified: true,
value: v ? rquote.test(v) ? v.slice(1, -1) : v : ""
}
attributes.push(binding)
}
return cacheAttr(str, attributes)
}
}
avalon允许使用script, noscript, textaea作为子模块的容器,但script节点需要修改type属性,textarea要手动display:none,noscript无疑是最好的选择,但noscript在IE78中竟然抽风了,在chrome下也有坑。avalon被逼又正则一番了……
var rnoscripts = /<noscript.*?>(?:[\s\S]+?)<\/noscript>/img
var rnoscriptText = /<noscript.*?>([\s\S]+?)<\/noscript>/im
if (el.tagName === "NOSCRIPT" && !(el.innerHTML || el.fixIE78)) { //IE7-8 innerText,innerHTML都无法取得其内容,IE6能取得其innerHTML
var xhr = getXHR() //IE9-11与chrome的innerHTML会得到转义的内容,它们的innerText可以
xhr.open("GET", location, false) //谢谢Nodejs 乱炖群 深圳-纯属虚构
xhr.send(null)
//http://bbs.csdn.net/topics/390349046?page=1#post-393492653
var noscripts = DOC.getElementsByTagName("noscript")
var array = (xhr.responseText || "").match(rnoscripts) || []
var n = array.length
for (var i = 0; i A,IMG标签的src, href路径的转义,这个真是够隐秘啊!if (!W3C && (method === "src" || method === "href")) {
val = val.replace(/&/g, "&")//处理IE67自动转义的问题
}oninput事件在IE6-9的兼容问题:
if (W3C) { //先执行W3C
element.addEventListener("input", updateVModel)
data.rollback = function() {
element.removeEventListener("input", updateVModel)
}
} else {
removeFn = function(e) {
if (e.propertyName === "value") {
updateVModel()
}
}
element.attachEvent("onpropertychange", removeFn)
data.rollback = function() {
element.detachEvent("onpropertychange", removeFn)
}
} if (DOC.documentMode === 9) { // IE9 无法在切剪中同步VM
var selectionchange = function(e) {
if (e.type === "focus") {
DOC.addEventListener("selectionchange", updateVModel)
} else {
DOC.removeEventListener("selectionchange", updateVModel)
}
}
element.addEventListener("focus", selectionchange)
element.addEventListener("blur", selectionchange)
var rollback = data.rollback
data.rollback = function() {
rollback()
element.removeEventListener("focus", selectionchange)
element.removeEventListener("blur", selectionchange)
}
}
}此外还有许多许多,但都是见诸于jQuery源码的常见问题,我就不便贴出来了,它们的实现也与jQuery的相差无几。可见兼容旧式IE是多么头痛纠结的一件事。但由于OA的要求,甲方的要求,公司上头的要求,我们总是奔于疲命。jQuery帮我们搞定了浏览器的兼容问题,但业务上的复杂性,让我们的代码在DOM与业务逻辑上两头跳。用了avalon后,我们就能从搬砖似的DOM操作上解放出来,研究设计模式,算法,分层架构等具有更高附加值的东西。从码农到工程师到架构师的道路迈进!
迷你MVVM框架avalon在兼容旧式IE做的努力的更多相关文章
- MVVM框架avalon在兼容旧式IE
迷你MVVM框架avalon在兼容旧式IE做的努力 当前标签: avalon 共3页: 1 2 3 下一页 迷你MVVM框架avalon在兼容旧式IE做的努力 司徒正美 2014-03-13 11: ...
- 迷你MVVM框架 avalonjs 0.8发布
本版本最重要的特性是引进了AMD规范的模块加载器,亦即原来mass Framework 的并行加载器, 不同之处,它引进了requirejs的xxx!风格的插件机制,比如要延迟到DOM树建完时触发,是 ...
- 迷你MVVM框架 avalonjs 0.9发布
本版本最大的改进是引进了ms-with绑定,现在可轻松遍历对象了. 改进列表如下: 重新使用082的scanNodes方法,因为有关旧式IE下UI渲染锁死的问题已经解决了. 优化each绑定与Coll ...
- 迷你MVVM框架 avalonjs 1.2发布
avalon1.2 带来了许多新特性,让开发更轻松!详见如下: 升级路由系统与分页组件. 对ms-duplex的绑定值进行增强,以前只能prop或prop.prop2,现在可以prop["x ...
- 轻量级前端MVVM框架avalon - 初步接触
迷你简单易用的MVVM框架 avalon的介绍http://rubylouvre.github.io/mvvm/ 按照作者的介绍,在HTML中添加绑定,在JS中用avalon.define定义View ...
- 迷你MVVM框架 avalonjs 0.95发布
迷你MVVM框架 avalonjs 0.95发布 本版本最主要的改进是ms-with 深层绑定的实现,至少,avalon1.0所有重要的feature已经开发完毕,之后就是小补小漏,性能优化了. ms ...
- 迷你MVVM框架 avalonjs 0.85发布
迷你MVVM框架 avalonjs 0.85发布 本版本对循环绑定做了巨大改进,感谢@soom, @limodou, @ztz, @Gaubee 提供的大量测试文件. fix scanNodes, 在 ...
- 迷你MVVM框架 avalonjs 1.3.8发布
avalon1.3.8主要是在ms-repeat. ms-each. ms-with等循环绑定上做重大性能优化,其次是对一些绑定了事件的指令添加了roolback,让其CG回收更顺畅. 重构ms-re ...
- 迷你MVVM框架 avalonjs 1.3.6发布
本版本是一次重要的升级,考虑要介绍许多东西,也有许多东西对大家有用,也发到首页上来了. 本来是没有1.36的,先把基于静态收集依赖的1.4设计出来后,发现改动太多,为了平缓升级起见,才减少了一部分新特 ...
随机推荐
- 配置比对脚本(python)
# -*- coding: utf- -*- from datetime import * import MySQLdb import sys import time import datetime ...
- linux中redis安装
一.登录redis官网下载redis-3.0.7.tar.gz 二.通过ftp工具上传至自己的服务器中 三.tar -zxvf redis-3.0.7.tar.gz解压 四.cd redis-3.0. ...
- Kafka、RabbitMQ、RocketMQ消息中间件的对比 —— 消息发送性能-转自阿里中间件
引言 分布式系统中,我们广泛运用消息中间件进行系统间的数据交换,便于异步解耦.现在开源的消息中间件有很多,前段时间我们自家的产品 RocketMQ (MetaQ的内核) 也顺利开源,得到大家的关注. ...
- Nginx %00空字节执行php漏洞
Nginx如下版本:0.5.*, 0.6.*, 0.7 <= 0.7.65, 0.8 <= 0.8.37在使用PHP-FastCGI执行php的时候,URL里面在遇到%00空字节时与Fas ...
- sqlmap 帮助信息
Usage: sqlmap.py [options] 选项: -h, --help 显示基本的帮助信息并退出 -hh 显示高级的帮助信息并退出 --version 显示程序版本号并退出 -v VERB ...
- Pascal 语言中的关键字及保留字
absolute //指令(变量) abstract //指令(方法) and //运算符(布尔) array //类型 as //运算符(RTTI) asm //语句 assembler //向后兼 ...
- d-规则
[问题描述]对任意给定的m(m∈N+)和n(n∈N+),满足m<n,构造一初始集合:P={x|m≤x≤n,x∈N+} (m,n≤100).现定义一种d规则如下:若存在a∈P,且存在K∈N+ ,K ...
- 关于android 加载https网页的问题
我在加载https网页时出现空白, 因此,我就百度一下,可以发现: webView.setWebViewClient(new WebViewClient(){ @Override public voi ...
- Set和存储顺序
set(interface) 存入Set的每个元素必须是唯一的,因为Set不保存重复的元素.加入Set的元素必须定义 equal()方法以确保对象的唯一性.Set和Collection有完全一样的接口 ...
- solr DIH 知识梳理
solr DIH 知识梳理 web.xml中listener配置 <listener> <listener-class>org.apache.solr.handler.data ...