鸿蒙的基本项目_tabbar,首页,购物车,我的

以上效果,由四个ets文件实现,分别是容器页面。首页,购物车,我的。

页面里的数据,我是用json-server进行模拟的数据。

一、容器页面

使用组件Tabs和Tabcontent结合。

import Home from "./Home";
import ShoppingCar from "./ShoppingCar";
import My from "./My";

@Entry
@Component
struct TabsExample {

  // 定义变量,表示当前选中的下标
  @State currentIndex:number = 0;

  @State arr:Array<Object> =[
    {
      icon:"/imgs/home.png",
      selectedIcon:"/imgs/home2.png",
      text:"首页"
    },
    {
      icon:"/imgs/gouwuche.png",
      selectedIcon:"/imgs/gouwuche2.png",
      text:"购物车"
    },
    {
      icon:"/imgs/wode.png",
      selectedIcon:"/imgs/wode2.png",
      text:"我的"
    }
  ]

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End }) {
        ForEach(this.arr,(item,idx)=>{
          TabContent() {
            if(this.currentIndex==0){
              Home()
            }else if(this.currentIndex==1){
              ShoppingCar()
            }else{
              My()
            }
          }.tabBar({
            icon: (this.currentIndex==idx)?item.selectedIcon:item.icon,
            text:item.text
          })
        })

      }
      .width(360)
      .height("100%")
      .onChange((idx)=>{
        this.currentIndex = idx;
      })

    }.width('100%')
  }
}

二、首页

import http from '@ohos.net.http';
import router from '@ohos.router';

interface IBook{
  id:string,
  name:string,
  author:string,
  publish:string,
  img:string
}

@Entry
@Component
  // 对外开放
export default struct Home {

  @State books:Array<IBook> = [];

  @State imgs: Array<string> = [];
  scroller: Scroller = new Scroller()

  // 创建http的请求对象
  httpRequest = http.createHttp();

  // 获取轮播图数据
  getBanners(){

    this.httpRequest.request("http://localhost:3000/bannerImgs",(err,data)=>{
      if(!err){
        this.imgs = JSON.parse(data.result as string);
        this.initScroll();
      }
    })
  }

  // 获取书籍信息
  getBooks(){
    //发送请求
    this.httpRequest.request("http://localhost:3000/books",(err,data)=>{
      if(!err){
        // console.log("data",data)
        //   data对象的result属性是数据
        //   console.log("data.result",data.result)
        //   JSON.parse():把字符串转成json对象。
        this.books = JSON.parse(data.result as string);
      }
    })
  }

  // aboutToAppear():这个生命周期钩子函数的调用时机:当本页面(组件)加载时,
  aboutToAppear(){
    this.getBooks();
    this.getBanners();
  }

  // 自行实现轮播图功能:
  initScroll(){
    let index = 0;
    let maxIndex = this.imgs.length-1;
    setInterval(()=>{
      index++;
      if(index>maxIndex){
        index = 0;
      }
      this.scroller.scrollTo({
        xOffset:index*400,
        yOffset:0,
        animation:{
          duration:1000,
          curve:Curve.Linear
        }
      })
    },2000)
  }

