重点!内容来自:
https://www.zhangxinxu.com/wordpress/2019/02/link-rel-alternate-website-skin/
https://egoist.moe/2015/12/13/how-does-array-slice-call-arguments-work/
小陈一谷歌,发现确实如参考文章中所说,大部分实现换肤功能有两种方法:
- 全局class控制样式切换
- 改变皮肤元素link的href地址,例如:
<link id="skinLink" href="skin-default.css" rel="stylesheet" type="text/css">
skinLink.href = 'skin-red.css';
缺点是:1,全局class控制样式,提高了样式优先级,换肤样式多,导致代码不易维护;2,JS改变href属性会带来延时,切换不流畅,体验感不好;
实际上,原生浏览器有原生特性,适合实现网站换肤。
实战
让我们开始吧!小陈也很期待呢。(#.#)
HTML rel属性:规定当前文档和被链接文档之间的关系。使用 href 属性时,才能使用 rel 属性
有以下属性值:
- alternate 文档的替代版本(比如打印页、翻译或镜像)。
- stylesheet 文档的外部样式表,所有浏览器支持。
- start 集合中的第一个文档。
- next 集合中的下一个文档。
- prev 集合中的上一个文档。
- contents 文档的目录。
- index 文档的索引。
- glossary 在文档中使用的词汇的术语表(解释)。
- copyright 包含版权信息的文档。
- chapter 文档的章。
- section 文档的节。
- subsection 文档的小节。
- appendix 文档的附录。
- help 帮助文档。
- bookmark 相关文档。
借助alternate属性值实现换肤:
<link href="reset.css" rel="stylesheet" type="text/css">
<link href="default.css" rel="stylesheet" type="text/css" title="默认">
<link href="red.css" rel="alternate stylesheet" type="text/css" title="红色">
<link href="green.css" rel="alternate stylesheet" type="text/css" title="绿色">
- 没有title属性,rel属性值仅仅是stylesheet的无论如何都会加载并渲染,如reset.css;
- 有title属性,rel属性值仅仅是stylesheet的作为默认样式CSS文件加载并渲染,如default.css;
- 有title属性,rel属性值同时包含alternate stylesheet的作为备选样式CSS文件加载,默认不渲染,如red.css和green.css;
划重点:如果有title属性并有值,性质上就变成了一个可以控制其渲染或者不渲染的特殊元素了。
使用JS修改link元素的DOM对象的disabled值为false,可以让默认不渲染的CSS开始渲染。
// 渲染red.css这个皮肤
document.querySelector('link[href="red.css"]').disabled = false;
这里模拟有三个换肤单选框可以选择:
//选择全部带有title属性的link
var eleLinks = document.querySelectorAll('link[title]');
//选择全部带有radio属性的单选框
var eleRadios = document.querySelectorAll('[type="radio"]');
//
[].slice.call(eleRadios).forEach(function (radio) {
radio.addEventListener('click', function () {
var value = this.value;
[].slice.call(eleLinks).forEach(function (link) {
link.disabled = true;
if (link.getAttribute('href') == value) {
// 该样式CSS文件生效
link.disabled = false;
}
});
});
});
这里注意点:
.slice 这个方法在不接受任何参数的时候会返回 this 本身,这是一个 Array.prototype 下的方法,因此 this 就是指向调用 .slice 方法的数组本身。
arguments 是属于函数内部的变量,其值是函数参数列表,一个类数组对象。
以此获得真正的参数数组
[].slice.call(arguments)
Array.prototype.slice.call(arguments)
优点
- 兼容性非常好。IE9+(IE8我没测,理论也支持),Chrome和Firefox均支持这种更原生的换肤效果实现。
- 语义非常好。用户,开发者,尤其搜索引擎或者其他辅助阅读设备能够准确识别网站还有其他替换CSS样式。(alternate的语义就是可替换的)
- 交互体验更好。rel=alternate方法实现的换肤功能在网站样式变换的时候是瞬间切换,完全无感知。因为浏览器已经把换肤的CSS文件预加载好了,比JS改变href地址的体验要更好。配合http2.0,几乎可以说是完美无瑕的解决方案了。