马上掌握的LayUI树形权限菜单,助力你的权限管理!

news2024/10/5 14:55:15

目录

一、树形菜单的介绍

1、什么是树形菜单?

二、实现思路流程

三、实现步骤

1、查看数据

1)表数据

2) 最终效果

2、编程

1)实体类编写

2)PermissionDao编写(难点)

第一

 在线转json格式查看

第二

BuildTree解析

TreeVo

  在线转json格式查看

3)PermissionAction编写

4)xml配置文件

5)jsp界面


一、树形菜单的介绍

1、什么是树形菜单?

LayUI是一款基于jQuery的前端UI框架,而树形权限菜单是一种常见的网页导航菜单设计。LayUI树形权限菜单结合了LayUI框架的特性和树状结构的展示方式,用于实现对用户权限的管理和控制。

树形权限菜单通常由多层级的树状菜单构成,每个节点表示一个功能或者页面,父节点表示上级菜单,子节点表示下级菜单。通过这种层级结构,可以清晰地展示网站或系统的功能模块之间的关系

权限管理是指根据用户的角色或权限级别对不同的用户展示不同的菜单选项。在LayUI树形权限菜单中,可以根据用户的权限动态生成菜单,并且对菜单进行增删改操作。通过这种方式,可以灵活地控制不同用户所能访问的功能模块,提高系统的安全性和可用性。

总之,LayUI树形权限菜单是一种基于LayUI框架和树状结构设计的前端UI组件,用于实现网页导航菜单和权限管理

二、实现思路流程

实现LayUI树形权限菜单的思路流程可以分为以下几个步骤:

  1. 数据准备:首先,需要准备好菜单数据和用户权限数据。菜单数据包括菜单名称、菜单ID、父菜单ID等信息,用户权限数据包括用户ID和可访问的菜单ID列表等信息。这些数据可以从数据库或者后端接口获取。
  2. 数据处理:根据准备好的菜单数据和用户权限数据,进行数据处理和筛选。根据用户的权限列表,筛选出用户可以访问的菜单数据。
  3. 构建树形结构:使用LayUI提供的树形菜单组件,将筛选后的菜单数据构建成树形结构。树形结构可以通过递归的方式进行构建,每个节点包含菜单的名称、ID等信息,以及其子菜单节点。
  4. 动态渲染:将构建好的树形菜单结构动态渲染到页面上。使用LayUI提供的组件和模板引擎,将树形结构展示在页面上,并实现菜单的展开、折叠、跳转等功能。
  5. 权限控制:根据用户的权限列表,对菜单进行权限控制。对于用户无权限的菜单,可以进行隐藏或者禁用操作,以达到权限管理的目的。
  6. 事件处理:为菜单的点击事件绑定相应的处理函数。根据菜单的ID或其他标识符,处理菜单点击后的逻辑,例如跳转到对应的页面或执行相应的操作。

通过以上步骤,就可以实现LayUI树形权限菜单的设计与功能。需要注意的是,具体实现的细节和方式可能会根据项目需求和实际情况有所变化,上述流程提供了一个基本的思路和框架。

三、实现步骤

1、查看数据

1)表数据

我们查看数据库里面t_oa_permission表的数据,知道这是一个二级菜单

2) 最终效果

2、编程

根据前面的博客的步骤的配置,下面是我们树形菜单需要写的样子

1)实体类编写

package com.zking.entity;

/**
 * 树形实体类
 * 
 * @author tgq
 *
 */
public class Permission {
	private long id;
	private String name;
	private String description;
	private String url;
	private long pid;
	private int ismenu;// 控制当前系统的权限是菜单还是按钮
	private long displayno;// 排序

	public Permission() {
		// TODO Auto-generated constructor stub
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public long getPid() {
		return pid;
	}

	public void setPid(long pid) {
		this.pid = pid;
	}

	public int getIsmenu() {
		return ismenu;
	}

	public void setIsmenu(int ismenu) {
		this.ismenu = ismenu;
	}

	public long getDisplayno() {
		return displayno;
	}

	public void setDisplayno(long displayno) {
		this.displayno = displayno;
	}

	@Override
	public String toString() {
		return "Permission [id=" + id + ", name=" + name + ", description=" + description + ", url=" + url + ", pid="
				+ pid + ", ismenu=" + ismenu + ", displayno=" + displayno + "]";
	}

	public Permission(long id, String name, String description, String url, long pid, int ismenu, long displayno) {
		super();
		this.id = id;
		this.name = name;
		this.description = description;
		this.url = url;
		this.pid = pid;
		this.ismenu = ismenu;
		this.displayno = displayno;
	}

}

2)PermissionDao编写(难点)

