SpringBoot+Vue 实现简单的:登录、注册、查看详情、商品页面、购物车功能

SpringBoot+Vue 实现简单的:登录、注册、查看详情、商品页面、购物车功能一 用户登录界面 实现思路 用户在界面输入用户名和密码传入变量 用 post 方法传输到后端 后端接收整个实体对象 将用户名提取出 在 dao 层方法中通过 select 注解查询 返回数据库对应的数据对象 如果返回为空则 return false 不为空则通过比对数据库返回的密码和用户输入的密码 如果二者匹配则 return true

大家好,我是讯享网,很高兴认识大家。

 一、用户登录界面

实现思路:用户在界面输入用户名和密码传入变量。用post方法传输到后端,后端接收整个实体对象。将用户名提取出。在dao层方法中通过select注解查询,返回数据库对应的数据对象。如果返回为空则return false。不为空则通过比对数据库返回的密码和用户输入的密码,如果二者匹配则return true,否则return false。在前端axios框架中,通过if语句判断,如果return true则提示登录成功信息,跳转到首页。如果return false则提示登录失败请重试。

效果:


讯享网

改进思路:

已实现:

用cookie记住用户的登录状态。1. 在首页上方显示“欢迎xxx登录!!”字样,xxx必须根据用户名动态变化。2. 个人中心状态区分,已登录状态在右上角显示“个人中心”,个人中心下拉显示“退出登录”;未登录则显示“登录”,无个人中心。3. 实现退出登录的功能。4.设置一个具有权限的页面(购物车),如果未登录页面上方弹窗显示“权限不足,请登录”,如果已登录则可以正常浏览页面内容。5. 对登录的用户名和密码进行加密,接收端进行解密匹配。

1.1 初始版本

第1步:dao层编写如下代码:

@Select("select * from tb_user where username=#{username}" ) public User login(String username);

讯享网

第2步: controller层编写如下代码:

讯享网@RestController @RequestMapping("/api/") public class DataController { @PostMapping("login") public boolean loginmodule(@RequestBody User user){ System.out.println(user.getUsername()); System.out.println(user.getPassword()); User u = bookDao.login(user.getUsername()); if(u==null) return false; System.out.println(u.getPassword()); if(user.getPassword().equals(u.getPassword())) return true; else return false; } }

第3步:编写请求代码:

methods: {
  login() {
     axios.post("/api/login",this.form).then((response)=>{
     if(response.data==true) {
         confirm('登录成功!');
         window.location.href="home.html";
     }
     else alert('用户名或密码错误,请重试!');
   })
 },
}

第4步: 编写登录界面,定义变量:

登录界面:

讯享网<!--登录界面--> <h1 style="margin-left:125px;color: #">登录</h1> <el-form ref="form" :model="form" label-width="80px" style="margin-top: 30px"> <el-form-item label="用户名"> <el-input v-model="form.username" style="width: 200px;"></el-input> </el-form-item> <el-form-item label="密码"> <el-input v-model="form.password" style="width: 200px;"></el-input> </el-form-item> <div style="margin-left: 200px;margin-bottom: 15px"><el-link type="primary" @click="register" >点击注册</el-link></div> <el-form-item> <el-button type="primary" @click="login">登录</el-button> <el-button>取消</el-button> </el-form-item> </el-form>

定义变量: 

data() { return { form: { username: '', password: '' } } }

1.2 完善版本 

技术难点1:cookie如何定义

document.cookie = `loginStatus=true,username=${this.form.username}`;这句话定义了2个cookie,注意不同的cookie间最好以逗号分割。等号左边两边分别是键和值,以键值对的形式目的是方便切割。

