谷粒商城第六天-商品服务之分类管理下的获取三级分类树形列表

目录

一、总述

1.1 前端思路

1.2 后端思路

二、前端部分

2.1 在网页中建好目录及菜单

2.1.1 建好商品目录

2.1.2 建好分类管理菜单

​编辑

2.2 编写组件

2.2.1 先完成组件文件的创建

2.2.2 编写组件

2.2.2.1 显示三级分类树形列表

三、后端部分

3.1 编写商品分类的相关接口

3.1.1 获取树形三级分类列表

四、总结


一、总述

就是在前端编写好相应的组件,展示内容,绑定好相关的事件,然后向后端发送请求,在后端编写好想要的接口,执行操作或者是返回前端想要的数据。

具体细节:

1.1 前端思路

前端组件的编写就参考elementUI进行编写,只需稍作修改即可。

前端组件的写法按照那三部分即可,模板、脚本、样式

发的请求依靠请求对象,在api文件夹中写好相应的api对象向后端发好请求,然后在组件中进行引入,发送请求即可

1.2 后端思路

基本上直接使用若依提供好的逆向代码,只需稍作修改即可。

编写好各层代码。

二、前端部分

2.1 在网页中建好目录及菜单

这个比较简单在页面中找到菜单管理新建一个目录即可,首先还不是着急创建菜单,而是创建好目录,一个目录即代表一个一个大的类别,其实也就是对应着后端的一个微服务。比如说商品服务,优惠卷服务啥的,为什么说是一个大的类别,因为商品中就有类别管理,品牌管理啥的,一些细的管理,这就作为前端的一个菜单出现了,而菜单其实就对应后端的一个控制器。一个菜单里面实际上就是对一张表或者是多张表做增删改查的。

说了总体的,其实就是新建一个目录代表商品服务。建的步骤如下:

2.1.1 建好商品目录

不会写的,就参考之前已经存在了的目录,就比如这个路由地址,有点模糊,就参考之前的,比如是之前的系统工具这个目录的路由地址写的就是tool,可以知道其实也就是目录的英文简写,那这个就叫product就行了,其他按钮部分基本上默认就行了。 

2.1.2 建好分类管理菜单

同样也是参考之前写好的,创建好分类管理菜单

到目前为止页面的基本框架就有了,但是这个分类菜单缺少实际的内容。接下来就是到前端项目里面按照刚刚的路径创建好组件,并进行编写 1.2 在前端项目中编写前端组件

2.2 编写组件

2.2.1 先完成组件文件的创建

2.2.2 编写组件

2.2.2.1 显示三级分类树形列表

这里直接使用elementUI的树形组件

在elementUI官网中到组件中找到树形控件,在data一栏中可以找到

这里因为不单单的只是展示节点,还涉及到节点的新增以及删除,因此得在节点的后面自定义上内容,定义上新增和删除按钮,所以直接使用上

这个组件,这里我们使用scoped slot这个。

 复制下面的样例代码,注意别复制多了,只复制需要的,然后打开运行前端项目就能有官网的那种效果了,当然还是需要作一些优化的,比如说复制下来的某些东西不需要,就比如说这里的

模板就保留这里:

 <el-tree
      :data="data"
      show-checkbox
      node-key="id"
      default-expand-all
      :expand-on-click-node="false">
      <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <el-button
            type="text"
            size="mini"
            @click="() => append(data)">
            Append
          </el-button>
          <el-button
            type="text"
            size="mini"
            @click="() => remove(node, data)">
            Delete
          </el-button>
        </span>
      </span>
    </el-tree>

可能有人会问,为什么不用div盖着,其实这个并不是必要的,只是有个时候可能需要,需要的时候我们在添上即可。

脚本部分:

<script>
  let id = 1000;

  export default {
    data() {
      const data = [{
        id: 1,
        label: '一级 1',
        children: [{
          id: 4,
          label: '二级 1-1',
          children: [{
            id: 9,
            label: '三级 1-1-1'
          }, {
            id: 10,
            label: '三级 1-1-2'
          }]
        }]
      }, {
        id: 2,
        label: '一级 2',
        children: [{
          id: 5,
          label: '二级 2-1'
        }, {
          id: 6,
          label: '二级 2-2'
        }]
      }, {
        id: 3,
        label: '一级 3',
        children: [{
          id: 7,
          label: '二级 3-1'
        }, {
          id: 8,
          label: '二级 3-2'
        }]
      }];
      return {
        data: JSON.parse(JSON.stringify(data)),
        data: JSON.parse(JSON.stringify(data))
      }
    },

    methods: {
      append(data) {
        const newChild = { id: id++, label: 'testtest', children: [] };
        if (!data.children) {
          this.$set(data, 'children', []);
        }
        data.children.push(newChild);
      },

      remove(node, data) {
        const parent = node.parent;
        const children = parent.data.children || parent.data;
        const index = children.findIndex(d => d.id === data.id);
        children.splice(index, 1);
      }
    }
  };
