关于前端:手摸手教你实现页面tab和导航菜单记忆功能

2次阅读

共计 7680 个字符,预计需要花费 20 分钟才能阅读完成。

在大型 PC 利用开发中,多 tab 和多级菜单的形式比拟罕用,如果可能记忆用户上次关上的 tab 和菜单对用户来说是十分便当的,每次关上零碎就能看到之前关上的页面持续进行浏览,晋升体验和效率,上面咱们来看看如何应用浏览器的存储和 layuiTab 组件实现这个性能。

首先是次要的顶部 layui tab 组件的构造,tab 外面有个 iframe 容器,次要应用 iframe 来当做对应页面的视图,相似 vueRouter 中的 <router-view>,每个一个 tab 内容都有一个视图,这样就能多个视图独立保留状态,不影响其余 tab
咱们菜单对应页面模块文件构造是一个文件夹一个模块,文件夹名就是模块名,文件夹下的 index.html 就是对应的页面(模块 1 /index.html),所以在点击时须要存储以后文件夹的名字就能晓得上一次用户关上的模块页面

网站的一级导航构造在这里就不给大家展现了,间接给代码:

   <ul id="main-menu" class="font-optimize">
      <li
        id="53a86ff50bbf443fb1a142fd78483ed7"
        class="homePage_1 sec-menu-item menu-authority-control"
      >
        <a
          href="#"
          onclick="changeUrl('homePage/index.html','homePage_1',this)"
        >
          <p class="fontColor"> 首页 </p>
        </a>
      </li>
      <li
        id="ff09a2cdd1b941329ff480eed06feb7c"
        class="seatManagement_1 sec-menu-item menu-authority-control"
      >
        <a
          href="#"
          onclick="changeUrl('seatManagement/index.html','seatManagement_1',this)"
        >
          <p class="fontColor"> 工作台 </p>
        </a>
      </li>
      <li
        id="84cc08dfaa9047e087ca4104c1e28820"
        class="WorkOrderManagement_1 sec-menu-item menu-authority-control"
      >
        <a
          href="#"
          onclick="changeUrl('WorkOrderManagement/workStation.html','WorkOrderManagement_1',this)"
        >
          <p class="fontColor"> 工单治理 </p>
        </a>
      </li>
      <li
        id="d6d8c3f28cc2427ba13fe26170645960"
        class="BasicSet_1 sec-menu-item menu-authority-control"
      >
        <a
          href="#"
          onclick="changeUrl('BasicSet/index.html','UserManage',this)"
        >
          <p class="fontColor">xxxx</p>
        </a>
      </li>
    </ul>

    <div class="body-main">
      <div
        class="layui-tab active"
        lay-filter="mainTab"
        lay-allowClose="true"
        style="height: 100%"
      >
        <ul class="layui-tab-title">
          <li class="layui-this" lay-id="53a86ff50bbf443fb1a142fd78483ed7">
            首页
          </li>
          <li lay-id="ff09a2cdd1b941329ff480eed06feb7c" class="seatManagement">
            坐席工作台
          </li>
        </ul>
        <div class="layui-tab-content" style="height: calc(100% - 42px)">
          <div class="layui-tab-item layui-show">
            <div class="report-list">
              <iframe
                id="home"
                src="./home/index.html"
                width="100%"
                height="100%"
                scrolling="no"
                marginheight="0"
                marginwidth="0"
              ></iframe>
            </div>
          </div>
          <div class="layui-tab-item" style="height: 100%">
      
           ...

          </div>
        </div>
      </div>
    </div>

这里我给菜单的惟一 id 设置了哈希值,大家能够本人定义一个语义化的,只有放弃惟一就行

tab 局部示例图:


这里是设置首页和工作台的 tab 不可敞开(暗藏掉敞开按钮)

    .body-main .seatManagement{display: none;}
    .layui-tab-title > li:first-child .layui-tab-close {display: none;}
    .layui-tab-title > .seatManagement .layui-tab-close {display: none;}
    body {padding: 0;}
    .body-main iframe {
      background-color: #fff;
      border: 0px;
    }
    .body-main {
      width: 100%;
      height: 100%;
    }
    .layui-tab-item {height: 100%;}

