uniapp实现购物商城主页面
向服务器发送请求,获取数据,还将数据保存到本地缓存中,以便在用户下次访问时可以直接使用缓存中的数据。”:垂直滚动的视图。2.使用“uni.getStorageSync()”方法从本地缓存中获取名为“cates”的数据,如果本地缓存中没有该数据,则执行“this.getCategories()”方法从服务器端获取数据。数据请求:使用异步函数,在请求指定 URL 的数据后,将结果赋值给this.get
文章目录
1. 下载 HBuilderX
官网链接:https://www.dcloud.io/hbuilderx.html
2. 安装 HBuilderX
1.将在官网下载好的压缩包解压到文件夹中
2.解压完成后双击.exe文件就能打开HBuilderX
3. 首页
3.1 效果图:
3.2 实现代码:
数据请求:使用异步函数,在请求指定 URL 的数据后,将结果赋值给this.getSwiperList()、this.getNavList()、this.getFloordata() 变量。
export default {
data() {
return {
swiperList: [],
navList: [],
floordata: []
}
},
onLoad() {
this.getSwiperList()
this.getNavList()
this.getFloordata()
},
methods: {
async getSwiperList() {
const res = await this.$Https({
url: '/home/swiperdata'
})
// console.log(res);
this.swiperList = res.message;
},
async getNavList() {
const res = await this.$Https({
url: '/home/catitems'
})
// console.log(res);
this.navList = res.message;
},
async getFloordata() {
const res = await this.$Https({
url: '/home/floordata'
})
// console.log(res);
this.floordata = res.message;
}
}
}
3.3 页面ui结构:
<template>
<view>
<view class="content">
<!-- 搜索框组件 -->
<zujian-header></zujian-header>
</view>
<!-- 轮播图区域 -->
<swiper :indicator-dots="true" :autoplay="true" :interval="3500" :duration="1000" :circular="true">
<swiper-item v-for="(item, i) in swiperList" :key="i">
<view class="swiper-item">
<image :src="item.image_src"></image>
</view>
</swiper-item>
</swiper>
<!-- 导航区域 -->
<view class="nav-list">
<view class="nav-item" v-for="(item,i) in navList" :key='i'>
<image :src="item.image_src" class="nav-img"></image>
</view>
</view>
<!-- 楼层区域 -->
<view class="floor-list">
<view class="floor-item" v-for="(item, i) in floordata" :key="i">
<image :src="item.floor_title.image_src" class="floor-title"></image>
<view class="floor-img-box">
<view class="left-img-box">
<image :src="item.product_list[0].image_src"
:style="{width: item.product_list[0].image_width + 'rpx'}" mode="widthFix"></image>
</view>
<view class="right-img-box">
<view class="right-img-item" v-for="(item2, i2) in item.product_list" :key="i2" v-if="i2 !== 0">
<image :src="item2.image_src" mode="widthFix" :style="{width: item2.image_width + 'rpx'}">
</image>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
4. 分类页面
4.1 效果图
4.2 动态渲染分类列表
4.2.1 页面左侧列表ui结构
“scroll-view”:垂直滚动的视图。使用v-bind指令来绑定属性值,以实现动态更新属性。在这里,scroll-y属性被设置为true,以启用垂直滚动。"scroll-top"属性来设置视图的初始滚动位置。这个属性可以用来控制视图的滚动位置,以便用户可以直接跳转到他们感兴趣的内容。
<view class="left-list">
<scroll-view scroll-y="true" class="left-scroll-view" :style="{height:winh+'px'}">
<view class="left-view" :class="index == active ? 'active' : '' " v-for="(item,index) in leftview"
:key="index" @tap="ChangedIndex(index)">
<text>{{item}}</text>
</view>
</scroll-view>
</view>
4.2.3 页面右侧列表ui结构
<scroll-view scroll-y="true" class="right-list" :style="{height:winh+'px'}" :scroll-top="scrollTop">
<view class="right-view" v-for="(item,index) in rightview" :key="index">
<view>
<view><span>/</span>{{item.cat_name}}<span>/</span></view>
</view>
<view class="lv3-list">
<navigator v-for="(item2,index2) in item.children" :key="index2"
:url="'../../subpkg1/goods-list/goods-list?cid='+item2.cat_id">
<image :src="item2.cat_icon"></image>
<text>{{item2.cat_name}}</text>
</navigator>
</view>
</view>
</scroll-view>
4.3实现代码
1.使用生命周期函数“onLoad()”,它在页面加载时会自动执行。
2.使用“uni.getStorageSync()”方法从本地缓存中获取名为“cates”的数据,如果本地缓存中没有该数据,则执行“this.getCategories()”方法从服务器端获取数据。
onLoad() {
const Cates = uni.getStorageSync('cates');
if (!Cates) {
this.getCategories();
} else {
if ((Date.now() - Cates.time) > 1000 * 10) {
this.getCategories();
} else {
console.log('使用旧数据');
this.categories = Cates.data;
this.leftview = this.categories.map(e => e.cat_name)
this.rightview = this.categories[0].children
}
}
},
3.getCategories方法:这是异步方法,它使用了async和await关键字,以便在等待服务器返回数据时不会阻塞页面的渲染。向服务器发送请求,获取数据,还将数据保存到本地缓存中,以便在用户下次访问时可以直接使用缓存中的数据。如果数据保存失败,则会弹出一个提示框。
4.ChangedIndex方法:处理分类切换的方法。它接收参数index,表示用户选择的分类的索引。该方法将data中的“active”属性设置为index,以标记当前选中的分类。然后,更新data中的“rightview”属性,以显示该分类下的子分类。
methods: {
async getCategories() {
const res = await this.$Https({
url: '/categories'
})
this.categories = res.message
try {
uni.setStorageSync('cates', {
time: Data.now(),
data: this.categories
});
} catch (e) {
uni.showToast({
tital: "数据缓存失败",
duration: 2000
})
}
this.leftview = this.categories.map(v => v.cat_name)
this.rightview = this.categories[0].children
// console.log(this.rightview);
},
ChangedIndex(index) {
this.active = index;
this.rightview = this.categories[index].children
this.scrollTop = this.scrollTop === 0 ? 1 : 0
}
}
5. 购物车页面
5.1 效果图
5.2 页面ui结构
<template>
<view>
<view v-if="cart.length!==0">
<zujian-address :address='address'></zujian-address>
<view class="cart-title">
<text class="cart-title-text">购物车</text>
</view>
<zujian-goods v-for="(item,index) in cart" :key="index" :goods='item' :showCheck='true' :showNum='true'
:allowLongTop='true' @changeNum='changeNum' @changeChecked='changeChecked'></zujian-goods>
<zujian-setter :cartData="cart" :showAllCheck="true" :buttonText="'结算'" @changeAllChecked="changeAllChecked">
</zujian-setter>
</view>
<view v-else class="cartNull">
<img src="../../static/none.png" alt="">
</view>
</view>
</template>
5.3 实现代码
- data属性:在组件中定义data属性,包含了默认图片链接和两个用于控制商品数量的属vshowNum和vshowNumOnly。
- props属性:在组件中定义props属性,用于接收父组件传递过来的数据。其中,goods属性表示商品的详细信息,showCheck属性表示是否显示选择框,showNum属性表示是否显示商品数量,allowLongTop属性表示是否允许长按删除,showNumOnly属性表示是否只显示商品数量而不显示加减按钮。
- methods方法:在组件中定义了一些方法,用于处理用户的操作。showNumEdit方法用于显示商品数量编辑框,gotoDetail方法用于跳转到商品详情页面,changeChecked方法用于切换商品的选中状态,numSub方法用于减少商品数量,numAdd方法用于增加商品数量,deletegoods方法用于长按删除商品。
- emit方法:组件中使用了emit方法来触发父组件的事件,以便将商品的选中状态和数量更新到父组件中。
export default {
name: "yjs-goods",
data() {
return {
defaultImg: '../../static/no.gif',
vshowNum: this.showNum,
vshowNumOnly: this.showNumOnly
};
},
props: {
goods: {
type: Object,
default: null
},
showCheck: {
type: Boolean,
default: false
},
showNum: {
type: Boolean,
default: false
},
allowLongTop: {
type: Boolean,
default: false
},
showNumOnly: {
type: Boolean,
default: false
}
},
methods: {
showNumEdit() {
this.vshowNum = true;
this.vshowNumOnly = false;
},
gotoDetail() {
uni.navigateTo({
url: '../../subpkg1/goods-detail/goods-detail?goods_id=' + this.goods.goods_id
})
},
changeChecked() {
this.$emit('changeChecked', {
goods_id: this.goods.goods_id,
checked: !this.goods.checked
})
},
numSub() {
if (this.goods.cartNum > 1) {
this.$emit('changeNum', {
goods_id: this.goods.goods_id,
cartNum: this.goods.cartNum - 1
});
}
},
numAdd() {
this.$emit('changeNum', {
goods_id: this.goods.goods_id,
cartNum: this.goods.cartNum + 1,
})
},
//长按删除
deletegoods() {
if (this.allowLongTop) {
uni.showModal({
title: '删除',
content: '是否删除此商品',
success: (res) => {
if (res.confirm) {
this.$emit('changeNum', {
goods_id: this.goods.goods_id,
cartNum: 0
});
}
}
})
}
}
}
}
6.我的页面
6.1 效果图
6.2 页面ui结构
<template>
<view>
<view class="my-userinfo-container" :style="{height:winh+'px'}">
<view class="top-box">
<img :src="userInfo.avatarUrl" alt="" style="width: 90px;height: 90px; border-radius: 50%;">
<view class="nickname">{{userInfo.nickName}}</view>
</view>
<view class="panel-list">
<view class="panel">
<view class="panel-body">
<view class="panel-item" v-for="(item,index) in Feet" :key="item.id">
<text>{{item.num}}</text>
<text>{{item.text}}</text>
</view>
</view>
</view>
<view class="panel">
<view class="panel-title">我的订单</view>
<view class="panel-body">
<view class="panel-item" v-for="(item,index) in FeetTow" :key="item.id"
@click="gotoOrder(index)">
<i :style="{ fontFamily: 'iconfont' }" v-html="item.icon"
style="font-size: 25px; color:var(--blue); font-weight: 600;"></i>
<text>{{item.text}}</text>
</view>
</view>
</view>
<view class="panel">
<view class="panel-list-item but">
<text>收货地址管理</text>
<uni-icons type="arrowright" size="15"></uni-icons>
</view>
<view class="panel-list-item">
<text>联系客服</text>
<text>400-123-654</text>
</view>
<view class="panel-list-item">
<text>意见反馈</text>
<uni-icons type="arrowright" size="15"></uni-icons>
</view>
<view class="panel-list-item">
<text @click="gotoOrder">关于我们</text>
<uni-icons type="arrowright" size="15"></uni-icons>
</view>
</view>
<button class="btn-login" @click="logout">退出登录</button>
</view>
</view>
</view>
</template>
6.3 实现代码
- 使用“uni.getStorageSync()”方法从本地缓存中获取“userInfo”的数据,将其保存在data的“userInfo”属性中。这个数据包含了用户的基本信息,如用户名、头像等。
- 使用“uni.getStorageSync()”方法从本地缓存中获取名为“token”的数据,将其保存在data的“token”属性中。用于验证用户的身份,以便在用户进行一些敏感操作时进行权限验证。
- 如果本地缓存中没有“token”数据,则将当前页面的标识保存在本地缓存中,使用“uni.reLaunch()”方法跳转到登录页面。
- methods方法中定义了两个方法,其中logout方法用于实现用户退出登录的功能。它使用“uni.showModal()”方法弹出一个模态框,询问用户是否确认退出登录。如果用户确认退出,则使用“uni.removeStorageSync()”方法从本地缓存中移除“token”、“address”和“userinfo”数据,并使用“uni.redirectTo()”方法跳转到登录页面。
- gotoOrder方法用于跳转到订单页面,如果订单数量为0,则跳转到订单页面,并将订单数量作为参数传递给订单页面。
data() {
return {
winh: 0,
token: '',
userInfo: {},
Feet:
[
{id: 0,num: 0,text: '收藏的店铺'},
{id: 1,num: 0,text: '收藏的商品'},
{id: 2,num: 0,text: '关注的商品'},
{id: 3,num: 0,text: '我的足迹'},
],
FeetTow:
[
{id: 0,icon: '',text: '全部订单'},
{id: 1,icon: '',text: '待付款'},
{id: 2,icon: '',text: '待收货'},
{id: 3,icon: '',text: '退款/退货'},
]
}
}
},
onShow() {
this.userInfo = uni.getStorageSync('userInfo');
// console.log(this.userInfo);
this.token = uni.getStorageSync('token');
if (!this.token) {
uni.setStorageSync('page', 'user')
uni.reLaunch({
url: '../../subpkg2/login/login'
})
}
},
methods: {
async logout() {
const result = await uni.showModal({
title: '提示',
content: '确认退出登录吗'
});
const {
err = null, confirm: succ = false
} = result || {};
if (succ) {
uni.removeStorageSync('token');
uni.removeStorageSync('address');
uni.removeStorageSync('userinfo');
uni.redirectTo({
url: '../../subpkg2/login/login'
});
}
},
gotoOrder(num) {
if (num == 0) {
uni.navigateTo({
url: '../../subpkg2/order/order?num=' + num
})
}
}
}
}
更多推荐
所有评论(0)