</script>

 这里的数据先留着,方便初看效果,下面的renderContent方法可以删掉,这是

 样式部分一般不要动,保留即可:

<style>
  .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
  }
</style>

注意:这里除了对原有的内容进行删减之后,还需要优化一些内容,就比如说:

1. 就结构而言,我是需要点击箭头才展开子节点。

2. 就内容:append和delete按钮来说,append因为最多只有三级分类,所以如果当前分类的层级已经是三层了,不能添加这个append,对于delete,如果当前分类下面还有子分类的话,也不能添加delete。 

具体实现如下:

其实完成这些操作,注意参考element的官方文档,对于它给我的这些数据,有什么可以使用控制台打印查看,对于一些你想要的操作这里比如说想点击箭头再展开这样的特殊操作,就需要查看文档下面的属性配置

所以: 

经过上面的两处优化,基本上三级分类也就是这个样子了,现在只是数据不是我们的真实数据罢了。

接下来的工作就是:在前端工程中写好请求对象,用来请求后端获得三级分类的树形列表,然后在组件中引入,然后使用,得到数据,然后再参考文档,将数据正确显示出来即可。

1. 在api文件夹中编写好请求对象

export function treeListCategory() {
    return request({
        url: '/product/category/treeList',
        method: 'get'
    })
}

2, 在组件中引入并使用

 现在是创建了一个方法,调用接口

 其实很简单,就是前端写好树形控件基本的架子先搭起来,然后将数据换成经由调用后端接口返回的数据。步骤也是很简单。到这里网页已经是可以显示三级分类的分类列表了。 

三、后端部分

3.1 编写商品分类的相关接口

3.1.1 获取树形三级分类列表

无论是前台页面还是后台管理页面都得将分类列表以子父的树形三级列表体现出来。

所以就得写一个接口获取到树形三级分类列表。

树形子父关系如何体现呢?貌似有点抽象,其实很简单,就是一个分类下面有许多的子分类,在面向对象的思想中就是分类的这个类中有一个类型为集合,集合元素为分类的子分类属性。

如下图所示:

注意: 非表的字段一定得加上@TabelField(exist = false)注解,来标明此字段是非表字段,如果不加这个注解,MyBatis字段映射的时候就会出问题,就比如说sql查了记录的所有字段,但是却找不到该字段,就会报错

好,现在字段是有了,最终肯定是需要为这个字段赋上值的,所有的子分类是计算出来的,那到底如何计算呢?其核心业务实现如何写?请看下面我写的:

其实很简单,就两步,其实获取子分类的关键就是 依靠表中的父类别字段。有了这一个就很容易得到一个类别的下的子类别。

第一步:编写获取子分类的方法(不带真正实现)。

遍历所有分类,为每个分类赋上子分类

第二步:编写获取子分类的具体实现

也就是根据当前分类的id,然后遍历所有的分类,找到它的子分类,其实也就是分类的父id为当前分类的id,那么这个分类就为当前分类的子分类

最关键的业务实现思路就有了,最关键最重要的一步其实已经想明白了,接下来就是常规的写好各个层的代码。我现在已经习惯逆向编写了,也就是从控制层开始写,一直写到dao层。话不多说,直接贴代码:

controller:

@ApiOperation("获取商品分类的树形结构")
    @GetMapping("/treeList")
    public AjaxResult treeList(){
        List<Category> treeList = categoryService.treeList();
        return AjaxResult.success(treeList);
    }

service:

service接口:

 service实现:

@Override
    public List<Category> treeList() {
        //获取到所有分类
        List<Category> list = list();
        //为每个分类添加上子分类
        list.stream().forEach(category -> category.setChildren(getChildren(category,list)));
        //为根父类排序
        list.stream().sorted((c1,c2)->
            c1 == null ? 0 : c1.getSort().intValue() - (c2 == null ? 0 : c2.getSort().intValue()));
        return list;
    }