接下来是 js 逻辑:
changeUrl 为菜单跳转的办法

外围逻辑是在用户关上网站的时候利用浏览器的 storage 和 layuitab 的 element 把之前记忆的 tab 先一个个创立进去,而后通过记忆的 activeMenuId 切换到上次关上的 tab:

  if (sessionStorage.getItem("lastTabList")) {
        // 把记忆的 tab 全副创立进去

        var crrentTabName = $(".layui-tab.active").attr("lay-filter");
        var lastTabList = JSON.parse(sessionStorage.getItem("lastTabList"));
        lastTabList.forEach(function (i) {
          element.tabAdd(crrentTabName, {
            title: i.text,
            content:
              '<iframe  src="./' +
              i.url +
              '"width="100%"height="100%"scrolling="no"marginheight="0"marginwidth="0"></iframe>', // 反对传入 html
            id: i.id,
          });
        });
      }

而后用户在点击导航的时候,如不存在该 tab,也就是用户没有记忆这个菜单的 tab,那么咱们就依据传入的 url 创立新的 tab 并记忆。

如已存在该 tab 的话就简略,间接 tabChange 切换过来就好,tab 的内容能够是对应 iframe 视图,视图里能够有二级菜单,二级菜单的记忆是独自的,文章前面会介绍。

大家可能会纳闷 tab 里对应的页面是怎么记忆的,其实是咱们在点击菜单跳转的时候就曾经把以后页面的 url 存储到了 storage 外面,在下次关上网站时读取记忆并动静增加 iframe 的形式给显示进去。
留神每次删除和增加新 tab 的时候都要对 storage 进行批改(更新一下记忆),增加的时候存储一下以后关上的 tab 名 activeMenuId
残缺代码:

    layui.use(["element", "layer"], function () {
      var element = layui.element;
      window.changeUrl = function (url, className, e) {$("#main-menu > li").removeClass("selected");
        $("#main-menu > ." + url.split("/")[0] + "_1").addClass("selected");
        sessionStorage.setItem("url", url);
        sessionStorage.setItem("className", className);
   var crrentTabName = $(".layui-tab.active").attr("lay-filter");
        var reportName = $(e).parent().attr("id");
        if (
          url === "homePage/index.html" ||
          url === "seatManagement/index.html"
        ) {
          // 如为首页或坐席间接切换 tab,默认已有页面
          element.tabChange(crrentTabName, reportName);
          return;
        }
        // 记忆以后关上的 tab 信息
        var lastTabList = JSON.parse(sessionStorage.getItem("lastTabList"));
        var id = $(e).parent().attr("id");
        if (!lastTabList) {
          sessionStorage.setItem(
            "lastTabList",
            JSON.stringify([{ id: id, text: $(e).find(".fontColor").text(), url: url},
            ])
          );
        } else {var arridx = lastTabList.some(function (i) {return i.id === id;});
          if (!arridx) {
            lastTabList.push({
              id: id,
              text: $(e).find(".fontColor").text(),
              url: url,
            });
          }
          sessionStorage.setItem("lastTabList", JSON.stringify(lastTabList));
        }

        // 点击后新增 tab
        element.tabDelete(crrentTabName, reportName);
        element.tabAdd(crrentTabName, {title: $(e).find(".fontColor").text(),
          content:
            '<iframe  src="./' +
            url +
            '"width="100%"height="100%'+'" scrolling="no" marginheight="0" marginwidth="0"></iframe>', // 反对传入 html
          id: reportName,
        });

        element.tabChange(crrentTabName, reportName);
      };

      //tab 切换
      element.on("tab(mainTab)", function (data) {if ($(".layui-show iframe").attr("src")) {var url = $(".layui-show iframe").attr("src").slice(2);
          sessionStorage.setItem("url", url);
        }
        sessionStorage.setItem("activeMenuId", $(this).attr("lay-id"));
      });
      //tab 删除
      element.on("tabDelete(mainTab)", function (data) {var delId = $(this).parent().attr("lay-id");
        var lastTabList = JSON.parse(sessionStorage.getItem("lastTabList"));
        lastTabList.forEach(function (i, idx) {
          // 删除对于记忆的 tab 项
          console.log(i.id, delId);
          if (i.id === delId) {lastTabList.splice(idx, 1);
          }
        });
        sessionStorage.setItem("lastTabList", JSON.stringify(lastTabList));
      });

      if (sessionStorage.getItem("lastTabList")) {
        // 把记忆的 tab 全副创立进去

        var crrentTabName = $(".layui-tab.active").attr("lay-filter");
        var lastTabList = JSON.parse(sessionStorage.getItem("lastTabList"));
        lastTabList.forEach(function (i) {
          element.tabAdd(crrentTabName, {
            title: i.text,
            content:
              '<iframe  src="./' +
              i.url +
              '"width="100%"height="100%"scrolling="no"marginheight="0"marginwidth="0"></iframe>', // 反对传入 html
            id: i.id,
          });
        });
      }

      element.tabChange($(".layui-tab.active").attr("lay-filter"),
        sessionStorage.getItem("activeMenuId")
      );
    });

    if (sessionStorage.getItem("activeMenuId")) {$("#main-menu > #" + sessionStorage.getItem("activeMenuId")).addClass("selected"); // 高亮一级
    } else {$(".homePage_1").addClass("selected");
    }


        // 页面加载实现后调整主体高度
                $(".body-main").css(
                  "height",
                  "calc(100% -" +
                    ($(".main-top").outerHeight() +
                      $(".main-header").outerHeight() +
                      30) +
                    "px)"
                );
                $("#home").height($(".body-main").height() -
                    $(".body-main .layui-tab-title").outerHeight());