我们需要继承BaseDao写两个dao方法,一个查询所有的,一个是讲平级数据转换为父级数据
用来作比较,难点和思路基本在这里

第一

package com.zking.dao;

import java.util.ArrayList;
import java.util.List;

import com.zking.entity.Permission;
import com.zking.util.BaseDao;
import com.zking.util.BuildTree;
import com.zking.util.PageBean;
import com.zking.util.TreeVo;
/**
 * dao方法
 * 
 * @author tgq
 *
 */
public class PermissionDao extends BaseDao<Permission> {

	/**
	 * 查询导所有的
	 * 
	 * @param permission
	 * @param pageBean
	 * @return
	 * @throws Exception
	 */
	public List<Permission> listPermission(Permission permission, PageBean pageBean) throws Exception {
		String sql = "select * from t_oa_Permission";
		return super.executeQuery(sql, Permission.class, pageBean);
	}

}

junit测试:

package com.zking.dao;

import java.util.List;

import org.junit.Test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zking.entity.Permission;
import com.zking.util.TreeVo;

/**
 * junit4测试
 * 
 * @author tgq
 *
 */
public class PermissionDaoTest {
	private PermissionDao permissionDao = new PermissionDao();

	@Test
	public void testListPermission() throws Exception {
		List<Permission> listPermission = permissionDao.listPermission(null, null);

		ObjectMapper om = new ObjectMapper();
		System.out.println(om.writeValueAsString(listPermission));

	}


}

 在线转json格式查看

我们可以看到并没有父级

第二

package com.zking.dao;

import java.util.ArrayList;
import java.util.List;

import com.zking.entity.Permission;
import com.zking.util.BaseDao;
import com.zking.util.BuildTree;
import com.zking.util.PageBean;
import com.zking.util.TreeVo;

/**
 * dao方法
 * 
 * @author tgq
 *
 */
public class PermissionDao extends BaseDao<Permission> {

	/**
	 * 查询导所有的
	 * 
	 * @param permission
	 * @param pageBean
	 * @return
	 * @throws Exception
	 */
	public List<Permission> listPermission(Permission permission, PageBean pageBean) throws Exception {
		String sql = "select * from t_oa_Permission";
		return super.executeQuery(sql, Permission.class, pageBean);
	}

	// 将数据库的平级数据,转换为父子关系数据
	public List<TreeVo<Permission>> menus(Permission permission, PageBean pageBean) throws Exception {

		List<TreeVo<Permission>> listtp = new ArrayList<>();
		List<Permission> list = this.listPermission(permission, pageBean);
		for (Permission p : list) {// 把我们的平级对象转换为父级关系
			TreeVo<Permission> tv = new TreeVo<>();
			tv.setId(p.getId() + "");
			tv.setText(p.getName());
			tv.setParentId(p.getPid() + "");
			listtp.add(tv);
		}
		// 这是我们还没有构建父子关系
		// return listtp;
		// 我们要做一个外层循环和一个内层循环
		return BuildTree.buildList(listtp, "-1");
	}

}

我们可以看到后面有这个代码

        // 这是我们还没有构建父子关系
		// return listtp;
		// 我们要做一个外层循环和一个内层循环
		return BuildTree.buildList(listtp, "-1");

如果返回的是第一个还是没有父级的所以我们要做一个外层循环和一个内层循环

如果有三级菜单的话可以添加一个

public TreeVo<Permission> menu(Permission permission, PageBean pageBean) throws Exception {
		List<TreeVo<Permission>> trees = new ArrayList<TreeVo<Permission>>();
		List<Permission> list = this.listPermission(permission, pageBean);
		for (Permission p : list) {
			TreeVo<Permission> vo = new TreeVo<>();
			vo.setId(p.getId() + "");
			vo.setText(p.getName());// 节点名称
			vo.setParentId(p.getPid() + "");
			vo.setChildren(menus(null, null));// 将分好的二级节点和三级节点加到顶级节点里
			trees.add(vo);
		}
		return BuildTree.build(trees);
	}

