用 JS 给网页加个深色模式保护眼睛(和一个失败的实现)。
起因
最近在看的一些技术文档都是用VuePress 写的,虽然很简洁好看,但是大部分网页都是白屏黑字,对于一个每天除了睡觉就是盯着电子屏幕的人来说,#fff
的背景色配上黑色小字实在是太伤眼睛了。这我大JS不就派上用场了?为了保护视力,写个脚本加个深色模式吧!
开干
首先分析下页面结构,主页面是个叫page
的class
,侧边栏是个叫sidebar
的class
,那么很简单,直接用qeurySelector
改改颜色就行了:
1 | document.querySelector(".page").style.backgroundColor = '#111'; |
改完之后的效果:
果然舒服多了。而且由于前端路由的特性,页面变化相当于在document
这个容器中装各种各样的内容,这样切换到别的页面也还是深色模式。但是技术文档的特点就是有很多行内代码块,在VuePress中颜色是#476582
,深色背景下就不是很友好,比如:
这也很简单,行内代码都是用<code></code>
包裹的,那直接选中改色不就完了:
1 | const codeList = Array.from(document.querySelectorAll("code")); |
大功告成,现在的效果是这样的:
但是,当我们跳转到另一个页面,行内代码的颜色又变回去了🤒
因此,新的问题就是:怎样在路由变化时也能让行内代码变为想要的颜色呢?
根据Vue Router的两种实现方式:Hash Router和History Router,可以很容易的想到只要监听路由变化,在路由变化的时候改个颜色就行了呀!如果是Hash Router,就非常简单,直接监听hashchange
事件就行了。但是很多网站为了优雅
,都是使用的History Router模式(但我怀疑使用Hash Router是不是没法用锚点链接和copy link to highlight
了?在自己的站点上测试了下貌似没法用)。
复习下History Router的实现方式,主要就是利用History API:
- 用
pushState
和replaceState
来实现页面内容的更新和会话历史栈的更新 - 用
popState
来监听前进后退等事件
pushState
和replaceState
是相辅相成的,前者记录历史,后者切换url
,这样点击浏览器的前进后退时也能滚动到锚点位置,而且有好看的滚动动画。那么监听哪个事件呢?
从使用场景上来想,如果是在一个文档中有不同的标题,那么进入文档时,首先进行pushState
记录历史(url
),然后使用replaceState
定位到当前的锚点链接(标题),在滑动浏览的过程中,不断使用replaceState
来更新当前的锚点链接,而直接点击某个小标题时,则使用pushState
保证回退时可以回退到正确位置。这样看来应该是使用pushState
执行的次数会少一些。
接下来就开始实现了。由于个人使用,不用考虑兼容性什么的问题(日常用IE那是不可能的),直接用ES6的proxy
做代理即可:
1 | history.pushState = new Proxy(history.pushState, { |
判断是为了减少反复更改的次数。不过这么写还有一个问题,就是如果从侧边栏进入到另一个文档,第一次视图不会更新。这个问题不知道该怎么解决,我目前的做法是手动再push一遍,如下:
1 | history.pushState = new Proxy(history.pushState, { |
这样会导致得回退两次才能退回去,且加载时会有一闪而过的白屏。
接着给window
添加一个onload
事件,让第一次进入页面时代码就亮起来:
1 | window.onload = function() { |
最后是侧边栏,不过我觉得侧边栏不是很有必要,稍微写一下:
1 | Array.from(document.querySelectorAll(".sidebar-link:not(.sidebar-link.active)")).forEach(item => {item.style.color="#aaaaaa"}) |
最终效果:
最后
为了保护眼睛折腾了好半天,最后实现的效果还不尽如人意,健康真费劲啊。从结果上说,可能看屏幕一小时就出去晒晒太阳是更经济的选择。不过借这个突发奇想复习了下history router,也挺好的。
- 本文标题:写个脚本保护视力
- 本文作者:WoodenStone
- 创建时间:2021-12-19 13:28:51
- 本文链接:https://woodenstone.github.io/Whim/create-my-dark-mode/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!