前端框架Layui实现动态树效果(书籍管理系统左侧下拉列表)

news2024/11/25 11:55:06

目录

一、前言

1.什么是树形菜单

2.树形菜单的使用场景

二、案例实现

1.需求分析

2.前期准备工作

①导入依赖

②工具类

BaseDao(通用增删改查)

BuildTree(完成平级数据到父子级的转换)

ResponseUtil(将数据转换成json格式进行回显)

③编写实体

3.dao层编写

4.servlet层编写

5.jsp页面搭建

6.案例演示


一、前言

在完成案例之前我们先来了解一下什么是树形菜单

1.什么是树形菜单

        树形菜单是一种用户界面设计模式,常用于组织和展示大量信息的层次结构。它的名称来自于菜单呈现的结构类似于树的分支和节点。树形菜单通常由主节点和多个子节点组成,每个子节点可以有自己的子节点,形成了父子关系的层级结构

        在树形菜单中,主节点代表顶级选项或类别,而子节点代表与主节点相关联的具体选项或子类别。用户可以通过展开或折叠子节点来浏览更详细的层级。通常,叶子节点是最底层的节点,表示最具体的选项或内容。

        树形菜单适用于需要组织和展示复杂数据或多级目录的应用程序和网站。它们使用户可以方便地导航和选择所需的选项,提供了一种简洁而直观的方式来浏览和访问信息。

2.树形菜单的使用场景

树形菜单在各种应用和网站中被广泛使用,以下是一些常见的使用场景:

  • 1. 文件资源管理:树形菜单可用于浏览和管理文件资源,特别是当文件被组织成多级目录结构时。用户可以展开和折叠目录以访问所需的文件或文件夹。
  • 2. 组织结构和人员管理:企业或组织的组织结构可以通过树形菜单进行可视化展示。每个节点代表一个部门、团队或个人,用户可以通过展开节点查看更详细的层级和信息。
  • 3. 导航菜单:网站或应用程序的主要导航菜单常常使用树形结构,以显示不同的页面或功能选项。用户可以根据需要展开或折叠菜单项,快速定位所需的功能或内容。
  • 4. 产品分类和目录导航:在线商店或电子商务网站通常使用树形菜单来组织产品分类和目录。用户可以通过展开和折叠不同的类别来浏览和选择产品。
  • 5. 内容管理系统:树形菜单在内容管理系统中被广泛使用,用于组织和管理网站的页面、文章、类别和标签等内容。

总而言之,树形菜单适用于任何需要展示和组织层次结构数据的场景,以提供清晰且易于导航的用户界面。

二、案例实现

1.需求分析

我们要完成一个书籍管理系统的左侧列表展示,必不可少的就是表的设计,表设计关乎到我们jsp页面的展示,下面是我的表设计仅供大家参考

表设计有了数据也必不可少,当然表数据也不要随便编写,不然可能会出错哦!!

        这里的数据都是有讲究的,我们平常通过dao层拿到的数据都是平级数据,并不符合我们的要求,我们所需要的是有父子级别的数据,那么怎么从平级数据转换成我们的父子级数据呢?? 这时候我们的表设计就起到了至关重要的作用,我们可以看到父级节点的pid都是0,而他们的子节点的pid对应的都是父级节点的id。

        得出结论我们只需要两个方法,一个查询全部的方法(拿到平级数据),另一个将平级数据进行两次for遍历加到新集合(父子级容器)的方法,第一次for将pid编号是顶级节点也就是父节点的数据加入容器中,第二次遍历将pid与新集合里面的id做比较,如果相同那就是新集合里的children。

 

2.前期准备工作

注意:更多细节在我所编写的自定义MVC三部曲中。

①导入依赖

将我们所需的依赖导入到WebContent➡WEB-INF下

创建一个存放js/css的目录将所需文件放入

将多个页面共用的文件封装成公共文件

<%@ 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>


</head>

</html>

②工具类

这里我们需要用到工具类

BaseDao(通用增删改查)

package com.zking.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 所有Dao层的父类 BookDao UserDao OrderDao ...
 * 
 * @author Administrator
 *
 * @param <T>
 */
public class BaseDao<T> {

