目录

保姆级教学从0搭建微信小程序SpringBootVue二

保姆级教学:从0搭建微信小程序SpringBoot+Vue(二)

保姆级教学:从0搭建微信小程序SpringBoot+Vue(二)

上篇有人看,趁放假玩耍间隙来更完这篇!国庆快乐各位~~~

教学(一)链接:

目前在玩儿cursor,做一个备忘录uni-app开发,有人有兴趣的话后续也放上来

五、微信小程序前端

1.新建Vue项目

打开HbuilderX(更新至最新版),新建项目,选择uni-app,版本选择Vue2。

https://i-blog.csdnimg.cn/direct/53ba36d1705c42358429253d0ec0abb1.png

初始配置结构如下

https://i-blog.csdnimg.cn/direct/059457b5488d42f2abaf17781e3e0d69.png

2.前端页面设计

在路径pages/index/index.vue文件中粘贴如下代码:

<template>
	<view>
	<view class="order-view">
		<view class="commodity">
			<view class="order-left"><!-- 左 -->
				<scroll-view scroll-y="true" class="scroll-Hei" :scroll-with-animation="true" :enhanced="true" :show-scrollbar="false">
					<block v-for="(item,index) in itemize" :key="index">
						<view class="itemize-text" :class="{active: index == trigger}" @click="itemIze(index,item.id)">
							<text>{{item.name}}</text>
						</view>
					</block>
				</scroll-view>
			</view> 
			<view class="order-right"><!-- 右 -->
				<scroll-view scroll-y="true" class="scroll-Hei"  :scroll-with-animation="true" :enhanced="true" :show-scrollbar="false" :scroll-into-view="scroll_into" @scroll="scroLl">
					<block v-for="(item,index) in goods" :key="index">
						<view :id="item.id" class="rig-height">
							<view class="classif">{{item.name}}</view>
								<view class="classif-goods" v-for="(itemgood,good_index) in item.dishList" :key="good_index" @click="popup_item(true,index,good_index,item.id,itemgood)">
									<view class="goods-image"><image :src="baseUrl+'/image/dish/'+itemgood.image" mode="aspectFill"></image></view>
									<view class="goods-Price">
										<view class="goods-name">
											<text class="Bold">{{itemgood.name}}</text>
										</view>
										<view class="unit-price">
											<text class="Symbol">¥</text>
											<text class="Bold">{{itemgood.price}}</text>
											<text class="Thinning">/{{itemgood.unit}}</text>
										</view>
									</view>
								</view>
						</view>
					</block>
					<view style="height: 400rpx;"></view>
				</scroll-view>
			</view>
		</view>
	</view>
	</view>
</template>
<script>
	import { getBaseUrl,requestUtil } from "../../utils/requestUtil.js"