BuildTree解析

BuildTree在我们的util包里面,里面有两个方法,一个build,一个buildList。

而我们的外层循环和内层循环在我们的buildList里面,方法里面我打了注释可以看这里就不解说了。

package com.zking.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BuildTree {

	/**
	 * 默认-1为顶级节点
	 * 
	 * @param nodes
	 * @param <T>
	 * @return
	 */
	public static <T> TreeVo<T> build(List<TreeVo<T>> nodes) {

		if (nodes == null) {
			return null;
		}
		List<TreeVo<T>> topNodes = new ArrayList<TreeVo<T>>();

		for (TreeVo<T> children : nodes) {
			String pid = children.getParentId();
			if (pid == null || "-1".equals(pid)) {
				topNodes.add(children);

				continue;
			}

			for (TreeVo<T> parent : nodes) {
				String id = parent.getId();
				if (id != null && id.equals(pid)) {
					parent.getChildren().add(children);
					children.setHasParent(true);
					parent.setChildren(true);
					continue;
				}
			}

		}

		TreeVo<T> root = new TreeVo<T>();
		if (topNodes.size() == 1) {
			root = topNodes.get(0);
		} else {
			root.setId("000");
			root.setParentId("-1");
			root.setHasParent(false);
			root.setChildren(true);
			root.setChecked(true);
			root.setChildren(topNodes);
			root.setText("顶级节点");
			Map<String, Object> state = new HashMap<>(16);
			state.put("opened", true);
			root.setState(state);
		}

		return root;
	}

	/**
	 * 指定idparam为顶级节点
	 * 
	 * @param nodes
	 * @param idParam
	 * @param <T>
	 * @return
	 */
	public static <T> List<TreeVo<T>> buildList(List<TreeVo<T>> nodes, String idParam) {
		if (nodes == null) {
			return null;
		}
		List<TreeVo<T>> topNodes = new ArrayList<TreeVo<T>>();

		// 外循环
		for (TreeVo<T> children : nodes) {
			// 外层循环的副id
			String pid = children.getParentId();
			if (pid == null || idParam.equals(pid)) {
				topNodes.add(children);

				continue;
			}
			// 内循环
			for (TreeVo<T> parent : nodes) {
				String id = parent.getId();
				// 外层循环的id和内层循环的id做比较
				if (id != null && id.equals(pid)) {
					parent.getChildren().add(children);
					children.setHasParent(true);
					parent.setChildren(true);

					continue;
				}
			}

		}
		return topNodes;
	}

}
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();
	}

}

junit测试:

package com.zking.dao;

import java.util.List;

import org.junit.Test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zking.entity.Permission;
import com.zking.util.TreeVo;

/**
 * junit4测试
 * 
 * @author tgq
 *
 */
public class PermissionDaoTest {
	private PermissionDao permissionDao = new PermissionDao();

	@Test
	public void testListPermission() throws Exception {
		List<Permission> listPermission = permissionDao.listPermission(null, null);

		ObjectMapper om = new ObjectMapper();
		System.out.println(om.writeValueAsString(listPermission));

	}

	@Test
	public void menus() throws Exception {
		List<TreeVo<Permission>> menus = permissionDao.menus(null, null);

		ObjectMapper om = new ObjectMapper();
		System.out.println(om.writeValueAsString(menus));

	}

}

  在线转json格式查看

这个方法后我们可以看到以及对好了,有父级

3)PermissionAction编写

我们要继承和实现两个类,继承ActionSupport,实现ModelDriver<Permission>

package com.zking.web;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zking.dao.PermissionDao;
import com.zking.entity.Permission;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.ResponseUtil;
import com.zking.util.TreeVo;

public class PermissionAction extends ActionSupport implements ModelDriver<Permission> {
	private Permission permission = new Permission();
	private PermissionDao permissionDao = new PermissionDao();

	
	
	public void menus(HttpServletRequest req, HttpServletResponse resp) throws Exception {

		List<TreeVo<Permission>> menus = permissionDao.menus(null, null);
		ResponseUtil.writeJson(resp, menus);
	}
	
	
	@Override
	public Permission getModel() {
		
		return permission;
	}

}

4)xml配置文件

