• js动态改变css伪类样式


    首先我们来看下页面上需要实现的基本效果,如下图所示:

    因此我们可以使用如下js代码来试试看,是否能使用js改变伪类?如下代码所示:

    $(function() {
      $('.listnav li').click(function(){
        var index = $(this).index();
        var offset = 11; // 左侧偏移 11像素
        var imgWidth = 240; // 图片的宽度是240
        var pos = 0;
        // 因此第一个tab项的居中位置就是 240/2 + 11
        if (index === 0) {
          pos = imgWidth / 2 + offset + 'px';
        } else {
          /*
            如果不是第一个tab项的话,那么计算方式就变为如下:
            pos = imgWidth / 2 + offset + imgWidth * index + 33 * index
          */
          pos = imgWidth / 2 + offset + imgWidth * index + 33 * index;
        }
        console.log(pos);
        $(".tab-content:before, .tab-content:after").css({ "left": pos });
      });
    });

    如上代码并不生效,因此可以断定使用 jquery这样单纯的改变伪类样式是行不通的。 如上有一个定位的计算方式,如上代码,下面我们来简单的分析下,为什么可以这样计算,请看如下图所示:

    第一个tab项的时候,小三角形的定位如下:

    点击第二个tab项的时候,小三角形的定位如下图所示:

    点击第三个tab项的时候,小三角形的定位变为如下图所示:

    既然使用如上方式行不通,我们肯定需要查找资料了,正好看到有一篇文章 能解决改变css伪类样式, 请点击查看

    因此我这边来详细总结一下,如何做?那么这边肯定需要分二种情况,第一种是使用css内联style样式写的css,第二种是外链的css,也就是html和css分离的那种,因为做项目的时候,分离css还是很有必要的。


    一:JS动态改变style内联css写的伪类样式

    如下代码:

    $(function() {
      $('.listnav li').click(function(){
        var index = $(this).index();
        var offset = 11; // 左侧偏移 11像素
        var imgWidth = 240; // 图片的宽度是240
        var pos = 0;
        // 因此第一个tab项的居中位置就是 240/2 + 11
        if (index === 0) {
          pos = imgWidth / 2 + offset + 'px';
        } else {
          /*
            如果不是第一个tab项的话,那么计算方式就变为如下:
            pos = imgWidth / 2 + offset + imgWidth * index + 33 * index
          */
          pos = imgWidth / 2 + offset + imgWidth * index + 33 * index;
        }
        var styleSheetObject = document.getElementById('colorFlipFlop');
        console.log(pos);
        changeStyle(styleSheetObject, 'left', pos);
      });
    });
    /*
     * @param styleSheetObject style标签的id
     * @param attr 需要改变的style属性
     * @param pos 需要改变的值
    */
    function changeStyle(styleSheetObject, attr, pos) {
      var beforeIndex = 7;  // 定位到style标签中的第几行
      console.log(styleSheetObject.sheet);
      console.log(styleSheetObject.sheet.cssRules[beforeIndex]);
      // console.log(styleSheetObject.sheet.cssRules[beforeIndex].style[attr])
      styleSheetObject.sheet.cssRules[beforeIndex].style[attr] = pos + 'px';
    }

    我们首先来分析下,上面的代码的含义; 在分析之前我们首先看下css的样式代码如下:

    <style type="text/css" id="colorFlipFlop">
      * {margin:0; padding: 0;}
      .operating-report-container {
        position: relative;
        width: 1000px;
        margin: 30px;
        border: 1px solid #ccc;
        overflow: hidden;
      }
      .operating-report-container .listnav {
        margin-left: 14px;
        margin-top: 24px;
        overflow: hidden;
      }
      .operating-report-container .listnav li {
        float: left;
        width: 240px;
        margin-left: 33px;
        cursor: pointer;
        overflow: hidden;
      }
      .operating-report-container .listnav li .pic {
        width: 240px;
        height: 160px;
        background: #f6f6f6;
      }
      .operating-report-container .listnav li .desc {
        display: block;
        text-align: center;
        font-size: 15px;
        color: #616161;
        margin-top: 8px;
      }
      .operating-report-container .tab-content {
        margin: 24px 30px;
        border-top: 1px solid #e6e5e5;
        position: relative;
      }
      .operating-report-container .tab-content:before, 
      .operating-report-container .tab-content:after {
        bottom: 100%;
        left: 131px;
        border: solid transparent;
        content: " ";
        height: 0;
        width: 0;
        position: absolute;
        pointer-events: none;
      }
      .operating-report-container .tab-content:before {
        border-bottom-color: #e6e5e5;
        border-width: 11px;
        margin-left: -11px;
      }
      .operating-report-container .tab-content:after {
        border-bottom-color: #fff; 
        border-width: 10px;
        margin-left: -10px;
      }
    </style>

    首先js代码 var styleSheetObject = document.getElementById('colorFlipFlop'); 这句代码是获取 style标签的,因为style标签上有一个id元素叫 'colorFlipFlop'。

    然后我们看下打印下 console.log(styleSheetObject.sheet);这个;看看他有哪些属性,如下图所示:

    然后打印 console.log(styleSheetObject.sheet.cssRules[beforeIndex]);,代码中 beforeIndex 为什么等于7呢?因此 tab-content:before 的样式在 style标签的第八行,因此为了找到 style标签的中的具体元素的位置。因为是从0开始的。如下图所示

    因此最后一句代码,找到对应的元素对应的属性重新赋值,如代码:

    styleSheetObject.sheet.cssRules[beforeIndex].style[attr] = pos + 'px';

    如下图所示:

    查看效果请点击我

    二:JS动态改变使用link标签引入的伪类样式

    2.1)理解 insertRule 方法的使用

    首先我们先要来理解下 insertRule() 和 addRule() 这两个方法,可能很多人之前对这js中这两个方法并不熟悉,其实在研究之前,我也并不知道这两个方法的,这两个方法的作用是:向现有的样式表中添加新规则,在firefox,safari,opera和chrome中使用 insertRule()方法,该方法接收两个参数,规则文本 和 表示在哪里插入规则的索引。比如下面简单的demo:
    insertRule.html 代码如下:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    <link type="text/css" rel="stylesheet" href="./css/insertRule.css" />
    <script type="text/javascript" src="./js/jquery.js"></script>
    </head>
    <body>    
        <div class="container" id="container">
          欢迎光临
        </div>
        <script type="text/javascript" src="./js/insertRule.js"></script>
    </body>
    </html>

    /css/insertRule.css 中的代码如下:

    * {margin:0; padding: 0;}

    js/insertRule.js 代码如下:

    function getStyleSheet(element) {
        return element.sheet || element.styleSheet;
    }
    var link = document.getElementsByTagName("link")[0];
    var sheet = getStyleSheet(link);
    console.log(sheet)
    sheet.insertRule("body { background-color: red }", 0);  //DOM方法

    如上js代码,先获取到页面上第一个link标签,然后对代码进行插入body的背景色的样式即可:在firefox下的效果如下:

    再看看firefox下的代码如下:

    然后在safari下查看下效果如下:

    如上js代码,console.log(sheet) 打印的信息在firefox如下:

    之前我们说过 insertRule 该方法在 firefox,safari,opera 和 chrome是支持的,但是在mac电脑下(我电脑目前是mac电脑),Chrome 66 以后的版本是不支持该属性的。如下是在我chrome中的情况,如下所示:

    或者也可以请看这篇文章说的(https://www.noxxxx.com/uncaught-domexception-failed-to-execute-insertrule-on-cssstylesheet.html), 我现在chrome版本是70版本的,那也是不支持,如下我的chrome版本:

    文章中说需要手动创建 style 标签插入。 因此我们的 insertRule.js 代码变为如下:

    /*
    function getStyleSheet(element) {
        return element.sheet || element.styleSheet;
    }
    var link = document.getElementsByTagName("link")[0];
    var sheet = getStyleSheet(link);
    console.log(sheet);
    sheet.insertRule("body { background-color: red }", 0);  //DOM方法
    */
    
    var stylesheet = createStyleSheet();
    stylesheet.insertRule("body { background-color: red }", 0);  //DOM方法
    
    function createStyleSheet() {
      var style = document.createElement('style');
      style.appendChild(document.createTextNode(""));
      document.head.appendChild(style);
      return style.sheet;
    }

    我们继续运行下,现在在firefox,safari,和 chrome浏览器下都支持了。chrome浏览器下的效果如下:

    2.2)理解 addRule() 方法的使用

    addRule方法是IE支持的一个类似的方法,该方法也是接收两个必选参数和一个可选参数:
    第一个参数为:选择符文本。第二个参数为:css样式信息,第三个参数是可选的,表示的含义是:插入规则的位置,和insertRule()方法中的第二个参数类似。

    基本使用方式如下:sheet.addRule("body", "background-color: red", 0); // 仅仅对IE有效

    因此为了跨浏览器支持向样式表中插入规则,我们可以封装一个方法,既支持IE,也支持标准浏览器,如下代码:

    /*
    function getStyleSheet(element) {
        return element.sheet || element.styleSheet;
    }
    var link = document.getElementsByTagName("link")[0];
    var sheet = getStyleSheet(link);
    console.log(sheet);
    sheet.insertRule("body { background-color: red }", 0);  //DOM方法
    */
    /*
    var stylesheet = createStyleSheet();
    stylesheet.insertRule("body { background-color: red }", 0);  //DOM方法
    
    function createStyleSheet() {
      var style = document.createElement('style');
      style.appendChild(document.createTextNode(""));
      document.head.appendChild(style);
      return style.sheet;
    }
    */
    function createStyleSheet() {
      var style = document.createElement('style');
      style.appendChild(document.createTextNode(""));
      document.head.appendChild(style);
      return style.sheet;
    }
    function insertRule(selectorText, cssText, position) {
      var stylesheet = createStyleSheet();
      if (stylesheet.insertRule) {
        stylesheet.insertRule(selectorText + "{" + cssText + "}", position);
      } else if (stylesheet.addRule) {
        stylesheet.addRule(selectorText, cssText, position);
      }
    }
    insertRule("body", "background-color: red", 0);

    请点击查看效果

    所以我们现在可以使用如上的知识点,去做那个切换的demo了,index2.html代码如下

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    <link rel="stylesheet" href="./css/index2.css" />
    <script type="text/javascript" src="./js/jquery.js"></script>
    </head>
    <body>    
        <div class="operating-report-container" id="operating-report">
          <ul class="listnav">
            <li>
              <div class="pic"></div>
              <div class="desc">铜板街2018年度各月运营报告</div>
            </li>
            <li>
              <div class="pic"></div>
              <div class="desc">铜板街2018年度各月运营报告</div>
            </li>
            <li>
              <div class="pic"></div>
              <div class="desc">铜板街2018年度各月运营报告</div>
            </li>
          </ul>
          <div class="tab-content" id="tab-content">
            
          </div>
        </div>
        <script type="text/javascript" src="./js/index2.js"></script>
    </body>
    </html>

    index2.js 代码如下:

    $(function() {
      $('.listnav li').click(function(){
        var index = $(this).index();
        var offset = 11; // 左侧偏移 11像素
        var imgWidth = 240; // 图片的宽度是240
        var pos = 0;
        // 因此第一个tab项的居中位置就是 240/2 + 11
        if (index === 0) {
          pos = imgWidth / 2 + offset;
        } else {
          /*
            如果不是第一个tab项的话,那么计算方式就变为如下:
            pos = imgWidth / 2 + offset + imgWidth * index + 33 * index
          */
          pos = imgWidth / 2 + offset + imgWidth * index + 33 * index;
        }
        addRule(".operating-report-container .tab-content:before", {
          left: pos + 'px'
        });
        addRule(".operating-report-container .tab-content:after", {
          left: pos + 'px'
        });
      });
    });
    function createStyleSheet() {
      var style = document.createElement('style');
      style.appendChild(document.createTextNode(""));
      document.head.appendChild(style);
      return style.sheet;
    }
    var stylesheet = createStyleSheet();
    function addRule(selector, css) {
      var propText = typeof css === "string" ? css : Object.keys(css).map(function (p) {
          console.log(p)
          return p + ":" + (p === "content" ? "'" + css[p] + "'" : css[p]);
      }).join(";");
    
      if (stylesheet.insertRule) {
        // 标准浏览器支持的
        stylesheet.insertRule(selector + "{" + propText + "}", stylesheet.cssRules.length);
    
      } else if(stylesheet.addRule) {
        // IE支持的
        stylesheet.addRule(selector, propText, stylesheet.cssRules.length);
      }
    }

    如上代码封装好了的,点击查看效果

    注意:如上demo目前在mac电脑上的firfox,safari,chrome测试过的,因为是mac电脑,所以在IE下还没有测试过,如果有问题可以留言哦!

    查看github代码

  • 相关阅读:
    UVA 11997 K个最小和
    UVALive 3135阿格斯
    UVA 10635 王子和公主
    UVA11991线性查询
    UVA1339仿射和换位密码
    UVA 10382喷水设施
    LA2965字符串合并
    FatMouse's Speed--hdu1160(dp+输出路径)
    Dividing--hdu1059(动态规划)
    Piggy-Bank--hdu1114(完全背包)
  • 原文地址:https://www.cnblogs.com/tugenhua0707/p/10004654.html
Copyright © 2020-2023  润新知