export default{
	data() {
		return {
			baseUrl:'',
			exist:true,
			itemize:[],//类目
			trigger:0,//类目选中的值
			goods:[],//所有菜品
			heightset:[],//存储右边每一个分类菜品的高度
			tophei:0,//滚动时距离顶部的高度
			scroll_into:'',
		}
	},
	methods:{
		// 点击类目加上背景色
		itemIze(index,id){
			this.trigger = index
			this.scroll_into = id
			setTimeout(()=>{
				this.scroll_into = ''
			},200)
		},
		// 右边菜品滚动时触发
		scroLl(event){
			// console.log(event.detail.scrollTop)
			let scrollTop = event.detail.scrollTop
			if(scrollTop >= this.tophei){//上拉
				// 当前分类商品的高度小于滚动高度时跳转下一个分类
				if(scrollTop >= this.heightset[this.trigger]){
					this.trigger += 1
				}
			}else{//下拉
				// 当前分类商品的高度大于滚动高度时跳转下一个分类
				if(scrollTop < this.heightset[this.trigger - 1]){
					this.trigger -= 1
				}
			}
			this.tophei = scrollTop
		},
		//请求数据
		async dishEs(){
					const res=await requestUtil({url:"/menu/ListAll",method:"get"})
					const res2=await requestUtil({url:"/dish/ListAll",method:"get"})
					console.log(res)
					this.itemize = res.menulistall//类目
					this.goods = res2.dishList//所有菜品
					this.$nextTick(()=>{
						this.goods_height()
					})
				},
				// 计算右边每个分类菜品的高度
		goods_height(){
			this.heightset = []
			let cate_height = 0
			const query = wx.createSelectorQuery()
			query.selectAll('.rig-height').boundingClientRect()
			query.exec((res)=>{
				res[0].forEach((item)=>{
					cate_height += item.height
					this.heightset.push(cate_height)
				})
				this.exist = false
			})
		}
	},
	onLoad(){
		this.baseUrl=getBaseUrl()
		this.dishEs()
	}
}
</script>
<style scoped>
/* 点餐界面 */
.order-view{
	top:0;
}
.commodity{
	display: flex;
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	}
.order-left{
	background-color: #fafafa;
	width: 150rpx;
	overflow-y: auto;
}
.itemize-text{
	font-size: 27rpx;
	padding: 30rpx 10rpx;
	display: flex;
	align-items: center;
	color: #797979;
}
.itemize-text text:nth-child(1){flex: 1;}
.itemize-text text:nth-child(2){
	background-color: #eb5941;
	border-radius: 50%;
	font-size: 20rpx;
	color: #FFFFFF;
	width: 30rpx;
	height: 30rpx;
	display: flex;
	justify-content: center;
	align-items: center;
	margin-left: 2rpx;
}
.scroll-Hei{
	height: 100vh;
	/* white-space: nowrap; */
}
.order-right{
	background-color: #FFFFFF;
	flex: 1;
	overflow-y: auto;
	
}
.classif{
	font-size: 27rpx;
	padding: 30rpx 20rpx;
	color: #797979;
}
/* 分类商品 */
.classif-goods{
	display: flex;
	justify-content: space-between;
	padding: 0 20rpx;
	height: 150rpx;
	font-size: 30rpx;
	margin-bottom: 45rpx;
}

.goods-image image{
display: block;
width: 150rpx;
height: 150rpx;
border-radius: 10rpx;
}
.goods-Price{
flex: 1;
position: relative;
padding: 0 20rpx;
}
.goods-Price text{display: block;}
.goods-name{
display: flex;
flex-direction: column;
position: relative;
top: 0;
}
.goods-name text:nth-child(1){padding-bottom: 9rpx;}
.unit-price{
position: absolute;
bottom: 0;
display: flex;
align-items: baseline;
}
.Bold{font-weight: bold;}
.Symbol{font-size: 20rpx;}
.Thinning{font-size: 25rpx;
color: #cccccc;
}
/_ 点击分类列表加上背景色 _/
.active{
background-color: #FFFFFF;
color: #000000 !important;
}
</style>

3.前端请求配置

新建 utils 文件目录 → 新建 requestUtil.js 文件,设定请求方法。

https://i-blog.csdnimg.cn/direct/bd50d8d19b25408f8862f42ba723523c.png

代码如下:

// 同时发送异步代码的次数
let ajaxTimes=0;

// 定义公共的 url
const baseUrl="http://localhost:80";

/**

- 返回 baseUrl
  */
  export const getBaseUrl=()=>{
  return baseUrl;
  }

