侧边栏折叠一秒钟并在页面加载时扩展 [英] Sidebar collapses for a second and expands on page load

查看:23
本文介绍了侧边栏折叠一秒钟并在页面加载时扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个侧边栏,单击按钮即可展开或折叠.现在,我已经成功地将其状态存储在 localStorage 中,并且工作正常,除了有一个小问题.

I have this sidebar which expands or collapses on a button click. Now I've successfully stored it's state in localStorage and it's working fine except there's a slight issue.

当页面加载且 localStorage 中没有任何状态保存时,边栏折叠一秒钟,然后扩展 .如果在 localStorage 中没有存储状态,则 Expand 应该是默认状态.我不希望它先折叠然后折叠.我只希望页面使用侧栏 expanded 加载.

When the page loads and there is no state saved in localStorage, the sidebar collapses for a split second and expands. Expand is supposed to be the default state when there is no state stored in localStorage. I don't want it to collapse first and then expand. I just want the page to load with the sidebar expanded.

我一直在尝试用自己的代码解决问题.但这没有用,然后我将我的代码与SO的帖子结合在一起.仍然不起作用.

I have been trying to solve the issue with my own code. But it didn't work then I combined my code with of of SO's posts. It still doesn't work.

完整代码: Codepen

下面是代码(请注意, localStorage 在SO中将无法运行):

Here's the code(please note that localStorage won't work in 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>

推荐答案

您可以通过告诉浏览器仅一次拍摄一次 repaint 来最小化闪烁效果.但是,您的侧边栏总是有一个初始大小:在您的标记内定义的大小.

You can minimize the the flashing effect, by telling the browser to repaint just only one time, in one shot. BUT there will be always one initial size for Your sidebar: the size which has been defined inside Your markup.

在我的示例中,我正在使用两个 Observers 来跟踪样式和大小的更改.请注意初始的侧边栏宽度.您可以将初始侧边栏宽度设置为0,或者不指定它的宽度,或者可以将其样式设置为与扩展侧边栏相同的大小,但是总会有一个初始重新绘制.

In my example, I am using two Observers to track the style and size changes. Please, note the initial sidebar width. You may set the initial sidebar width equal to 0, or let it unassigned, or maybe You can style it the same size as Your expanded sidebar, but there will be always an initial repaint.

最后,我坚信您需要从 body 删除两个初始类.

Finally, I strongly believe You need to remove the two initial classes from the 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>

如果您查看由观察者记录的消息,您将注意到总是有重新粉刷,如上所述.

If You look at the messages logged by the Observers, You will notice that there is always a repaint, as mentioned above.

在阅读完您之前的问题的解决方案后:

After reading this solution of Your previous question: Dark mode flickers a white background for a millisecond on reload I believe You can implement Your Sidebar toggler the same way.

您可以将其应用于 html ,而不是将CSS类应用于 body .这是完整代码:

Instead of applying the CSS class to the body, You can apply it to the html. Here is the full code:

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仍将保持不变.

Your CSS will remain untouched beside of a small change (I just only removed the #body id).

现在,如果您比较 Observed 的更改,您会注意到第二种解决方案(使用 head 中的阻塞JS脚本)仅显示了初始的侧边栏大小,即:最初的重绘已消失:

Now, if You compare the Observed changes, You will notice that the second solution, which is using the blocking JS script in head, is showing only the initial Sidebar size, i.e.: the initial repaint is gone:

   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 ):

更多信息:

以下是有关观察者的一些文档:

Here is some documentation about that Observers:

这篇关于侧边栏折叠一秒钟并在页面加载时扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