记得在我们的mvc.xml里面进行一个配置

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<action path="/blog" type="com.zking.web.BlogAction">
		<forward name="list" path="/blogList.jsp" redirect="false" />
		<forward name="toList" path="/blog.action?methodName=list"
			redirect="true" />
		<forward name="toEdit" path="/blogEdit.jsp" redirect="false" />
	</action>
	<action path="/userAction" type="com.zking.web.UserAction">

	</action>

	<action path="/tree" type="com.zking.web.PermissionAction">

	</action>

</config>

5)jsp界面

<%@ 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>
<%@include file="/common/header.jsp"%>
</head>
<body>
<div class="layui-layout layui-layout-admin">
  <div class="layui-header">
    <div class="layui-logo layui-hide-xs layui-bg-black">layout demo</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="//tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg" class="layui-nav-img">
          tester
        </a>
        <dl class="layui-nav-child">
          <dd><a href="">Your Profile</a></dd>
          <dd><a href="">Settings</a></dd>
          <dd><a href="login.jsp">Sign out</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">
      
     <<li class="layui-nav-item layui-nav-itemed">
          <a class="" href="javascript:;">menu group 1</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">menu 1</a></dd>
            <dd><a href="javascript:;">menu 2</a></dd>
            <dd><a href="javascript:;">menu 3</a></dd>
            <dd><a href="">the links</a></dd>
          </dl>
        </li>
        
     <li class="layui-nav-item">
          <a href="javascript:;">menu group 2</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">list 1</a></dd>
            <dd><a href="javascript:;">list 2</a></dd>
            <dd><a href="">超链接</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item"><a href="javascript:;">click menu item</a></li>
        <li class="layui-nav-item"><a href="">the links</a></li>
        
      </ul>
    </div>
  </div>
  
  <div class="layui-body">
    <!-- 内容主体区域 -->
    <div style="padding: 15px;">内容主体区域。记得修改 layui.css 和 js 的路径</div>
  </div>
  
  <div class="layui-footer">
    <!-- 底部固定区域 -->
            底部固定区域
  </div>
</div>
</body>
</html>

jsp界面效果

 我们用scriptLayui编写

<%@ 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>
<%@include file="/common/header.jsp"%>
</head>
<body>
<div class="layui-layout layui-layout-admin">
  <div class="layui-header">
    <div class="layui-logo layui-hide-xs layui-bg-black">layout demo</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="//tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg" class="layui-nav-img">
          tester
        </a>
        <dl class="layui-nav-child">
          <dd><a href="">Your Profile</a></dd>
          <dd><a href="">Settings</a></dd>
          <dd><a href="login.jsp">Sign out</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">
      
     <!--  <li class="layui-nav-item layui-nav-itemed">
          <a class="" href="javascript:;">menu group 1</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">menu 1</a></dd>
            <dd><a href="javascript:;">menu 2</a></dd>
            <dd><a href="javascript:;">menu 3</a></dd>
            <dd><a href="">the links</a></dd>
          </dl>
        </li>  -->
        
      <!--   <li class="layui-nav-item">
          <a href="javascript:;">menu group 2</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">list 1</a></dd>
            <dd><a href="javascript:;">list 2</a></dd>
            <dd><a href="">超链接</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item"><a href="javascript:;">click menu item</a></li>
        <li class="layui-nav-item"><a href="">the links</a></li>
         -->
        
      </ul>
    </div>
  </div>
  
  <div class="layui-body">
    <!-- 内容主体区域 -->
    <div style="padding: 15px;">内容主体区域。记得修改 layui.css 和 js 的路径</div>
  </div>
  
  <div class="layui-footer">
    <!-- 底部固定区域 -->
            底部固定区域
  </div>
</div>
<script>
//JS 
layui.use(['element', 'layer', 'util'], function(){
  var element = layui.element
  ,layer = layui.layer
  ,util = layui.util
  ,$ = layui.$;
 
  $.ajax({
		url : '${pageContext.request.contextPath }/tree.action?methodName=menus',
		method : 'post',
		dataType : 'json',
		success : function(data) {
			console.log(data);
			var htmlTree="";
			$.each(data,function(index,node){
				htmlTree+='<li class="layui-nav-item layui-nav-itemed">';
				
				htmlTree+='<a href="javascript:;">'+node.text+'</a>';
				
				if (node.hasChildren) {
					var children=node.children;
					htmlTree+='<dl class="layui-nav-child">';
					$.each(children,function(i,n){
						
						htmlTree+='<dd><a href="javascript:;">'+n.text+'</a></dd>';
						
					});
					htmlTree+='</dl>';
				}
				
				htmlTree+='</li>';
			});
			
			$("#menu").html(htmlTree);
			/* 进行渲染 */
			element.render('menu');
				} 
			});
  
});
</script>
</body>
</html>

