迷你MVVM框架avalon在兼容旧式IE做的努力

当前标签: avalon

共3页: 1 2 3 下一页 
迷你MVVM框架avalon在兼容旧式IE做的努力 司徒正美 2014-03-13 11:40 阅读:741 评论:6  
 
迷你MVVM框架 avalonjs 组件编写指南 司徒正美 2014-02-28 14:55 阅读:1268 评论:5  
 
迷你MVVM框架 avalonjs 1.2发布 司徒正美 2014-02-19 09:31 阅读:649 评论:2  
 
迷你MVVM框架 avalonjs 1.1发布 司徒正美 2014-01-25 12:28 阅读:751 评论:4  
 
2013年最后的收成:avalon1.0正式发布 司徒正美 2014-01-13 10:25 阅读:4845 评论:45  
 
迷你MVVM框架 avalonjs 0.99发布 司徒正美 2013-12-18 14:46 阅读:1059 评论:3  
 
迷你MVVM框架 avalonjs 0.98发布 司徒正美 2013-11-20 15:11 阅读:975 评论:1  
 
使用avalon实现SKU组合查询功能 司徒正美 2013-11-18 10:47 阅读:1393 评论:1  
 
angular与avalon对复杂对象的修改 司徒正美 2013-11-17 09:20 阅读:857 评论:1  
 
for in 循环的输出顺序问题 司徒正美 2013-10-30 09:52 阅读:1474 评论:1  
 
avalon最佳实践 司徒正美 2013-10-24 10:30 阅读:2442 评论:4  
 
迷你MVVM框架 avalonjs 0.97发布 司徒正美 2013-10-21 16:52 阅读:1306 评论:4  
 
ms-class的进化 司徒正美 2013-10-15 21:54 阅读:655 评论:1  
 
利用状态模式处理多个模态弹出层的显示隐藏 司徒正美 2013-09-24 10:58 阅读:1401 评论:3  
 
迷你MVVM框架 avalonjs 0.96发布 司徒正美 2013-09-21 11:43 阅读:1101 评论:3  
 
使用avalon 实现一个订座系统 司徒正美 2013-09-19 14:31 阅读:1516 评论:4  
 
迷你MVVM框架 avalonjs 0.95发布 司徒正美 2013-09-07 22:14 阅读:1387 评论:2  
 
使用avalon 实现一个序列号功能 司徒正美 2013-09-07 10:11 阅读:1409 评论:3  
 
迷你MVVM框架 avalonjs 0.94发布 司徒正美 2013-08-26 09:48 阅读:644 评论:7  
 
迷你MVVM框架 avalonjs 0.93发布 司徒正美 2013-08-17 09:50 阅读:770 评论:2  
 
 

很多时候,写代码就像砌砖头,只要我们不关心盖楼的原因、建筑的原理、土木工程基础和工程经验,就算我们砌了100栋高楼,我们也就只是一个砌砖工人,永远也成为不了一个工程师,更别说建筑师了。而那些包工头也只会把我们当成劳动力罢了。——左耳朵耗子

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 = /<\w+\b(?:(["'])[^"]*?(\1)|[^>])*>/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 < n; i++) {
var tag = noscripts[i]
if (tag) { //IE6-8中noscript标签的innerHTML,innerText是只读的
tag.style.display = "none" //http://haslayout.net/css/noscript-Ghost-Bug
tag.fixIE78 = (array[i].match(rnoscriptText) || ["", " "])[1]
}
}
}

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操作上解放出来,研究设计模式,算法,分层架构等具有更高附加值的东西。从码农到工程师到架构师的道路迈进!

如果您觉得这文章对您有帮助,可以打赏点钱给我,鼓励我继续写博,我的支付宝

 
 
 
标签: avalon

