项目(小u商城)、项目初始化、封装网络请求、项目

项目【小U商城】

一、项目初始化

安装步骤

1.打开数据库服务  
	wampserve
	
2.新建数据库  导入shop_db       root 没有密码

3.打开后台数据接口 shop_api  
	npm install
	npm start

4.打开后台管理系统 shop_vue_admin 
	npm install
	npm start
			admin 123123
	
5.导入静态页面
	运行 h5
		微信小程序

二、封装网络请求

1.封装config.js 管理常量

// 常量

let baseUrl = ""
if(process.env.NODE_ENV === 'development'){
    // console.log('开发环境')
	baseUrl = "http://localhost:3000"
}else{
    // console.log('生产环境')
	baseUrl = "https://uapi.xqb.ink"
}

export default {
	baseUrl
}

2.封装 http.js 网络请求

request 异步请求(不能直接在调用http方法时拿到请求的结果)

​ 所以 要通过promise形式返回值,但是request方法 有返回的默认值,不会直接返回promise

​ 所以 只能自己封装一个 返回 promise 的请求方法,

// 封装网络请求
import config from "./config.js"

let http = (option={})=>{
	// url  data method header timeout
	return new Promise((resolve,reject)=>{
		
		uni.request({
			url: config.baseUrl + option.url,
			data: option.data || {},
			method: option.method || "GET",
			header: option.header || {
				"content-type":"application/json"
			},
			timeout: option.timeout || 60000,
			// success:res=>{
			// 	resolve(res)
			// },
			success:resolve,
			fail:err=>{
				reject(err)
			}
		})
		
	})
}
export default http

3.封装api.js

可以统一管理所有接口,

    // 管理所有请求接口

    import http from "./http.js"

    // 1.获取一级分类
    const _getFirstCate=()=>{
        let option={
            url:"/api/getcate"
        }
        return http(option)
    }
    // 2.获取banner


    export default {
        _getFirstCate
    }

4.挂载到原型上

main.js

import api from "./utils/api.js"
Vue.prototype.$api = api

三、项目

2.首页数据

2.1获取首页一级分类

接口

api.js

// 1.获取一级分类数据
const _getFirstCate=()=>{
	let option={
		url:"/api/getcate"
	}
	return http(option)
}
// 2.获取banner


export default {
	_getFirstCate
}

数据请求

(1)获取一级分类

代码案例

index.vue

// 1.获取一级分类
    async getFirstCate(){
        // let res = await this.$http({url:"/api/getcate"})
        // console.log(res);

        let res = await this.$api._getFirstCate()
        // console.log(res);
        this.firstCate = res.data.list	
    },

(2)选项卡切换

代码案例

<scroll-view id="tab-bar" class="scroll-h" scroll-x="{true}">
    <view class="uni-tab-item">
        <text 
              @click="changeIndex(0)"
              class="uni-tab-item-title " 
              :class="activeIndex == 0?'uni-tab-item-title-active' :''">
            		推荐
        </text>
    </view>
    <view class="uni-tab-item " v-for="(item,index) in firstCate">
        <text
              @click="changeIndex(index+1)" 
              class="uni-tab-item-title " 
              :class="activeIndex == index+1 ?'uni-tab-item-title-active' :''">								{{item.catename}}
        </text>
    </view>
				
</scroll-view>
// 2.一级分类 切换选项卡
    changeIndex(index){
        this.activeIndex = index
    }

2.2首页轮播图

接口

// 2.获取banner
const _getBanner = ()=>{
	let option={
		url:"/api/getbanner"
	}
	return http(option)
}

export default {
	_getFirstCate,
	_getBanner
}

数据请求

代码案例