	/**
	 * 适合多表联查的数据返回
	 * @param sql
	 * @param pageBean
	 * @return
	 * @throws SQLException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public List<Map<String, Object>> executeQuery(String sql, PageBean pageBean)
			throws SQLException, InstantiationException, IllegalAccessException {

		List<Map<String, Object>> list = new ArrayList<>();
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = null;
		ResultSet rs = null;

		/*
		 * 是否需要分页? 无需分页(项目中的下拉框,查询条件教员下拉框,无须分页) 必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
		 */
		if (pageBean != null && pageBean.isPagination()) {
			// 必须分页(列表需求)
			String countSQL = getCountSQL(sql);
			pst = con.prepareStatement(countSQL);
			rs = pst.executeQuery();
			if (rs.next()) {
				pageBean.setTotal(String.valueOf(rs.getObject(1)));
			}

			// 挪动到下面,是因为最后才处理返回的结果集
			// -- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'
			// -- pageSql=sql limit (page-1)*rows,rows 对应某一页的数据
			// -- countSql=select count(1) from (sql) t 符合条件的总记录数
			String pageSQL = getPageSQL(sql, pageBean);// 符合条件的某一页数据
			pst = con.prepareStatement(pageSQL);
			rs = pst.executeQuery();
		} else {
			// 不分页(select需求)
			pst = con.prepareStatement(sql);// 符合条件的所有数据
			rs = pst.executeQuery();
		}

		// 获取源数据
		ResultSetMetaData md = rs.getMetaData();
		int count = md.getColumnCount();
		Map<String, Object> map = null;
		while (rs.next()) {
			map = new HashMap<>();
			for (int i = 1; i <= count; i++) {
//				map.put(md.getColumnName(i), rs.getObject(i));
				map.put(md.getColumnLabel(i), rs.getObject(i));
			}
			list.add(map);
		}
		return list;

	}

	/**
	 * 
	 * @param sql
	 * @param attrs
	 *            map中的key
	 * @param paMap
	 *            jsp向后台传递的参数集合
	 * @return
	 * @throws SQLException
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public int executeUpdate(String sql, String[] attrs, Map<String, String[]> paMap) throws SQLException,
			NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = con.prepareStatement(sql);
		for (int i = 0; i < attrs.length; i++) {
			pst.setObject(i + 1, JsonUtils.getParamVal(paMap, attrs[i]));
		}
		return pst.executeUpdate();
	}

	/**
	 * 批处理
	 * @param sqlLst
	 * @return
	 */
	public static int executeUpdateBatch(String[] sqlLst) {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			conn = DBAccess.getConnection();
			// 设置不自动提交
			conn.setAutoCommit(false);
			for (String sql : sqlLst) {
				stmt = conn.prepareStatement(sql);
				stmt.executeUpdate();
			}
			conn.commit();
		} catch (Exception e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
				throw new RuntimeException(e1);
			}
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			DBAccess.close(conn, stmt, null);
		}
		return sqlLst.length;
	}

	/**
	 * 通用的增删改方法
	 * 
	 * @param book
	 * @throws Exception
	 */
	public int executeUpdate(String sql, T t, String[] attrs) throws Exception {
		// String[] attrs = new String[] {"bid", "bname", "price"};
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = con.prepareStatement(sql);
		// pst.setObject(1, book.getBid());
		// pst.setObject(2, book.getBname());
		// pst.setObject(3, book.getPrice());
		/*
		 * 思路: 1.从传进来的t中读取属性值 2.往预定义对象中设置了值
		 * 
		 * t->book f->bid
		 */
		for (int i = 0; i < attrs.length; i++) {
			Field f = t.getClass().getDeclaredField(attrs[i]);
			f.setAccessible(true);
			pst.setObject(i + 1, f.get(t));
		}
		return pst.executeUpdate();
	}

	/**
	 * 通用分页查询
	 * 
	 * @param sql
	 * @param clz
	 * @return
	 * @throws Exception
	 */
	public List<T> executeQuery(String sql, Class<T> clz, PageBean pageBean) throws Exception {
		List<T> list = new ArrayList<T>();
		Connection con = DBAccess.getConnection();
		;
		PreparedStatement pst = null;
		ResultSet rs = null;

		/*
		 * 是否需要分页? 无需分页(项目中的下拉框,查询条件教员下拉框,无须分页) 必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
		 */
		if (pageBean != null && pageBean.isPagination()) {
			// 必须分页(列表需求)
			String countSQL = getCountSQL(sql);
			pst = con.prepareStatement(countSQL);
			rs = pst.executeQuery();
			if (rs.next()) {
				pageBean.setTotal(String.valueOf(rs.getObject(1)));
			}

			// 挪动到下面,是因为最后才处理返回的结果集
			// -- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'
			// -- pageSql=sql limit (page-1)*rows,rows 对应某一页的数据
			// -- countSql=select count(1) from (sql) t 符合条件的总记录数
			String pageSQL = getPageSQL(sql, pageBean);// 符合条件的某一页数据
			pst = con.prepareStatement(pageSQL);
			rs = pst.executeQuery();
		} else {
			// 不分页(select需求)
			pst = con.prepareStatement(sql);// 符合条件的所有数据
			rs = pst.executeQuery();
		}

		while (rs.next()) {
			T t = clz.newInstance();
			Field[] fields = clz.getDeclaredFields();
			for (Field f : fields) {
				f.setAccessible(true);
				f.set(t, rs.getObject(f.getName()));
			}
			list.add(t);
		}
		return list;
	}

	/**
	 * 将原生SQL转换成符合条件的总记录数countSQL
	 * 
	 * @param sql
	 * @return
	 */
	private String getCountSQL(String sql) {
		// -- countSql=select count(1) from (sql) t 符合条件的总记录数
		return "select count(1) from (" + sql + ") t";
	}

	/**
	 * 将原生SQL转换成pageSQL
	 * 
	 * @param sql
	 * @param pageBean
	 * @return
	 */
	private String getPageSQL(String sql, PageBean pageBean) {
		// (this.page - 1) * this.rows
		// pageSql=sql limit (page-1)*rows,rows
		return sql + " limit " + pageBean.getStartIndex() + "," + pageBean.getRows();
	}
}

