前端框架Layui实现动态选项卡&iframe使用(附源码)

简介: 前端框架Layui实现动态选项卡&iframe使用(附源码)

一、前言

1.什么是Tab选项卡

       选项卡(Tab)是一种常见的用户界面元素,用于在一个容器中显示多个内容页面。每个选项卡通常由一个标签和一个对应的内容区域组成

当用户点击选项卡的标签时,相应的内容区域将显示出来,而其他选项卡的内容区域则隐藏起来。这样用户可以通过点击不同的选项卡来在不同的页面之间进行切换,从而提供更好的用户体验。

       在网页开发中,实现选项卡通常有多种方法,如使用HTML、CSS和JavaScript来手动编写代码,或者使用现有的选项卡插件/库来简化开发过程。常见的选项卡插件/库包括Bootstrap的Tab插件、jQuery UI的Tabs组件等。

       通过选项卡,用户可以在一个页面中方便地切换不同内容,这在许多应用场景中都非常有用,例如网页导航菜单、设置面板、多标签浏览器等。选项卡的外观和交互方式可以根据设计需求和用户体验进行定制

tab效果展示:

2.什么是iframe标签

iframe(内嵌框架)是HTML中的一个标签,用于在网页中嵌入另一个页面或文档。

通过使用iframe标签,可以在网页中创建一个独立的内联框架,用于显示来自不同源或同一源的外部内容。这个嵌入的页面可以是其他网页、视频、地图、广告等等。

iframe标签通常包含以下属性:

  • src:指定要加载的内容的URL。
  • width:指定`iframe`的宽度。
  • -height:指定`iframe`的高度。
  • frameborder:指定是否显示边框。
  • scrolling:指定是否显示滚动条。

示例代码如下:

<iframe src="http://www.example.com" width="500" height="300" frameborder="0" scrolling="auto"></iframe>

需要注意的是,使用iframe标签时,被嵌入的内容将在一个单独的框架中显示,与父页面有一定的隔离性。这使得iframe非常有用,例如在网页中嵌入第三方内容、显示广告、集成其他网页应用等。但同时也需要注意安全性和设计上的考虑,避免滥用iframe可能引发的安全风险和用户体验问题。

3.使用iframe标签

当使用iframe标签时,您需要指定要嵌入的内容的URL或源文件,并定义相应的属性。下面是一个使用`iframe`标签的示例:

<!DOCTYPE html>
<html>
<head>
  <title>嵌入页面示例</title>
</head>
<body>
  <h1>主页面</h1>
  <iframe src="http://t.csdn.cn/ommMR" width="800" height="600" frameborder="0" scrolling="auto"></iframe>
  <p>这是主页面中的其他内容。</p>
</body>
</html>

在这个示例中,iframe标签嵌入了来自"http://t.csdn.cn/ommMR"的网页。宽度设置为800像素,高度设置为600像素。frameborder属性设置为0以隐藏边框,scrolling属性设置为"auto"以根据内容是否超出框架显示滚动条。

请注意,使用iframe标签时需要确保嵌入的内容是可信的,并且遵循安全性最佳实践,以防止潜在的安全风险。

效果演示:

二、案例实现

1.需求分析

在线Layui示例寻找合适的选项卡

下面是静态效果展示:

②点击左侧右侧没有url属性

由于我们的工具类TreeVo不可能有我们数据库的全部字段,那么应该怎么动态生成拥有属性url的TreeVo工具类??

TreeVo工具类