private List<Category> getChildren(Category root, List<Category> all) {
        //从所有类别中找到子分类,并排好序
        List<Category> childrenCategory = all.stream().filter(c -> c.getParentCid().equals(root.getCatId())).sorted((c1,c2)->
            c1 == null ? 0 : c1.getSort().intValue() - (c2 == null ? 0 : c2.getSort().intValue())
        ).collect(Collectors.toList());
        //针对所有的子分类也递归找其对应的子分类
        childrenCategory.stream().forEach(category -> category.setChildren(getChildren(category,childrenCategory)));
        return childrenCategory;
    }

这里由于是直接使用的MP,并且没有复杂查询,也就不需要直接显式的写dao层了

四、总结

其实从后端编写好接口,到前端编写好组件,整个过程还是比较简单的

在这里前端相较于后端而言反而要繁琐一点,后端主要把真正的获取逻辑写明白就好了

而前端就根据elememtUI的组件库选好组件,然后将参数写好,使得能正确的将数据渲染出来,还有一些其他的修改,优化一下就行了。

另外写好api,使得可以正确的访问后端,其实不难,但是繁琐,之后的功能实现大体都是这些步骤,主要就是核心组件不同,后端无非还是CURD。

这次相当于是Vue+Boot的开发,这是比较主流的开发方式,利用若依框架开发也是公司中常用的,因此需要熟练掌握。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

matlab编程实践16、17

捕食者与猎物模型 人口增长 在人口增长或衰减的最简单模型中&#xff0c;增长速度或衰减速度与人口本身的数目成正比。增加或减少人口规模会导致出生和死亡数量成比例地增加或减少。在数学上&#xff0c;可以由以下微分方程描述。 可以得出&#xff1a;&#xff0c;其中。 该简…

2023-08-01 LeetCode每日一题(英雄的力量)

2023-08-01每日一题 一、题目编号 2681. 英雄的力量二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始的整数数组 nums &#xff0c;它表示英雄的能力值。如果我们选出一部分英雄&#xff0c;这组英雄的 力量 定义为&#xff1a; i0 &#xff0c;i1 &…

Redis - 三大缓存问题(穿透、击穿、雪崩)

缓存穿透 概念&#xff1a; 查询一个数据库中也不存在的数据&#xff0c;数据库查询不到数据也就不会写入缓存&#xff0c;就会导致一直查询数据库 解决方法&#xff1a; 1. 缓存空数据 如果数据库也查询不到&#xff0c;就把空结果进行缓存 缺点是 - 消耗内存 2. 使用布…

ModuleNotFoundError: No module named ‘_sqlite3‘

前言 遇到报错信息如下&#xff1a; ModuleNotFoundError: No module named _sqlite3解决方式 参考解决方式&#xff1a; https://blog.csdn.net/jaket5219999/article/details/53512071 find / -name _sqlite*.socp /usr/lib64/python3.6/lib-dynload/_sqlite3.cpython-36…

Go语言性能优化建议与pprof性能调优详解——结合博客项目实战

文章目录 性能优化建议Benchmark的使用slice优化预分配内存大内存未释放 map优化字符串处理优化结构体优化atomic包小结 pprof性能调优采集性能数据服务型应用go tool pprof命令项目调优分析修改main.go安装go-wrk命令行交互界面图形化火焰图 性能优化建议 简介&#xff1a; …

从0到1开发go-tcp框架【1-搭建server、封装连接与业务绑定、实现基础Router、抽取全局配置文件】

从0到1开发go-tcp框架【1-搭建server、封装连接与业务绑定、实现基础Router】 本期主要完成对Server的搭建、封装连接与业务绑定、实现基础Router&#xff08;处理业务的部分&#xff09;、抽取框架的全局配置文件 从配置文件中读取数据&#xff08;服务器监听端口、监听IP等&a…

记一次phpmyadmin巧妙利用

声明&#xff1a;文中涉及到的技术和工具&#xff0c;仅供学习使用&#xff0c;禁止从事任何非法活动&#xff0c;如因此造成的直接或间接损失&#xff0c;均由使用者自行承担责任。 点点关注不迷路&#xff0c;每周不定时持续分享各种干货。 原文链接&#xff1a;众亦信安&a…

Spring中最简单的过滤器和监听器

1. 过滤器概念引入 Filter也称之为过滤器&#xff0c;它是Servlet技术中最实用的技术&#xff0c;Web开发人员通过Filter技术&#xff0c;对web服务器管理的所有web资源&#xff1a;例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截&#xff0c;从而实现一些特殊的功…

