获取元素"正在应用"的css样式

DeEpReD

DeEpReD

发表于 2017-01-11 20:59:27
内容来源: 网络

使用phantomjs抓取页面详情,并且保存页面样式

  • getMatchedCSSRules 获取元素匹配到css规则,返回CSSStyleRule 集合

  • getComputedStyle 获取元素所有最终使用的CSS属性值

  • 大招

getMatchedCSSRules

想到获取元素的css样式,第一时间就想到了这货

// chrome 里面
var style = getMatchedCSSRules(document.body)
// 'getMatchedCSSRules()' is deprecated. For more help, check 
// https://code.google.com/p/chromium/issues/detail?id=437569#c2

被废弃了.

getMatchedCSSRules这货没法使用了,接下来就看下面getComputedStyle

getComputedStyle

这个方法也是挂在windows上的可以直接使用

var style = getComputedStyle(document.body)
// 返回 CSSStyleDeclaration 对象

然后看一下CSSStyleDeclaration对象,有261个属性,看着可以使用的样子,接下来就是把这个对象拼接成style字符串,就行了

如果这么简单就好了。。

首先CSSStyleDeclaration属性太多,保存到文档里面太占用空间,其次...它是经过计算

<style>
 .conent {
   width:100%;
}
</style>
<div class="content"></div>
<script>
    var style = getComputedStyle(div)
    console.log(style.width)
    // 100px
</script>

代码的本意是想获得 100%这个数值,但是却获得了XXXpx,这样的话就没法做朋友了..

看来需要使用大招了.

大招

所有正规军失败了,下面就是游击队的表演了

  1. 获取通过链接进来的css样式表

  2. 通过ajax获取样式表内容

  3. 计算元素命中的样式

获取所有页面样式

本来是能通过document.styleSheets 来获取样式,但是有个css优先级问题,所以需要通过document.querySelectorAll('link') 获取所有link标签

var sheets = []
 $('link').each(function () {
                    var link = $(this)
                    sheets.push({
                        prev: link.prev(), // 记录元素位置,便于插入
                        el: link,// 记录当前元素,用来删除
                        href: link.attr('href')
                    })
                })

获取样式表内容

所幸的是在phantomjs里面可以跨域发送ajax请求,并且能够获取response.text

function iterLink(sheets, func) {
    var sheet = sheets.pop()
    if (!sheet) {
        return
    }
    var g = new XMLHttpRequest
    g.open('GET', sheet.href)
    g.onreadystatechange = function () {
        if (this.readyState == this.DONE) {
            var h = $('<style type="text/css"></style>')
            h.prop('textContent', this.responseText)
            sheet.el.remove() // 删除当前元素
            sheet.prev.after(h)// 在当前元素的位置上插入重新创建的元素
            if (sheets.length === 0) {
                func && func()
            } else {
                iterLink(sheets, func)
            }
        }
    }
    g.send()
}

计算元素命中的样式规则

研究文档才发现dom还有matches方法,天不绝人之路啊
matches接收selectorString返回true or false

上面做的所有工作都是为了这个坑货,直接上代码吧

function getElStyleStr(a) {
    var sheets = document.styleSheets 
    a.matches = a.matches || a.webkitMatchesSelector //获取到真正的matches方法
    var tmp = {}
    var tmpArr = []

    for (var i in sheets) {
        var rules = sheets[i].rules || sheets[i].cssRules //前面两步执行之后才能得到所有的css rules
        // 计算rule
        for (var r in rules) {
            var rule = rules[r]
            var style = rule.style 
            if (a.matches(rule.selectorText)) { // 调用matches获取,测试匹配
                for (var j = 0; j < style.length; j++) {
                    tmp[style[j]] = style[style[j]]
                }
            }
        }
    }

    for (var k in tmp) {
        tmpArr.push(k + ':' + tmp[k])
    }
    return tmpArr.join(';')
}

得到styleStr之后就可以直接写入到对应元素的style属性里面了

又填了一个大坑...

内容来源:https://segmentfault.com/a/1190000008072894

用户评论
开源开发学习小组列表