原理分析
常规做法:等文档加载完成再执行js代码切换黑夜模式,有屏闪。
我的做法:加载到body标签后立即执行js代码,为其添加黑夜模式的类,无屏闪。
网页的加载是从上往下的,并且遇到< script >标签包裹的js代码会立即执行,然后接着加载下面内容,这样的话,我们就可以在< body >标签下面放< script >包裹的黑夜模式代码,执行后,会给标签添加一个class=“类”,这个类就是黑夜模式的css样式,这样,一个完美的黑夜模式就实现了。
下面是一个例子
html部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="darkto.js"></script>
<title>Document</title>
</head>
<body>
<div class="darkto"></div>
</body>
</html>
js部分
const loadJS=(url, callback)=>{
var script = document.createElement('script')
var fn = callback || function () { };
script.type = 'text/javascript';
if (script.readyState) {
script.onreadystatechange = function () {
if (script.readyState == 'loaded' || script.readyState == 'complete') {
script.onreadystatechange = null;
fn();
}
};
} else {
script.onload = function () {
fn();
};
}
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
};
const loadStyle = (style) => {
var dataStyle = document.createElement('style');
dataStyle.type = 'text/css';
dataStyle.appendChild(document.createTextNode(style));
var head = document.getElementsByTagName('head')[0];
head.appendChild(dataStyle)
};
const darktoCss = `
.dark {
background-color:var(--bg_color);
color: var(--font_color);
}`;
class storage {
constructor(isLocal = true) {
this.storage = isLocal ? localStorage : sessionStorage;
}
setItem(params = {}) {
if (params) {
let {
key,
value,
} = params;
let obj = {
time: new Date().getTime(),
type: typeof (value),
key: key,
value: value
};
this.storage.setItem(key, JSON.stringify(obj));
}
}
getItem(key) {
let params = this.storage.getItem(key);
if (params) {
params = JSON.parse(params);
return params.value;
}
}
};
const l = new storage();
const darkFrom=()=>{
loadStyle(darktoCss);
$("body").css({ "--bg_color": "rgb(33, 33, 33)", "--font_color": "rgb(255, 255, 255)" })
$(".darkto").css({
"width": "30px", "height": "30px", "user-select": "none", "-moz-user-select": "none", "border-radius": "50%",
"display": "flex", "font-size": "20px", "justify-content": "center", "align-items": "center"
}).css({ "cursor": "pointer" }).on("click", function () {
dark.clickDark();
})
}
const dark = {
darkText: () => { $(".darkto").text("🌞"); },
lightText: () => { $(".darkto").text("🌜"); },
setFlag: () => {
l.setItem({
key: "dark",
value: "yes",
});
},
removeFlag: () => {
l.setItem({
key: "dark",
value: "no",
});
},
getFlag: (key) => {
return l.getItem(key);
},
setDark: () => {
$("body").addClass("dark");
},
removeDark: () => {
$("body").removeClass("dark");
},
firstDark: function () {
if (this.getFlag("dark") == "yes") {
this.lightText();
this.setFlag();
this.setDark();
} else {
this.darkText();
this.removeFlag();
this.removeDark();
}
},
clickDark: function () {
if (this.getFlag("dark") == "no") {
this.lightText();
this.setFlag();
this.setDark();
} else {
this.darkText();
this.removeFlag();
this.removeDark();
}
},
};
!(function () {
loadJS("https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js", () => {
var username = '钱辉'; var usertext = "一支穿云箭,千军万马来相见!";
var userurl = "https://github.com/quinhua";
var consoleA = "color:#fff;background:#6cf;padding:5px 0;border: 1px solid #6cf;";
var consoleB = "color:#6cf;background:none;padding:5px 0;border: 1px solid #6cf;";
console.log(`\n %c ${username} %c ${usertext}`, consoleA, consoleB);
console.log(`\n %c ${username} %c ${userurl}`, consoleA, consoleB);
if (dark.getFlag('dark') != null) {
dark.firstDark();
} else {
dark.removeFlag();
$("#darkto").text("深色");
}
darkFrom();
})
})();
See the Pen
暗夜模式1 by qianhuiya (
@quinhua) on
CodePen.