在最后我们需要添加一个方法进行一个渲染,不然有的时候运行并不会出现还会是原来的一个布局和树形菜单

/* 进行渲染 */
element.render('menu');

我们可以看到如果我把渲染关闭,并没有收回的一个

 如果我们渲染加上就会有一个收回

我的分享就在这里,也有相应的文件,这是一个比较通用的方法,并不是全通用。

希望对你们有些帮助!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/744197.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue+springboot基于Web的电子产品销售系统设计与实现 gqon2a

随着人们生活水平的高速发展&#xff0c;电子产品销售方面在近年来呈直线上升&#xff0c;人们也了解到电子产品的实用性&#xff0c;因此电子产品的销售数量也逐年递增&#xff0c;电子产品销售的增加加大了在管理上的工作难度。为了能更好的维护电子产品销售管理秩序&#xf…

Grafana 图形面板定制方案

Grafana 在一个 Panel 中添加多数据源同时展示以及修改通过 transform 修改图表图例的方式。 多个数据在一个折线图中 在 Grafana 中我们可能会希望多个数据在一个Panel 中展示&#xff0c;比如&#xff1a; 通过编辑 Panel 增加 Query 数据我们即可做到&#xff1a;像上面中…

SQL数据库连接类型与常用函数

目录 1. 创建表插入数据 2. 连接类型 2.1 内连接 2.2 外连接 2.2.1 左外连接 2.2.2 右外连接 2.3 交叉连接 2.4 子查询&公用表达式 2.5 UNION连接 3. SQL常用函数 3.1 CASE WHEN函数 3.2 COALESCE函数 3.3 NULLIF函数 3.4 LEAST 和 GREATEST函数 3.5 DISTINCT…

LayUi之树形结构的详解(附有全案例代码)

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于LayUi的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一. 什么是树形结构 二.树形结构在什么时…

表格编程之争:Python VS VBA?Excel用户:新编程语言才真香

Python和VBA哪个更好用&#xff1f; Python和VBA是两种不同的编程语言&#xff0c;它们都有自己的特点和优缺点。在表格编程方面&#xff0c;VBA在Excel中的应用非常广泛&#xff0c;可以通过宏来实现自动化操作和数据处理&#xff0c;也可以通过VBA代码来实现自定义函数和界面…

python qt安装软件包

安装 opencv pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple/ 安装pyqt5 pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple/ 安装pyqt5-tools pip install pyqt5-tools -i https://pypi.tuna.tsinghua.edu.cn/simple/

RLHF-基于人类反馈的强化学习

RLHF 文章目录 RLHF强化学习基础回顾为什么要使用基于人类反馈的强化学习大纲RLHF的起源大预言模型中的RLHF案例 ChatGPT RLHF中的技术细节预训练语言模型训练奖励模型基于RL进行微调 RLHF 的未来 强化学习基础回顾 智能体通过采取行动与环境进行交互&#xff0c;并返回状态和奖…

【C语言督学营 第十八天】考研408排序大题初探(将排序思想融入题目)

文章目录 题目一分析代码实战 题目二分析代码实战 补充(快排与归并)数据结构大题注意点&#xff01;&#xff01;&#xff01;(评分标准) 题目一 分析 (1&#xff09;算法的基本设计思想 由题意知&#xff0c;将最小的nl2个元素放在Ai中&#xff0c;其余的元素放在A2中&#x…

FreeRTOS实时操作系统(十三)任务通知

系列文章目录 文章目录 系列文章目录任务通知任务通知值和通知状态任务通知值通知状态 任务通知API函数发送通知函数接收通知函数 实验测试模拟二值信号量实验模拟计数型信号量模拟事件标志组实验模拟消息邮箱实验 任务通知 任务通知&#xff1a;用来通知任务的&#xff0c;任…

ATMEGA16 Proteus仿真自动人体感应电风扇DS18B20温度 -0069