讯享网methods: {
    login() {
        axios.post("/api/login",this.form).then((response)=>{
            if(response.data==true) {
                confirm('登录成功!');
                document.cookie = `loginStatus=true,username=${this.form.username}`;
                window.location.href="home.html";
            }
            else alert('用户名或密码错误,请重试!');
        })
},

— — — — — — 知识加油站 — — — — — — 

1. ${}是 JavaScript 中的模板字符串语法。它允许在字符串中插入动态的表达式或变量。最终会被解析为具体的值。

2. 在 JavaScript 中document对象提供了一个cookie属性,用于访问和操作浏览器中的 cookie。

3. Cookie 是存储在用户计算机上的小型文本文件,用于在浏览器和服务器之间存储和传递数据。它可以用于在用户的不同请求之间存储会话信息、用户偏好设置、购物车数据等。

— — — — — — — — — — — — — — — — 

技术难点2:如何提取cookie中的目标数据,进行实时显示

上面定义完cookie之后可以直接通过document.cookie直接取得cookie,然而此时的cookie还是以字符串的形式存在,所以需要进行适当的切分:

function getCookie(username){ const cookies = document.cookie.split(",") for(let i=0;i<cookies.length;i++){ const cookie = cookies[i].split('='); if(cookie[0]==username) return cookie[1]; } return ""; }

cookies就是loginStatus=true和username=${this.form.username}。cookie就是loginStatus,true,username,${this.form.username}。

通过匹配cookie[0]是否是username键,可以返回username的值,供前端实时显示欢迎xxx。

技术难点3:如何根据登录与否,显示不同的页面样式

讯享网document.addEventListener("DOMContentLoaded", function() { // 在首页上方显示欢迎信息和登录状态 const loginStatus = getCookie("loginStatus"); //获取loginStatus的值赋值给loginStatus,是true或false const welcomeMessage = document.getElementById("welcome-message"); const loginStatusText = document.getElementById("login-status"); if (loginStatus === "true") {// 已登录状态 const username = getCookie("username"); // 假设用户名保存在名为"username"的cookie中 console.info(username); welcomeMessage.textContent = "欢迎 " + username + " 登录!!"; } else {// 未登录状态 welcomeMessage.textContent = ""; loginStatusText.textContent = "登录"; } });

技术难点2和难点3的代码需要同导航栏的代码进行配套使用,才能保证各个页面的一致性,因此可以把上述两段代码封装到一个cookie.js中,然后需要引用的时候就在前端加上如下代码即可:

<script src="cookie.js"></script>

— — — — — — 知识加油站 — — — — — — 

1. <script src="navigation.js"></script>这段代码用于在页面中引入navigation.js文件,该文件包含了导航栏和登录界面的代码。

2. <div id="navigation"></div>这段代码创建了一个空的<div>元素,并为其设置了一个唯一的 id 属性值为 "navigation"。这个 div 元素将被用于展示导航栏的代码。

3. <script>document.getElementById("navigation").innerHTML = navigationCode;</script>这段代码使用 JavaScript 获取到 id 为navigation的 div 元素,并将导航栏的代码navigationCode插入到这个 div 元素中。这样就将导航栏的代码动态地展示在页面上。

4.<div>标签本身不具备任何特定的语义或功能,它只是一个用于容纳其他 HTML 元素的容器。

— — — — — — — — — — — — — — — — 

技术难点4:如何封装前端重复性的代码

前端的每个页面都具有导航栏,每个导航栏的代码如下这么长,如果每个页面都填写,显得及其臃肿。

于是我们选择将代码封装到一个navigation.js的文件中,

讯享网const navigationCode = `
<el-menu
        :default-active="activeIndex2"
        class="el-menu-demo"
        mode="horizontal"
        @select="handleSelect"
        background-color="#545c64"
        text-color="#fff"
        active-text-color="#ffd04b">
    <el-menu-item><a href="ADSS.html" style="font-size: large;text-decoration: none;">数据查询</a></el-menu-item>
    <el-menu-item><a  href="home.html" style="font-size: large;text-decoration: none;">首页</a></el-menu-item>
    
    <el-menu-item><a href="login.html" style="font-size: large;text-decoration: none;"><h id="login-status"></h></a></el-menu-item>
    <el-submenu index="2" style=" position: absolute;right: 135px;" >
        <template  slot="title">个人中心</template>
        <el-menu-item @click="clear" >退出登录</el-menu-item>
    </el-submenu>
    <h5 id="welcome-message" style="color: #edf2fc;display: flex;justify-content: flex-end;"></h5>
    
</el-menu>`

 见上面知识加油站:

<!--导航栏--> <script src="navigation.js"></script> <div id="navigation"></div> <script>document.getElementById("navigation").innerHTML = navigationCode;</script>

二、用户注册界面

实现思路:用户输入用户名和密码,利用post方式传回后端,后端根据用户名比对数据是否已在数据库内(select),如果已在则直接提示登录跳转登录界面,如果不在则将数据插入数据库,然后提示注册成功,跳转登录界面。

实现效果:

改进思路:1. 增加验证码机制2. 可以在旁边实时显示是否已注册。

第1步:dao层编写如下代码:

讯享网@Insert("Insert into tb_user(username,password) "+ "values(#{username},#{password})") public void register(User user);
@Select("select * from tb_user where username=#{username}" ) public User login(String username);

 第2步:controller层编写如下代码,判断逻辑:通过用户输入的username,查看数据库中是否有相应的实体对象,如果有说明已注册,如果没有则将数据插入数据库。

讯享网@RestController @RequestMapping("/api/") public class DataController { @PostMapping("register") public boolean registermodule(@RequestBody User user) { User compare = bookDao.login(user.getUsername()); //根据用户输入的用户名返回数据库中对应实体对象 if(compare!=null) return false; bookDao.register(user); return true; } }

第3步:编写注册界面,定义变量:

注册界面如下:

<!--注册界面-->
<h1 style="margin-left:100px;color: #333333">注册账号</h1>
<el-form ref="form" :model="form" label-width="80px" style="margin-top: 30px">
    <el-form-item label="用户名">
        <el-input v-model="form.username" style="width: 200px;"></el-input>
    </el-form-item>
    <el-form-item label="密码">
        <el-input v-model="form.password" style="width: 200px;"></el-input>
    </el-form-item>
    <el-form-item>
        <el-button type="primary" @click="onSubmit">注册</el-button>
        <el-button href="register.html">取消</el-button>
    </el-form-item>
</el-form>

接收数据的变量如下:

讯享网data() { return { form: { username: '', password: '' },

第4步:编写请求代码:

onSubmit() {
    axios.post("/api/register",this.form).then((response)=>{
        if(response.data==false) alert("注册失败,用户名已存在!");
        else {
            confirm("注册成功,即将跳转登录界面")
            window.location.href="login.html";
        }
    })
}

三、详情界面

界面效果:

实现功能:1.实现评论区实时展现数据库评论(定义评论类,id和评论,id同商品id相同,根据id现实对应评论,用select方法进行展现)按照时间先后顺序排序。

2.实现写评论点击发送实时展现在评论区,同时存入数据库(用post方法传递,用Insert插入数据库)。实现评论的用户信息显示已登录的当前用户,未登录用户不可评论。

3. 实现用户名和头像可根据用户信息改变(设置用户类,登录账号,密码,用户名,头像)。

4.实现文本的自由化编辑:内容每段前置空2格,实现字体可变,可变字号,可变间隔。5. 收藏,可以放入收藏夹,同一个物品一个人只能收藏一次,旁边实时显示收藏次数。6. 实现轮播图实时展现图片。7. 修改,实现图片的实时上传,存储到某个位置可以修改轮播图(封面的图片是轮播图的第1张图),修改简介,修改具体的内容,实现实时的更新。

实现步骤:

技术难点1:用户名和头像是在tb_user数据库中,评论是在comments数据库中,如何分别抽取出期望的数据?如何将评论与用户对应上?

解决方法:通过v-for进行双重循环,在卡片内部用v-if进行逻辑判断,只有当评论的id和用户的id一致时,才能确认是该用户发表了该条评论。

讯享网<!--评论区--> <el-row :gutter="8"> <el-col :span="24" v-for="data_comment in data_comments" > <el-card shadow="hover"> <div v-for="data_user in data_users"> <template v-if="data_comment.id==data_user.id"> { 
  
    
  { data_user.name }} <div class="demo-type" style="display: flex; align-items: center;"> <div style="margin-right: 10px;"> <el-avatar :src="data_user.picture"></el-avatar> </div> { 
  
    
  { data_comment.comment }} </div> </template> </div> </el-card> </el-col> </el-row>

四、商品界面

界面效果如下图:

实现功能:

已完成:1. 通过卡片展示商品的基本信息(包括图片、标题、简介、价格)2. 制作购物车按钮、购物车菜单栏、新增、一键删除、删除等按钮。3.实现购物车功能:点击卡片左下角的购物车,进入购物车界面可以看到该商品存入,实时更新。5. 实现连接功能:点击卡片能够进入一个新的页面,里面展示有商品详细的信息。

未完成:3. 购物车:点击购物车提示已加入购物车,4. 实现新增功能:存入图片,输入标题、简介、价格,点击确定,返回商品界面,可以看到新增的商品。

拓展功能:6.实现单品删除功能。7.实现修改单品信息功能。

第1步:数据库设计,创建实体类。数据库4个字段对应Commodity实体类4个变量,实体类中编写set、get和toString。

第2步:dao层编写:

/*实时显示商品信息*/ @Select("select * from commodity") public List<Commodity> selectCommodity();

第3步:controller层编写:

讯享网@GetMapping("commodity") public List<Commodity> commodityModule() { return bookDao.selectCommodity(); }

第4步:前端代码编写:

注意几个点:1. v-for="(data, index) in datas",datas是后端传回的json数据,是一个数据集合,通过v-for来获得单个数据data,index会根据数据的条数来动态变化。2.  图片的动态显示只能通过如下方式<img :src="data.picture" class="image">,千万要注意用 :src ,千万不能使用{ {data.picture}},否则图片无法显示。3. 其余需要动态显示的内容用双花括号括起即可<span>标题:{ {data.title}}</span> 4. 是使用element中带图片的卡片进行制作。

<!--商品信息卡片--> <div class="card"> <el-row> <!--span是每张卡片的宽,v-for是卡片数量,offset第2参是卡片间的间距,第3参是距离左边的距离--> <el-col :span="4" v-for="(data, index) in datas" :key="1" :offset="index > 0 ? 0 : 0"> <el-card :body-style="{ padding: '0px' }"> <div clss="image-container"> <img :src="data.picture" class="image" id="picture"> </div> <div style="padding: 7px;"> <span>标题:{ 
  
    
  {data.title}}</span> <div class="bottom clearfix"> <el-button type="text" class="a;button" style="color: #72767b">简介:{ 
  
    
  {data.introduction}}</el-button> <div style="display: flex; align-items: center;"> <el-button class="el-icon-shopping-cart-1" size="mini" class="button"></el-button> <el-button type="text" class="button">¥{ 
  
    
  {data.price}}</el-button> </div> </div> </div> </el-card> </el-col> </el-row> </div>
讯享网datas:[]

第5步:请求逻辑编写:

 mounted(){ axios.get("/api/commodity").then(response=>{ this.datas = response.data; }) },

五、购物车功能

界面效果:

实现功能:

已实现功能:1. 商品页

点击商品加入购物车,购物车页实时出现该商品:1. 创建数据库表:图片,标题,简介,价格double,是否购买boolean。2. 给购物车绑定事件,获取当前商品数据,Insert入购物车表。3.然后实时更新页面,将商品展现在购物车。

2. 勾选商品,右侧实时计算价格:1. 当用户点击复选框,将boolean值变更为true,获取商品价格。2. 加到一个总价格变量上,绑定给输出框,实现对金额的实时展现。

3. 可以点击商品查看详细信息,可以将商品移除购物车,可以点击购买键弹出支付弹窗。

实现步骤:

技术难点1:如何通过点击商品的加入购物车,获取商品的详细信息?

通过给@click的函数绑定一个参数data,注意名字一定只能是data,data就包含有商品的详细数据,作为参数传入:

讯享网<div style="display: flex; align-items: center;"> <el-button class="el-icon-shopping-cart-1" size="mini" class="button" @click="cart(data)"></el-button> <el-button type="text" class="button">¥{ 
  
    
  {data.price}}</el-button> </div>
cart(data){ console.info(data); },

 技术难点2:如何给返回的对象加入一个参数?

首先要定义一个对象。然后通过<对象.属性名=值>的形式来给DATA对象创建属性并赋值。

讯享网data(){ return{ DATA:{} } } 
methods: { cart(data){ this.DATA.title = data.title; this.DATA.introduction = data.introduction; this.DATA.price = data.price; this.DATA.picture = data.picture; this.DATA.ifchecked = 0; console.info(this.DATA); axios.post("api/shopping-cart",this.DATA); },

 之所以要重新创建一个对象的原因是,对象内的属性必须要和相应的实体类以及对应数据库中的字段一致,否则会报错,导致数据无法插入数据库。

小讯
上一篇 2025-03-21 13:54
下一篇 2025-01-28 18:59

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/127648.html