以上效果,由四个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%")
}
}