ATMEGA16 Proteus仿真自动人体感应电风扇DS18B20温度 -0069 Proteus仿真小实验&#xff1a; ATMEGA16 Proteus仿真自动人体感应电风扇DS18B20温度 -0069 功能&#xff1a; Protues版本&#xff1a;7.8 程序编写&#xff1a;ICCAVR:7.12 硬件组成&#xff1a;ATMEGA16单片机…

嵌入式开发之编码器速度采集

光电编码器&#xff0c;是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。这是应用最多的传感器&#xff0c;光电编码器是由光源、光码盘和光敏元件组成。光栅盘是在一定直径的圆板上等分地开通若干个长方形孔。由于光电码盘与电动机同轴&#xff0c;…

spark和zeppelin认证不一致:Only one of --proxy-user or --principal can be provided

spark和zeppelin认证不一致&#xff1a;Only one of --proxy-user or --principal can be provided 如果配置principal认证方式&#xff0c;zeppelin走的是hadoop权限&#xff0c;如果配置proxy-user认证方式&#xff0c;zeppelin走的是当前登录用户的权限&#xff08;ranger控…

GitHub上cambel的ur3项目调试经验

按照https://github.com/cambel/ur3/wiki/Compile-from-source配置环境时&#xff0c;遇到以下问题&#xff1a; catkin clean时报错 [clean] Error: The current or desired workspace could not be determined. Please run catkin clean from within a catkin workspace or…

【学会动态规划】第 N 个泰波那契数(1)

目录 动态规划怎么学&#xff1f; 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 4. 空间优化 写在最后 动态规划怎么学&#xff1f; 学习一个算法没有捷径&#xff0c;更何况是学习动态规划&#xff0c; 跟…

MySQL 中索引是如何实现的,有哪些类型的索引,如何进行优化索引

MySQL 中的索引 前言 上篇文章聊完了 MySQL 中的锁&#xff0c;这里接着来看下 MySQL 中的索引。 一般当我们数据库中的某些查询比较慢的时候&#xff0c;正常情况下&#xff0c;一顿分析下来&#xff0c;大多数我们会考虑对这个查询加个索引&#xff0c;那么索引是如何工作的呢…

从零开始的前后端分离项目学习(前后端从零环境搭建)

一、 前后端分离介绍&#xff1a; 前端独立编写客户端代码&#xff08;用户交互数据展示&#xff09;&#xff0c;后端独立编写服务端代码&#xff08;提供数据处理接口&#xff09;&#xff0c;并提供数据接口就行。 前端通过Ajax访问后端数据借口&#xff0c;将model展示到…

使用VESD脉冲离子风机5年内至少可节省一半的维护成本

之前的文章有给大家详细介绍过&#xff0c;来自VESD的脉冲离子风机&#xff0c;它有着特殊的设计&#xff1a;插拔式结构和可水洗针架&#xff0c;因此对我们的很多客户来说&#xff0c;这款风机性价比是非常高的。 早在15年以前&#xff0c;VESD就对市面上大部分风机进行过测试…

解决Google浏览器网页覆盖问题

在使用 Google 进行搜索的时候出现打开新页面会覆盖当前页面的问题 针对此问题&#xff0c;解决方法如下&#xff1a; 1、首先在浏览器的地址栏中随便搜索内容 2、页面的 右上角有个⚙️的设置图标&#xff0c;点进去 点击 “查看所有设置” 3、在结果打开方式中进行勾选 设…

uniapp打包APP实现应用内整包更新或热更新

思路&#xff1a; 1.首先要理解更新方式的区别 静默更新、弱更新以及强制更新。 APP更新机制-静默更新、弱更新、强更新 - 知乎 2.其次要理解不同更新方式要用到的插件----------这里推荐插件应用市场的插件。 app升级、整包更新和热更新组件 支持vue3 支持打开安卓、苹果应…

使用 SMT求解机 根据变迁关系生成迁移后系统的状态

本文的例子来源于2011年发布的论文 IC3: Where Monolithic and Incremental Meet 文章目录 Ⅰ、变迁系统的介绍状态图变迁公式 Ⅱ、SMT求解机简介公式的计算计算另一状态 结果展示参考文献 Ⅰ、变迁系统的介绍 状态图 论文中给出了一个系统的状态迁移图和它的的变迁公式。现在…