來杭一週,收穫不少,成長不少。javascript
週六在搞一個插件的時候碰到須要動態添加僞元素的需求,搜了一下解決方案,有人用正則寫出了讀取僞元素的函數;我以爲卻是能夠經過注入css rule的方式,來讓預留有某些類的標籤動態產生僞元素。css
而後在google上搜到這樣一篇文章,講了一下以前沒了解到的api函數:addrule等,翻譯一下,分享一下好了。html
原博文網址:http://davidwalsh.name/add-rules-stylesheetsjava
譯文以下:web
由於咱們在開發中javascript使用的愈來愈多,因此咱們老是想盡辦法想讓它更快。咱們使用事件代理來監聽事件,使用函數節流來限制單位時間內函數的調用次數,使用loader方法來加載最須要的資源。這些方法均可以讓咱們的頁面加載、渲染、執行的速度有必定的加快。本文要說另外一種方法:經過動態添加刪除CSS樣式代替原有的查找節點並修改來應用某些樣式。chrome
咱們能夠選擇向頁面內的某條stylesheet中添加樣式。能夠給<link>標籤或者<style>標籤添加ID,經過引用節點的sheet屬性來獲取CSSStyleSheet對象。頁面中的stylesheets可使用document.styleSheets來獲取:api
var sheets = document.styleSheets; // returns an Array-like StyleSheetList //返回一個類數組對象 /* Returns: StyleSheetList {0: CSSStyleSheet, 1: CSSStyleSheet, 2: CSSStyleSheet, 3: CSSStyleSheet, 4: CSSStyleSheet, 5: CSSStyleSheet, 6: CSSStyleSheet, 7: CSSStyleSheet, 8: CSSStyleSheet, 9: CSSStyleSheet, 10: CSSStyleSheet, 11: CSSStyleSheet, 12: CSSStyleSheet, 13: CSSStyleSheet, 14: CSSStyleSheet, 15: CSSStyleSheet, length: 16, item: function} */ // Grab the first sheet, regardless of media //先無論第一個樣式的具體應用media(注:多是print等) var sheet = document.styleSheets[0];
在咱們選取link或者style標籤時,咱們應該考慮被選中的樣式表標籤是不是應用於screen,而不是print等。CSSStyleSheet對象給咱們提供了這樣的屬性:數組
// Get info about the first stylesheet console.log(document.styleSheets[0]); /* Returns: CSSStyleSheet cssRules: CSSRuleList disabled: false href: "http://davidwalsh.name/somesheet.css" media: MediaList ownerNode: link ownerRule: null parentStyleSheet: null rules: CSSRuleList title: null type: "text/css" */ // Get the media type //獲取media類型 console.log(document.styleSheets[0].media.mediaText) /* Returns: "all" or "print" or whichever media is used for this stylesheet */
固然除了上面的,還有別的方法能夠獲取stylesheet對象。瀏覽器
有些狀況下,可能新建一個style節點來承裝新添加的style rule。方法很簡單:app
var sheet = (function() { // Create the <style> tag var style = document.createElement("style"); // Add a media (and/or media query) here if you'd like! // style.setAttribute("media", "screen") // style.setAttribute("media", "only screen and (max-width : 1024px)") // WebKit hack :( //webkit內核瀏覽器的hack: style.appendChild(document.createTextNode("")); // Add the <style> element to the page 插入頁面 document.head.appendChild(style); return style.sheet; })();
請留意上面第三條語句是爲webkit瀏覽器添加的hack。
Stylesheets對象提供了insertRule(譯者注:IE8及如下不兼容,具體參考連接http://www.quirksmode.org/dom/w3c_css.html )方法。insertRule函數要求傳入css樣式風格的str做爲參數。
具體調用方法:
sheet.insertRule("header { float: left; opacity: 0.8; }", 1);
(譯者注:傳入的樣式str的格式要求不少。就我目前發現的:1.{}兩個花括號和先後最好都有一個空格 2.若是是webkit內核,函數在解析帶有-moz-前綴的樣式規則時會拋err)
這種方法看上去有點醜,可是確實有用。第二個參數Index,表示咱們將在樣式內部的哪一條插入新樣式css rule,這就能夠幫助咱們實現原有樣式的覆蓋。默認index取值是-1(譯者注:可是輸入-1在chrome 41下拋了err,提示參數不能小於0,這裏值得在研究一下),表示默認在樣式最後追加。若是想強制覆蓋,可使用!important,來避免插入次序引發其餘問題。
CSSStyleSheet對象有一個非標準函數addRule,和insertRule相比,它更像js api的調用風格,無需本身注意插入的樣式字符串的格式。addRule方法接受三個參數,分別是選擇器selector,樣式字符串"color:red;font-size:12px",和插入次序index。
sheet.addRule("#myList li", "float: left; background: red !important;", 1);
方法有返回值,爲-1。可是沒有什麼具體含義。
這種方式能夠快速高效的改變頁面上節點的已有樣式。
由於上面提到兩個函數都不是常見api函數,因此須要作瀏覽器兼容性處理。
function addCSSRule(sheet, selector, rules, index) { if("insertRule" in sheet) { sheet.insertRule(selector + "{" + rules + "}", index); } else if("addRule" in sheet) { sheet.addRule(selector, rules, index); } } // Use it! addCSSRule(document.styleSheets[0], "header", "float: left");
這種方法能夠應用於全部高級的瀏覽器,若是仍是有擔憂的話,能夠在調用時使用try-catch結構。
若是你須要插入media-queries的css樣式規則,你只能使用第一個insertRule方法。
sheet.insertRule("@media only screen and (max-width : 1140px) { header { display: none; } }");
IE不支持insertRule函數,因此另外一種方法是建立style標籤節點,經過寫入的方式來注入樣式規則。
動態添加樣式規則是有效且容易的。在下一個應用裏嘗試一下吧,你會發現這個真的很好用~
譯文結束