
简介面向仍在维护动易 SiteWeaver 6.8 系统的站长与后台运维人员这份文档针对后台编辑器在 IE9、IE10、IE11 下无法正常调用、按钮失效等兼容性问题给出可直接实施的修复思路。内容分两类方案展开一是用随包文件直接覆盖 Editor.asp 及 Admin 目录下的 Admin_Article.asp、Admin_Index.asp快速恢复编辑功能二是手动改写逐处说明浏览器版本判断代码的替换、YUSERONCLICK 事件绑定的兼容处理以及为后台与会员中心补充 X-UA-Compatible 声明的位置并提示覆盖前先备份、改完清除缓存等注意点。压缩包内为 1 个 doc 文档约 21KB体量轻便可离线查阅、对照修改。目前已有 937 人学习适合需要在不升级整站的前提下低成本解决老系统 IE 兼容问题的技术人员参考。1. 周五下午的一通电话IE9 之后后台编辑器集体失声周五下午接到一个电话说后台文章编辑器在 Win7 加 IE11 上打开是一片白换台老机器用 IE8 又是好的。这套 6.8 版的 ASP 建站系统跑了好些年后台编辑器是十几年前的老控件浏览器一升级到 IE9、IE10、IE11工具栏按钮点了没反应插入图片的弹窗也弹不出来编辑区连光标都点不进去。问题不在服务器权限也不在数据库而是编辑器脚本在加载阶段就先抛了异常后面的初始化根本没跑完。这次要改的只有三个文件根目录的 Editor.asp以及 Admin 目录下的 Admin_Article.asp 和 Admin_Index.asp会员中心那条线还得单独补 User_Article.asp 一行 meta。适合手上只有现成站点、没有完整源码、只能靠改文件救活后台的开发者。2. 病灶定位Editor.asp 的浏览器嗅探为什么会把 IE9/IE10/IE11 全带崩2.1 编辑链路三个文件各自管哪一段先把这条链路捋清楚不然改错文件是家常便饭。Editor.asp 是编辑器的宿主页面里面既有服务端拼出来的 HTML 外壳也有客户端那段负责初始化工具栏、绑定按钮事件的脚本Admin_Article.asp 是「添加/编辑文章」的表单框架页它负责把 Editor.asp 以 iframe 的形式嵌进来Admin_Index.asp 是后台的主框架页左侧菜单、顶部导航都在这里。这三个文件构成一条自上而下的文档链Admin_Index.asp 先加载用户点进文章管理Admin_Article.asp 作为子框架加载再往里才是 Editor.asp。IE 的文档模式由最顶层文档决定子框架一般继承父页面的模式。也就是说如果只在 Editor.asp 上加兼容声明而 Admin_Index.asp 和 Admin_Article.asp 没加最外层仍然是 IE11 标准模式里层的编辑器照样跑在老脚本上。很多人第一次改完发现没效果就是只动了 Editor.asp 这一个文件。另外要区分后台和会员中心这两套入口。后台走 Admin 目录页面 head 是 ASP 用 Response.Write 一段段拼出来的加 meta 得改服务端代码会员中心走 User 目录User_Article.asp 里的 head 是写死的静态 HTML直接加一行标签就行。两者路径不同、写法不同但根子是同一个页面没有告诉 IE「请用老模式渲染我」。2.2MSIE (.)这条正则从 IE10 开始就已经在骗人了真正让编辑器白屏的是 Editor.asp 里的这两行// 老代码从 appVersion 里抠版本号 BrowserInfo.MajorVer navigator.appVersion.match(/MSIE (.)/)[1] ; BrowserInfo.MinorVer navigator.appVersion.match(/MSIE .\.(.)/)[1] ;navigator.appVersion在老 IE 里长这样4.0 (compatible; MSIE 8.0; Windows NT 6.1; ...)。/MSIE (.)/只匹配一个字符所以 IE8 拿到8IE9 拿到9看起来没问题。但 IE10 的 UA 变成了MSIE 10.0这条正则只吃到第一位MajorVer变成了1—— 不报错但版本判断彻底错了编辑器会误以为自己跑在 IE1 上走了一条完全不匹配的分支。IE11 更直接微软把 UA 里的MSIE字样去掉了改成Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko。match()找不到匹配就返回null紧接着[1]就去取null的下标抛TypeError: 无法获取未定义或 null 引用的属性 1。脚本在这一行就中断了后面所有初始化代码一行都没执行。所以用户看到的是白屏、按钮全死而不是「某个功能不好用」。浏览器UA 关键片段match(/MSIE (.)/)结果表现IE8MSIE 8.08正常IE9MSIE 9.09正常IE10MSIE 10.01版本误判部分功能异常IE11Trident/7.0; rv:11.0null抛异常编辑器白屏这张表解释了一个很常见的误判有人觉得「IE10 上还能用说明代码没问题是 IE11 太新了」。实际上 IE10 已经在错只是错得比较安静。改的时候必须把 IE9、IE10、IE11 一起覆盖不然换台机器又复发。2.3 动手前先做的三件准备第一件是备份。这类站点的后台文件往往被前人改过好几轮直接覆盖等于把别人的二次开发成果一起冲掉出问题连后悔药都没有。我会把 Editor.asp、Admin_Article.asp、Admin_Index.asp、User_Article.asp 四个文件原样复制一份到站点目录之外文件名带上日期比如Editor.asp.bak20240612。第二件是确认改的是线上真正在跑的那份。老站点常见的情况是服务器上有多个副本测试目录、备份目录、迁移遗留目录各有一套改了半天发现改的是废弃文件。改之前先在浏览器里打开后台用 F12 的「网络」面板看一眼 Editor.asp 的请求路径照着这个路径去找文件比凭记忆靠谱。第三件是统一文件编码。这套系统整体是 GB2312 环境ASP 文件如果用记事本另存成 UTF-8尤其是带 BOM 的那种页面头部会多出不可见字符轻则中文乱码重则直接报「无法显示 XML 页」。用记事本改完另存时编码一定选 ANSI用 Notepad 之类的工具右下角确认显示的是 ANSI 再保存。提示改之前把四个文件的原件打包留一份改完验证通过再删。老系统的文件依赖比较复杂回滚成本远低于排查成本。3. 手动改造Editor.asp 两处 后台两个文件的一行 meta3.1 第一处把版本嗅探从 appVersion 换成 userAgent打开 Editor.asp用编辑器的查找功能搜BrowserInfo.MajorVer能定位到 2.2 节那两行。把这两行注释掉行首加//或者直接删掉换成下面两行// 用 userAgent 整串去匹配[\d.] 能吃下多位数版本号 var ua navigator.userAgent.toLowerCase(); BrowserInfo.MajorVer ua.match(/msie ([\d.])/)[1];之所以换成userAgent是因为appVersion在部分浏览器里会被裁剪而userAgent是各家都老实写全的字段。正则里的([\d.])是捕获组\d匹配数字、.在字符组里就是字面点号所以MSIE 10.0能完整吃到10.0不会像原来那样只取一位。toLowerCase()是为了防止某些环境输出MSIE大写、某些输出小写统一转小写后正则只写小写形式就够了。要注意的是这行代码单独用是救不了 IE11 的 —— 因为 IE11 的 UA 里压根没有msie匹配结果还是null。它必须和 3.3 节那个 meta 配合一旦页面被强制切到 IE7 兼容模式IE11 的 UA 会回落成带MSIE 7.0的形式这行正则才拿得到值。两者是一套组合拳缺一个都不行这也是很多人只改了 JS 却依旧白屏的根本原因。3.2 第二处YUSERONCLICK 的分支两处都要改继续在 Editor.asp 里搜YUSERONCLICK会找到这样一行// 老写法把字符串拼上 anonymous() 再用 eval 执行 if (element.YUSERONCLICK) eval(element.YUSERONCLICK anonymous());这里先说清楚它在干什么。这套编辑器的每个工具栏按钮都会把自己的处理逻辑以字符串形式挂到元素的YUSERONCLICK属性上点击时把字符串拼成一个函数调用再eval出去。anonymous()是那个年代拼匿名函数的老套路依赖 IE 非标准的 eval 行为到了 IE9 之后的标准模式这套玩法失效结果就是按钮看着在、点了没反应。改成按浏览器分流的写法// IE7~IE12 走真实事件触发其它浏览器保持原逻辑 if (navigator.appVersion.match(/MSIE (7|8|9|10|11|12)\./i) ! null) { if (element.YUSERONCLICK) eval(element.YUSERONCLICK onclick(event)); } else { if (element.YUSERONCLICK) eval(element.YUSERONCLICK anonymous()); }正则/(7|8|9|10|11|12)\./i的意思是「版本号是 7 到 12 中任意一个且后面紧跟一个点」用\.卡住点号是为了避免1误匹配10、12这类多位数末尾的i忽略大小写。分支里把anonymous()换成onclick(event)是把「直接调用一个拼出来的函数体」改成「触发一次真实点击事件」IE7 到 IE11 都认这套。非 IE 浏览器当时的 Firefox、Chrome仍然走else分支保持原样不动避免把本来能用的环境改坏。这一行在文件里出现了两次两处一模一样都要改。用「全部替换」是最省事的但替换前先数一下命中数量是不是 2如果只命中 1 处说明这个文件被前人改过得手工核对另一处长什么样别盲目全替。3.3 第三处Admin_Article.asp 与 Admin_Index.asp 注入 X-UA-Compatible现在处理最外层的两个框架页。打开 Admin 目录下的 Admin_Article.asp搜索Response.Write meta http-equivContent-Type contenttext/html; charsetgb2312 vbCrLf在它下面紧跟着插入一行 强制 IE 以 IE7 兼容模式渲染位置必须紧跟 Content-Type Response.Write meta http-equivX-UA-Compatible contentIEEmulateIE7 vbCrLf这里有两个 VB 语法细节。一是 ASP 里字符串用双引号包裹内部要输出双引号必须写成两个连续的双引号所以X-UA-Compatible两侧写成X-UA-Compatible最终浏览器收到的是正常的X-UA-Compatible二是结尾的 vbCrLf是拼一个回车换行别漏漏了会和下一段输出粘在同一行虽然大多数情况下浏览器还能解析但一旦碰上注释或条件编译就容易出玄学问题。Admin_Index.asp 用完全相同的办法处理搜同一行 Content-Type 输出在下面加同一行 X-UA-Compatible。两个文件都要改因为 Admin_Index 是最外层框架Admin_Article 是中间层任何一层漏了文档模式都可能被拉回 IE11 标准模式。至于为什么用IEEmulateIE7而不是IE7区别在于前者还会尊重页面的 DOCTYPE 声明有标准 DOCTYPE 就按 IE7 标准模式没有就退回怪异模式。这套老系统的页面 DOCTYPE 五花八门用EmulateIE7让 IE 自己去判断比硬写IE7稳当。这也是原方案里选它的原因。3.4 验证顺序清缓存、看文档模式、点按钮改完之后别急着说好了按这个顺序验一遍完全关闭 IE 的所有窗口不是关标签页是退出进程。IE 的文档模式和页面缓存会粘在进程里只关标签等于没清。重新打开 IE进「Internet 选项」清一次临时文件或者进后台后按Ctrl F5强制刷新。打开后台文章编辑页按 F12 打开开发者工具看「文档模式」这一项显示的是不是IE7 标准。显示IE11就说明 meta 没生效回去查位置和文件路径。在编辑区里点一下看光标能不能落进去再点工具栏的加粗、插入图片看弹窗能不能出来。切到「源码」模式再切回来这一步能验证 3.2 节那个事件分支改对了没有 —— 模式切换按钮是最依赖YUSERONCLICK的一类操作。第 3 步是关键。很多人改完只看「页面能不能打开」页面当然能打开白屏的是编辑器 iframe。只有确认文档模式真的降到 IE7才说明 meta 起了作用后面的 JS 改动才有意义。4. 会员中心支线User_Article.asp 的一行 meta 与覆盖包取舍4.1 会员中心为什么不跟着后台一起好后台改完能用了会员中心投个稿还是白屏这是很典型的情况。原因在于这两套入口的页面结构根本不同后台的 head 是 ASP 在服务端一段段Response.Write拼出来的加 meta 等于加一段服务端代码会员中心的 User_Article.asp 里head 是直接写死的静态 HTML后台那套改动压根覆盖不到它。还有一个容易忽略的点会员中心的编辑器往往是另一份 Editor.asp 副本或者干脆是简化版。如果会员中心目录下也有独立的编辑器文件3.1 和 3.2 的改动同样要在那份文件上再做一遍只加 meta 只能让它「不再白屏」按钮该没反应还是没反应。判断方法很简单改完 meta 后点一下加粗按钮能用就说明共用同一份编辑器脚本不能用就得去找会员中心自己那份。4.2 User_Article.asp 的一行静态 meta打开 User 目录下的 User_Article.asp搜索这一行meta http-equivContent-Type contenttext/html; charsetgb2312 /在它下面紧跟着插入meta http-equivX-UA-Compatible contentIEEmulateIE7 /静态 HTML 里不用 ASP 的双引号转义直接写正常标签就行这是它和 3.3 节最大的区别别把那套照抄过来抄过来会在页面上原样输出两个引号。位置上有个硬要求X-UA-Compatible必须出现在 head 里足够靠前的位置最好就在 Content-Type 后面。如果它前面已经有一堆样式表、脚本、甚至一行空输出IE 有可能已经开始按默认模式解析文档这时候再声明就被忽略了。这也是为什么原方案强调「在 Content-Type 这行下面加」而不是「加到 head 里随便哪个位置」。改完同样走一遍 3.4 的验证流程重点看文档模式是不是也降到了 IE7。会员中心的页面往往没有后台那么规整F12 里如果看到「文档模式」显示成「IE7 标准页面默认」之类的字样说明生效了。4.3 覆盖包和手改怎么选原方案给了两条路直接拿现成的文件包覆盖或者照着手改。两者不是随便挑得看站点的实际情况。对比项直接覆盖文件包手动改四个文件耗时几分钟复制粘贴半小时左右要逐处核对前提站点没做过二次开发无所谓改的是自己这份风险会冲掉别人改过的模板、样式、自定义字段改错位置会引入新问题适合场景全新部署、标准版、代码没动过长期运营、后台被改过多轮可回滚性靠备份覆盖后难比对差异改动点明确容易还原我的选择标准很直接先比对文件大小和修改时间。如果线上的 Editor.asp 和文件包里的体积差得明显或者修改时间比站点上线时间还晚说明被人动过绝不能直接覆盖。这种情况下只能手改改完用文本比对工具把新旧文件 diff 一遍确认只多了那几行。注意覆盖前必须备份而且要备份到站点目录之外。放在同目录下改名某些服务器配置下仍然可能被 Web 访问到等于把后台源码暴露在公网。5. 避坑与排查五个改完不生效的现场5.1 现象改完打开还是白屏一点变化都没有原因是文件没改对或者缓存没清干净。老站点经常有多份副本本地编辑的是D:\backup\Editor.asp服务器跑的却是另一路径下的文件另一种情况是 IE 进程没真正退出文档模式还粘在上一次的会话里。解决顺序先用 F12 的网络面板确认 Editor.asp 的实际请求路径照着这个路径去服务器上找文件再看响应内容里有没有出现X-UA-Compatible没有就是文件改错了都有但界面没变就彻底退出 IE 进程、清临时文件、Ctrl F5重来。这三步能排掉九成「改了没反应」。5.2 现象编辑器出来了工具栏按钮点了没反应原因是只改了 meta没改 YUSERONCLICK 的分支或者只改了其中一处。meta 让页面降到了 IE7 模式编辑器能渲染出来但按钮的事件绑定还走老的anonymous()路径点了自然没反应。解决回到 Editor.asp 搜anonymous()确认文件里已经没有残留的旧写法两处都换成了带(7|8|9|10|11|12)判断的新写法。改完记得Ctrl F5JS 文件的缓存比 HTML 更顽固。5.3 现象改完页面顶部多出一行乱码或者弹出「无法显示 XML 页」原因是文件编码被改坏了。用记事本另存时选了 UTF-8或者带了 BOMASP 解析器读到 BOM 就把它当输出内容吐出去GB2312 页面里出现 UTF-8 的 BOM 字节直接表现为乱码如果 BOM 出现在文件最开头还可能让服务端认为输出已经开始后续的 Response 头设置全部失效。解决用支持编码显示的编辑器打开右下角确认是ANSI也就是 GB2312 本地代码页不是就转换回去再保存。已经出问题的把文件开头那几个不可见字节删掉重新保存。5.4 现象后台好了会员中心投稿还是白屏原因是只改了 Admin 目录下的两个文件User 目录的 User_Article.asp 没动。会员中心是另一套入口head 由静态 HTML 写死后台注入的 meta 完全覆盖不到它。解决按 4.2 节在 User_Article.asp 的 Content-Type 后面补一行静态 meta如果会员中心目录下有独立的编辑器文件3.1 和 3.2 的改动也要在那边再做一遍。改完同样退进程、清缓存再验。5.5 现象直接用覆盖包后台样式全乱、自定义字段不见了原因是站点做过二次开发覆盖包里的文件是标准版把前人加的模板改动、字段扩展、自定义按钮一股脑冲掉了。这类事故在长期运营的老站上特别常见而且往往过几天才被发现。解决立刻用备份还原然后改用手动修改的方式只加那几行代码。以后遇到「覆盖包 vs 手改」的选择先比对文件体积和修改时间差异明显就一律手改别图省事。6. 二次开发把这次补丁写成可回滚的一层改完能跑只是及格线真正省事的是把这几个散落的改动收成一层下次换机器、加站点、迁移环境能直接复用。第一步是把兼容模式做成配置项别把IEEmulateIE7硬编码在三个文件里。老 ASP 站点常见做法是在公共的配置 include 文件里定义常量然后在各页面引用 config.asp 里定义改一处全站生效 Const COMPAT_MODE IEEmulateIE7 各页面引用避免三处文件各写一份 Response.Write meta http-equivX-UA-Compatible content COMPAT_MODE vbCrLf这样以后要试IE9或者临时关掉兼容模式只改常量就行不用再去三个文件里翻。反过来说如果站点根本没引入公共配置文件那就老老实实三处写死但要在每处上方加一行注释标明改动日期和原因方便后来人看懂。第二步是把 Editor.asp 里那段版本嗅探单独抽成一小段放到try/catch里兜住异常// 版本嗅探失败也不能让整个脚本中断 try { var ua navigator.userAgent.toLowerCase(); var m ua.match(/msie ([\d.])/); BrowserInfo.MajorVer m ? m[1] : 11; } catch (e) { BrowserInfo.MajorVer 11; }这里的思路和原方案略有不同原方案是直接取[1]前提是 meta 已经把 UA 拉回带MSIE的形态加上try/catch和m ? ... : ...的判断是为了在 meta 万一没生效的环境里也不至于白屏退化成「版本号未知但脚本继续跑」。老系统上这种兜底很值因为你永远不知道用户的 IE 装了什么插件、组策略改了什么设置。第三步是留一份可复现的改动清单。我一般会在站点根目录之外放一个patch-note.txt写清楚改了哪几个文件、每个文件改了哪几行、验证时看哪个指标。不是为了给别人看是为了半年后自己再遇到同类站点时不用从零开始回忆。文件改动位置改动内容验证点Editor.aspBrowserInfo.MajorVer换用 userAgent 正则控制台无 TypeErrorEditor.aspYUSERONCLICK两处按 MSIE 7~12 分支工具栏按钮可点Admin_Article.aspContent-Type 输出后注入 X-UA-CompatibleF12 文档模式为 IE7Admin_Index.aspContent-Type 输出后注入 X-UA-Compatible同上User_Article.asp静态 head加静态 meta会员中心可编辑有一年我图快直接在服务器上改改完发现后台好了就没再管。两个月后同一个人又打电话说换了台电脑又不行了 —— 那次是会员中心我只改了后台那条线User 目录压根没碰。从那以后我每次动这类老站点都强制走一遍「四个文件全查、两套入口全验」的流程改完先在纸上把清单勾完再看浏览器。希望帮到你。本文还有配套的精品资源点击获取