• Zepto的天坑汇总


    前言

    最近在做移动端开发,用的是zepto,发现他跟jquery比起来称之为天坑不足为过,但是由于项目本身原因,以及移动端速度要求的情况下,也只能继续用下去。

    所以在这里做一下汇总

    对img标签空src属性用attr取值会取得当前url地址的BUG

    如下图,某img标签有src属性,但是其src属性值为空,但是用zepto的attr取src属性值却是当前页面的url地址

    BUG原因分析:

    //zepto源码
    attr: function(name, value){ var result return (typeof name == 'string' && !(1 in arguments)) ? (!this.length || this[0].nodeType !== 1 ? undefined : (!(result = this[0].getAttribute(name)) && name in this[0]) ? this[0][name] : result ) : this.each(function(idx){ if (this.nodeType !== 1) return if (isObject(name)) for (key in name) setAttribute(this, key, name[key]) else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name))) }) },

    问题在于这个 this[0][name] ,相当于直接取img标签DOM元素的src属性,而不是他的attributes属性里面的值。

    在很多情况下元素的DOM属性和attributes属性是不一致的,比如臭名昭著的布尔类类型属性,jquery在这方面做了完善兼容而zepto就没有,非常简单粗暴。

    临时解决方案:

    编写一个原生js的获取属性的方法

    function getAttr(ele, attr) {
        var e = ele.get(0);                
        var attrs = e.attributes;
        if (attrs == undefined) {
            return "";
        } else if (attrs[attr] == undefined) {
            return "";
        } else {
            return attrs[attr].value;
        }
    }

    判断当前对象是否是Zepto实例化对象的方法

    在jquery中,判断是不是jquery实例化对象,直接用instanceof就行,即:

    var a=$("body");
    if(a instanceof jQuery){
        //...  
    }

    但是在zepto中这样用是无效的,好在zepto自己提供了一份方法来判断,即:

    var a=$("body");
    if(Zepto.zepto.isZ(a)){
        //...
    }

    其源码是:也就是我们直接去判断instanceof是否zepto.Z即可。

      // `$.zepto.Z` swaps out the prototype of the given `dom` array
      // of nodes with `$.fn` and thus supplying all the Zepto functions
      // to the array. Note that `__proto__` is not supported on Internet
      // Explorer. This method can be overriden in plugins.
      zepto.Z = function(dom, selector) {
        dom = dom || []
        dom.__proto__ = $.fn
        dom.selector = selector || ''
        return dom
      }
    
      // `$.zepto.isZ` should return `true` if the given object is a Zepto
      // collection. This method can be overriden in plugins.
      zepto.isZ = function(object) {
        return object instanceof zepto.Z
      }

    使用深度扩展($.extend(true,*,*))后的zepto对象无法使用zepto.isZ来继续判断的bug

    直接看图:

    原本正常的zepto对象,经过深度扩展后,变成不属于zepto对象了!!

    再看下扩展前后的变化:

    obj.a.__proto__;//Object {}
    obj2.a.__proto__;//[]

    根据前面的zepto的源码可知,原始对象是有原型属性的,但是经过深度扩展后原型属性没有了!!!

    这肯定是$.extend内部写的有问题了:

    function extend(target, source, deep) {
      for (key in source)
        if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
          if (isPlainObject(source[key]) && !isPlainObject(target[key]))
            target[key] = {}
          if (isArray(source[key]) && !isArray(target[key]))
            target[key] = []
          extend(target[key], source[key], deep)
        }
        else if (source[key] !== undefined) target[key] = source[key]
    }
    
    // Copy all but undefined properties from one or more
    // objects to the `target` object.
    $.extend = function(target){
      var deep, args = slice.call(arguments, 1)
      if (typeof target == 'boolean') {
        deep = target
        target = args.shift()
      }
      args.forEach(function(arg){ extend(target, arg, deep) })
      return target
    }

    看完以后发现简直太敷衍了好么!!

    直接就用for in遍历也就算了,好歹也得判断下是对象属性还是原型属性呀!

    当然既然原型没了,那原型上的方法也就自然全跑到对象上面去了,如此敷衍我也是醉了,如图:

    临时解决方案:

    目前没想到很好的解决办法,自己多加一些判断。如果有谁有更好的方案请一定告诉我。

    扩展阅读

    http://chaoskeh.com/blog/some-experience-of-using-zepto.html

  • 相关阅读:
    面试题,找出每个产品的最新五个产品,还有其它方法吗 —— 游标加表变量
    SQL排序,重名和调名
    存储过程分页
    Perl/Python 感概
    Perl解析INI文件
    Perl 多进程文件锁
    Windows Sharepoint Services 版本更新
    工作、SOA、MBF...
    Windows Sharepoint Services 版本更新
    被CDOEXM折磨了一把
  • 原文地址:https://www.cnblogs.com/xxcanghai/p/5435902.html
Copyright © 2020-2023  润新知