JavaScript实现动态创建CSS样式规则方案

 更新时间:2014年09月06日 09:21:30   投稿:junjie  
这篇文章主要介绍了JavaScript实现动态创建CSS样式规则方案,本文包含获取样式表、创建样式表、插入规则、添加规则等内容,需要的朋友可以参考下

现在Web应用中有大量的JavaScript代码,而我们也一直在追寻各种使他们更快的解决方案。

1.我们通过 事件代理(event delegation) 让事件监听更高效,
2.我们利用 函数降频技术(function debouncing) 来限制一段时间内给定方法被调用的次数,请参考:如何防止事件函数的高频触发(中文翻译)
3.我们使用 JavaScript加载器 来加载我们确实需要的那部分资源,等等。

还有一种方式,可以让我们的页面更加的快速和高效.那就是直接通过JS动态地添加和删除样式表中的某些样式,用来取代不断地查询DOM元素,并应用各种样式。下面是它的工作原理。

获取样式表

你可以选择任意的样式表来添加样式规则。如果你有确定的样式表,则可以在HTML页面中给 <link> 或 <style> 标签添加ID属性,然后直接通过这个DOM元素的 sheet 属性就可以取得 CSSStyleSheet 对象。样式表也可以通过 document.styleSheets 遍历到:

复制代码 代码如下:

// 返回一个类似数组的(Array-like)样式列表 StyleSheetList
var sheets = document.styleSheets;

/*
返回值类似下面这样: 

StyleSheetList
{
    0: CSSStyleSheet,
    1: CSSStyleSheet,
    2: CSSStyleSheet,
    3: CSSStyleSheet,
    4: CSSStyleSheet,
    length: 5,
    item: function
}
*/

// 获取第一个sheet, 先不管 media属性
var sheet = document.styleSheets[0];

需要特别注意的是样式表的media属性 —— 当你想在屏幕上显示的时候,你肯定不能把CSS规则加到打印样式表中。你可以仔细的看一下CSSStyleSheet对象的属性信息:

复制代码 代码如下:

// 控制台输出第一个样式表的信息
console.log(document.styleSheets[0]);

/*
返回值: 

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"
*/

// 获取媒体类型(media type)
console.log(document.styleSheets[0].media.mediaText)
/*
返回值可能是:
    "all" 或者 "print" 或者是其他应用到此样式表的 media
*/

在各种情况下,你肯定都有办法来获取到要添加规则的样式表。

创建一个新样式表

在许多情况下,最好的方法可能是创建一个新的 <style> 元素来存放这些动态规则。这也很简单:

复制代码 代码如下:

var sheet = (function() {
    // 创建 <style> 标签
    var style = document.createElement("style");

    // 可以添加一个媒体(/媒体查询,media query)属性
    // style.setAttribute("media", "screen")
    // style.setAttribute("media", "only screen and (max-width : 1024px)")

    // 对WebKit hack :(
    style.appendChild(document.createTextNode(""));


    // 将 <style> 元素加到页面中
    document.head.appendChild(style);

    return style.sheet;
})();

悲剧的是WebKit需要一点hack手段才能正确创建,但我们只需要关心这个sheet。

插入规则

在早期版本的IE中 Stylesheets 的 insertRule方法并不可用,虽然现在这是规则注入的标准。insertRule 方法需要编写整个CSS规则,和在样式表中是一样的写法:

复制代码 代码如下:

sheet.insertRule("header { float: left; opacity: 0.8; }", 1);

这个JavaScript API方法虽然看起来有点土,但它确实就是这样运行的。第二个参数 index 表示要插入规则的位置(索引)。这也是非常有用的,这样你就可以插入同样的规则/代码,这可以让靠后的规则生效。默认的index是 -1 ,代表整个集合的末尾。如果想要有额外的/懒惰控制规则,你也可以添加 !important 标记到某条规则后,以避免索引的问题。

添加规则 —— 非标准的 addRule 方法

CSSStyleSheet 对象有一个 addRule 方法,允许你注册CSS规则到样式表中。 addRule 方法接受三个参数: 第一个参数是选择器(selector)、第二个参数是CSS规则代码, 第三个则是从0开始的整数索引,表示样式的位置(在同一个选择器中):

