Layui之动态树 左侧树形菜单栏 详细全面

news2025/1/10 3:08:22

⭐ฅʕ•̫͡•ʔฅ本期看点:该篇是运用Layui框架来编写后台树形菜单栏,并且结合MySql来编写完成

目录

一.效果图

二.具体步骤

 2.1 数据库 

 2.2 树形导航栏

    第一个类:Treevo

             第二个类:BuildTree:

2.3  Dao方法

        2.3.1 basedao

                 2.3.2 Dao类

2.4  后台Servlet

2.5 前台代码


一.效果图

Layui就一般都为这种水墨风,哈哈,大概就是图片的左侧的样子

二.具体步骤

 2.1 数据库 

        需要准备的数据:首先准备好需要展示在树形菜单中的数据。这些数据应该包含节点的id、父节点id、节点名称等信息,以便构建树形结构。

 2.2 树形导航栏

 写一个java文件,里面包含了所有关于树形导航栏的方法和属性,把关于导航栏的单独用一个类写出,这样会更加清晰明了

    第一个类: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();
	}

}

第二个类:BuildTree:

        这个类里面定义了两个循环,一个循环可视为外层循环,即可定义为将所有的数据循环一遍,接着第二个循环可视为内层循环,将第二个循环的父id和第一个循环的id进行判断,如果相等就说明 他们是父子关系,并且在这里还指定了默认最高节点也就是父节点,这个可根据自己的数据库里的来进行变化

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

}

2.3  Dao方法

        2.3.1 basedao

package com.yinzi.utils;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import com.yinzi.utils.DBAccess;
import com.yinzi.utils.PageBean;

public class BaseDao<T> {
	/**
	 * 带分页的模糊查询
	 * @param c
	 * @param sql
	 * @param pagebean
	 * @return
	 * @throws Exception
	 */
	public List<T> executeQuery(Class c ,String sql,PageBean pagebean) throws Exception{
		//创建集合保存数据
		List<T> list = new ArrayList<>();
		//获取连接
		Connection conn =null;
		//执行SQL语句
		PreparedStatement ps = null;
		//结果集对象
		ResultSet rs =null;
		
		//判断是否需要分页
		if(pagebean!=null && pagebean.isPagination()) {//如果需要分页,就拼接SQL语句
			String Countsql=getCountsql(sql);//获取总数量
			conn = DBAccess.getConnection();
			ps = conn.prepareStatement(Countsql);//执行改变后的SQL语句
			rs = ps.executeQuery();
			if(rs.next()) {
				pagebean.setTotal(rs.getObject("n").toString());
			}
			
			String pagesql=getPagesql(sql,pagebean);
			conn = DBAccess.getConnection();
			ps = conn.prepareStatement(pagesql);//执行改变后的SQL语句
			rs = ps.executeQuery();
		}else {//否则不需要,就按照原sql语句执行
			conn = DBAccess.getConnection();
			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();
		}
		
		//循环遍历数据
		while(rs.next()) {
			T t = (T) c.newInstance();
			//拿到所有的属性
			Field[] fields = c.getDeclaredFields();
			for (Field field : fields) {
				//打开访问权限
				field.setAccessible(true);
				field.set(t,rs.getObject(field.getName()));
			}
			list.add(t);
		}
		return list;
	}
	/**
	 * 最终SQL语句
	 * @param sql
	 * @param pagebean
	 * @return
	 */
	private String getPagesql(String sql, PageBean pagebean) {
		return sql+" limit "+pagebean.getStartIndex()+","+pagebean.getRows();
	}
	/**
	 * 总记录数
	 * @param sql
	 * @return
	 */
	private String getCountsql(String sql) {
		return "select count(1) as n from ("+sql+") t";
		
	}
	
	
	
	
	