MVVM框架avalon在兼容旧式IE的更多相关文章

  1. 迷你MVVM框架avalon在兼容旧式IE做的努力

    很多时候,写代码就像砌砖头,只要我们不关心盖楼的原因.建筑的原理.土木工程基础和工程经验,就算我们砌了100栋高楼,我们也就只是一个砌砖工人,永远也成为不了一个工程师,更别说建筑师了.而那些包工头也只 ...

  2. 轻量级前端MVVM框架avalon - 初步接触

    迷你简单易用的MVVM框架 avalon的介绍http://rubylouvre.github.io/mvvm/ 按照作者的介绍,在HTML中添加绑定,在JS中用avalon.define定义View ...

  3. 前端MVVM框架avalon - 模型转换1

    轻量级前端MVVM框架avalon - 模型转换(一) 接上一章 ViewModel modelFactory工厂是如何加工用户定义的VM? 附源码 洋洋洒洒100多行内部是魔幻般的实现 1: fun ...

  4. 轻量级前端MVVM框架avalon - 执行流程2

    接上一章 执行流程1 在这一大堆扫描绑定方法中应该会哪些实现? 首先我们看avalon能帮你做什么? 数据填充,比如表单的一些初始值,切换卡的各个面板的内容({{xxx}},{{xxx|html}}, ...

  5. 轻量级前端MVVM框架avalon - 整体架构

    官网提供架构图 单看这个图呢,还木有说明,感觉有点蛋疼,作者的抽象度太高了,还好在前面已经大概分析过了执行流程 如图 左边是View视图,我们就理解html结构,换句话就是说用户能看到的界面,渲染页面 ...

  6. 轻量级前端MVVM框架avalon - ViewModel

    废话说了大几篇,我们开始来点干货了~ ViewModel的内部机制 在MVVM中,数据是核心.而jQuery则以DOM为核心. 而DOM只是HTML在JS的世界的抽象,是一个很易变的东西.因此如果业务 ...

  7. 轻量级前端MVVM框架avalon - 执行流程1

    基本上确定了avalon的几个重要元素的关系: M,即model,一个普通的JS对象,可能是后台传过来的,也可能是直接从VM中拿到,即VM.$json.有关的这个$json的名字还在商讨 V,即Vie ...

  8. 轻量级前端MVVM框架avalon - 模型转换

    接上一章 ViewModel modelFactory工厂是如何加工用户定义的VM? 附源码 洋洋洒洒100多行内部是魔幻般的实现 1: function modelFactory(scope) { ...

  9. 轻量级前端MVVM框架avalon源码分析-总结

    距avalon0.7版本发布有一段时间,由于之前的稳定性,就停止一段时间更新,期间研究了下Knockout源码,也尝试写了一个小型的mvvm的实现模型,仅仅只是仿造ko的核心实现,把无关的东西给剥离掉 ...

随机推荐

  1. asp.net学习之数据绑定控件、数据源控件概述

    原文:asp.net学习之数据绑定控件.数据源控件概述 1.asp.net数据绑定控件分为三大类,每个类分别进行详细:      ● 列表式数据绑定控件: 列表式数据绑定控件常用来在一个表格内的一个字 ...

  2. android开源系列:CircleImageView采用圆形控制它们的定义

    1.定义自己的圆形控制github住址:https://github.com/hdodenhof/CircleImageView 基本的类: package de.hdodenhof.circleim ...

  3. HDU 2048 号码塔(DP)

    号码塔 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  4. MVC4 + EF为Model添加单独的验证属性

    可使用以下方式给Model加上相关的meta验证属性,这样实体的验证属性就不会被例如EF或其他工具自动生成的Model所替换了. using System.ComponentModel.DataAnn ...

  5. 无废话WCF入门教程五[WCF的通信模式]

    一.概述 WCF在通信过程中有三种模式:请求与答复.单向.双工通信.以下我们一一介绍. 二.请求与答复模式 描述: 客户端发送请求,然后一直等待服务端的响应(异步调用除外),期间处于假死状态,直到服务 ...

  6. MAC使用小技巧(二)

    一.Safari-->广告数量不足 --原因:DNS被拦截,被恶意推送广告. ----------------------------- [ 思路 ] 修改hosts文件 $ cd /etc $ ...

  7. 解决VS 于 致命错误 RC1015: 无法打开包含文件 &#39;afxres.h&#39; 问题

    在试验VS2010当一个问题困扰了我,它是开放的c++项目达产后,rc的dialog入口.您不能拖动控制,让我疯狂... 而最有发言权的是在线Directions问题. .题明显不是这个问题. 于是我 ...

  8. Vim实用小技巧

    Vim实用小技巧 一些网络上质量较高的Vim资料 从我07年接触Vim以来,已经过去了8个年头,期间看过很多的Vim文章,我自己觉得非常不错,而且创作时间也比较近的文章有如下这些. Vim入门 目前为 ...

  9. CentOs Linux 安装MySql服务失败 安装需要依靠包error:Failed dependencies

    [root@sh158-xen data]#rpm -ivh MySQL-server-5.5.24-1.linux2.6.x86_64.rpm error: Failed dependencies: ...

  10. 【phpMyAdmin】更改配置文件连接到其他server

    默认phpMyAdmin安装完毕后对机器的访问mysql,但有时我们需要访问其它server的mysql数据库,所以我们需要配置. 真,phpMyAdmin已经为我们做了配置的选项.可是须要我们进行一 ...