JS让浏览器支持<style scoped> - 苹果cms模板大全
  1. 苹果cms模板大全 > 流量运营 >

JS让浏览器支持<style scoped>

【JS 】让浏览器支持<style scoped>

1. HTML style scoped 属性

今天无意中发现居然还有这么一个神仙属性 HTML style scoped 属性
他的作用主要是将 style的作用域控制在他自身的父元素之内。
例如:

<div>  <style type="text/css" scoped>    h1 {color:red;}    p {color:blue;}  </style>  <h1>这个标题是红色的</h1>  <p>这个段落是蓝色的。</p></div><h1>这个标题是黑色的</h1><p>这个段落是黑色的。</p>

以上代码中style中的样式只能作用于第一个div内的元素。
这样一个功能应用在目前公司老项目中非常nice(asp.net+mvc,导入部分页就不会影响当前页其他元素了)
但是可惜,除了火狐,其他浏览器都不支持!!!

  
所以我决定自己实现一个

 

2. 思路

  1. 判断浏览器是否支持scoped
  2. 找到页面中所有带有scoped属性的style元素,给其父元素添加一个属性
  3. 修改style中的所有css选择器,加上属性前缀
  4. 监听dom变化,处理动态创建的<style scoped>

3. 编码

1. 判断浏览器是否支持scoped

if (document.createElement("STYLE").scoped !== undefined) {    return;}

2. 找到页面中所有带有scoped属性的style元素,给其父元素添加一个属性

[...document.getElementsByTagName('style')].forEach(x => updateStyle(x));/** * 处理 <style> 标签 * @param style dom */function updateStyle(style) {    if (!style        || style.parentElement == null        || style.parentElement == document.head        || style.parentElement == document.body        || !style.hasAttribute("scoped")        || style.scoped === true) {        return;    }    style.scoped = true; // 防止重复处理    const scope = ("_" + (Math.random() * 100000000).toString("36")).replace('.', '');    style.parentElement.setAttribute(scope, '');    // 处理css}

3. 修改style中的所有css选择器,加上属性前缀

/** * 为选择器添加范围前缀scope * @param {String} selector css选择器 * @param {String} scope css范围前缀 * @returns 返回修改后的css选择器 */function updateSelector(selector, scope) {    return selector.split(",").map(x => x.replace(/((?<=^\s*)\s|^)([\S])/, "$1" + scope + " $2")).join(",");}/** * 将css代码中所有选择器都加上范围前缀scope * @param {String} css css代码 * @param {String} scope css范围前缀 * @returns 返回修改后的css代码 */function updateCss(css, scope) {    // css = css.replace(/[\n\r\s]+/g, " "); // 去掉多余的空格和回车    css = css.replace(/("[^"]*")|('[^']*')/g, x => x.charAt(0) + encodeURIComponent(x.slice(1, -1)) + x.charAt(0)); // 去字符串干扰     css = css.replace(/[^{}]+{/g, x => updateSelector(x, scope));    css = css.replace(/("[^"]*")|('[^']*')/g, x => x.charAt(0) + decodeURIComponent(x.slice(1, -1)) + x.charAt(0)); // 还原字符串     return css;}

用正则处理还是会有一些问题的,不过胜在代码简洁,实际使用中只要注意避开就好了,比如下面这段css就会有问题

@keyframes show {    100% {        opacity: 1;    }}

4. 监听dom变化,处理动态创建的<style scoped>

// 当观察到变动时执行的回调函数const callback = function (mutationsList) {    if (mutationsList.length == 0) {        return;    }    for (const mutation of mutationsList) {        for (const node of mutation.addedNodes) {            if (node.nodeName === "STYLE") {                updateStyle(node);            }        }    }};// 创建一个观察器实例并传入回调函数const observer = new MutationObserver(callback);const config = { childList: true, subtree: true };observer.observe(document, config);// MutationObserver 是异步的,回调时间不可控,所以需要设置一个轮询setInterval(() => callback(observer.takeRecords()), 100);

5. 完整代码

// style scoped(() => {    // 检测原生 style是否支持 scoped     if (document.createElement("STYLE").scoped !== undefined) {        return;    }    document.createElement("STYLE").__proto__.scoped = false;    /**     * 为选择器添加范围前缀scope     * @param {String} selector css选择器     * @param {String} scope css范围前缀     * @returns 返回修改后的css选择器     */    function updateSelector(selector, scope) {        return selector.split(",").map(x => x.replace(/((?<=^\s*)\s|^)([\S])/, "$1" + scope + " $2")).join(",");    }    /**     * 将css代码中所有选择器都加上范围前缀scope     * @param {String} css css代码     * @param {String} scope css范围前缀     * @returns 返回修改后的css代码     */    function updateCss(css, scope) {        // css = css.replace(/[\n\r\s]+/g, " "); // 去掉多余的空格和回车        css = css.replace(/("[^"]*")|('[^']*')/g, x => x.charAt(0) + encodeURIComponent(x.slice(1, -1)) + x.charAt(0)); // 去字符串干扰         css = css.replace(/[^{}]+{/g, x => updateSelector(x, scope));        css = css.replace(/("[^"]*")|('[^']*')/g, x => x.charAt(0) + decodeURIComponent(x.slice(1, -1)) + x.charAt(0)); // 还原字符串         return css;    }    /**     * 处理 <style> 标签     * @param style dom     */    function updateStyle(style) {        if (!style            || style.parentElement == null            || style.parentElement == document.head            || style.parentElement == document.body            || !style.hasAttribute("scoped")            || style.scoped === true) {            return;        }        style.scoped = true; // 防止重复处理        const scope = ("_" + (Math.random() * 100000000).toString("36")).replace(&                                                  

本文地址:https://www.31idc.com/helpcontent/608.html

  • 上一篇:微信小程序多种跳转页面方式
  • 下一篇:Windows 2008 如何安装IIS?

31IDC - 12 年深耕海外 IDC 高端资源

登陆 立即注册
7*24小时
全天服务支持
1V1
专属客户服务
99.9%
SLA 可用性保障
退订
无忧退款保障
100 %
故障补偿保障

服务器

物理服务器

关于我们

快速链接

联系我们

  • 微信:搜索公众号 “ 31IDC ”
  • 邮箱:max@31idc.com
  • 国内:+86 0551-65603607
  • 国际:400-018-2080
友情链接: IDC公司 网站测速 XHL.HK 网站历史查询 美国服务器 5118营销大数据 VPS234主机测评 香港IDC机房

这篇流量运营《JS让浏览器支持&lt;style scoped&gt;》,目前已阅读次,本文来源于31idc,在2024-09-19发布,该文旨在普及网站运营知识,如果你有任何疑问,请通过网站底部联系方式与我们取得联系

  • 上一篇:Windows中使用命令行杀进程
  • 下一篇:网站被挂马,百度搜索跳转怎么办?