	/**
	 *  增删改的方法
	 * @param sql sql语句
	 * @param t 实体类
	 * @param attr 实体类对应的属性
	 * @return
	 * @throws Exception 
	 */
	public int excuteUpdate(String sql ,T t,String[] attr) throws Exception {
		Connection conn=DBAccess.getConnection();//连接数据库
		PreparedStatement ps=conn.prepareStatement(sql);//执行sql语句
		//循环拿到属性
		for (int i = 0; i < attr.length; i++) {
			//一切反射从获取类类开始
			Field f = t.getClass().getDeclaredField(attr[i]);
			//打开访问权限
			f.setAccessible(true);
			ps.setObject(i+1, f.get(t));
		}
		
		return ps.executeUpdate();
		
	}
	
	
	
	
	
	
	
}

2.3.2 Dao类

        这个类里面首先做了一个查询所有获取所有的数据,接着 写一个方法将这些平级的数据转换成父子关系的数据,还调用了BuildTree里面的方法

package com.yinzi.dao;

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

import org.junit.Test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yinzi.entity.Permission;
import com.yinzi.utils.BaseDao;
import com.yinzi.utils.PageBean;
import com.zking.util.BuildTree;
import com.zking.util.TreeVo;

public class PermissionDao extends BaseDao<Permission>{
	/**
	 * 查詢所有
	 * @param permission
	 * @param pagebean
	 * @return
	 * @throws Exception
	 */
	public List<Permission> list(Permission permission,PageBean pagebean) throws Exception {
		String sql="select * from t_easyui_permission";
		return super.executeQuery(Permission.class, sql, pagebean);
	}
	
	
	
	//将这些平级数据转换成父子关系的数据
	public List<TreeVo<Permission>> menus(Permission permission,PageBean pagebean) throws Exception{
		//创建一个父子关系的集合  TreeVo
		List<TreeVo<Permission>> tvList = new ArrayList<TreeVo<Permission>>();
		//获取平级数据
		List<Permission> list = this.list(permission, pagebean);
		for (Permission per : list) {
			TreeVo<Permission> tv=new TreeVo<>();
			//将per对象转成tv对象,因为tv对象才有children
			tv.setId(per.getId()+"");
			tv.setText(per.getName());
			tv.setParentId(per.getPid()+"");
			tvList.add(tv);
		}
		return BuildTree.buildList(tvList, "0");//这个地方填写一级菜单的id
	}
	
	
	

	
	
	
}

2.4  后台Servlet

package com.yinzi.Servlet;

import java.util.List;

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

import com.yinzi.dao.PermissionDao;
import com.yinzi.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 pd=new PermissionDao();
	
	public void menus(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		//调用方法
		List<TreeVo<Permission>> menus = pd.menus(null, null);
		//回显给前台
		ResponseUtil.writeJson(resp, menus);
	}
	
	@Override
	public Permission getModel() {
		return permission;
	}

}

2.5 前台代码

        首先样式小编是复制的Layui的模式,然后在ajax里面进行了拼接循环,最后输出即可

<%@ 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>
<link rel="stylesheet"
	href="${pageContext.request.contextPath}/static/js/layui/css/layui.css"></link>
<script type="text/javascript"
	src="${pageContext.request.contextPath}/static/js/layui/layui.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">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}/permission.action?methodName=menus",
	  dataType:"json",
	  success:function(data){
		  console.log(data)
		//定义一个字符串进行拼接
		var htmlStr="";
		//遍历数据
		$.each(data,function(i,n){
			//拼接
			htmlStr+='<li class="layui-nav-item layui-nav-itemed">';
			htmlStr+='<a class="" href="javascript:;">'+n.text+'</a>';
			//如果其存在孩子,就在进行循环
			 if(n.hasChildren){
				var children =n.children;
				//因为这个只需要循环一次,所以放在循环外面
				htmlStr+='<dl class="layui-nav-child">';
				$.each(children,function(index,node){
					//这个需要循环多次
					htmlStr+='<dd><a href="javascript:;">'+node.text+'</a></dd>';
				})
				htmlStr+='</dl>';
			} 
			
			htmlStr+='</li>';
		})
		  $("#menu").html(htmlStr);
		//渲染
		element.render('menu');	
	  }
  });
		
		
  });
  
  
