小米商城全栈项目

前言:

        小米商城全栈项目采用了前后端分离的设计思路,后端的我使用到了nest.js框架,数据库方面,项目选择了MySQL来存储用户信息和商品数据。然后通过引用axios来获取后端数据,确保数据的实时性和准确性,因为刚刚才学习了nest.js框架,在本次项目中也遇到了一些问题,同时,我会将遇到的问题与解决思路给到大家,希望看完这篇博客对您会有一些帮助。

小米商城官网地址:点这里<<<        

        进入小米商城需要注意的是,因为小米商城全栈是移动端的项目,如果您是PC端,需要开启浏览器的模拟器来进入该页面:1.点击F12进入控制台 —— 2.ctrl+shift+M即可进入模拟器。否则会进入小米官网。

1.引入nest.js

        首先确保您的电脑下载了Node.js,Node.js安装会附带npx和npm包运行程序。要创建新的Nest.js,需要在终端上运行以下的命令:

pnpm i -g @nestjs/cli // 全局安装Nest
nest new project-name // 创建项目

        创建好项目后会询问您是想用什么方式去管理依赖包,这边建议优先去使用pnpm,不行的话改用npm。

创建好后就会自动生成文件,我们还需要创建一个数据库,这边我用的是小皮,然后在数据库中插入表,添加我们想要的数据,最后使用Nest.js连接数据库。

2.连接数据库

以上是我在数据库中创建的表,从上到下对应的是小米商城中的分类页面,米圈页面,轮播图以及用户的信息,用于登录页面中判断用户信息是否存在,存在就登录成功,否则就登录失败。

        在app.module.ts中连接数据库,首先需要在该目录下下载@nestjs/typeorm、typeorm以及mysql执行命令,在文件中使用import导入:

import { TypeOrmModule } from '@nestjs/typeorm'

        安装vscode的mysql插件: Database Client 用于在创建数据库

        然后就可以去连接我们创建的数据库了。

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm'

