IOS设备 出现 attempted-to-assign-to-readonly-property 报错
刚刚结束的广告位功能,在chrom和安卓手机上都能正常访问,但是在ios手机端,微信和支付宝中打开都无法访问。由于支付宝没有对外的开发工具,只能用微信开发工具进行调试,但是在里面也能正常展示,无法重现错误。看来应该是真机App中webView容器问题,于是通过逐行alert方式,定位到在:
let a = Dom7('<a href="#" class="frame_detail" url="'+setting_.pictureUrl+'"></a>'), a.attr({ 'style':'line-height:0;' });
处停止执行了,通过try catch 输出e.message错误信息为:attempted to assign to readonly property, 大致意思为“尝试分配定义只读属性”,第一行的Dom7是前端的一个选择器框架,attr的源码如下:
attr: function (attrs, value) { if (arguments.length === 1 && typeof attrs === 'string') { // Get attr if (this[0]) return this[0].getAttribute(attrs); else return undefined; } else { // Set attrs for (var i = 0; i < this.length; i++) { if (arguments.length === 2) { // String this[i].setAttribute(attrs, value); } else { // Object for (var attrName in attrs) { this[i][attrName] = attrs[attrName]; this[i].setAttribute(attrName, attrs[attrName]); } } } return this; } }
通过逐行删除,发现删除到this[i][attrName] = attrs[attrName];时,网页报错消失。重新查看代码,正确设置样式的api应该是下一行的setAttribute,这里为什么直接给DOM元素设置style属性呢?带着这个疑问继续梳理。结合此次attr调用场景,dom元素本身也是对象,理论上设置属性不应该报错,而且我前面对img元素也设置过属性(未设置style),它并没有报错:
let img = Dom7('<img />'); img.attr({ //强制图片按照比例变形 'src':setting_.rFdsUrl + setting_.picture, 'width':width, 'height':height });
当把代码增加设置style之后,报错又会出现:
let img = Dom7('<img />'); img.attr({ //强制图片按照比例变形 'src':setting_.rFdsUrl + setting_.picture, 'width':width, 'height':height, 'style':'line-height:0;' });
以上代码证实新创建的元素设置style会出现报错,其它属性正常,接下去我又用Dom7选择一个已经存在的元素,进行style设置,它也会出现相同报错:
Dom7('.rechage_type').attr({ //Dom具有创建和选择两重功能,当参数是不包含箭头的字符串时,作为选择器;当参数包含闭合箭头时为创建元素 'style':'background:#ff3300' });
经过上面验证的一些场景,又尝试用ul、p、h1等标签进行实验,结果也一致,说明这个报错应该跟标签没有直接关系,暂时把这个现象归类为:使用Dom7创建或者选择元素都不能进行style属性设置,否则在ios手机中直接报错。
TrackJS指出,这个报错是一个 ios中webkit内核的bug(我又用safari浏览器查看了之前的场景,也同样报错),而且每个框架都以独特的方式遇到这个问题,我这里遇到肯定和Dom7选择器封装,以及attr封装的特殊结构有关系,因为我单独给DOM元素,使用同样方法设置style属性,并不会报错。webkit bugs 也确认了该问题,在stackoverflow里也看到其它框架也有类似问题,Angular 1.2.25等。后来发现直接删除js开头的'use strict';就不会报错了,但是这样js语法就不是严格模式了。
为了不影响严格模式,我直接删除了attr封装方法中赋值属性那一行,从Dom7源码结构发现,this[i][attrName] = attrs[attrName]只是增加给DOM元素存储数据的能力,删除之后,把数据移至localStorage中进行存储更新。
记录下来,期待下次中奖!
参考资料:bugzilla、webkit bugs、trackJs、angular error
应为微信小程序出现错误,首页百度了一下。来到你这个博客
你好 微信小游戏遇到了 微信报:类型错误:试图分配只读属性Attempted to assign to readonly property 你的也是吗?解决了吗