搭建小程序本地后台&封装请求接口

本地后台

在这里插入图片描述
注意: 若没有 node_modules 文件夹 则 cnpm i 完善配置

src 目录结构

在这里插入图片描述

app.js

'use strict'

var path = require('path')
const express = require('express')
const bodyParser = require('body-parser')
const fs = require('fs')

let app = express()

// 注册 body-parser 中间件
app.use(bodyParser({ extended: false }))
// app.use(bodyParser.urlencoded({ extended: false }));

//1.0 初始化orm
const orm = require('orm')
app.use(
  orm.express('mysql://root:root@127.0.0.1:3306/dtcmsdb4', {
    define: function(db, models, next) {
      next()
    }
  })
)

//2.0 将所有api的请求响应content-type设置为application/json
app.all('/api/*', (req, res, next) => {
  //设置允许跨域响应报文头
  //设置跨域
  //res.header("Access-Control-Allow-Origin", "*");
  //res.header("Access-Control-Allow-Headers", "X-Requested-With"); // X-Requested-With
  //res.header("Access-Control-Allow-Methods", "*");

  res.header('Access-Control-Allow-Origin', '*')
  // 设置服务器支持的所有头信息字段
  res.header(
    'Access-Control-Allow-Headers',
    'Content-Type,Content-Length, Authorization, Accept,X-Requested-With'
  )
  // 设置服务器支持的所有跨域请求的方法
  res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS')

  res.setHeader('Content-Type', 'application/json;charset=utf-8')
  next()
})

//2.0 设置路由规则
const apiRoute = require('./routes/apiRoute.js')
app.use('/', apiRoute)
app.use(express.static(path.join(__dirname, 'public')))

app.listen(8082, () => {
   console.log('vue-cms的api服务已启动, :8082');
});

开启后台

运行命令 node ./src/app.js
在这里插入图片描述

输入接口url

在这里插入图片描述

启动成功

在这里插入图片描述
在这里插入图片描述

请求接口封装

原因:因为线上或开发过程中,网址域名可能变化,若不采取方案则会引起一个域名改变修改多处代码

实施办法

利用 异步 promise 封装

Promise 回顾

小程序端

在根目录下新建 request 文件夹
在这里插入图片描述

index.js

index.js 代码

let  ajaxtimes=0;
export const request=(params)=>{
    let header={...params.header};
    if (params.url.includes("/my/")) {
        header["Authorization"]=wx.getStorageSync('token')
    }


    ajaxtimes++;
    wx.showLoading({
      title: '加载中',
      mask: true
    })
    
    const baseUrl="https://api-hmugo-web.itheima.net/api/public/v1"
    return new Promise((resolve,reject)=>{
        wx.request({
            ...params,
            header:header,
            url:baseUrl+params.url,
            success:(result)=>{
                resolve(result);
            },
            fail:(err)=>{
                reject(err);
            } ,
            complete:()=>{
                ajaxtimes--;
                if(ajaxtimes==0){
                wx.hideLoading();
            }
            }
        });
    })
}

使用页面

使用页面代码

import { request } from "../../request/index";
wx-Page({
  data: {
    swiperlist:[ ],
    cateslist:[ ],
    floorlist:[],
  },

  /**
   * 生命周期函数--监听页面加载
   * 页面加载 就会触发
   */
  onLoad: function (options) {
    // wx.request({
    //   url: 'https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata',
    //   success: (result) => {
    //     console.log(result);
    //     this.setData({
    //       swiperlist:result.data.message
    //     })
        
    //   },
    // })
     
    this.getswiperlist(); 
    this.getcatelist();
    this.getfloorlist();
  },

 getswiperlist(){

  request({ url: '/home/swiperdata'})
  .then(result => {
    this.setData({
      
     swiperlist:result.data.message
    })
  })
      
  },

  getcatelist(){

    request({ url: '/home/catitems'})
    .then(result => {
      this.setData({
       cateslist:result.data.message
      })
    })

  },

  getfloorlist(){

    request({ url: '/home/floordata'})
    .then(result => {
      var data =JSON.stringify(result.data.message);
      var data1=data.replace(/goods_list/g, 'goods_list/index')
      var data2=JSON.parse(data1)
      this.setData({
        floorlist:data2,
      })
    })
    
    
  },


});