剩下其余的就是一些款式调整和默认 selected

storage 的存储状况:


以下是二级菜单的构造,应用 layui 的导航组件为例:

<body>
  <div class="body-left">
    <div class="left-nav">
      <ul class="layui-nav layui-nav-tree layui-inline" lay-filter="leftnav">
            <li id="f21c3279e67448d1a5a96d376b3695f6" class="layui-nav-item  UserManage" ><a href="#" onclick="changeUrlSec('BasicSet/UserManage/index.html','UserManage')"> 用户治理 </a></li>
                    <li id="4145cd3cde9740bb9bec57ec9bfba31a" class="layui-nav-item  UserAuthorization" ><a href="#" onclick="changeUrlSec('BasicSet/UserAuthorization/index.html','UserAuthorization')"> 用户角色 </a></li>

          <li  class="layui-nav-item version" ><a href="#" onclick="changeUrlSec('BasicSet/index.html','version')"> 版本更新 </a></li>
      </ul>
    </div>
  </div>
       <div class="left-button layui-icon layui-icon-left" ></div>
  <div class="body-main">
    <iframe id="Iframe"  width="100%" height="100%" scrolling="no"
    marginheight="0" src="./UserManage/index.html" marginwidth="0"></iframe>
  </div>
</body>

这里的话就比较简单,存储对应二级页面的文件夹名,而后在下次关上时间接设置视图的 src 对记忆页面进行显示。


  window.changeUrlSec = function (url, className) {var currtMenu = url.slice(0, url.indexOf("/")) + "/";
    if (window.location.pathname.indexOf(currtMenu) > -1) {sessionStorage.setItem("className", className);
    }
    var ss = window.location.href.indexOf("/html/");
    var aa = window.location.href.substr(0, ss + 6);
    url = aa + url.split("/")[0];
    console.log(url);
    document.getElementById("Iframe") &&
      (document.getElementById("Iframe").src =
        url + "/" + className + "/index.html"); // 跳转动作
  };

  var url = sessionStorage.getItem("url");
  var currtMenu = url.slice(0, url.indexOf("/")) + "/";
  if (sessionStorage.getItem("className") !== "null" &&
    window.location.pathname.indexOf(currtMenu) > -1 // 与记忆的 url 合乎才进行跳转
  ) {
    // 记忆上次停留菜单
    $("." + sessionStorage.getItem("className")).addClass("layui-this");
    if (url) {changeUrlSec(url, sessionStorage.getItem("className"));
    }
  } else {
    // 如上次菜单不匹配则默认第一个选中
    $(".layui-nav > .layui-nav-item:first-child").addClass("layui-this");
  }
});
正文完
 0