package com.zking.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class TreeVo<T> {
  /**
   * 节点ID
   */
  private String id;
  /**
   * 显示节点文本
   */
  private String text;
  /**
   * 节点状态,open closed
   */
  private Map<String, Object> state;
  /**
   * 节点是否被选中 true false
   */
  private boolean checked = false;
  /**
   * 节点属性
   */
  private Map<String, Object> attributes;
  /**
   * 节点的子节点
   */
  private List<TreeVo<T>> children = new ArrayList<TreeVo<T>>();
  /**
   * 父ID
   */
  private String parentId;
  /**
   * 是否有父节点
   */
  private boolean hasParent = false;
  /**
   * 是否有子节点
   */
  private boolean hasChildren = false;
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public String getText() {
    return text;
  }
  public void setText(String text) {
    this.text = text;
  }
  public Map<String, Object> getState() {
    return state;
  }
  public void setState(Map<String, Object> state) {
    this.state = state;
  }
  public boolean isChecked() {
    return checked;
  }
  public void setChecked(boolean checked) {
    this.checked = checked;
  }
  public Map<String, Object> getAttributes() {
    return attributes;
  }
  public void setAttributes(Map<String, Object> attributes) {
    this.attributes = attributes;
  }
  public List<TreeVo<T>> getChildren() {
    return children;
  }
  public void setChildren(List<TreeVo<T>> children) {
    this.children = children;
  }
  public boolean isHasParent() {
    return hasParent;
  }
  public void setHasParent(boolean isParent) {
    this.hasParent = isParent;
  }
  public boolean isHasChildren() {
    return hasChildren;
  }
  public void setChildren(boolean isChildren) {
    this.hasChildren = isChildren;
  }
  public String getParentId() {
    return parentId;
  }
  public void setParentId(String parentId) {
    this.parentId = parentId;
  }
  public TreeVo(String id, String text, Map<String, Object> state, boolean checked, Map<String, Object> attributes,
                  List<TreeVo<T>> children, boolean isParent, boolean isChildren, String parentID) {
    super();
    this.id = id;
    this.text = text;
    this.state = state;
    this.checked = checked;
    this.attributes = attributes;
    this.children = children;
    this.hasParent = isParent;
    this.hasChildren = isChildren;
    this.parentId = parentID;
  }
  public TreeVo() {
    super();
  }
}

看完以上代码我们可以发现虽然没有我们想要的属性但是拥有private Map<String, Object> attributes属性,那么我们就可以在进行将平级数据转换成父子级数据的时候将遍历的平级数据直接加到Map集合中,这样该属性就拥有了数据库表的全部字段。

③点击左侧列表右侧内容多开问题

我们只需要在添加tab选项卡之前加一个判断即可,我们发现tab中的li标签上都有一个lay-id属性,我们只需将我们TreeVo的id赋给它,然后每次点击的时候通过jquery获取该标签,如果没有找到说明没有打开,如果找到了那么我们就选中它。

//点击左侧列表右侧选项卡打开
    function opedTab(title, content, id) {
      //判断是否已经打开
      var node=$('li[lay-id="'+id+'"]');
      //没有找到该标签时就打开
      if(node.length==0){
        //因为element没有获取到要扩大权限(layui.use里有element)
          element.tabAdd('demo', {
          title : title,
          content :"<iframe frameborder='0' src='"+content+"' scrolling='auto' style='width:100%;height:100%;'></iframe>",
          id : id
        })  
      }
      //有该标签就打开
      element.tabChange('demo', id)
    }

④优化公共文件

因为我们在页面上需要写大量的${pageContext.request.contextPath}非常的繁琐,所以我们就可以使用一个标签——base标签

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html ">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
<!-- 引入layui.css-->
<link rel="stylesheet" href="${pageContext.request.contextPath}/static/js/layui/css/layui.css">
<!-- 引入layui.js-->
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/layui/layui.js"></script>
<!-- base标签 -->
<base href="${pageContext.request.contextPath}/">
</head>
</html>

小贴士:

<base> 标签是HTML中的一个元标签(meta tag),用于指定页面中所有相对路径的基准URL。

使用 <base> 标签可以改变页面中所有相对链接的基准URL,它是一种全局的设置。通常情况下,相对路径是以当前页面的URL为基准进行解析。但是,当使用 <base> 标签时,相对路径将以 <base> 标签中指定的URL为准。需要注意的是,一个页面只能有一个 <base> 标签,并且应放置在 <head> 标签中的最顶部

2.Dao层的优化

package com.xw.dao;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xw.entity.Permission;
import com.zking.util.BaseDao;
import com.zking.util.BuildTree;
import com.zking.util.TreeVo;
/**管理系统左侧列表
 * @author 索隆
 *
 */
public class PermissionDao extends BaseDao<Permission>{
  /**获取管理的所有信息(平级数据)
   * @return
   * @throws Exception 
   */
  public List<Permission> list() throws Exception{
    String sql="select * from t_oa_permission";
    return  super.executeQuery(sql, Permission.class, null);
  }
  /**将平级数据变成我们需要的父子级数据
   * @return
   * @throws Exception 
   */
  public List<TreeVo<Permission>> menu() throws Exception{
    //存放父子级的容器
    List<TreeVo<Permission>> menu=new ArrayList<TreeVo<Permission>>();
    //拿到平级数据
    List<Permission> list = this.list();
    //遍历平级数据
    for (Permission permission : list) {
      //工具类帮助我们完成父子级关系
      TreeVo<Permission> vo=new TreeVo<Permission>();
      vo.setId(permission.getId()+"");//id
      vo.setParentId(permission.getPid()+"");//父级id
      vo.setText(permission.getName());//列表名称
            //优化代码
      //利用一个map集合保存TreeVo没有的属性
      Map<String, Object> map=new HashMap<>();
      //将数据的所有信息保存到map容器中
      map.put("self", permission);
      vo.setAttributes(map);
      menu.add(vo);
    }
    //通过工具类筛选父级菜单的儿子,String是父级菜单的pid
    return BuildTree.buildList(menu, "-1");
  }
}