复制代码 代码如下:

sheet.addRule("#myList li", "float: left; background: red !important;", 1);

addRule方法的返回值总是 -1,所以这个值并没有什么实际意义.
记住,这种方式的优点在于,从页面添加的元素自动拥有了应用于他们的样式,也就是说你不必将它们添加到具体的元素上,而是直接注入到页面中。当然效率更高!

安全应用规则

因为并不是所有的浏览器都支持 insertRule 方法, 所以最好创建一个包装函数来处理规则应用。下面是一个快速的土方法:

复制代码 代码如下:

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);
    }
}

// 使用方式
addCSSRule(document.styleSheets[0], "header", "float: left");

这个工具方法应该涵盖了新增style规则的所有情况。如果你担心在应用中出错, 那么应该将该方法的代码用一个 try{} catch(e){} 块包起来。

插入媒体查询规则

媒体查询规则的添加有两种方式。第一个是使用标准 insertRule 方法:

复制代码 代码如下:

sheet.insertRule(
  "@media only screen and (max-width : 1140px) { header { display: none; } }"
  );

当然,因为IE老版本不支持 insertRule,所以另一种方法就是创建一个 STYLE 元素,并指定适当的 media 属性,然后将样式添加到新的样式表中。这可能需要使用多个 STYLE 元素,但也是很容易的。我可能会创建一个对象,指定媒体查询以及索引,并那样创建/获取他们。

动态添加规则到样式表是高效的手段,可能比你想象的还要简单。请记住这种方案,可能在你的下一个大应用中需要使用,因为它能在代码和元素处理这两方面避免你掉进坑里。

相关文章

  • JS控件的生命周期介绍

    JS控件的生命周期介绍

    JS控件的生命周期跟其他平台UI的生命周期类似,但是又有自己的特点,我们只有将控件的生命周期划分清晰,所有的控件编写、mixins的编写和plugin的编写才能遵循控件的生命周期做统一的管理
    2012-10-10
  • 一定有你会用到的JavaScript一行代码实用技巧总结

    一定有你会用到的JavaScript一行代码实用技巧总结

    这篇文章主要为大家介绍了一定有你会用到的JavaScript一行代码总结,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • SVG快速构建马赛克效果

    SVG快速构建马赛克效果

    这篇文章主要为大家介绍了SVG快速构建马赛克效果示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • mui上拉加载功能实例详解

    mui上拉加载功能实例详解

    最近小编在做移动端的项目,用到了mui的上拉加载功能,今天小编给大家整理一下分享到脚本之家平台,需要的朋友参考下
    2017-04-04
  • 在微信小程序中渲染HTML内容的方法示例

    在微信小程序中渲染HTML内容的方法示例

    这篇文章主要介绍了在微信小程序中渲染HTML内容的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • JS中的二叉树遍历详解

    JS中的二叉树遍历详解

    这篇文章主要为大家详细介绍了JS中的二叉树遍历,何为二叉树,什么是二叉树的遍历,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • 基于element-ui 动态换肤的代码详解

    基于element-ui 动态换肤的代码详解

    这篇文章主要介绍了element-ui 动态换肤,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • 效率高的Javscript字符串替换函数的benchmark

    效率高的Javscript字符串替换函数的benchmark

    这是经常使用的HTML特殊字符替换函数,即将 &、<、>、" 等函数替换成 &、<、>、"。通常的作法都是连续使用数个 replace 函数,而Clear仅使用一个 replace 就完成了替换。
    2008-08-08
  • JavaScript webpack5配置及使用基本介绍

    JavaScript webpack5配置及使用基本介绍

    webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。这篇文章主要介绍了JavaScript webpack5配置及使用基本介绍
    2022-09-09
  • JS实现的base64加密解密完整实例

    JS实现的base64加密解密完整实例

    这篇文章主要介绍了JS实现的base64加密解密,以完整实例形式分析了JavaScript基于base64编码实现加密与解密的具体步骤与相关技巧,并附带了相关的加密解密在线工具地址供大家参考,需要的朋友可以参考下
    2016-04-04

最新评论