</script>
</body>
</html>

今天的分享的案例就到这啦,有不懂的宝子,评论区留言,尽情期待哦~~

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

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

相关文章

【自我提升】Spring Data JPA之Specification动态查询详解

写在前面&#xff1a;刷完Spring Data JPA的课后&#xff0c;发现Specification动态查询还挺有意思的&#xff0c;还应用到了规约设计模式&#xff0c;在此记录下学习过程和见解。 目录 一、应用场景 二、源码解析 三、规约模式 四、实际应用 一、应用场景 1. 简介 有时我…

Linux中安装Tomcat

前提条件&#xff1a; 虚拟机中已经提前安装好jdk1.8。 安装步骤&#xff1a; 1.下载安装包 首先去Apache官网下载&#xff08;Apache Tomcat - Apache Tomcat 9 Software Downloads&#xff09; 2.上传到 linux 中&#xff0c;我这里上传的目录是&#xff1a; /opt 3. 解压…

element-plus坑总结

reactive和ref对比 // 定义变量 import { reactive } from vue; const person reactive({name: "John",age: 25, });// 赋值修改 person.name "Tom"; person.age 26;// 使用变量 <div>{{ person.name }}</div> <button click"perso…

layui介绍以及登录功能的实现

一. layui简介 1.1 layui介绍 Layui 是一套开源免费的 Web UI 组件库&#xff0c;采用自身轻量级模块化规范&#xff0c;遵循原生态的 HTML/CSS/JavaScript 开发模式&#xff0c;非常适合网页界面的快速构建。Layui 区别于一众主流的前端框架&#xff0c;它更多是面向于后端开…

3、Linux-进程管理类

进程管理类 进程是正在执行的一个程序或命令&#xff0c;每一个进程都是一个运行的实体&#xff0c;都有自己的地址空间&#xff0c;并占用一定的系统资源。 7.10.1 ps 查看当前系统进程状态 ps:process status 进程状态 1&#xff09;基本语法 ps aux | grep xxx &#xff08…

Python 导入引用其他文件的函数(持续更新)

文章目录 构造初始化文件结构&#xff0c;以此为例。【1】导入同目录且同级下其他文件的函数&#xff08;c.py文件导入d.py文件的函数&#xff09;&#xff08;1&#xff09;只引入d.py文件&#xff08;2&#xff09;直接引入函数&#xff08;3&#xff09;引入全部函数 【2】导…

docker服务启动过程分析

How docker.service start&#xff1f; just by ref 我们先了解docker的各个核心组件的介绍 runc&#xff1a;runc实现了容器的底层功能&#xff0c;例如创建、运行等。runc通过调用内核接口为容器创建和管理cgroup、namespace等Linux内核功能&#xff0c;来实现容器的核心特…

Spring5学习笔记--详细一文通

Spring5学习笔记--详细一文通 1 Spring 框架概述1.1 Spring 5 简述1.2 Spring5入门案例1.2.1 Spring5下载1.1.2 打开 idea 工具&#xff0c;创建普通 Java 工程1.2.3 导入 Spring5 相关 jar 包1.2.4 创建普通类&#xff0c;在这个类创建普通方法1.2.5 创建 Spring 配置文件&…

同时多项目多个node版本-比nvm好用的volta

一、node版本问题场景&#xff1a; 1、服务器上跑的多个node项目需要不同的node版本&#xff0c;且没条件上docker。 2、开发环境中多个项目需要node版本不同&#xff0c;且同时不止是一个项目在开发中&#xff0c;用了nvm进行node版本管理和切换&#xff0c;但是太麻烦。 二…

如何开发一款软件?

创建软件的步骤 1. 头脑风暴 创意生成是制作应用程序的第一步。考虑这个问题的最好方法是将你的应用想象成解决问题。 你自己的经历可以成为灵感的重要来源。试着想想你面临的问题&#xff0c;无论是软件和计算机&#xff0c;还是你的一般生活。很有可能&#xff0c;你面临的…