刚刚需求分析的时候也提到了,这里就不过多讲解,大家直接看代码即可。

3.JSP页面搭建

<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<!DOCTYPE>
<html>
<head>
<%@ include file="common/static.jsp"%>
<script type="text/javascript" src="js/index.js"></script>
</head>
<body>
  <div class="layui-layout layui-layout-admin">
    <div class="layui-header">
      <div class="layui-logo layui-hide-xs layui-bg-black">OA会议系统</div>
      <!-- 头部区域(可配合layui 已有的水平导航) -->
      <!-- <ul class="layui-nav layui-layout-left">
        移动端显示
        <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm"
          lay-header-event="menuLeft"><i
          class="layui-icon layui-icon-spread-left"></i></li>
        Top导航栏
        <li class="layui-nav-item layui-hide-xs"><a href="">nav 1</a></li>
        <li class="layui-nav-item layui-hide-xs"><a href="">nav 2</a></li>
        <li class="layui-nav-item layui-hide-xs"><a href="">nav 3</a></li>
        <li class="layui-nav-item"><a href="javascript:;">nav
            groups</a>
          <dl class="layui-nav-child">
            <dd>
              <a href="">menu 11</a>
            </dd>
            <dd>
              <a href="">menu 22</a>
            </dd>
            <dd>
              <a href="">menu 33</a>
            </dd>
          </dl></li>
      </ul> -->
      <!-- 个人头像及账号操作 -->
      <ul class="layui-nav layui-layout-right">
        <li class="layui-nav-item layui-hide layui-show-md-inline-block">
          <a href="javascript:;"> <img
            src="${pageContext.request.contextPath }/static/images/user/小黑子索隆.jpg"
            class="layui-nav-img">我的
        </a>
          <dl class="layui-nav-child">
            <dd>
              <a href="">修改信息</a>
            </dd>
            <dd>
              <a href="">安全管理</a>
            </dd>
            <dd>
              <a href="login.jsp">退出登录</a>
            </dd>
          </dl>
        </li>
        <li class="layui-nav-item" lay-header-event="menuRight" lay-unselect>
          <a href="javascript:;"> <i
            class="layui-icon layui-icon-more-vertical"></i>
        </a>
        </li>
      </ul>
    </div>
    <div class="layui-side layui-bg-black">
      <div class="layui-side-scroll">
        <!-- 左侧导航区域(可配合layui已有的垂直导航) -->
        <ul id="menu" class="layui-nav layui-nav-tree" lay-filter="menu">
        </ul>
      </div>
    </div>
    <div class="layui-body">
      <!-- 内容主体区域 -->
      <div class="layui-tab" lay-filter="demo" lay-allowclose="true">
        <ul class="layui-tab-title">
        </ul>
        <div class="layui-tab-content">
        </div>
      </div>
    </div>
    <div class="layui-footer">
      <!-- 底部固定区域 -->
      底部固定区域
    </div>
  </div>
  <script>
  var element,layer,util,$;
layui.use(['element', 'layer', 'util','jquery'], function(){
  element = layui.element
  ,layer = layui.layer
  ,util = layui.util
  ,$ = layui.jquery;
    $.ajax({
      url: " Permission.action?methodName=listmenu",
      type: 'post',
      dataType: 'json',
      success: function(data) {
        //定义一个变量将回显的数据进行拼接,最终追加到指定标签上
        var str='';
        $.each(data,function(i,n){
          str+='<li class="layui-nav-item layui-nav-itemed">';
          str+=' <a class="" href="javascript:;">'+n.text+'</a>';
          //判断有无children节点有就遍历
          if(n.hasChildren){
            //有children节点拿到children节点
            var children=n.children;
              str+='<dl class="layui-nav-child">';
            $.each(children,function(idx,node){
              str+='<dd><a href="javascript:;" onclick="opedTab(\''+node.text+'\',\''+node.attributes.self.url+'\',\''+node.id+'\')">'+node.text+'</a></dd>';
              })
                str+='</dl>';
          }
          str+='</li>';
        })
        //将拼接内容追加到指定ul标签
        $("#menu").html(str);
        //渲染ul标签
        element.render('menu');
      }
    })
});
    //点击左侧列表右侧选项卡打开
    function opedTab(title, content, id) {
      //判断是否已经打开
      var node=$('li[lay-id="'+id+'"]');
      //没有找到该标签时就打开
      if(node.length==0){
        //因为element没有获取到所有要去上面扩大权限
          element.tabAdd('demo', {
          title : title,
          content :"<iframe frameborder='0' src='"+content+"' scrolling='auto' style='width:100%;height:100%;'></iframe>",
          id : id
        })  
      }
      //有该标签就打开
      element.tabChange('demo', id)
    }
  </script>
