首页 > 解决方案 > 侧边栏折叠一秒钟并在页面加载时展开

问题描述

我有这个边栏,可以在单击按钮时展开或折叠。现在我已经成功地存储了它的状态localStorage并且它工作正常,除了有一个小问题。

当页面加载并且没有保存状态时localStorage,侧边栏会瞬间collapses出现expandsExpand当没有状态存储在中时,应该是默认状态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>

标签: javascripthtmljquerycss

解决方案


您可以通过告诉浏览器一次只重绘一次来最小化闪烁效果。但是 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);
  });
});

除了一个小改动(我只是删除了#bodyid)之外,您的 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的一些文档:


推荐阅读