data() {
			return {
				firstCate:[],
				activeIndex:2,
				baseUrl:"",
				banner:[]
			}
		},
		onShow() {
			this.getFirstCate()
			this.getBanner()
			this.baseUrl = this.$config.baseUrl
		},
		methods: {
            // 3.获取banner 轮播
                async getBanner(){
                    let res = await this.$api._getBanner()
                    console.log(res);
                    this.banner = res.data.list

                }
结构:            

    <!-- 推荐轮播图 -->
            <view class="banner-container">
                <swiper :indicator-dots="true" :autoplay="true" :interval="2000" :duration="1000">
                    <swiper-item v-for="(item,index) in banner" :key="index">
                        <view class="swiper-item">
                            <image :src="baseUrl+item.img" mode=""></image>
                        </view>
                    </swiper-item>
                </swiper>
            </view>

2.3限时秒杀

接口

// 3.获取秒杀活动
const _getSeckill = ()=>{
	let option={
		url:"/api/getseckill"
	}
	return http(option)
}


export default {
	_getFirstCate,
	_getBanner,
	_getSeckill
}

(1)获取活动信息

代码案例

	async getSeckill(){
        let res = await this.$api._getSeckill()
        console.log(res);
        this.secimg = res.data.list[0].img
    }

(2)处理倒计时

代码案例

async getSeckill(){
				let res = await this.$api._getSeckill()
				console.log(res);
    			// 页面倒计时活动 图片
				this.secimg = res.data.list[0].img
				
				// 获取倒计时 结束的时间戳
				let endTime = res.data.list[0].endtime
				// 倒计时显示
				this.timeObj = this.actionTime(endTime)
				this.time = setInterval(()=>{
					//console.log(111);
					this.timeObj = this.actionTime(endTime)
				},1000)	
			},
			// 处理时间
			actionTime(endTime){
                
                // 获取现在的时间  结束的时间戳-现在的时间戳
				var nowTime = new Date().getTime()
				// 时间差--秒 3670  1h 1min 10s
				var sTime = parseInt((endTime- nowTime)/1000)
				
				var h = parseInt(sTime/3600)
				var m = parseInt((sTime%3600)/60)
				var s = sTime % 60
				
				h < 10 ? h="0"+ h : h = h
				m < 10 ? m="0"+ m : m = m
				s < 10 ? s="0"+ s : s = s
				
				return {h,m,s}
				
				
			}

(3)优化—离开页面关闭定时器

代码案例

onHide(){
    clearInterval(this.time)
},

2.4底部商品信息

(1)底部商品选项卡切换

代码案例

// 7.底部商品 选项卡切换
    changeMenuIndex(index){
        this.menuIndex = index
    }
<!-- 商品标签 -->
			<view class="tags">
				<view class="tag_list" :class="menuIndex == 0 ?'active_tag_list' :''" @click="changeMenuIndex(0)">
					<label for="">热门推荐</label>
				</view>
				<view class="tag_list" :class="menuIndex == 1 ?'active_tag_list' :''" @click="changeMenuIndex(1)">
					<label for="">最新好货</label>
				</view>
				<view class="tag_list" :class="menuIndex == 2 ?'active_tag_list' :''" @click="changeMenuIndex(2)">
					<label for="">所有商品</label>
				</view>
			</view>
			<!-- 标签对应的商品 -->
			<view class="tags_product">
				
				<block v-if="indexGoods.length>0">
					<view class="product" v-for="(item,index) in indexGoods[menuIndex].content">
						<view class="GoodsLeft">
							<image class="GoodsImg" :src="baseUrl+item.img" alt />
						</view>
						<view class="GoodsCont">
							<view class="GoodConTit">{{item.goodsname}}</view>
							<view class="GoodsPrice">¥{{item.price}}</view>
							<view class="yimai">已售50件</view>
							<view class="Immed">立即抢购</view>
						</view>
					</view>
				</block>
			</view>

(2)数据获取

接口:


// 4.获取底部商品
const _getIndexGoods = ()=>{
	let option={
		url:"/api/getindexgoods"
	}
	return http(option)
}


export default {
	_getFirstCate,_getBanner,_getSeckill,_getIndexGoods
}

代码案例

// 6.获取底部商品
			async getIndexGoods(){
				let res = await this.$api._getIndexGoods()
				console.log(res);
				this.indexGoods = res.data.list
			},

2.5搜索框聚焦跳转到搜索页面

代码案例

@focus

// 8.顶部 聚焦 跳转到搜索页面
    toSearchPage(){
        uni.navigateTo({
            url:"../search/search"
        })
    }

3.搜索页

参数:

参数名说明
keywords搜索关键字,必填项

接口

// 5.搜索
const _search=(keywords)=>{
	let option={
		url:"/api/search",
		data:{
			keywords
		}
	}
	return http(option)
}


export default {
	_getFirstCate,_getBanner,_getSeckill,_getIndexGoods,_search
}

代码案例

data() {
			return {
				list:[],
				baseUrl:""
			}
		},
		onShow(){
			this.baseUrl = this.$config.baseUrl
		},
		methods:{
			// 键盘输入事件  
			async search(e){
				//console.log(e)
				let keywords = e.value
                if(keywords == "") return;
                
				let res = await this.$api._search(keywords)
				//console.log(res);
				this.list = res.data.list || []
			}
		}
<uni-search-bar :radius="100" bgColor="#ffffff" class="input_" @input="search"></uni-search-bar>
		<view class="list" v-if="list.length>0">
			
			<view class="row" v-for="(item,index) in list">
				<image :src="baseUrl+item.img" mode="widthFix"></image>
				<view class="info">
					<text>{{item.goodsname}}</text>	
					<text>原价¥{{item.price}}</text>	
					<text>现价¥{{item.market_price}}</text>	
					<text>3565评论</text>	
				</view>
			</view>
			
		</view>
		<view class="tishi" v-else>
			没有数据亲!
		</view>

4.商品分类

(1)跳转到商品分类页面

代码案例

index.vue

// 9.全部分类
			toCatePage(){
				uni.navigateTo({
					url:"../classify/classify"
				})
			}

(2)获取信息

接口:

// 6.获取全部分类
const _getCates = ()=>{
	let option={
		url:"/api/getcates"
	}
	return http(option)
}


export default {
	_getFirstCate,_getBanner,_getSeckill,_getIndexGoods,_search,_getCates
}

代码案例

classify.vue

<template>
	<view class="container">
		<!-- left左侧列表 -->
		<view class="left">
			<!-- 循环遍历的 -->
			<view @click="changeIndex(index)" v-for="(item,index) in cates" class="left_list" :class="activeIndex == index ? 'activeList' : '' ">
				<label for="">{{item.catename}}</label>
			</view>
			
		</view>
		<!-- right右侧详细分类商品 -->
		<view class="right">
			<!-- 每一个小类 -->
			<view class="right_list">
				<!-- 商品 -->
				<view class="bottom" v-if="cates.length>0">
					<view class="bottom_list" v-for="(item,index) in cates[activeIndex].children">
						<view>
							<image :src="baseUrl+item.img" alt="">
								<span>{{item.catename}}</span>
						</view>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				cates:[],
				activeIndex:0,
				baseUrl:""
			}
		},
		onShow(){
			this.getCates()
			this.baseUrl = this.$config.baseUrl
		},
		methods: {
			async getCates(){
				let res = await this.$api._getCates()
				console.log(res);
				this.cates = res.data.list
				
			},
			changeIndex(index){
				this.activeIndex = index
			}
		}
	}
</script>

<style>
	/* 导入外部的样式文件 */
	@import url("../../common/css/classify.css");
	/* 点击左侧导航,显示动态样式 */
	.activeList {
		border-left: 6rpx solid #f26b11;
		color: #f26b11;
	}

	.bottom {
		text-align: center;
		display: flex;
		flex-direction: row;
	}
</style>
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值