BuildTree(完成平级数据到父子级的转换)

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

			String pid = children.getParentId();
			if (pid == null || idParam.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;
				}
			}

		}
		return topNodes;
	}

}

ResponseUtil(将数据转换成json格式进行回显)

package com.zking.util;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;

import com.fasterxml.jackson.databind.ObjectMapper;

public class ResponseUtil {

	public static void write(HttpServletResponse response,Object o)throws Exception{
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out=response.getWriter();
		out.println(o.toString());
		out.flush();
		out.close();
	}
	
	public static void writeJson(HttpServletResponse response,Object o)throws Exception{
		ObjectMapper om = new ObjectMapper();
//		om.writeValueAsString(o)代表了json串
		write(response, om.writeValueAsString(o));
	}
}

③编写实体

Permission(数据表实体)

package com.xw.entity;

/**书籍管理系统实体
 * @author 索隆
 *
 */
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 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;
}

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 + "]";
}



}

注意:mysql里面的类型bigint在java中是long类型

3.dao层编写

​
package com.xw.dao;

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

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_easyui_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()+"");
			vo.setParentId(permission.getPid()+"");
			vo.setText(permission.getName());
			menu.add(vo);
		}
		
		//通过工具类筛选父级菜单的儿子,pid为0是父级菜单
		return BuildTree.buildList(menu, "0");
	}
	
	
	
	public static void main(String[] args) throws Exception {
		//测试数据
		PermissionDao d=new PermissionDao();
	 List<TreeVo<Permission>> menu = d.menu();
	 ObjectMapper om =new ObjectMapper();
	 System.out.println(om.writeValueAsString(menu));
		
		
	}
}

​

我们可以进行对比两组数据的不同之处:

  • 平级数据
  • 父子级数据

4.servlet层编写

package com.xw.web;

import java.util.List;

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

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

/**书籍管理的servlet处理
 * @author 索隆
 *
 */
public class PermissionAction extends ActionSupport implements ModelDriver<Permission>{
	private Permission Permission=new Permission();
	private PermissionDao pdao=new PermissionDao();
	
	/**初始化书籍管理系统的动态树
	 * @param req
	 * @param resp
	 * @throws Exception
	 */
	public void listmenu(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		//查询父子级数据
		List<TreeVo<Permission>> menu = pdao.menu();
		//将集合转换成json格式进行回显
		ResponseUtil.writeJson(resp, menu);
	}

	@Override
	public Permission getModel() {
		return Permission;
	}

}

编写完servlet别忘记编写配置文件

<?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="/user" type="com.xw.web.Useraction">
	</action>

	<!-- 书籍管理——树 -->
	<action path="/Permission" type="com.xw.web.PermissionAction">
	</action>





</config>

5.jsp页面搭建

这时候我们就可以去在线Layui网站找一个满意的jsp页面了

Layui 开发使用文档 - 入门指南

<%@ 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">书籍管理系统</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}/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:;">'+node.text+'</a></dd>';
  		  			})
  		  				str+='</dl>';
  				}
  				
  				str+='</li>';
  				
  			})
  			//将拼接内容追加到指定ul标签
  			$("#menu").html(str);
  			
  			element.render('menu');
  			
  		}
  	})
  
  
});
</script>
</body>
</html>

小贴士:

 element.render()的用处:

