使用JavaScript动态操作css,你知道多少种?
时间:2023-04-02 22:00:46
HTML
作者:areknawo译者:前端小智来源:css-tricks.com点赞阅读,微信搜索【大举走向世界】关注这个没有大厂背景,却有正能量的人态度。本文已收录到GitHubhttps://github.com/qq44924588...,文章已分类,也整理了很多我的文档和教程资料。大家都说简历里没项目可写,所以给大家找了一个项目,还给了一个【搭建教程】。JavaScript可以说是交互之王。作为一种脚本语言和众多的WebAPI,它进一步扩展了它的功能集,丰富了界面交互的可操作性。此类API的示例包括WebGLAPI、CanvasAPI、DOMAPI和一组鲜为人知的CSSAPI。由于JSX和无数的JS框架,通过JSAPI与DOM交互的想法确实变得流行,但在CSS中似乎没有太多使用类似的技术。当然,也有像CSS-in-JS这样的解决方案,但最流行的是基于转译,无需额外运行即可生成CSS。这绝对有利于性能,因为使用CSSAPI会导致额外的重绘,使用DOMAPI也是如此。但这不是我们想要的。如果公司要求我们不仅要操作DOM元素的样式和CSS类,还要像HTML一样使用JS来创建一个完整的样式表怎么办?内联样式在深入探讨一些复杂问题之前,让我们回顾一下基础知识。例如,我们可以通过修改其.style属性来编辑给定HTMLElement的内联样式。constel=document.createElement('div')el.style.backgroundColor='red'//或el.style.cssText='background-color:red'//或el.setAttribute('style','background-color:red')直接在.style对象上将需要使用camelCase作为属性键而不是破折号。如果我们需要设置更多的内联样式属性,我们可以通过设置.style.cssText属性以更高效的方式进行设置。请记住,设置cssText后,原来的css样式被清除了,所以我们需要一次死掉一堆样式。如果这种设置内联样式太麻烦,我们也可以考虑使用.style和Object.assign()一次设置多个样式属性。//...Object.assign(el.style,{backgroundColor:"red",margin:"25px"})这些“基础知识”比我们想象的要多得多。.style对象实现了CSSStyleDeclaration接口。这说明它有一些有趣的属性和方法,包括刚才用到的.cssText,还有.length(设置属性的个数),还有.item()、.getPropertyValue()和.setPropertyValue()likeMethod://...constpropertiesCount=el.style.lengthfor(leti=0;i{if(!el.classList.contains(className)){el.classList.add(className);}});StylesheetsWebApi一直有一个由document.styleSheets属性实现的StyleSheetList接口。document.styleSheets只读属性,返回一个由StyleSheet对象组成的StyleSheetList,每个StyleSheet对象是文档中链接或嵌入的样式表。for(styleSheetofdocument.styleSheets){console.log(styleSheet);}通过打印结果我们可以知道每次循环打印一个CSSStyleSheet对象,每个CSSStyleSheet对象由以下属性组成:属性描述media获取当前风格效果媒体。disabled启用或禁用样式表。href返回连接到CSSStyleSheet对象的样式表的地址。title返回CSSStyleSheet对象的标题值。type返回CSSStyleSheet对象的类型值,通常是text/css。parentStyleSheet返回包含当前样式表的样式表。ownerNode返回CSSStyleSheet对象所在的DOM节点,通常是或中上面代码中,style标签是一个CSSStyleSheet样式表对象,其中包含两个CSSStyleRule对象,即两条css样式规则。CSSStyleRule对象有如下属性:1.type:返回一个0到6的数字,表示规则的类型,类型列表如下:0:CSSRule.UNKNOWN_RULE。1:CSSRule.STYLE_RULE(定义一个CSSStyleRule对象)。2:CSSRule.CHARSET_RULE(定义一个CSSCharsetRule对象,用于设置当前样式表的字符集,默认与当前网页相同)。3:CSSRule.IMPORT_RULE(定义一个CSSImportRule对象,即使用@import引入其他样式表)4:CSSRule.MEDIA_RULE(定义一个CSSMediaRule对象,用于设置该样式是用于显示器、打印机还是投影仪,ETC。)。5:CSSRule.FONT_FACE_RULE(定义一个CSSFontFaceRule对象,CSS3的@font-face)。6:CSSRule.PAGE_RULE(定义一个CSSPageRule对象)。2.cssText:返回代表当前规则内容的字符串,例如:div{color:green}3.parentStyleSheet:返回其所在的CSSStyleRule对象。4.parentRule:如果规则位于另一个规则中,则该属性引用另一个CSSRule对象。5.selectorText:返回该规则的选择器,比如上面的div就是选择器。6.style:返回一个CSSStyleDeclaration对象。//...construleIndex=styleSheet.insertRule("div{background-color:red}");construle=styleSheet.cssRules.item(ruleIndex);rule.selectorText;//"div"rule.style.backgroundColor;//"red"实现现在我们对CSS相关的JSAPI有了足够的了解,可以创建我们自己的、小型的、基于运行时的CSS-in-JS实现。这个想法是创建一个函数,通过一个简单的样式配置对象,生成一个新创建的CSS类的哈希名称供以后使用。实现过程很简单,我们需要一个可以访问某个样式表的函数,只需要使用.insertrule()方法和样式配置即可运行。让我们从样式表部分开始:functioncreateClassName(style){//...letstyleSheet;for(leti=0;i标签并将其附加到HTML文档的。这会自动将新样式表添加到document.styleSheets列表中,并允许我们通过标记的.sheet属性访问它,是不是很聪明?functioncreateRandomName(){constcode=Math.random().toString(36).substring(7);return`css-${code}`;}functionphraseStyle(style){constkeys=Object.keys(style);constkeyValue=keys.map(key=>{constkebabCaseKey=key.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();constvalue=`${样式[key]}${typeofstyle[key]==="number"?"px":""}`;return`${kebabCaseKey}:${value};`;});return`{${keyValue.join("")}}`;}除了上面的提示。自然地,我们首先需要一种方法来为CSS类生成新的随机名称。然后,样式对象被正确地表示为有效的CSS字符串。这包括驼峰式和虚线全名之间的转换,以及像素单位(px)转换的可选处理。functioncreateClassName(style){constclassName=createRandomName();让样式表;//...styleSheet.insertRule(`.${className}${phraseStyle(style)}`);returnclassName;}完整代码如下:HTML
JSfunctioncreateRandomName(){constcode=Math.random().toString(36).substring(7);return`css-${code}`;}functionphraseStyle(style){constkeys=Object.keys(style);constkeyValue=keys.map(key=>{constkebabCaseKey=key.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();constvalue=`${style[key]}${typeofstyle[key]==="number"?"px":""}`;return`${kebabCaseKey}:${value};`;});返回`{${keyValue.join("")}}`;}functioncreateClassName(style){constclassName=createRandomName();让样式表;for(leti=0;i