Vue 浏览器端(H5)

同理使用 Promise 封装

在根目录下新建 util 文件夹 ,在此文件夹下 编写 api.js
在这里插入图片描述

api.js

api.js 代码

const BASE_URL = 'http://localhost:8082'
export const myRequest = (options)=>{
	return new Promise((resolve,reject)=>{
		uni.request({
			url:BASE_URL+options.url,
			method: options.method || 'GET',
			data: options.data || {},
			success: (res)=>{
				if(res.data.status !== 0) {
					return uni.showToast({
						title: '获取数据失败'
					})
				}
				resolve(res)
			},
			fail: (err)=>{
				uni.showToast({
					title: '请求接口失败'
				})
				reject(err)
			}
		})
	})
}

使用页面

methods: {
			// 获取轮播图的数据
			async getSwipers () {
				const res = await this.$myRuquest({
					url: '/api/getlunbo'
				})
				this.swipers = res.data.message
			},

在这里插入图片描述
全部代码

<template>
	<view class="home">
		<swiper indicator-dots circular>
			<swiper-item v-for="item in swipers" :key="item.id">
				<image :src="item.img"></image>
			</swiper-item>
		</swiper>
		<!-- 导航区域 -->
		<view class="nav">
			<view class="nav_item" v-for="(item,index) in navs" :key="index" @click="navItemClick(item.path)">
				<view :class="item.icon"></view>
				<text>{{item.title}}</text>
			</view>
		</view>
		<!-- 推荐商品 -->
		<view class="hot_goods">
			<view class="tit">推荐商品</view>
			<goods-list @goodsItemClick="goGoodsDetail" :goods="goods"></goods-list>
		</view>
	</view>
</template>

<script>
	import goodsList from '../../components/goods-list/goods-list.vue'
	export default {
		data() {
			return {
				swipers: [],
				goods: [],
				navs: [
					{
						icon: 'iconfont icon-ziyuan',
						title: 'Shop_超市',
						path: '/pages/goods/goods'
					},
					{
						icon: 'iconfont icon-guanyuwomen',
						title: '联系我们',
						path: '/pages/contact/contact'
					},
					{
						icon: 'iconfont icon-tupian',
						title: '社区图片',
						path: '/pages/pics/pics'
					},
					{
						icon: 'iconfont icon-shipin',
						title: '学习视频',
						path: '/pages/videos/videos'
					}
				]
			}
		},
		onLoad() {
			this.getSwipers()
			this.getHotGoods()
		},
		components: {"goods-list":goodsList},
		methods: {
			// 获取轮播图的数据
			async getSwipers () {
				const res = await this.$myRuquest({
					url: '/api/getlunbo'
				})
				this.swipers = res.data.message
			},
			// 获取热门商品列表数据
			async getHotGoods () {
				const res = await this.$myRuquest({
					url: '/api/getgoods?pageindex=1'
				})
				this.goods = res.data.message
			},
			// 导航点击的处理函数
			navItemClick (url) {
				uni.navigateTo({
					url
				})
			},
			// 导航到商品详情页
			goGoodsDetail (id) {
				uni.navigateTo({
					url: '/pages/goods-detail/goods-detail?id='+id
				})
			}
		}
	}
</script>

<style lang="scss">
	.home{
		swiper{
			 750rpx;
			height: 380rpx;
			image{
				height: 100%;
				 100%;
			}
		}
		.nav {
			display: flex;
			.nav_item {
				 25%;
				text-align: center;
				view{
					 120rpx;
					height: 120rpx;
					background: $shop-color;
					border-radius: 60rpx;
					margin: 10px auto;
					line-height: 120rpx;
					color: #fff;
					font-size: 50rpx;
				}
				.icon-tupian{
					font-size: 45rpx;
				}
				text{
					font-size: 30rpx;
				}
			}
		}
		.hot_goods {
			background: #eee;
			overflow: hidden;
			margin-top: 10px;
			.tit{
				height: 50px;
				line-height: 50px;
				color: $shop-color;
				text-align: center;
				letter-spacing: 20px;
				background: #fff;
				margin: 7rpx 0;
			}
		}
		
	}
</style>

原文地址:https://www.cnblogs.com/lzhCreate/p/14401175.html