zoukankan      html  css  js  c++  java
  • 对avalon的类名操作进行升级

    在对SVG元素进行类名操作时,发现有一个坑爹的事情,它的className竟然是一个对象,因此报一系列BUG。第一次想到的方法是添加setClasses, getClasses两个更底层的方法。于是相应代码变成:

        var rclass = /s+/g
        function getClasses(node) {
            if (node && node.className) {
                var classes = node.className//SVG元素是返回一个SVGAnimatedString对象
                if ("baseVal" in classes) {
                    classes = classes.baseVal
                }
                return classes.split(rclass)
            }
            return []
        }
        function setClasses(node, cls) {
            if (node && node.nodeType === 1) {
                if ("baseVal" in node.className) {
                    node.setAttribute("class", cls)
                } else {
                    node.className = cls
                }
            }
        }
    
        avalon.fn.mix({
            hasClass: function(cls) {
                var classList = getClasses(this[0])
                if (classList.length) {
                    return (" " + classList.join(" ") + " ").indexOf(" " + cls + " ") > -1
                }
                return false
            },
            addClass: function(cls) {
                var node = this[0]
                if (cls && node && node.nodeType === 1) {
                    var arr = getClasses(node)
                    cls.replace(/S+/g, function(c) {
                        if (arr.indexOf(c) === -1) {
                            arr.push(c)
                        }
                    })
                    setClasses(node, arr.join(" "))
                }
                return this
            },
            removeClass: function(cls) {
                var node = this[0], classList = getClasses(node)
                if (cls && classList.length) {
                    var set = " " + classList.join(" ") + " "
                    cls.replace(/S+/g, function(c) {
                        set = set.replace(" " + c + " ", " ")
                    })
                    setClasses(node, set.slice(1, set.length - 1))
                }
                return this
            },
            toggleClass: function(value, stateVal) {
                var state = stateVal,
                        className, i = 0
                var classNames = value.split(rclass)
                var isBool = typeof stateVal === "boolean"
                while ((className = classNames[i++])) {
                    state = isBool ? state : !this.hasClass(className)
                    this[state ? "addClass" : "removeClass"](className)
                }
                return this
            }
    })
    

    这里的麻烦处是,IE6,IE7不能直接通过getAttribute("class")得到className,而SVG如果直接用className又没有用,于是抽取出getClasses方法,赋值也一样。

    在高级浏览器,classList在SVG中是没有兼容问题。看avalon.mobile的相关实现是多么简洁:

        "add,remove".replace(rword, function(method) {
            avalon.fn[method + "Class"] = function(cls) {
                var el = this[0]
                //https://developer.mozilla.org/zh-CN/docs/Mozilla/Firefox/Releases/26
                if (cls && typeof cls === "string" && el && el.nodeType == 1) {
                    cls.replace(/S+/g, function(c) {
                        el.classList[method](c)
                    })
                }
                return this
            }
        })
        
        avalon.fn.mix({
            hasClass: function(cls) {
                var el = this[0] || {} //IE10+, chrome8+, firefox3.6+, safari5.1+,opera11.5+支持classList,chrome24+,firefox26+支持classList2.0
                return el.nodeType === 1 && el.classList.contains(cls)
            },
            toggleClass: function(value, stateVal) {
                var state = stateVal,
                        className, i = 0
                var classNames = value.split(/s+/)
                var isBool = typeof stateVal === "boolean"
                var node = this[0] || {}, classList
                if (classList = node.classList) {
                    while ((className = classNames[i++])) {
                        state = isBool ? state : !classList.contains(className)
                        classList[state ? "add" : "remove"](className)
                    }
                }
                return this
            }
    })
    

    因此新的思路来了,为IE6-9等实现一个classList,通过它来屏蔽底层,再在classList的基础上构建avalon的addClass, removeClass, toggleClass,hasClass

        function ClassList(node) {
            if (!("classList" in node)) {
                node.classList = {
                    node: node,
                    toString: function() {
                        var node = this.node
                        return (node.hasAttribute ? node.getAttribute("class") || "" : node.className).split(/s+/).join(" ")
                    },
                    contains: function(cls) {
                        return (" " + this + " ").indexOf(" " + cls + " ") > -1
                    },
                    _set: function(cls) {
                        var node = this.node
                        if (typeof node.className == "string") {
                            node.className = cls
                        } else {
                            node.setAttribute("class", cls)
                        }
                    },
                    add: function(cls) {
                        if (!this.contains(cls)) {
                            this._set(this + " " + cls)
                        }
                    },
                    remove: function(cls) {
                        this._set((" " + this + " ").replace(" " + cls + " ", " ").trim())
                    }
                }
            }
            return node.classList
        }
        "add,remove".replace(rword, function(method) {
            avalon.fn[method + "Class"] = function(cls) {
                var el = this[0]
                //https://developer.mozilla.org/zh-CN/docs/Mozilla/Firefox/Releases/26
                if (cls && typeof cls === "string" && el && el.nodeType == 1) {
                    cls.replace(/S+/, function(c) {
                        ClassList(el)[method](c)
                    })
                }
                return this
            }
        })
        avalon.fn.mix({
            hasClass: function(cls) {
                var el = this[0] || {}
                return el.nodeType === 1 && ClassList(el).contains(cls)
                return false
            },
            toggleClass: function(value, stateVal) {
                var state = stateVal,
                        className, i = 0
                var classNames = value.split(/s+/)
                var isBool = typeof stateVal === "boolean"
                while ((className = classNames[i++])) {
                    state = isBool ? state : !this.hasClass(className)
                    this[state ? "addClass" : "removeClass"](className)
                }
                return this
            }
    })
    
    http://baike.baidu.com/view/957693.htm
  • 相关阅读:
    获取Unity和UGUUI内置组件的属性名
    Sqlite管理工具
    C#对象属性浅拷贝和深拷贝
    fbx查看软件
    如何区分Unity国内版和国际版
    Unity2019及Unity2020打包android的环境配置
    提高Unity编译dll的速度
    SpringBoot使用swagger
    SpringBoot 使用 Interceptor 拦截器
    SpringBoot 使用 Filter 过滤器
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/3900223.html
Copyright © 2011-2022 走看看