• 【仿美团点餐App】—— 首页(一)


    一、首页布局

    pages.json的代码如下

    1. {
    2. "pages": [
    3. {
    4. "path": "pages/main/main",
    5. "style": {
    6. "navigationBarTitleText": "点餐小程序",
    7. "navigationStyle": "custom", "enablePullDownRefresh": true
    8. }
    9. }
    10. ],
    11. "globalStyle": {
    12. "navigationBarTextStyle": "black",
    13. "navigationBarTitleText": "点餐小程序",
    14. "navigationBarBackgroundColor": "#F8F8F8",
    15. "backgroundColor": "#F8F8F8", "onReachBottomDistance": 50
    16. }
    17. }
    • navigationStyle属性值为custom,设置成自定义导航;
    • enablePullDownRefresh属性值为true,表示下拉刷新;
    • onReachBottomDistance属性值未50,表示上拉触底事件触发时距底部的距离,单位为px;  

    二、异步数据流对接配合地图定位显示附近的商铺

     uni-app已内置Vuex,无须安装即可使用。

     1.首先配置Vuex,在根目录创建store->index.js

    1. import Vue from "vue";
    2. import Vuex from "vuex";
    3. Vue.use(Vuex);
    4. const store=new Vuex.Store({
    5. modules:{}
    6. });
    7. export default store;

    2.将Vuex注册到Vue中,main.js文件中的代码如下:

    1. import Vue from 'vue'
    2. import App from './App'
    3. import store from "./store";
    4. Vue.config.productionTip = false
    5. App.mpType = 'app'
    6. const app = new Vue({
    7. ...App,
    8. store
    9. })
    10. app.$mount()

    3.封装request()方法:在static->js->utils->request.js文件

    1. function request(url,method="get",data={}){
    2. return new Promise(((resolve, reject) => {
    3. uni.request({
    4. url: url,
    5. data: data,
    6. method:method.toLocaleUpperCase(),
    7. header: {
    8. 'content-type': 'application/x-www-form-urlencoded'
    9. },
    10. success: (res) => {
    11. resolve(res.data)
    12. },
    13. fail:(res)=>{
    14. reject(res)
    15. }
    16. });
    17. }))
    18. }
    19. export {
    20. request
    21. }

    4.配置公共的参数,其中存放接口地址。在static->js->conf->config.js文件

    1. let baseApi="https://diancan.glbuys.com/api";
    2. export default {
    3. baseApi
    4. }

    5.请求服务端数据:根目录创建api文件夹,在该文件夹下创建business/index.js文件。

    1. import config from "../../static/js/conf/config";
    2. import {request} from "../../static/js/utils/request";
    3. //显示首页商家列表
    4. export function getShopData(data){
    5. return request(config.baseApi+"/v1/business/shop","get",data)
    6. }

    6.与Vuex对接:store->business->index.js

    1. import {getShopData} from "../../api/business";
    2. export default {
    3. namespaced: true,
    4. state:{
    5. shops:[]
    6. },
    7. mutations:{
    8. //设置商铺列表
    9. ["SET_SHOPS"](state,payload){
    10. state.shops=payload.shops;
    11. }
    12. },
    13. actions:{
    14. //显示首页商家列表
    15. getShop(conText,payload){
    16. getShopData(payload).then(res=>{
    17. if(res.code==200){
    18. conText.commit("SET_SHOPS",{shops:res.data});
    19. }
    20. })
    21. }
    22. }
    23. }

    7.首页是自定义导航,需要先解决iPhoneX“刘海”的兼容性问题

    由于这个项目会有多个页面需要自定义导航,因此我们需要一个全局变量去识别是否在iPhoneX中,全局首选Vuex。

    store->system->index.js中:

    1. export default {
    2. namespaced:true,
    3. state:{
    4. isIpx:false, //是否iPhoneX
    5. platform:1//平台类型。值:1:微信小程序,2:微信公众号
    6. },
    7. mutations:{
    8. //设置isIpx
    9. ["SET_IPX"](state,payload){
    10. state.isIpx=payload.isIpx;
    11. }
    12. }
    13. }

    注册到Vuex中,store->index.js文件中新增代码如下:

    1. import Vue from "vue";
    2. import Vuex from "vuex";
    3. import system from "./system";
    4. import business from "./business";
    5. Vue.use(Vuex);
    6. const store=new Vuex.Store({
    7. modules:{
    8. system,
    9. business
    10. }
    11. });
    12. export default store;

    判断是否在iPhoneX中进行,在App.vue中新增代码如下:  

    1. onLaunch: function() {
    2. uni.getSystemInfo({
    3. success: res=> {
    4. if(res.model.indexOf('iPhone X')>-1){
    5. this.$store.commit("system/SET_IPX",{isIpx:true});
    6. }
    7. }
    8. });
    9. },

    将Vuex的数据对接到pages/main/main.vue中,该文件中的代码如下:

    (1)使用getSetting()方法获取用户的当前设置,利用返回值res.authSetting['scope.userLocation']判断用户是否开启地理位置。

    如果没有开启,使用openSetting()方法调起客户端小程序设置界面。

    用户开启地理位置后,使用getLocation()方法获取地理位置。

    注意:为例定位准确,务必使用GCJ-02获取坐标,最后调用getShop()方法获取商品列表数据

    (2)如果用户没有关闭地理位置功能。可以直接获取地理位置并获取商铺列表数据。

    1. <template>
    2. <view class="page">
    3. <view class="status_bar">view>
    4. <view class="header">
    5. <view :class="{'search-header':true,ipx:isIpx}">
    6. <view class="search-wrap">
    7. <view class="icon">view>
    8. <view class="text">请输入商家名或菜品view>
    9. view>
    10. view>
    11. view>
    12. <view class="shop-main">
    13. <view class="shop-list" v-for="item in shops" :key="item.branch_shop_id">
    14. <view class="shop-wrap">
    15. <view class="image">
    16. <image :src="item.logo">image>
    17. view>
    18. <view class="shop-info">
    19. <view class="shop-name">{{item.branch_shop_name}}view>
    20. <view class="distance">{{item.distance}}view>
    21. <view class="address">{{item.address}}view>
    22. <view class="pack-btn">自提view>
    23. view>
    24. view>
    25. view>
    26. view>
    27. view>
    28. template>
    29. <script>
    30. import {mapState,mapActions} from "vuex";
    31. export default {
    32. data() {
    33. return {
    34. }
    35. },
    36. onLoad() {
    37. this.lng=0;//经度
    38. this.lat=0;//纬度
    39. },
    40. onShow(){
    41. uni.getSetting({
    42. success:(res)=> {
    43. //用户没有开启地位位置
    44. if(!res.authSetting['scope.userLocation']){
    45. uni.showModal({
    46. title: '开启获取地理位置',
    47. content: '请打开"位置信息"权限,找到附近的店铺',
    48. success: (res)=> {
    49. if (res.confirm) {
    50. //调起客户端小程序设置界面
    51. uni.openSetting({
    52. success:(res2)=> {
    53. //如果用户打开了地理位置
    54. if(res2.authSetting['scope.userLocation']){
    55. uni.getLocation({
    56. type: 'gcj02',
    57. success: (res)=> {
    58. this.lng=res.longitude;
    59. this.lat=res.latitude;
    60. this.getShop({page:1,lng:this.lng,lat:this.lat});
    61. }
    62. });
    63. }
    64. }
    65. });
    66. }
    67. }
    68. });
    69. }
    70. }
    71. })
    72. uni.getLocation({
    73. type: 'gcj02',
    74. success: (res)=> {
    75. this.lng=res.longitude;
    76. this.lat=res.latitude;
    77. this.getShop({page:1,lng:this.lng,lat:this.lat});
    78. }
    79. });
    80. },
    81. methods: {
    82. ...mapActions({
    83. getShop:"business/getShop"
    84. })
    85. },
    86. computed:{
    87. ...mapState({
    88. isIpx:state=>state.system.isIpx,
    89. shops:state=>state.business.shops
    90. })
    91. },
    92. onShareAppMessage(res) {
    93. return {
    94. title: '点餐小程序',
    95. path: '/pages/main/main'
    96. }
    97. }
    98. }
    99. script>
    100. <style scoped>
    101. .page{width:100%;min-height:100vh;orverflow:hidden;}
    102. .header{width:100%;background-color:#eb1625;overflow:hidden;position: fixed;left:0;top:0;z-index:90;}
    103. .header .search-header{width:100%;height:170rpx;margin-top:40rpx;padding-bottom:20rpx;display:flex;justify-content: center;align-items: flex-end;}
    104. .header .search-header.ipx{height:210rpx;}
    105. .header .search-wrap{width:80%;height:52rpx;background-color:rgba(255,255,255,0.9);border-radius: 5px;display: flex;align-items: center;}
    106. .header .icon{width:44rpx;height:44rpx;background-image:url("@/static/images/main/search_icon.png");background-size:100%;background-position: center;background-repeat: no-repeat;margin:0 20rpx;}
    107. .header .text{color:#999999;font-size:28rpx;}
    108. .shop-main{width:100%;margin-top:220rpx;}
    109. .shop-main .shop-list{width:100%;border-bottom:1px solid #EFEFEF;box-sizing: border-box;padding:20rpx 0;}
    110. .shop-main .shop-list .shop-wrap{width:92%;margin:0 auto;display:flex;}
    111. .shop-main .shop-list .shop-wrap .image{width:160rpx;height:160rpx;margin-right:20rpx;}
    112. .shop-main .shop-list .shop-wrap .image image{width:100%;height:100%;border-radius: 5px;}
    113. .shop-main .shop-list .shop-info{width:72%;clear: both;}
    114. .shop-main .shop-list .shop-info .shop-name{width:100%;height:44rpx;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;font-size:32rpx;font-weight: bold;}
    115. .shop-main .shop-list .shop-info .distance{font-size:28rpx;margin-top:10rpx;color:#666666}
    116. .shop-main .shop-list .shop-info .address{font-size:28rpx;margin-top:10rpx;color:#666666;width:100%;height:44rpx;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;}
    117. .shop-main .shop-list .shop-info .pack-btn{padding:10rpx 20rpx;background-color:#eb1625;font-size:28rpx;color:#FFFFFF;display: table;border-radius: 5px;float: right;margin-top:10rpx;}
    118. style>

    注:项目教程来自《uni-app多端跨平台开发从入门到企业级实战》

  • 相关阅读:
    随便看看官方教程-FPS Microgame
    Android学习笔记 13. TableLayout 表格布局
    阿里云99元服务器新老用户同享396元4年!
    2023年Java面试题及答案整理
    [二进制学习笔记]C中的格式化字符串
    职场成长的三种方式
    【软件测试成长记】之 基础篇
    分享!JetBrains IDE中的GitLab支持
    软件测试/测试开发丨Python文件操作 学习笔记
    Redis 高可用之持久化
  • 原文地址:https://blog.csdn.net/qq_34235864/article/details/126060141