黑马商城实战项目
项目搭建
利用HBuilder X创建基本项目结构
运行项目
整理基本项目结构,并修改窗口外观
1
2
3
4
5
6"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "黑马商城",
"navigationBarBackgroundColor": "#1989fa",
"backgroundColor": "#F8F8F8"
}
配置tabbar
创建tabbar对应的四个页面和图标准备好
将页面路径配置到pages.json中的pages数组中
1
2
3
4
5
6
7
8
9
10
11
12
13
14"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index"
},
{
"path": "pages/member/member"
},
{
"path": "pages/cart/cart"
},
{
"path": "pages/search/search"
}
]配置tabbar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31{
"tabBar": {
"list": [
{
"pagePath":"pages/index/index",
"text":"首页",
"iconPath":"static/icon/home.png",
"selectedIconPath":"static/icon/home-active.png"
},
{
"pagePath":"pages/member/member",
"text":"会员",
"iconPath":"static/icon/member.png",
"selectedIconPath":"static/icon/member-active.png"
},
{
"pagePath":"pages/cart/cart",
"text":"购物车",
"iconPath":"static/icon/cart.png",
"selectedIconPath":"static/icon/cart-active.png"
},
{
"pagePath":"pages/search/search",
"text":"搜索",
"iconPath":"static/icon/search.png",
"selectedIconPath":"static/icon/search-active.png"
}
]
}
}
获取轮播图数据
封装uni.request请求,并挂在到全局
创建util》api.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// 封装get请求
const baseUrl = "http://localhost:8082"
export const myRequest = (options)=>{
return new Promise((resolve,reject)=>{
uni.request({
method: options.method,
data: options.data,
url: baseUrl+options.url,
success(res) {
if(res.data.status !== 0) {
return uni.showToast({
title: '获取数据失败'
})
}
resolve(res)
},
fail(err) {
uni.showToast({
title: '获取数据失败'
})
reject(err)
}
})
})
}在main.js中导入并挂载到全局
1
2import { myRequest } from './util/api.js'
Vue.prototype.$myRequest = myReques
获取轮播图的数据
定义获取轮播图的方法
1
2
3
4
5
6
7
8
9methods: {
async getSwipers () {
const res = await this.$myRequest({
method: 'GET',
url: '/api/getlunbo'
})
this.swipers = res.data.message
}
}在onLoad中调用该方法
1
this.getSwipers()
实现轮播图的结构和数据渲染
定义轮播图的基本结构
1
2
3
4
5<swiper class="swiper" indicator-dots :autoplay="true" :interval="2000" circular>
<swiper-item v-for="item in swipers" :key="item.id">
<image :src="item.img"></image>
</swiper-item>
</swiper>样式,在工具中安装scss
1
2
3
4
5
6
7
8
9
10
11<style lang="scss">
.home{
swiper{
height: 380rpx;
image{
width: 750rpx;
height: 380rpx;
}
}
}
</style>
实现菜单导航结构
引入字体图标初始化样式
1 | <style> |
完成菜单导航基本结构
1 | <view class="nav"> |
菜单导航样式
1 | .nav{ |
实现推荐商品列表
定义基本结构
1 | <view class="hot_goods"> |
美化样式
1 | .hot_goods { |
获取数据
定义获取数据的方法
1
2
3
4
5
6
7// 获取推荐商品
async getGoods () {
const res = await this.$myRequest({
url: '/api/getgoods?pageindex=1'
})
this.goods = res.data.message
}在onLoad生命周期中调用该方法
1
this.getGoods()
渲染数据
通过v-for渲染数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14<view class="hot_goods">
<view class="tit">推荐商品</view>
<!-- 一般用法 -->
<view class="goods_list">
<view class="goods_item" v-for="item in goods" :key="item.id">
<image :src="item.img_url"></image>
<view class="price">
<text>{{item.sell_price}}</text>
<text>{{item.market_price}}</text>
</view>
<view class="name">{{item.title}}</view>
</view>
</view>
</view>
完成黑马超市页面
改造导航菜单
定义数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22navs: [
{
icons: "iconfont icon-ziyuan",
title: "黑马超市",
path: "/pages/goods/list"
},
{
icons: "iconfont icon-tupian",
title: "社区图片",
path: "/pages/pics/pics"
},
{
icons: "iconfont icon-guanyuwomen",
title: "联系我们",
path: "/pages/contact/contact"
},
{
icons: "iconfont icon-shipin",
title: "学习视频",
path: "/pages/videos/videos"
}
]渲染数据
1
2
3
4
5
6<view class="nav">
<view class="item" v-for="(item,index) in navs" :key="index">
<view :class="item.icons"></view>
<text>{{item.title}}</text>
</view>
</view>给导航菜单注册点击事件
1
<view class="goods_item" v-for="item in goods" :key="item.id">
定义跳转的方法
1
2
3
4
5goNavigator (url) {
uni.navigateTo({
url
})
}
创建黑马超市页面
- 创建页面,goods>list.vue
- 将页面路劲配置到pages文件中,修改标题
封装商品列表组件
在components下面创建goods>list.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58<template>
<view class="goods_list">
<view class="goods_item" v-for="item in goods" :key="item.id">
<image :src="item.img_url"></image>
<view class="price">
<text>{{item.sell_price}}</text>
<text>{{item.market_price}}</text>
</view>
<view class="name">{{item.title}}</view>
</view>
</view>
</template>
<script>
export default {
props:{
goods:Array
}
}
</script>
<style lang="scss">
.goods_list {
display: flex;
padding: 0 15rpx;
justify-content: space-between;
overflow: hidden;
flex-wrap: wrap;
.goods_item {
width: 355rpx;
margin-bottom: 15rpx;
background: #fff;
padding: 10px;
box-sizing: border-box;
image{
height: 150px;
width: 150px;
display: block;
margin: 10px auto;
}
.price{
font-size: 18px;
color: red;
padding: 8px 0;
text:nth-child(2){
color: #ccc;
text-decoration: line-through;
margin-left: 10px;
font-size: 13px;
}
}
.name {
font-size: 14px;
}
}
}
</style>在首页引入该组件
1
2
3
4
5import goodsList from "../../components/goods-list/index.vue"
components: {
"goods-list":goodsList
}使用组件并将数据传递到组件内部
1
<goods-list :goods="goods"></goods-list>
渲染商品列表
定义获取商品列表数据的方法并调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<script>
export default {
data () {
return {
goods: []
}
},
methods: {
async getGoods () {
const res = await this.$myRequest({
url: '/api/getgoods?pageindex=1'
})
this.goods = res.data.message
},
},
onLoad () {
this.getGoods()
}
}
</script>引入商品组件并使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14<template>
<view class="goods_list">
<goods-list :goods="goods"></goods-list>
</view>
</template>
<script>
import goodsList from "../../components/goods-list/index.vue"
export default {
components: {
"goods-list": goodsList
}
}
</script>
实现上拉加载更多
通过onReachBottom来监听触底
1
2
3
4onReachBottom () {
this.pageindex++
this.getGoods()
}修改给goods赋值
1
this.goods = [...this.goods,...res.data.message]
动态显示底线
通过onReachBottom监听是否还有更多
1
if(this.pageindex*10>this.goods.length) return this.flag = true
通过v-if控制底线
1
<view class="over_line" v-if="flag">----------我是有底线的----------</view>
实现下拉刷新
通过onPullDownRefresh进行下拉刷新的操作
1
2
3
4
5
6
7
8
9
10onPullDownRefresh() {
this.goods = []
this.pageindex = 1
this.flag = false
setTimeout(()=>{
this.getGoods(()=>{
uni.stopPullDownRefresh()
})
},1000)
}
关于我们
实现社区图片
实现资讯列表
实现列表项的结构和样式
结构
1 | <view class="news_item"> |
样式
1 | .news{ |
封装为组件
创建news-item.vue
1 | <template> |
在新闻页面导入并使用
1 | <template> |
点击列表进入详情
点击子组件列表项通过this.$emit触发父组件的方法
1
2
3navigatorTo (item) {
this.$emit('clickItem',item)
}父组件通过注册clickItem事件及事件函数实现跳转操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<template>
<view class="news">
<new-item :data="newsList" @clickItem="goDetail"></new-item>
</view>
</template>
<script>
export default {
methods: {
goDetail (data) {
console.log(data)
uni.navigateTo({
url: '/pages/news-detail/news-detail'
})
}
}
}
</script>新建/pages/news-detail/news-detail页面
实现资讯详情
实现基本结构
1 | <template> |
获取详情的数据
1 | methods: { |
实现详情的渲染
1 | <view class="news_title"> |
实现商品详情页
商品列表注册点击事件
1 | <template> |
父组件绑定自定义事件进行跳转
1 | <goods-list @itemClick="godetail" :goods="goods"></goods-list> |
创建商品详情页
获取详情轮播图数据
1 | methods: { |
渲染轮播图
1 | <swiper indicator-dots> |
获取商品信息
1 | methods: { |