/**

- 后端请求工具类
- @param {_} params 请求参数
  _/
  export const requestUtil=(params)=>{

  let header={...params.header};

      // 拼接header 带上token
      header["token"]=uni.getStorageSync("token");

      ajaxTimes++;

       // 显示加载中 效果
      wx.showLoading({
        title: "加载中",
        mask: true
      });

      var start = new Date().getTime();

      // 模拟网络延迟加载
      while(true)  if(new Date().getTime()-start > 1000*1) break;

return new Promise((resolve,reject)=>{
wx.request({
...params,
header:header,
url:baseUrl+params.url,
success:(result)=>{
resolve(result.data);
},
fail:(err)=>{
uni.showToast({
icon:'error',
title:'连接服务器失败',
duration:3000
})
reject(err);
},
complete:()=>{
ajaxTimes--;
if(ajaxTimes===0){
// 关闭正在等待的图标
wx.hideLoading();
}
}
});
})
}

4.后端图片远程访问配置

首先需要上传图片,将提前准备好的用于前端菜品展示的图片放到自己电脑中(即本地服务器),位置通常为后端项目路径下的资源文件夹 \src\main\resources\image ,方便部署到远程服务器时一起打包(放在其它位置应该也找得到,程序中路径修改了就行)。图片命名对应数据库菜单表中 image 字段。

https://i-blog.csdnimg.cn/direct/e7ef0743f11e473bbd445777ab387f78.png

为保证前端能通过 url 向后端获取到图片,需要后端配置处理器接口。右键包 org.example.xiaomaibu,新建一个 package 命名为 config→ 新建 ImageConfig.java 文件,贴进如下代码。记得将程序末尾的路径修改为图片存放位置。

package org.example.xiaomaibu.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class ImageConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/image/dish/**").addResourceLocations("file:C:\\Users\\IdeaProjects\\XiaoMaiBu\\src\\main\\resources\\image\\");
    }

}

5.小程序参数配置

获取自己的小程序:注册登录地址https://mp.weixin.qq.com

管理 → 开发管理 → 开发设置 → 开发者 ID

https://i-blog.csdnimg.cn/direct/c3bc557b7c0441709583742d7a9fe983.png

打开 HbuilderX 的项目,manifest.json 配置,输入自己的小程序 ID

https://i-blog.csdnimg.cn/direct/39785308030c4bbab16c5e299fa81db8.png

打开工具 → 设置 → 运行配置 → 微信开发者工具路径,输入安装好的微信开发者工具路径

https://i-blog.csdnimg.cn/direct/003dc2e8b5504374bcb86099f8639b90.png

登录微信开发者工具 → 设置 → 安全 → 服务端口启用

https://i-blog.csdnimg.cn/direct/ec32d022c9fd4458a3e61f10a621c5fd.png

6.模拟器测试

打开 HbuilderX→ 运行 → 运行到小程序模拟器 → 微信开发者工具

https://i-blog.csdnimg.cn/direct/3bde33dd0b674ab8968690a82cc985b8.png

7.实现效果

HbuilderX 会自动打开微信开发者工具,并编译成微信原生态。

https://i-blog.csdnimg.cn/direct/6f5368db3a974258b3abd7e6cc420587.png

https://i-blog.csdnimg.cn/direct/c6094a35f4194c4ea46cdb9627a851bb.png

https://i-blog.csdnimg.cn/direct/71abc2672bff44f8bfbaa91dc8c8c817.png

六、调试及错误处理

微信小程序中,发现点击类别右侧滚动功能失效。定位到 index.vue 的 scroll-view 滚动组件,scroll-into-view 属性可以指定滚动到指定 id 的位置。在前端下面设计中:

<scroll-view scroll-y="true" class="scroll-Hei"
:scroll-with-animation="true" :enhanced="true"
:show-scrollbar="false" :scroll-into-view="scroll_into" @scroll="scroLl">

scroll_into 为其 id,发现滚动功能失效是因为不能以数字开头。

因此,第一种办法是在点击方法将 itemIze 下面的 this.scroll_into = id 加上前缀字符串。

itemIze(index,id){
this.trigger = index
this.scroll_into = "item"+id
setTimeout(()=>{
this.scroll_into = ''
},200)
}

同时,在右侧滚动的组件中,将 <view :id="item.id" class="rig-height"> 更换为 <view :id="'item'+item.id" class="rig-height"> 以此对应所选类别。

第二种是在数据库设计中,菜单类别新增一列是字母开头的唯一识别,与类别一一对应,将 item.id 替换为 item.新增列。

七、总结

至此,从 0 搭建微信小程序 SpringBoot+Vue 最基本的功能便成功搭建了,从后台到前端,实现了最基本的访问后台数据库展示功能。接下来我们应该考虑商品页的购物车功能、订单功能、用户登录等功能,但基本框架已经成型,后续只需要在此基础上继续叠加。