</body>
</html>

4.案例演示

登录成功才可访问我们的主页面

因为这里的url页面我项目中还没有编写,所以404是必然的,不用管他!!!

5.总结

  • ①因为我们自己所编写的方法中要用到element,而这个元素我们在方法内没有获取所有要在layui.use(加载模块)获取element的时候扩大作用域。
  • ②url在TreeVo工具类中没有该属性,所以我们要在平级数据转成父子级数据的时候下文章,加到Map中再将Map赋值给TreeVo中的Attributes属性,从而拿到数据库表的全部字段及内容。
  • ③选项卡打开后不可重复打开,应该做判断。如果已经有该选项卡存在,那么我就让其选中,不存在我才打开。

到这里我的分享就结束了,欢迎到评论区探讨交流!!

如果觉得有用的话还请点个赞吧 ♥  ♥


相关文章
|
7月前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
646 1
|
8月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
507 70
|
7月前
|
存储 前端开发 JavaScript
|
9月前
|
前端开发 算法 NoSQL
前端uin后端php社交软件源码,快速构建属于你的交友平台
这是一款功能全面的社交软件解决方案,覆盖多种场景需求。支持即时通讯(一对一聊天、群聊、文件传输、语音/视频通话)、内容动态(发布、点赞、评论)以及红包模块(接入支付宝、微信等第三方支付)。系统采用前后端分离架构,前端基于 UniApp,后端使用 PHP 框架(如 Laravel/Symfony),配合 MySQL/Redis 和自建 Socket 服务实现高效实时通信。提供用户认证(JWT 集成)、智能匹配算法等功能,助力快速上线,显著节约开发成本。
268 1
前端uin后端php社交软件源码,快速构建属于你的交友平台
|
8月前
|
监控 前端开发 小程序
陪练,代练,护航,代打小程序源码/前端UNIAPP-VUE2.0开发 后端Thinkphp6管理/具备家政服务的综合型平台
这款APP通过技术创新,将代练、家政、娱乐社交等场景融合,打造“全能型生活服务生态圈”。以代练为切入点,提供模块化代码支持快速搭建平台,结合智能匹配与技能审核机制,拓展家政服务和商业管理功能。技术架构具备高安全性和扩展性,支持多业务复用,如押金冻结、录屏监控等功能跨领域应用。商业模式多元,包括交易抽成、增值服务及广告联名,同时设计跨领域积分体系提升用户粘性,实现生态共生与B端赋能。
775 12
|
12月前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
840 4
|
JSON 前端开发 Java
震惊!图文并茂——Java后端如何响应不同格式的数据给前端(带源码)
文章介绍了Java后端如何使用Spring Boot框架响应不同格式的数据给前端,包括返回静态页面、数据、HTML代码片段、JSON对象、设置状态码和响应的Header。
594 2
震惊!图文并茂——Java后端如何响应不同格式的数据给前端(带源码)
|
前端开发 程序员 API
前端|基于 Layui 实现动态搜索选择框
网页端实现动态搜索选择框,要求下拉选项列表能根据用户输入内容动态刷新,最终提交的值必须是由选项列表中点选的。
437 3
|
存储 前端开发 Java
验证码案例 —— Kaptcha 插件介绍 后端生成验证码,前端展示并进行session验证(带完整前后端源码)
本文介绍了使用Kaptcha插件在SpringBoot项目中实现验证码的生成和验证,包括后端生成验证码、前端展示以及通过session进行验证码校验的完整前后端代码和配置过程。
2267 0
验证码案例 —— Kaptcha 插件介绍 后端生成验证码,前端展示并进行session验证(带完整前后端源码)
|
JSON 前端开发 JavaScript
Vue微前端新探:iframe优雅升级,扬长避短,重获新生
Vue微前端新探:iframe优雅升级,扬长避短,重获新生
784 0

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
  • 10
    【面试题】20个常见的前端算法题,你全都会吗?
  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    512
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    191
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    189
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    145
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    251
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    359
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    157
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    95
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    161
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    225