在Windows 10和11中恢复已删除的照片

可以在Windows 10或11上恢复已删除的照片吗&#xff1f; 随着技术的发展&#xff0c;越来越多的用户习惯在电子设备上存储照片。如果这些照片被删除&#xff0c;可能会给用户带来重大损失。当照片丢失时&#xff0c;您可能会想是否可以恢复已删除的照片&#xff1f; …

LabVIEW 开发在不确定路况下自动速度辅助系统

LabVIEW 开发在不确定路况下自动速度辅助系统 智能驾驶辅助系统是汽车行业最先进的升级和尖端技术&#xff0c;智能交通系统依靠智能驾驶辅助系统在公共交通部门工作。该智能驾驶辅助系统技术包括自适应巡航控制&#xff0c;防抱死制动系统&#xff0c;安全气囊展开&#xff0…

腾讯云从业者认证考试考——云服务器

文章目录 云服务器的产品概览腾讯云服务器的优势腾讯云服务器选型腾讯云服务器计费方案 云服务器的产品概览 腾讯云服务器的产品&#xff1f; CVM云服务器&#xff08;Cloud Virtual Machine&#xff0c;CVM&#xff09;提供安全可靠的弹性计算服务。 可以在云端获取和启用 CV…

根据前序和中序遍历序列构造二叉树 (递归+迭代两种方法实现)

给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]源代码如下…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(13)-Fiddler请求和响应断点调试

1.简介 Fiddler有个强大的功能&#xff0c;可以修改发送到服务器的数据包&#xff0c;但是修改前需要拦截&#xff0c;即设置断点。设置断点后&#xff0c;开始拦截接下来所有网页&#xff0c;直到取消断点。这个功能可以在数据包发送之前&#xff0c;修改请求参数&#xff1b…

逻辑回归变量系数可为负数吗?应该如何解释?

之前很多学员来问逻辑回归变量系数是否都应该为正数&#xff0c;如果出现负的变量系数该怎么办&#xff1f;是否需要重新建模&#xff1f;这些学员都是在网上搜索时&#xff0c;被错误信息误导。网上信息可以随意转载&#xff0c;且无人审核对错。我见过最多情况时很多文章正确…

第4章 案例研究:JavaScript图片库

案例 html部分 <h1 id"title">图片1</h1> <ul><li><!-- onclick绑定点击事件&#xff0c;this为触发dom&#xff0c;return false阻止默认行为 --><a onclick"show_img(this); return false" title"图片1" h…

命令模式-请求发送者与接收者解耦

去小餐馆吃饭的时候&#xff0c;顾客直接跟厨师说想要吃什么菜&#xff0c;然后厨师再开始炒菜。去大点的餐馆吃饭时&#xff0c;我们是跟服务员说想吃什么菜&#xff0c;然后服务员把这信息传到厨房&#xff0c;厨师根据这些订单信息炒菜。为什么大餐馆不省去这个步骤&#xf…

装饰器模式(Decorator)

装饰器模式是一种结构型设计模式&#xff0c;用来动态地给一个对象增加一些额外的职责。就增加对象功能来说&#xff0c;装饰器模式比生成子类实现更为灵活。装饰器模式的别名为包装器(Wrapper)&#xff0c;与适配器模式的别名相同&#xff0c;但它们适用于不同的场合。 Decor…

HTML笔记(1)

介绍 浏览器中内置了HTML的解析引擎&#xff0c;通过解析标记语言来展现网页&#xff1b;HTML标签都是预定义好的&#xff1b;Java工程师&#xff1a;后台代码的编写&#xff0c;和数据库打交道&#xff0c;把数据给网页前端的工程师&#xff1b;网页前端工程师&#xff1a;写H…

快速了解MyBatis---映射关系多对一

文章目录 映射关系多对一映射关系-官方文档映射关系多对1-基本介绍基本介绍注意细节 映射关系多对1-映射方式映射方式配置Mapper.xml 方式-应用实例注解实现多对1 映射-应用实例 映射关系多对一 映射关系-官方文档 文档地址: https://mybatis.org/mybatis-3/zh/sqlmap-xml.ht…

linux驱动定时器实现按键按下打印字符

#include <linux/init.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/interrupt.h>struct device_node *dev; unsigned int irqno; //中断处理函数 irqreturn_t myirq_handler(int irq,void *…