@Module({
  // 连接创建的数据库
  imports: [
    TypeOrmModule.forRoot({
      type:'mysql', 
      host:'127.0.0.1', 
      port:3306, 
      username:'root',
      password:'root', 
      database:'mi_data', 
      autoLoadEntities:true, // 自动加载实体
      synchronize:true,  // 自动同步实体
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

我们也可以添加全局前缀,在main.ts中添加:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  
  const app = await NestFactory.create(AppModule);
  // 设置全局路由前缀
  app.setGlobalPrefix('/api')
  await app.listen(3000);
  
}
bootstrap();

到这里我们可以先去将页面的静态效果先去制作好,通过html、css、js来实现。

3.首页

将首页的静态页面做完后,将轮播图的图片地址改为用后端传来的图片地址,我们首先需要使用 nest g res swiper 生成轮播图模块。

选择REST API,在 swiper.entity.ts 文件里面添加实体,实体是一 个映射到数据库表的类。换句话说实体就是一张数据表,在typeorm中我们不需要对数据库的表使用相 关工具进行创建与关联,而只需要创建一个实体,并且将实体中的数据内容设置好,那么在项目启动 后,就会自动生成对应的表,并且将表与表之间的关系给创建好。

以上是数据库中的数据。

import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";

@Entity('swiper') 
export class Swiper {
    @PrimaryGeneratedColumn('uuid')
    id:number 

    @Column({
        type:'timestamp', // 列类型
        nullable: true,
        comment:'创建时间' //注释
    })
    create_at:string

    @Column({
        type:'timestamp',
        nullable: true,
        comment:'更新时间'
    })
    update_at:string

    @Column({
        type:'varchar',
        length:50,
        unique:true,
        comment:'图片名称'
    })
    name:string
}

添加实体,与数据库中的数据要一一对应。

        首先我们了解我们需要做什么,就是想要拿取数据库的中数据,然后渲染到页面上,我们就只用去查数据,增删改都不需要去实现。就拿swiper这个表,nest.js的查询过程是这个表的数据会首先进入到swiper.controller.ts然后再会到swiper.service.ts中,然后我们就可以根据地址去访问到数据。

        在swiper.controller.ts中,因为我们需要的是查数据,就用Get请求去查询,我们发现该文件下有两个Get请求。

@Get('')
  findAll() {
    return this.swiperService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.swiperService.findOne(+id);
  }

        上面的是查询所有数据,下面的是通过id去查询单个数据,从使用到的方法上就能看出来,查询所有数据使用的是findAll方法,单个数据则使用的是findOne方法。

        然后根据直接的需求去对应使用,这里我需要查询所有数据,我就使用上面这个,给其添加一个路由前缀。

 @Get('/all')
  findAll() {
    return this.swiperService.findAll();
  }

        在swiper.service.ts文件中,我们需要手动通过import去引入实体,以及下载的typeorm和@nestjs/typeorm。

import { Injectable } from '@nestjs/common';
import { CreateSwiperDto } from './dto/create-swiper.dto';
import { UpdateSwiperDto } from './dto/update-swiper.dto';
import { Swiper } from './entities/swiper.entity';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
@Injectable()
export class SwiperService {
  // 依赖注入
  constructor(
    @InjectRepository(Swiper) 
    private swiperRepository: Repository<Swiper> 
  ){}

  async create(createSwiperDto: CreateSwiperDto) {
    return await this.swiperRepository.save(createSwiperDto);
  }

  async findAll() {
    return await this.swiperRepository.find();
}

async findOne(id: number) {
  return await this.swiperRepository.findOne({ where: { id } });
}

  async update(id: number, updateSwiperDto: UpdateSwiperDto) {
    return await this.swiperRepository.update(id, updateSwiperDto);
  }

  remove(id: number) {
    return `This action removes a #${id} swiper`;
  }
}

在swiper.module.ts中导入@nestjs/typeorm和实体

import { Module } from '@nestjs/common';
import { SwiperService } from './swiper.service';
import { SwiperController } from './swiper.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Swiper } from './entities/swiper.entity';

@Module({
  imports: [TypeOrmModule.forFeature([Swiper])],
  controllers: [SwiperController],
  providers: [SwiperService],
})
export class SwiperModule {}

        这里可以在vscode中下载一个扩展Postcode。它主要作为Postman的替代品,为开发者提供了在VSCode环境中进行API测试的功能。

        直接在Postcode可以输入地址,获取数据库中的数据。

        到这里我们就已经成功获取到了数据。在再首页中使用axios获取数据并渲染到页面。

 const swiperBox = document.getElementById("swiperBox");
    axios.get("http://127.0.0.1:3000/api/swiper/all")
        .then((res) => {
            let html = "";
            for (let i = 0; i < res.data.length; i++) {
                // console.log(res.data[i].name);
                html += `
                <div class="swiper-slide">
                  <img src="./小米商城图片资源/${res.data[i].name}" alt="" />
                </div>
                `;
            }
            swiperBox.innerHTML = html;
        })
        .catch((error) => {
            console.error("Error fetching images:", error);
        });
};

4.登录页面

        在中登录页面时,需要和上述步骤一样,首先要获取数据库的数据,然后前端需要将用户填写的用户名和密码的数据传给后端,后端需要对传过来的数据进行判断,如果传过来的数据后后端数据库的数据匹配上了,就将数据发给前端,否则就返回null。前端也可以从后端去拿取数据做判断,但前端是不安全的,这种操作一般是需要后端去完成的。

登录接口逻辑:

1.后端登录接口/api/user/login

2.前端提交用户名密码到后端

3. 后端获取前端传的数据,通过该数据查询数据库,如果查询到数据,则返回登录成功以及用户信息和token,否则返回登录失败

4.前端根据返回结果做出相应的提示

5.如果登录成功就跳转到首页,否则就提示登录失败

axios.post("http://127.0.0.1:3000/api/user/login", {
              username: username,
              password: password,
            })

上述代码将数据传给后端。后端先先是需要获取到前端传来的数据。

这里需要先在user.controller.ts中创建一个post请求来接收数据。

@Post('/login')
  login(@Body() data: any) {
    return this.userService.login(data);
  }

然后到user.service.ts中继续判断,我们只需要数据库的一条数据就可以了,不用获取全部数据,使用findOne方法。

 // 登录
    async login(data) {
      const user = await this.userRepository.findOne({
        where:{username: data.username, password: data.password}
      })
      console.log(user)
      if(user){
        return {
          code: 0,
          data: user,
          message: '登录成功'
        }
      }else{
        return {
          code: 1,
          message: '用户名或密码错误',
          data: null
        }
      }
    }

将判断结果返回给前端。然后前端可以通过传来的code来进行一个成功和失败的判断,将用户的头像和用户名保存到本地存储中。我这里的话登录成功后会跳转到首页。

  axios.post("http://127.0.0.1:3000/api/user/login", {
              username: username,
              password: password,
            })
            .then((res) => {
              if (res.data.code === 0) {
                console.log("登录成功");
                localStorage.setItem("avatar",res.data.data.avatar);
                localStorage.setItem("username", res.data.data.username);
                window.location.href =
                  "./index.html";
              } else {
                text.textContent = "用户名或密码错误";
              }
            });
        });

 5.项目总结

        小米商城全栈项目是一个充满挑战和机遇的项目。通过本次项目的开发,我们不仅提升了技术能力,还积累了宝贵的项目经验。相信在未来的日子里,我们将能够创造出更多优秀的项目,为互联网行业的发展贡献自己的力量。

        通过本次小米商城全栈项目的开发,不仅加深了对前后端分离开发模式的理解,还掌握了nest.js的基本使用。在项目实现过程中,遇到了许多技术难点和挑战,但通过不断学习和实践,最终成功完成了项目的开发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值