保姆级教学从0搭建微信小程序SpringBootVue二
保姆级教学:从0搭建微信小程序SpringBoot+Vue(二)
保姆级教学:从0搭建微信小程序SpringBoot+Vue(二)
上篇有人看,趁放假玩耍间隙来更完这篇!国庆快乐各位~~~
教学(一)链接:
目前在玩儿cursor,做一个备忘录uni-app开发,有人有兴趣的话后续也放上来
五、微信小程序前端
1.新建Vue项目
打开HbuilderX(更新至最新版),新建项目,选择uni-app,版本选择Vue2。
初始配置结构如下
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 文件,设定请求方法。
代码如下:
// 同时发送异步代码的次数
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 字段。
为保证前端能通过 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
打开 HbuilderX 的项目,manifest.json 配置,输入自己的小程序 ID
打开工具 → 设置 → 运行配置 → 微信开发者工具路径,输入安装好的微信开发者工具路径
登录微信开发者工具 → 设置 → 安全 → 服务端口启用
6.模拟器测试
打开 HbuilderX→ 运行 → 运行到小程序模拟器 → 微信开发者工具
7.实现效果
HbuilderX 会自动打开微信开发者工具,并编译成微信原生态。
六、调试及错误处理
微信小程序中,发现点击类别右侧滚动功能失效。定位到 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 最基本的功能便成功搭建了,从后台到前端,实现了最基本的访问后台数据库展示功能。接下来我们应该考虑商品页的购物车功能、订单功能、用户登录等功能,但基本框架已经成型,后续只需要在此基础上继续叠加。