假设你正在使用某个具体的前端框架或库,其中的`element`是对应的组件或对象,调用`render()`方法。一般而言,`render()`方法用于将组件或元素渲染到网页中的具体位置。具体作用如下:

  • 1. 渲染组件:`render()`方法用于将特定的组件渲染到页面上。它会将组件的内容和样式解析生成对应的 HTML 结构,并使其在浏览器中可见。
  • 2. 更新页面:如果已经存在该组件或元素并在页面上显示,再次调用`render()`可以触发页面的更新。这在需要根据数据的变化进行页面更新时很有用。
  • 3. 绑定事件:在渲染组件时,`render()`方法通常会将组件的事件绑定到相应的 DOM 元素上。这样可以确保用户与组件进行交互时,组件能够响应相应的操作。
  • 需要注意的是,`render()`方法的具体实现和用法取决于所使用的前端框架或库,可能会有额外的参数和选项。要确切了解`render()`方法的作用,请参考相应框架或库的文档和使用指南。

6.案例演示

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

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

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

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

相关文章

能“出汗”,会“呼吸”的户外行走机器人

美国亚利桑那州立大学(ASU)科学家研制出了世界上第一个能像人类一样出汗、颤抖和呼吸的户外行走机器人模型。这个机器人名叫ANDI&#xff0c;是一个能模仿人类出汗的热敏“热模型”。 ANDI 身上不仅有可以使它行走的关节&#xff0c;还有其他机器人身上都没有的东西——它浑身…

高并发的哲学原理(一)-- 找出单点,进行拆分

人列计算机 《三体》中&#xff0c;刘慈欣设计了一个用人进行二进制运算的计算机&#xff0c;使用了三千万名士兵(晶体管)&#xff1a; 计算机名&#xff1a;秦一号 CPU&#xff1a;秦始皇最精锐的五个军团 挥舞旗帜进行二进制运算 用三个士兵来组成与门、或门、与非门、或非门…

Python批量实现word中查找关键字

一、背景 在日常办公和文档处理中&#xff0c;我们常常需要在大量的Word文档中查找特定的关键字&#xff0c;然后进行接下来的操作&#xff0c;比如关键字替换等。手动逐个打开并搜索文档显然是费时费力的。因此&#xff0c;利用Python编写一个批量实现Word中查找关键字的程序可…

18、气象学中风场的绘制

文章目录 前言一、批量读取数据二、绘制2022年的平均风场三、绘制每个季节的平均风场四、绘制每个月的风场 前言 数据及代码下载链接➡️&#xff1a;如何绘制自定义颜色的风场图 一、批量读取数据 import os import xarray as xrfolder_path "./" file_pattern …

22、ThreadLocal的原理和使用场景

ThreadLocal的原理 每一个thread对象均含有一个ThreadLocalMap类型的成员变量threadLocals&#xff0c;它存储本线程中所有 ThreadLocal对象及其对应的值 ThreadLocalMap 由一个个Entry对象构成 Entry继承自WeakReference<ThreadLocal<?>>&#xff0c;一个Entry…

Qt6 绘制矩形和一些字符串函数讲解

Qt6 绘制矩形和一些字符串函数讲解 【1】Qt 6 模拟C的cout输出QTextStream类简介举例 &#xff08;标准输出&#xff09; 【2】Qt 6 绘制移动的矩形事件运行效果UI界面头文件.h源文件.cpp 【1】Qt 6 模拟C的cout输出 只教方法&#xff0c;更多内容请学习官方文档 QTextStream…

使用FreeMarker自定义生成word文档

使用FreeMarker自定义生成word文档 最终生成word文档如下&#xff1a; 实现思路&#xff1a; 按照要生成的文档模板格式&#xff0c;创建一个新的word&#xff08;doc&#xff09;文档&#xff0c;将其调整成所需格式&#xff0c;然后处理其中需要动态填充的数据&#xff0…

stable diffusion如何确保每张图的面部一致?

可以使用roop插件&#xff0c;确定好脸部图片后&#xff0c;使用roop固定&#xff0c; 然后生成的所有图片都使用同一张脸。 这款插件的功能简单粗暴&#xff1a;一键换脸。 如图所示&#xff1a; 任意上传一张脸部清晰的图片&#xff0c;点击启用。 在其他提示词不变的情况下…

LoRA: 大模型快速训练的秘诀

本文是四两拨千斤&#xff0c;训练大模型的PEFT方法的最后一小节&#xff0c;感兴趣读者可以阅读完整版。 LoRA LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS 核心思路是对模型参数做低秩分解&#xff0c;仅训练分解后的参数&#xff0c;模型部署也需额外保存低秩参数&…

SIP业务之BLF