3DVR全景乡村振兴创新展示,助力数字化乡村建设

导语&#xff1a; 随着社会进步和科技发展&#xff0c;3D虚拟现实&#xff08;VR&#xff09;全景技术在乡村振兴领域展现出巨大的潜力和创新空间。通过结合3DVR全景技术和乡村振兴理念&#xff0c;我们可以为乡村带来全新的展示方式和体验&#xff0c;推动乡村振兴的进程。本…

MiniGPT4 在RTX-3090 Ubuntu服务器部署步骤详解

主要参考知乎帖子&#xff1a; MiniGPT-4 本地部署 RTX 3090 - 知乎 MiniGPT-4部署比麻烦&#xff0c;首先需要获取LLaMA权重&#xff0c;并结合Vicuna的bitwise XOR增量文件完成Vicuna模型权重生成&#xff0c;最后准备好预训练的MiniGPT-4进行模型部署。为了便于理解&#…

Photoshop简单案例(10)——利用PS修改证件照尺寸为1寸(或其他)

目录 一、项目介绍二、基本流程三、效果演示 一、项目介绍 本文介绍一下利用Photoshop修改证件照尺寸为1寸的方法。 二、基本流程 首先打开新建一个空白画布&#xff0c;设置画布宽度和高度分别为25mm和35mm&#xff0c;分辨率为300&#xff0c;背景颜色与证件照背景相同&am…

基于GPT4All的大型语言模型设计生态系统

GPT4All 一套专为强大、定制的大型语言模型设计的生态系统,能够在消费级CPU上本地运行。在GPT4All中,所使用的模型是一个3GB至8GB的文件,读者可以自行下载该文件,并将其插入到GPT4All的开源生态系统软件中。这一软件生态系统由Nomic AI提供支持并进行维护,其目的是确保系统…

04-树 (数据结构和算法)

4.1 树的基本概念 树&#xff08;Tree&#xff09;是n&#xff08;n>0&#xff09;个结点的有限集&#xff0c;它或为空树&#xff08;n 0&#xff09;&#xff1b;或为非空树&#xff0c;对于非空树 T&#xff1a; 有且只有一个称之为根的结点 除根节点以外的其他结点可…

随手笔记——关于齐次变换矩阵的理解

随手笔记——关于齐次变换矩阵的理解 说明符号坐标系表示&#xff08;coordinate representation&#xff09;坐标系变换&#xff08;coordinate transformation&#xff09;点的操作&#xff08;point operator&#xff09; 说明 齐次变换矩阵的几种解释&#xff0c; 主要从坐…

十大排序算法【原理】【步骤】【动图】【C++实现】

十大排序算法 排序算法可以分为内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。常见的内部排序算法有&#xff1a;插入排序、希尔…

【面试题32】include和require的区别及用法

文章目录 一、前言二 、include和require的区别三、include和require的用法介绍3.1 include的用法3.2 require的用法及示例 四、include和require的用法示例4.1 包含文件4.2 包含文件并将结果赋值给变量4.3 动态包含文件4.4 使用绝对路径包含文件4.5 包含文件失败处理4.6 包含文…

MATLAB 的函数计算与作图

基本初等函数的输入系统运算与操作函数的输入函数值的计算1. 数值计算方式2. 符号计算方式2.1 函数&#xff1a;sym2.2 函数&#xff1a;syms 函数的作图1. 一般函数 yf(x) 的作图&#xff08;二维&#xff09;作图基本形式作多重线作图的线型和颜色作图的网格和标记、图例、字…

React Dva项目创建Model,并演示数据管理与函数调用

本文的话 我们讲一下定义Model 也就是Dva中redux的部分 我们打开一个刚创建的Dva项目 看到 src下的models 下 就是Model部分 这里 他给我们了一个案例 如果用 react-redux 管理 模块多了之后会看着比较乱 或 很麻烦 但是 大家会发现 在Model中 他将这些都放在一起了 只需要创建…