Markdown sidebar侧边栏 - 展开/关闭父级目录

完整代码在最后~ 这个js作为脚本导入html就可以直接使用~

一、展开/隐藏子级

  1. 查找所有子级元素
  2. 隐藏所有子级元素
  3. 给父级元素添加点击事件(展开/关闭)
hook.doneEach(function () {
    // 1. 查询所有子菜单
    var subMenus = document.querySelectorAll('.sidebar-nav li > ul');//所有直接嵌套在 <li> 元素内部的 <ul> 元素

    subMenus.forEach(function (ul) {
        var parent = ul.previousElementSibling; // 每个子级元素对应的 父级元素

        // 2. 隐藏子菜单
        ul.style.display = 'none'; 

        // 3. 设置父级元素的点击事件
        parent.onclick = function (e) {

            var isDisplayed = ul.style.display === 'block';
            ul.style.display = isDisplayed ? 'none' : 'block';
            
        };
    });
});

hook.doneEach这个钩子可以让代码内容在 每次页面内容被解析和渲染完成后 调用。

二、点击子页面刷新时 不更改目录显示状态

此时预览页面会发现,点击子页面刷新后,目录的展开状态也被刷新了,所以为了能够保持目录的状态,需要将数据保存再在刷新后重现。

但是我这里多一个要求,即如果重新刷新了整个网页(窗口卸载)的情况下,需要恢复至初始所有隐藏状态。

  1. 在点击事件中保存当前菜单状态
  2. 在设置菜单隐藏前添加判断逻辑,是否保存了菜单状态
  3. 添加一个窗口卸载的监听器,该情况下清除保存数据
/* 注意!这里是代码片段!不是完全连续的!*/


// 2. 从 localStorage 中恢复菜单栏状态
var storedDisplay = localStorage.getItem('sidebar_' + parent.textContent.trim());
if (storedDisplay) {
    ul.style.display = storedDisplay;
} else {
    ul.style.display = 'none'; 
}


// 1. 点击事件中添加保存数据操作
parent.onclick = function (e) {
    
    var isDisplayed = ul.style.display === 'block';
    ul.style.display = isDisplayed ? 'none' : 'block';
    
    localStorage.setItem('sidebar_' + parent.textContent.trim(), ul.style.display);// 保存到 localStorage
};


// 3. 在窗口卸载前,清除所有保存的状态
window.addEventListener('beforeunload', function () {
    var subMenus = document.querySelectorAll('.sidebar-nav li > ul');
    subMenus.forEach(function (ul) {
        var parent = ul.previousElementSibling;
        localStorage.removeItem('sidebar_' + parent.textContent.trim());
    });
});

三、在父级目录前添加箭头图标以示状态

  1. 加载箭头图标,并设置样式
  2. 添加图标到父级元素前
  3. 点击事件内添加旋转操作(注意刷新页面的恢复也要恢复图片的旋转状态)

完整代码:

(function (hook, vm) {
    window.$docsify = window.$docsify || {};
    window.$docsify.plugins = (window.$docsify.plugins || []).concat(function(hook, vm) {
        hook.doneEach(function () {

        
            var subMenus = document.querySelectorAll('.sidebar-nav li > ul');
            subMenus.forEach(function (ul) {
                var parent = ul.previousElementSibling;

                // 加载图标
                var icon = parent.querySelector('img') || document.createElement('img');
                icon.src = './images/UI/arrow.png'; 
                icon.className = 'expand-icon'; // 添加类名
                icon.style.width = '25px';
                icon.style.height = '25px';
                icon.style.marginRight = '8px';
                icon.style.verticalAlign = 'middle'; // 设置垂直对齐,使图标与文本水平居中
                icon.style.transition = 'transform 0.5s'; // 平滑转动动画
    
                // 将图标添加到标题前
                if (!parent.contains(icon)) {
                    parent.insertBefore(icon, parent.firstChild); 
                }

                // 恢复菜单状态
                var storedDisplay = localStorage.getItem('sidebar_' + parent.textContent.trim());
                if (storedDisplay) {
                    ul.style.display = storedDisplay;
                    icon.style.transform = storedDisplay === 'block' ? 'rotate(90deg)' : 'rotate(0deg)';
                } else {
                    ul.style.display = 'none';
                    icon.style.transform = 'rotate(0deg)';
                }
                
                //开合菜单
                parent.onclick = function (e) {
                    e.stopPropagation(); // 停止事件传播到父元素
                    
                    var isDisplayed = ul.style.display === 'block';
                    ul.style.display = isDisplayed ? 'none' : 'block';
                    icon.style.transform = isDisplayed ? 'rotate(0deg)' : 'rotate(90deg)';
                    // 保存当前状态到本地存储
                    localStorage.setItem('sidebar_' + parent.textContent.trim(), ul.style.display);
                };
            });
        });

        // 窗口卸载时刷新,清除存储
        window.addEventListener('beforeunload', function () {
            var subMenus = document.querySelectorAll('.sidebar-nav li > ul');
            subMenus.forEach(function (ul) {
                var parent = ul.previousElementSibling;
                localStorage.removeItem('sidebar_' + parent.textContent.trim());
            });
        });
    });
})();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值