javascript - 侧边栏折叠一秒钟并在页面加载时展开
问题描述
我有这个边栏,可以在单击按钮时展开或折叠。现在我已经成功地存储了它的状态localStorage
并且它工作正常,除了有一个小问题。
当页面加载并且没有保存状态时localStorage
,侧边栏会瞬间collapses
出现expands
。Expand
当没有状态存储在中时,应该是默认状态localStorage
。我不希望它collapse
先然后expand
。我只希望页面与侧边栏一起加载expanded
。
我一直在尝试用我自己的代码解决这个问题。但它没有用,然后我将我的代码与 SO 的帖子结合起来。它仍然不起作用。
完整代码:Codepen
这是代码(请注意localStorage
在 SO 中不起作用):
$('document').ready(function() {
if (typeof window.isMinified === "undefined") {
window.isMinified = false;
}
const body = $('#body');
$("#sidebar-toggler").on("click", function () {
if (window.isMinified === false) {
// localStorage.setItem('menu-closed', !$(body).hasClass("sidebar-minified"));
body.removeClass("sidebar-minified-out").addClass("sidebar-minified");
window.isMinified = true;
} else {
// localStorage.setItem('menu-closed', !$(body).hasClass("sidebar-minified"));
body.removeClass("sidebar-minified").addClass("sidebar-minified-out");
window.isMinified = false;
}
});
const state = // localStorage.getItem('menu-closed');
if (state === null) {
$(body).removeClass('sidebar-minified');
} else {
const closed = state === "true" ? true : false;
if (!closed) {
$(body).removeClass('sidebar-minified');
}
}
});
#body {
background: #fff;
transition: all 0.3s;
}
aside.left-sidebar{
background-color: #2c0963;
height: 100vh;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
transition: width .3s ease-in;
}
.sidebar-minified .left-sidebar {
width: 75px;
transition: width .3s ease-in;
}
.sidebar-toggle {
font-weight: 300;
font-size: 15px;
cursor: pointer;
height: 30px;
position: absolute;
left: 20%;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body id="body" class="sidebar-minified sidebar-minified-out">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
解决方案
您可以通过告诉浏览器一次只重绘一次来最小化闪烁效果。但是 Your 总是有一个初始大小sidebar
:在 Your 标记中定义的大小。
在我的示例中,我使用两个Observers
来跟踪样式和大小的变化。请注意初始sidebar
宽度。您可以将初始侧边栏宽度设置为 0,或者让它未分配,或者您可以将其设置为与扩展侧边栏相同的大小,但总会有一个初始重绘。
最后,我坚信您需要从body
.
$(function() {
/* avoid SO unsecure operation error */
var storage = (function () {
return {
setItem: function(k,v){try{return localStorage.setItem(k,v)}catch(e){return !1}},
getItem: function(k){try{return localStorage.getItem(k)}catch(e){return null}}
};
})();
log("jQuery DOM Ready");
$("#sidebar-toggler").on("click", function() {
var isMinified = !$("body").hasClass("sidebar-minified-out");
$("body")
.toggleClass("sidebar-minified", !isMinified)
.toggleClass("sidebar-minified-out", isMinified);
storage.setItem('menu-closed', +!isMinified);
});
var closed = +storage.getItem('menu-closed');
log('Closed: ' + !!closed);
$("body")
.addClass(closed ? "sidebar-minified" : "sidebar-minified-out")
.css({"visibility": "visible"});
});
body {
background: #fff;
transition: all 0.3s;
}
aside.left-sidebar{
background-color: #2c0963;
height: 100vh;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
transition: width .3s ease-in;
}
.sidebar-minified .left-sidebar {
width: 75px;
transition: width .3s ease-in;
}
.sidebar-toggle {
font-weight: 300;
font-size: 15px;
cursor: pointer;
height: 30px;
position: absolute;
left: 20%;
top: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sidebar State</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body style="visibility: hidden;">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
<div id="log" style="position:absolute;top:0;right:0;padding:1em;"></div>
<script>
/* only debug functions inside this script block */
function log(msg) {
$("<div>").appendTo("#log").text(msg);
}
var mo = new MutationObserver(function (ml){
for(var m of ml) {
if (m.type == 'attributes') log('Body ' + m.attributeName + ' changed');
}
});
mo.observe(document.getElementsByTagName('body')[0], {attributes: true});
var ro = new ResizeObserver(function (rl){
for(var r of rl) {
var w = r.contentRect.width;
if(w<=75 || w>=180) log('Sidebar width: ' + r.contentRect.width);
}
});
ro.observe(document.getElementsByClassName("left-sidebar")[0]);
</script>
</body>
</html>
编辑:
如果您查看Observers记录的消息,您会注意到始终存在重绘,如上所述。
在阅读了您上一个问题的解决方案后:Dark mode flickers a white background for a millisecond on reload我相信您可以以相同的方式实现您的侧边栏切换器。
body
您可以将CSS 类应用于html
. 这是完整的代码:
HTML
<!DOCTYPE html>
<html>
<head>
<script>
/* Render blocking script */
var c = +localStorage.getItem('menu-closed');
document.documentElement.classList.add(c ? 'sidebar-minified' : 'sidebar-minified-out');
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
</html>
JS
$(function() {
$("#sidebar-toggler").on("click", function (e) {
var isMinified = !$("html").hasClass("sidebar-minified-out");
$("html")
.toggleClass("sidebar-minified", !isMinified)
.toggleClass("sidebar-minified-out", isMinified);
localStorage.setItem('menu-closed', +!isMinified);
});
});
除了一个小改动(我只是删除了#body
id)之外,您的 CSS 将保持不变。
现在,如果您比较Observed的更改,您会注意到第二个解决方案,即在 中使用阻塞 JS 脚本head
,仅显示初始侧边栏大小,即:初始重绘已消失:
1st solution 2nd solution
==============================================================
Sidebar width: 601 Closed: false
jQuery DOM Ready Sidebar width: 180
Closed: false jQuery DOM Ready
Body class changed
Body style changed
Sidebar width: 180
(学分:Roko C. Buljan):
更多信息:
我的第一个示例中的调试函数仅用于描述浏览器中调整大小和重新设置样式事件的顺序。
以下是有关该Observers的一些文档:
推荐阅读
- apache-spark - 如何调整 Spark 以避免排序磁盘溢出?
- gnuradio - GNU Radio OOT 块:AttributeError:模块“twoTypes”没有属性“passthrough_cc”
- nginx - Jenkins Https 反向代理配置在 centos 中不起作用
- merge - 如何从分层文档结构中展开/合并数组?
- java - 是否可以在日志中对 ThreadName 进行颜色编码?(Java - 回退)
- string - 在不到 o(n^2) 的时间内使用常数空间交换 char* 中的两个单词
- reactjs - 从哪里可以找到这个标记我希望高度等于 0
- javascript - 带有手风琴风格子菜单的响应式水平(桌面)/垂直(移动)多级下拉菜单
- ssl - OpenSSL OCSP 响应者索引文件的格式
- python - python中带有布尔值的向量方程