  build() {
    // 最外层使用弹性盒布局,纵向分为三部分:搜索框,滚动容器,底部。
    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween }) {
      // 1、搜索框
      Search({ placeholder: '请输入您要搜索的内容', icon: "imgs/search01.png" })
        .searchButton('搜索')
        .textAlign(TextAlign.Center)
        .width("100%")
        .height(60)
        .backgroundColor('#F5F5F5')
        .placeholderColor(Color.Grey)
        .placeholderFont({ size: 20, weight: 400 })
        .textFont({ size: 30, weight: 400 })
        .onSubmit(()=>{
          console.log("onSubmit")
          router.pushUrl({
            url:"pages/SearchPage"
          })
        })

      Scroll() {
        Column() {
          // 1)、轮播图
          List({scroller:this.scroller}){
            ForEach(this.imgs,(item)=>{
              ListItem(){
                Image(item)
                  .width(400)
                  .height("100%")
              }
            })
          }
          .width("100%")
          .height(250)
          .listDirection(Axis.Horizontal)

          Swiper(){
            ForEach(this.imgs,(item)=>{
                Image(item)
                  .width(400)
                  .height("100%")
            })
          }

          // 2)、导航
          Grid() {
            GridItem() {
              Column() {
                Image("https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/178015/31/13828/6862/60ec0c04Ee2fd63ac/ccf74d805a059a44.png")
                  .width(40)
                  .height(40)
                Text("京东超市")
              }
            }

            GridItem() {
              Column() {
                Image("https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/178015/31/13828/6862/60ec0c04Ee2fd63ac/ccf74d805a059a44.png")
                  .width(40)
                  .height(40)
                Text("京东超市")
              }
            }

            GridItem() {
              Column() {
                Image("https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/178015/31/13828/6862/60ec0c04Ee2fd63ac/ccf74d805a059a44.png")
                  .width(40)
                  .height(40)
                Text("京东超市")
              }
            }

            GridItem() {
              Column() {
                Image("https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/178015/31/13828/6862/60ec0c04Ee2fd63ac/ccf74d805a059a44.png")
                  .width(40)
                  .height(40)
                Text("京东超市")
              }
            }

            GridItem() {
              Column() {
                Image("https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/178015/31/13828/6862/60ec0c04Ee2fd63ac/ccf74d805a059a44.png")
                  .width(40)
                  .height(40)
                Text("京东超市")
              }
            }

            GridItem() {
              Column() {
                Image("https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/178015/31/13828/6862/60ec0c04Ee2fd63ac/ccf74d805a059a44.png")
                  .width(40)
                  .height(40)
                Text("京东超市")
              }
            }

            GridItem() {
              Column() {
                Image("https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/178015/31/13828/6862/60ec0c04Ee2fd63ac/ccf74d805a059a44.png")
                  .width(40)
                  .height(40)
                Text("京东超市")
              }
            }

            GridItem() {
              Column() {
                Image("https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/178015/31/13828/6862/60ec0c04Ee2fd63ac/ccf74d805a059a44.png")
                  .width(40)
                  .height(40)
                Text("京东超市")
              }
            }

          }
          .columnsTemplate('1fr 1fr 1fr 1fr')
          .rowsTemplate('1fr 1fr')
          .columnsGap(10)
          .width('100%')
          .backgroundColor(0xededed)
          .height(180)

          // 3)、列表
          Column(){
            ForEach(this.books,(item)=>{
              Row(){
                Image(item.img).width(120).height(120).margin(20).onClick(()=>{
                  // 跳转到详情页面的同时,传递了参数:bookid
                  router.pushUrl({
                    url:"pages/Detail",
                    params:{
                      bookid:item.id
                    }
                  })
                })
                Column(){
                  Text(item.name).fontSize(22).width("100%").margin(10)
                  Text(item.author).fontSize(22).width("100%").margin(10)
                  Text(item.publish).fontSize(22).width("100%")
                }
                .width(200)
                .height("100%")
              }
              .width("95%")
              .height(140)
              .margin(10)
              .backgroundColor(0xdddddd)
              .borderRadius(10)
              .margin(10)
            })
          }.width("100%")

        }.width("100%")
      }
      .width("100%")
      .height("100%")
      .align(Alignment.TopStart)

    }
    .width("100%")
    .height("100%")
  }
}

三、购物车

import router from '@ohos.router';
import http from '@ohos.net.http';
import {storage} from "../utils/globalData"

// 自定义类型:商品类型

interface IBook{
  isChecked?:boolean,
  id:string,
  name:string,
  price:number,
  count:number,
  smallJi?:number,
  limit?:number
}

@Entry
@Component
export default struct ShoppingCar {

  // 定义状态
  // 购物车的商品
  @State bookList:Array<IBook> = []
  // 全选复选框的数据
  @State isAllChecked:boolean = false;
  // 定义一个状态,表示当前是否登录
  @State isLogin:boolean = storage.get("username");

  //获取购物车数据:
  getCarts(){
    const httpCreate = http.createHttp();
    httpCreate.request(`http://localhost:3000/carts`,(err,data)=>{
      if(!err){
       this.bookList = JSON.parse(data.result as string);
      }
    })
  }

  // 开闭原则:对扩展开放,对修改(逻辑)关闭。进一步解释,最好程序写成可配置的(数据就是配置项)。
  // 页面(组件)加载完毕
  aboutToAppear(){
    // 如果没有登录,则不获取购物车的数据
    if(this.isLogin){
      this.getCarts();
    }
  }

  // 更新数量
  updateCount(item){
    const httpCreate = http.createHttp();
    httpCreate.request(`http://localhost:3000/carts/${item.id}`,{
      method:http.RequestMethod.PUT,
      extraData:{
        name:item.name,
        price:item.price,
        count:item.count,
        smallJi:item.smallJi
      }
    },(err,data)=>{
      if(!err){
        //更新数量功后,重新获取最新数据
        this.getCarts();
      }
    })
  }

  // 定义加号按钮的功能
  addCount(item:IBook){
    //   点击加号按钮
    if(item.limit && item.count==item.limit){ //做限购的处理
      return;
    }
    item.count++;
    item.smallJi = item.count*item.price;
    console.log("item.count",item.count);
    this.bookList = [...this.bookList];
    this.updateCount(item);
  }

  // 定义减号按钮的功能
  subCount(item:IBook){
    //   点击减号按钮
    if(item.count==1){
      return;
    }
    item.count--;
    item.smallJi = item.count*item.price;
    console.log("item.count",item.count);
    this.bookList = [...this.bookList];
    this.updateCount(item);
  }