BLF&#xff08;Busy Lamp Field&#xff09;是SIP应用中的一项重要业务&#xff0c;用来监视目标号码的状态&#xff0c;常用于调度、坐席监控等场景。 一、 BLF原理 BLF功能需要IP终端或话机与SIP服务器协同实现的&#xff0c;主要流程如下&#xff1a; IP话机向SIP服务器发…

如何使用 ChatGP在TTPU(张量处理单元)上训练模型的指令

推荐&#xff1a;将NSDT场景编辑器加入你的3D工具链 3D工具集&#xff1a;NSDT简石数字孪生. ChatGPT 作为您的专家助手 ChatGPT 可以帮助我们学习新的编程语言、课程、技术和技能。它已成为许多寻求改进工作流程或学习新事物的专业人士的首选工具。ChatGPT 专家助手提示可以减…

IntelliJ IDEA安装教程

一、下载安装包 首先进入IDEA官网下载2021.2.1版本的安装包&#xff0c;不要问我为什么不下最新版&#xff0c;后面我会说。 二、安装与配置 打开安装包&#xff0c;安装完成后选择Evaluate for free&#xff08;免费试用&#xff09;&#xff0c;创建一个项目&#xff0c;进入…

基于单片机空气质量检测二氧化碳 一氧化碳温湿度PM2.5检测系统的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;对空气空气中有毒有害气体进行监测&#xff1b;使用LCD1602液晶显示&#xff0c;采集到的PM2.5值通过单片机串口传输&#xff1b;通过传感器对室内PM2.5粉尘进行检查&#xff1b;通过按键设置的上限值&#xff1b;当检测到有毒气体…

5.2 基于ROP漏洞挖掘与利用

通常情况下栈溢出可能造成的后果有两种&#xff0c;一类是本地提权另一类则是远程执行任意命令&#xff0c;通常C/C并没有提供智能化检查用户输入是否合法的功能&#xff0c;同时程序编写人员在编写代码时也很难始终检查栈是否会发生溢出&#xff0c;这就给恶意代码的溢出提供了…

网络ping丢包什么原因(附解决方案)

​  数据包丢失是一种网络问题&#xff0c;当通过网络(或设备之间或通过 Internet)传输的数据包在传输过程中丢失或丢弃并且无法到达目的地时&#xff0c;就会发生这种情况。简单来说&#xff0c;数据包丢失是指数据包无法通过互联网从发送者成功传输到接收者。 如何检测数据…

阿里云RockMQ与SpringBoot的整合

前言&#xff1a; 开源版本Rocket和商业版本的RocketMQ有些不同&#xff0c;研究的是商业版本的RocketMQ&#xff0c;阿里云的官方文档&#xff0c;感觉有点乱。看不咋明白&#xff0c;网上虽然有教程&#xff0c;大都还是有点缺少&#xff0c;有时候会突然跳了步骤&#xff0c…

微信小程序开发1

这里写目录标题 一、结构1.项目结构页面结构 3.小程序的通信模型4.小程序运行机制 二、组件视图容器组件 : 一、结构 1.项目结构 页面结构 2.语言结构 WXML与HTML区别 : WXSS与CSS区别 : .Js文件的分类 3.小程序的通信模型 ①他是由渲染层与逻辑层 根据微信客户端进行转…

RPC分布式网络通信框架(三)—— 服务配置中心Zookeeper模块

文章目录 一、使用Zookeeper的意义二、Zookeeper基础1 文件系统2 通知机制3 原生zkclient API存在的问题4 服务配置中心Zookeeper模块 三、Zk类实现Start方法创建节点、get节点值方法 四、框架应用rpc提供端框架rpc调用端&#xff08;客户端&#xff09;框架 总结 一、使用Zook…

平均精度 (mAP):常见定义、误区和误解

我们分解并揭开了常见对象检测指标的神秘面纱,包括平均精度 (mAP) 和平均平均召回率 (mAR)。 这篇文章深入介绍了如何正确计算和使用平均平均精度 (mAP) 和平均平均召回率 (mAR) 进行对象检测,同时消除对 AP、mAP 和第三方库(例如 TorchMetrics 或 pycocotools)的常见误解。…

基于冻土水文模拟的松花江流域水资源演变规律

原文信息 题目&#xff1a;基于冻土水文模拟的松花江流域水资源演变规律 作者&#xff1a;刘水清 周祖昊 刘佳嘉 李佳 谢新民 贾仰文 王浩 期刊&#xff1a;《南水北调与水利科技&#xff08;中英文&#xff09;》23年1期 摘要 为分析松花江流域水资源的演变规律&#…