  // 全选功能
  checkAll(){
    // 当界面上的复选框选中状态发生变化时,数据跟着变化
    this.isAllChecked = !this.isAllChecked;
    //让其它商品的选中状态跟着同步发生变化
    this.bookList.forEach(item=>item.isChecked = this.isAllChecked);

    this.bookList = [...this.bookList];
  }

  // 反向控制全选框
  backCheckAll(item:IBook){
    console.log(item.name+"的复选框被点了")
    item.isChecked = !item.isChecked;
    // console.log("item.isChecked",item.isChecked)
    // 数组的api:every 表示 当数组的每一项如果都符合回调函数里写的条件时,every的返回值是true;否则,返回false。
    // if(this.bookList.every(item=>item.isChecked==true)===true){
    //   this.isAllChecked= true;
    // }else{
    //   this.isAllChecked = false;
    // }
    this.isAllChecked = this.bookList.every(item=>item.isChecked==true);
    this.bookList = [...this.bookList];
  }

  // 总计
  totalMoney(){
    // let money = 0;
    // this.bookList.forEach(item=>{
    //   if(item.isChecked){
    //     money+=item.smallJi;
    //   }
    // })
    // return money;
    //
    return this.bookList.reduce((preValue,item)=>{return preValue+(item.isChecked?item.smallJi:0)},0)
  }

  // 删除购物车的商品
  deleteGoods(id){

    const httpCreate = http.createHttp();
    httpCreate.request(`http://localhost:3000/carts/${id}`,{
      method:http.RequestMethod.DELETE
    },(err,data)=>{
      if(!err){
        //删除成功后,重新获取最新数据
        this.getCarts();
      }
    })

  }

  // UI的描述
  build() {
    Column(){
      // 本页面的标签
      Row() {
        Image($r("app.media.back")).width(50).height(30).margin(20).onClick(()=>{
          router.back();
        })
        Blank().width(60)
        Text("购物车")
          .fontSize(30)
          .width("100%")
          .height(60)
      }
      if(!this.isLogin){
        Column(){
          Text("亲,您还没有登录").fontSize(30).fontColor(Color.Red);
          Button("请登录").onClick(()=>{
            router.replaceUrl({
              url:"pages/Login",
              params:{
                from:"pages/Index",
                data:1
              }
            })
          })
        }
      }else{
        // 购物车的标题行
        Row(){
          Checkbox()
            .select(this.isAllChecked)
            .onClick(()=>{
              this.checkAll();
            })
          Text("名称")
            .width(80)
          Text("价格")
            .width(40)
          Text("数量")
            .width(96)
            .textAlign(TextAlign.Center)
          Text("小计")
            .width(60)
            .textAlign(TextAlign.Center)
          Text("删除")
            .width(60)
            .textAlign(TextAlign.Center)
        }
        .width("100%")
        .height(60)
        .backgroundColor(0xededed)

        // 购物车中的数据的显示
        ForEach(this.bookList,(item,idx)=>{
          Row(){
            Checkbox().select(item.isChecked)
              .onClick(()=>{
                this.backCheckAll(item);
              })
            Text(item.name)
              .width(65)
            Text(item.price.toString())
              .width(50)
              .textAlign(TextAlign.Center)

            Counter() {
              Text(this.bookList[idx].count.toString())
            }.margin(10)
            .onInc(() => {
              this.addCount(item);
            })
            .onDec(() => {
              this.subCount(item);
            })
            // 小计
            Text((this.bookList[idx].smallJi).toString()).width(55)
            Image("/imgs/delete.png").width(40).height(40).onClick(()=>{
              this.deleteGoods(item.id)
            })
          }
          .width("100%")
          .height(60)
        })
        Divider().strokeWidth(10)
        Text(`总计:${this.totalMoney()}`)
      }
    }
    .width("100%")
    .height("100%")

  }
}

四、我的


import {storage} from "../utils/globaldata"

import router from '@ohos.router'
@Entry
@Component
export default struct My {

  //页面创建加载完毕
  aboutToAppear(){
    console.log("My:aboutToAppear")
  }
  // 页面显示
  onPageShow(){
    console.log("My:onPageShow")
  }
  // 页面隐藏
  onPageHide(){
    console.log("My:onPageHide")
  }
  // 销毁
  aboutToDisappear(){
    console.log("My:aboutToDisappear")
  }

  toLogin(){
    router.replaceUrl({
      url:"pages/Login",
      params:{
        from:"pages/Index",
        data:2
      }
    })
  }

  logout(){
    storage.delete("username");
    router.pushUrl({
      url:"pages/Index"
    })
  }

  build() {
    Scroll() {
      Column() {
        Row(){
          Image($r("app.media.back")).width(50).height(30).margin(20).onClick(()=>{
            router.back();
          })
          Button("去注册").onClick(()=>{
            router.pushUrl({
              url:"pages/Reg"
            })
          })
          Button("去登录").onClick(()=>{
           this.toLogin()
          })
          Button("退出登录").onClick(()=>{
            this.logout()
          })
          Button("修改密码").onClick(()=>{
            router.pushUrl({
              url:"pages/Password"
            })
          })
        }.width("100%").height(60)
        Row() {
          Image("/imgs/1.jpg").width(140).height(140).borderRadius(70).onClick(()=>{
            this.toLogin();
          })
        }.width("100%")
        .height(200)
        .margin({
          top: 50
        })
        .justifyContent(FlexAlign.Center)
        // 如果当前处于登录状态(是否保存着有用户名)
        if(storage.get('username')){
          Text(storage.get('username')).fontSize(30)
          Text(storage.get('phone')).fontSize(30).margin(10)
        }

        Blank().height(20)
        Divider().strokeWidth(2).backgroundColor(0xededed)

        Blank().height(20)
        Grid() {
          GridItem() {
            Text("待付款")
              .fontSize(20)
              .width(90)
              .height(90)
              .backgroundColor(0xededed)
              .borderRadius(10)
              .textAlign(TextAlign.Center)
          }

          GridItem() {
            Text("我的订单")
              .fontSize(20)
              .width(90)
              .height(90)
              .backgroundColor(0xededed)
              .borderRadius(10)
              .textAlign(TextAlign.Center)
          }

          GridItem() {
            Text("店铺关注")
              .fontSize(20)
              .width(90)
              .height(90)
              .backgroundColor(0xededed)
              .borderRadius(10)
              .textAlign(TextAlign.Center)
          }
        }
        .columnsTemplate('1fr 1fr 1fr')
        .rowsTemplate('1fr 1fr')
        .columnsGap(10)
        .rowsGap(10)
        .width('95%')
        .height(110)
        .backgroundColor(Color.White)
        .borderRadius(10)


        Blank().height(20)
        Divider().strokeWidth(2).backgroundColor(0xededed)
        Blank().height(20)

        Grid() {
          GridItem() {
            Text("优惠券")
              .fontSize(20)
              .width(90)
              .height(90)
              .backgroundColor(0xededed)
              .borderRadius(10)
              .textAlign(TextAlign.Center)
          }

          GridItem() {
            Text("我的足迹")
              .fontSize(20)
              .width(90)
              .height(90)
              .backgroundColor(0xededed)
              .borderRadius(10)
              .textAlign(TextAlign.Center)
          }

          GridItem() {
            Text("我的收藏")
              .fontSize(20)
              .width(90)
              .height(90)
              .backgroundColor(0xededed)
              .borderRadius(10)
              .textAlign(TextAlign.Center)
          }

          GridItem() {
            Text("浏览记录")
              .fontSize(20)
              .width(90)
              .height(90)
              .backgroundColor(0xededed)
              .borderRadius(10)
              .textAlign(TextAlign.Center)
          }

          GridItem() {
            Text("我的常卖")
              .fontSize(20)
              .width(90)
              .height(90)
              .backgroundColor(0xededed)
              .borderRadius(10)
              .textAlign(TextAlign.Center)
          }

          GridItem() {
            Text("我的推荐")
              .fontSize(20)
              .width(90)
              .height(90)
              .backgroundColor(0xededed)
              .borderRadius(10)
              .textAlign(TextAlign.Center)
          }
        }
        .columnsTemplate('1fr 1fr 1fr')
        .rowsTemplate('1fr 1fr')
        .columnsGap(10)
        .rowsGap(10)
        .width('95%')
        .height(220)
        .backgroundColor(Color.White)
        .borderRadius(10)

      }
      .align(Alignment.Start)
    }.height("100%")
    .width("100%")
  }
}

最近更新

  1. TCP协议是安全的吗?

    2023-12-28 08:56:02       17 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-28 08:56:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-28 08:56:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-28 08:56:02       18 阅读

热门阅读

  1. Scrum敏捷转型机构哪家好推荐

    2023-12-28 08:56:02       35 阅读
  2. Scrum敏捷转型培训公司有哪些?

    2023-12-28 08:56:02       36 阅读
  3. 在架构设计中,前后端分离有什么好处?

    2023-12-28 08:56:02       35 阅读
  4. Swift学习笔记第二节:数组类型

    2023-12-28 08:56:02       33 阅读
  5. Redis学习笔记-发布订阅PubSub

    2023-12-28 08:56:02       40 阅读
  6. 如何记录游戏开发过程中的日志

    2023-12-28 08:56:02       36 阅读
  7. APP打包如何生成

    2023-12-28 08:56:02       36 阅读