• uniapp相关记录


    一、自定义我的物品组件 my_goods.vue

    <template>
      <view class="goods-item">
        <!-- 左侧 -->
        <view class="goods-item-left">
          <radio :checked="goods.goods_state" color="#c00000" v-if="showRadio" @click="radioClickhandler"></radio>
          <image :src="goods.goods_small_logo || defaultPic" class="goods-pic"></image>
        </view>
        <!-- 右侧 -->
        <view class="goods-item-right">
          <!-- 商品名字 -->
          <view class="goods-name">{{goods.goods_name}}</view>
          <view class="goods-info-box">
            <view class="good-price">{{goods.goods_price}}</view>
            <uni-number-box :min="1" :max="9999" :value="goods.goods_count" v-if="showNum"
              @change="numChangeHandler"></uni-number-box>
          </view>
        </view>
      </view>
    </template>
    
    <script>
      export default {
        props: {
          // 商品的信息对象
          goods: {
            type: Object,
            defaul: {},
          },
          showRadio: {
            type: Boolean,
            // 默认不展示 radio 组件
            default: false
          },
          showNum: {
            type: Boolean,
            default: false
          }
        },
        data() {
          return {
            // 默认的图片
            defaultPic: 'https://img3.doubanio.com/f/movie/8dd0c794499fe925ae2ae89ee30cd225750457b4/pics/movie/celebrity-default-medium.png',
          };
        },
        methods: {
          // radio 组件的点击事件处理函数
          radioClickhandler() {
            this.$emit('radio-change', {
              goods_id: this.goods.goods_id,
              goods_state: !this.goods.goods_state
            })
          },
          // 监听购物车商品数量变化的事件
          numChangeHandler(val) {
            this.$emit('num-change', {
              goods_id: this.goods.goods_id,
              goods_count: +val
            })
          }
        }
      }
    </script>
    
    <style lang="scss">
      .goods-item {
        display: flex;
        padding: 10px 5px;
        border-bottom: 1px solid #dedede;
        background-color: #fff;
    
        .goods-item-left {
          margin-right: 5px;
          display: flex;
          justify-content: center;
          align-items: center;
    
          .goods-pic {
            width: 100px;
            height: 100px;
            display: block;
          }
        }
    
        .goods-item-right {
          display: flex;
          flex: 1;
          flex-direction: column;
          justify-content: space-between;
    
          .goods-name {
            font-size: 13px;
          }
    
          .goods-info-box {
            display: flex;
            justify-content: space-between;
            align-items: center;
    
            .good-price {
              color: #c00000;
              font-size: 16px;
            }
          }
        }
      }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106

    二、自定义商品列表组件 good_list.vue

    <template>
      <view>
        <view class="goods-list">
          <view v-for="(goods,i) in goodsList" :key="i" @click="gotoDetail(goods)">
            <my-goods :goods="goods"></my-goods>
          </view>
        </view>
      </view>
    </template>
    
    <script>
    	import {myGoods} from '@/components/my-goods/my-goods.vue'
      export default {
    	components: {myGoods},  
    	  
        data() {
            return {
                // 请求参数对象
                queryObj: {
                  query: '',
                  cid: '',
                  pagenum: 1,
                  pagesize: 10
                },
                goodsList: [],
                total: 0,
                isLoading: false
              }
            },
            onLoad(options) {
              this.queryObj.query = options.query || ''
              this.queryObj.cid = options.cid || ''
              this.getGoodsList()
            },
            methods: {
              // 获取商品列表数据
              async getGoodsList(cb) {
                // 打开节流阀
                this.isLoading = true
                const {
                  data: res
                } = await uni.$http.get('/api/public/v1/goods/search', this.queryObj)
                // 关闭节流阀
                this.isLoading = false
                cb && cb()
                if (res.meta.status !== 200) return uni.$showMsg()
                this.goodsList = [...this.goodsList, ...res.message.goods]
                this.total = res.message.total
              },
              gotoDetail(goods) {
                uni.navigateTo({
                  url: '/subpkg/goods_detail/goods_detail?goods_id=' + goods.goods_id
                })
              }
            },
            onReachBottom() {
              if (this.queryObj.pagenum * this.queryObj.pagesize >= this.total) return uni.$showMsg('数据加载完毕')
              if (this.isLoading) return
              // 让页码值自增+1
              this.queryObj.pagenum++
              this.getGoodsList()
            },
            onPullDownRefresh() {
              // 重置关键数据
              this.queryObj.pagenum = 1
              this.total = 0
              this.isLoading = false
              this.goodsList = []
              // 重新发起数据请求
              this.getGoodsList(() => {
                uni.stopPullDownRefresh()
              })
            }
          }
        </script>
        
        <style lang="scss">
        
        </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    三、自定义商品详情组件 good_detail.vue

    <template>
      <view v-if="goods_info.goods_name" class="goods-detail-container">
        <!-- 轮播图区域 -->
        <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" :circular="true">
          <swiper-item v-for="(item,i) in goods_info.pics" :key="i">
            <image :src="item.pics_big" @click="preview(i)"></image>
          </swiper-item>
        </swiper>
    
        <!-- 商品信息区域 -->
        <view class="goods-info-box">
          <!-- 商品价格 -->
          <view class="price">{{goods_info.goods_price}}</view>
          <!-- 商品信息主体区域 -->
          <view class="goods-info-body">
            <!-- 商品名字 -->
            <view class="goods-name">{{goods_info.goods_name}}</view>
            <!-- 收藏 -->
            <view class="favi">
              <uni-icons type="star" size="18" color="gray"></uni-icons>
              <text>收藏</text>
            </view>
          </view>
          <!-- 运费 -->
          <view class="yf">快递:免运费</view>
        </view>
        <rich-text :nodes="goods_info.goods_introduce"></rich-text>
    
        <!-- 商品导航组件区域 -->
        <view class="goods_nav">
          <uni-goods-nav :fill="true" :options="options" :buttonGroup="buttonGroup" @click="onClick"
            @buttonClick="buttonClick" />
        </view>
      </view>
    </template>
    
    <script>
      export default {
    	
        watch: {
          total: {
            handler(newVal) {
              const findResult = this.options.find(x => x.text === '购物车')
              if (findResult) {
                findResult.info = newVal
              }
            },
            immediate: true
          }
        },
        data() {
          return {
            goods_info: {},
            options: [{
              icon: 'shop',
              text: '店铺',
              infoBackgroundColor: '#007aff',
              infoColor: "red"
            }, {
              icon: 'cart',
              text: '购物车',
              info: 0
            }],
            buttonGroup: [{
                text: '加入购物车',
                backgroundColor: '#ff0000',
                color: '#fff'
              },
              {
                text: '立即购买',
                backgroundColor: '#ffa200',
                color: '#fff'
              }
            ],
          }
        },
        onLoad(options) {
          const goods_id = options.goods_id
          this.getGoodsDetail(goods_id)
        },
        methods: {
          async getGoodsDetail(goods_id) {
            const {
              data: res
            } = await uni.$http.get('/api/public/v1/goods/detail', {
              goods_id
            })
            if (res.meta.status !== 200) return uni.$showMsg()
            res.message.goods_introduce = res.message.goods_introduce.replace(//g,
                ')
              .replace(/webp/g, 'jpg')
            this.goods_info = res.message
          },
          preview(i) {
            uni.previewImage({
              current: i,
              urls: this.goods_info.pics.map(x => x.pics_big)
            })
          },
          onClick(e) {
            if (e.content.text === '购物车') {
              uni.switchTab({
                url: '/pages/cart/cart'
              })
            }
          },
          buttonClick(e) {
            if (e.content.text === '加入购物车') {
              // 组织商品的信息对象
              // 每个商品的信息对象,都包含如下 6 个属性:
              // { goods_id, goods_name, goods_price, goods_count, goods_small_logo, goods_state }
              const goods = {
                goods_id: this.goods_info.goods_id,
                goods_name: this.goods_info.goods_name,
                goods_price: this.goods_info.goods_price,
                goods_count: 1,
                goods_small_logo: this.goods_info.goods_small_logo,
                goods_state: true
              }
              // 调用 addToCart 方法
              // this.addToCart(goods)
            }
          }
        }
      }
    </script>
    
    <style lang="scss">
      swiper {
        height: 750rpx;
    
        image {
          width: 100%;
          height: 100%;
        }
      }
    
      .goods-info-box {
        padding: 10px;
        padding-right: 0;
    
        .price {
          color: #c00000;
          font-size: 18px;
          margin: 10px 0;
        }
    
        .goods-info-body {
          display: flex;
          justify-content: space-between;
    
          .goods-name {
            font-size: 13px;
            margin-right: 10px;
          }
    
          .favi {
            width: 120px;
            font-size: 12px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            border-left: 1px solid #eaeaea;
            color: gray;
          }
        }
    
        .yf {
          font-size: 12px;
          color: gray;
          margin: 10px 0;
        }
    
      }
    
      .goods_nav {
        position: fixed;
        bottom: 0;
        left: 0;
        width: 100%;
      }
    
      .goods-detail-container {
        padding-bottom: 50px;
      }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187

    四、自定义搜索组件 my_search.vue

    <template>
      <view class="my-search-container" :style="{'background-color': bgcolor}" @click="searchBoxHandler">
        <view class="my-search-box" :style="{'border-radius': radius + 'px'}">
          <uni-icons type="search" size="17"></uni-icons>
          <text class="placeholder">搜索</text>
        </view>
      </view>
    </template>
    
    <script>
      export default {
        name: "my-search",
        props: {
          // 背景颜色
          bgcolor: {
            type: String,
            default: '#c00000'
          },
          // 圆角尺寸
          radius: {
            type: Number,
            default: 18 //px
          }
        },
        data() {
          return {
    
          };
        },
        methods: {
          searchBoxHandler() {
            this.$emit('click')
          }
        }
      }
    </script>
    
    <style lang="scss">
      .my-search-container {
        height: 50px;
        // background-color: #c00000;
        display: flex;
        align-items: center;
        padding: 0 10px;
    
        .my-search-box {
          width: 100%;
          height: 36px;
          background-color: #fff;
          // border-radius: 18px;
          display: flex;
          justify-content: center;
          align-items: center;
    
          .placeholder {
            font-size: 15px;
            margin-left: 5px;
          }
        }
      }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    五、小程序首页 index.vue

    <template>
    	<view>
    		 <!-- 搜索组件 -->
    		<view class="search-box">
    		 <my-search @click="gotoSearch"></my-search>
    		  <!-- 动态给子组件传颜色和圆角像素值 -->
    		  <!-- <my-search @click="gotoSearch" :bgcolor="'black'" :radius="18"></my-search> -->
    		</view>
    		<!-- 轮播图区域 -->
    		<swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" :circular="true">
    		  <swiper-item v-for="(item,i) in swiperList" :key="i">
    			<navigator class="swiper-item" :url="'/subpkg/goods_detail/goods_detail?goods_id=' + item.good_id">
    			  <image :src="item.image_src"></image>
    			</navigator>
    		  </swiper-item>
    		</swiper>
    		 <!-- 分类导航区域 -->
    		<view class="nav-list">
    		  <view class="nav-item" v-for="(item,i) in navList" :key="i" @click="navClickHandler(item)">
    			<image :src="item.image_src" class="nav-img"></image>
    		  </view>
    		</view>
    		<!-- 楼层区域 -->
    		<view class="floor-list">
    		  <!-- 每个楼层的 item 项 -->
    		  <view class="floor-item" v-for="(item,i) in floorList" :key="i">
    			<!-- 楼层的标题 -->
    			<image :src="item.floor_title.image_src" class="floor-title"></image>
    			<!-- 楼层的图片区域 -->
    			<view class="floor-img-box">
    			  <!-- 左侧图片 -->
    			  <navigator class="left-img-box" :url="item.product_list[0].url">
    				<image :src="item.product_list[0].image_src" :style="{width: item.product_list[0].image_width + 'rpx'}"
    				  mode="widthFix">
    				</image>
    			  </navigator>
    			  <!-- 右侧图片 -->
    			  <view class="right-img-box">
    				<navigator class="right-img-item" v-for="(item2,i2) in item.product_list" :key="i2" v-if="i2 !== 0"
    				  :url="item2.url">
    				  <image :src="item2.image_src" :style="{width: item2.image_width + 'rpx'}" mode="widthFix"></image>
    				</navigator>
    			  </view>
    			</view>
    		  </view>
    		</view>
    		
    	</view>
    </template>
    
    <script>
    	import {mySearch} from '@/components/my-search/my-search.vue'
    	export default {
    		components:{mySearch},
    		data() {
    			return {
    				title: 'Hello',
    				 // 轮播图数据列表
    				swiperList: [],
    				// 分类导航的数据列表
    				navList: [],
    				// 楼层的数据
    				floorList: []
    			}
    		},
    		onLoad() {
    			this.getSwiperList()
    			this.getNavList()
    			this.getFloorList()
    		},
    		methods: {
    			gotoSearch() {
    				uni.navigateTo({
    				  url: '/subpkg/search/search'
    				})
    		    },
    		    async getSwiperList() {
    			   const {
    				 data: res
    			   } = await uni.$http.get('/api/public/v1/home/swiperdata')
    			   // 请求失败
    			   if (res.meta.status !== 200) return uni.$showMsg()
    			   // 请求成功
    			   this.swiperList = res.message
    			 },
    			 async getNavList() {
    				 const {
    				   data: res
    				 } = await uni.$http.get('/api/public/v1/home/catitems')
    				 // 请求失败
    				 if (res.meta.status !== 200) return uni.$showMsg()
    				 // 请求成功
    				 this.navList = res.message
    			},
    			navClickHandler(item) {
    				if (item.name === '分类') {
    				  uni.switchTab({
    					url: '/pages/category/category'
    				  })
    				}
    			},
    			async getFloorList() {
    				const {
    				  data: res
    				} = await uni.$http.get('/api/public/v1/home/floordata')
    				// 请求失败
    				if (res.meta.status !== 200) return uni.$showMsg()
    				// 请求成功
    				// 对每张图片的 navigator_url 数据进行处理
    				res.message.forEach(floor => {
    				  floor.product_list.forEach(prod => {
    					prod.url = '/subpkg/goods_list/goods_list?' + prod.navigator_url.split('?')[1]
    				  })
    				})
    				this.floorList = res.message
    			},
    		}
    	}
    </script>
    
    <style>
    	swiper {
    	    height: 330rpx;
    	  },
    	.swiper-item,
    	image {
    	  width: 100%;
    	  height: 100%;
    	},
    	
    	
    	.nav-list {
    	    display: flex;
    	    justify-content: space-around;
    	    margin: 15px 0;
    	  }
    	.nav-img {
    	  width: 128rpx;
    	  height: 140rpx;
    	}
    	
    	.floor-title {
    	    width: 100%;
    	    height: 60rpx;
    	  }
    	
    	  .floor-img-box {
    	    display: flex;
    	    padding-left: 10rpx;
    	  }
    	
    	  .right-img-box {
    	    display: flex;
    	    flex-wrap: wrap;
    	    justify-content: space-around;
    	  }
    	 
    	
     .search-box {
        position: sticky;
        top: 0;
        z-index: 999;
      }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165

    六、状态管理相关 store(以下文件分别为:store.js cart.js user.js)

    import Vue from 'vue'
    import Vuex from 'vuex'
    import moduleCart from '@/store/cart.js'
    import moduleUser from '@/store/user.js'
    
    Vue.use(Vuex)
    
    const store = new Vuex.Store({
      modules: {
        'm_cart': moduleCart,
        'm_user': moduleUser
      }
    })
    
    export default store
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    export default {
      namespaced: true,
      state: () => ({
        // 购物车的数组,用来存储购物车中每个商品的信息对象
        // 每个商品的信息对象,都包含如下 6 个属性:
        // { goodsId, goodsName, goodsPrice, goodsCount, goodsSmallLogo, goodsState }
        cart: JSON.parse(uni.getStorageSync('cart') || '[]')
      }),
      mutations: {
        addToCart(state, goods) {
          const findResult = state.cart.find(x => x.goodsId === goods.goodsId)
          if (!findResult) {
            state.cart.push(goods)
          } else {
            findResult.goods_count++
          }
          this.commit('m_cart/saveToStorage')
        },
        saveToStorage(state) {
          uni.setStorageSync('cart', JSON.stringify(state.cart))
        },
        // 更新购物车商品的勾选状态
        updateGoodsState(state, goods) {
          const findResult = state.cart.find(x => x.goodsId === goods.goodsId)
          if (findResult) {
            findResult.goodsState = goods.goodsState
            this.commit('m_cart/saveToStorage')
          }
        },
        updateGoodsCount(state, goods) {
          const findResult = state.cart.find(x => x.goodsId === goods.goodsId)
          if (findResult) {
            findResult.goodsCount = goods.goodsCount
            this.commit('m_cart/saveToStorage')
          }
        },
        // 根据 id 删除对应的商品
        removeGoodsById(state, goods_id) {
          state.cart = state.cart.filter(x => x.goodsId !== goodsId)
          this.commit('m_cart/saveToStorage')
        },
        // 更新购物车中所有的商品勾选状态
        updateAllGoodsState(state, newState) {
          state.cart.forEach(x => x.goodsState = newState)
          this.commit('m_cart/saveToStorage')
        }
      },
      getters: {
        // 购物车中所有商品的总数量
        total(state) {
          // let c = 0
          // state.cart.forEach(goods => c += goods.goods_count)
          // return c
          return state.cart.reduce((total, item) => total += item.goodsCount, 0)
        },
        // 购物车中已勾选的商品的总数量
        checkedCount(state) {
          return state.cart.filter(x => x.goodsState).reduce((total, item) => total += item.goodsCount, 0)
        },
        // 已勾选的商品的总价格
        checkedGoodsAmount(state) {
          return state.cart.filter(x => x.goodsState).reduce((total, item) => total += item.goodsCount * item.goodsPrice,
            0).toFixed(2)
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    export default {
      // 开启命名空间
      namespaced: true,
    
      // 数据
      state: () => ({
        address: JSON.parse(uni.getStorageSync('address') || '{}'),
        token: uni.getStorageSync('token') || '',
        // 用户的信息对象
        userinfo: JSON.parse(uni.getStorageSync('userinfo') || '{}')
      }),
      mutations: {
        // 更新收货地址
        updateAddress(state, address) {
          state.address = address
    
          this.commit('m_user/saveAddressToStorage')
        },
        // 持久化存储 address
        saveAddressToStorage(state) {
          uni.setStorageSync('address', JSON.stringify(state.address))
        },
        updateUserInfo(state, userinfo) {
          state.userinfo = userinfo
    
          this.commit('m_user/saveUserInfoToStorage')
        },
        saveUserInfoToStorage(state) {
          uni.setStorageSync('userinfo', JSON.stringify(state.userinfo))
        },
        updateToken(state, token) {
          state.token = token
          this.commit('m_user/saveTokenToStorage')
        },
        saveTokenToStorage(state) {
          uni.setStorageSync('token', state.token)
        }
      },
      getters: {
        // 收货地址
        addstr(state) {
          if (!state.address.provinceName) return ''
          return state.address.provinceName + state.address.cityName + state.address.countyName + state.address.detailInfo
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    七、main.js

    import App from './App'
    
    import store from '@/store/store.js'
    // 导入网络请求的包
    import { $http } from '@/node_modules/@escook/request-miniprogram'
    uni.$http = $http
    
    // 请求根路径
    $http.baseUrl = 'https://api-hmugo-web.itheima.net'
    // 请求拦截器
    $http.beforeRequest = function(options) {
      // 显示loading效果
      uni.showLoading({
        title: '数据加载中...',
      })
      // 判断当前请求的是否为有权限的接口
      if (options.url.indexOf('/my/') !== -1) {
        options.header = {
          Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjIzLCJpYXQiOjE1NjQ3MzAwNzksImV4cCI6MTAwMTU2NDczMDA3OH0.YPt-XeLnjV-_1ITaXGY2FhxmCe4NvXuRnRB8OMCfnPo"
        }
      }
    }
    // 响应拦截器
    $http.afterRequest = function() {
      // 隐藏loading效果
      uni.hideLoading()
    }
    // 封装数据请求失败的弹框方法
    uni.$showMsg = function(title = '数据请求失败', duration = 1500) {
      uni.showToast({
        title,
        duration,
        icon: 'none',
      })
    }
    Vue.config.productionTip = false
    
    
    
    
    import uView from '@/uni_modules/uview-ui'
    Vue.use(uView)
    
    // #ifndef VUE3
    import Vue from 'vue'
    Vue.config.productionTip = false
    App.mpType = 'app'
    
    try {
      function isPromise(obj) {
        return (
          !!obj &&
          (typeof obj === "object" || typeof obj === "function") &&
          typeof obj.then === "function"
        );
      }
    
      // 统一 vue2 API Promise 化返回格式与 vue3 保持一致
      uni.addInterceptor({
        returnValue(res) {
          if (!isPromise(res)) {
            return res;
          }
          return new Promise((resolve, reject) => {
            res.then((res) => {
              if (res[0]) {
                reject(res[0]);
              } else {
                resolve(res[1]);
              }
            });
          });
        },
      });
    } catch (error) { }
    
    const app = new Vue({
      ...App
    })
    app.$mount()
    // #endif
    
    // #ifdef VUE3
    import { createSSRApp } from 'vue'
    export function createApp() {
      const app = createSSRApp(App)
      return {
        app
      }
    }
    // #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    八、引入/uview组件(分别该四个文件:app.vue man.js page.json uni.scss)

    <style lang="scss">
    	/*每个页面公共css */
    	@import "@/uni_modules/uview-ui/index.scss";
    </style>
    
    • 1
    • 2
    • 3
    • 4
    import uView from '@/uni_modules/uview-ui'
    Vue.use(uView)
    
    • 1
    • 2
    "easycom": {
    		"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
    	},
    
    • 1
    • 2
    • 3
    @import '@/uni_modules/uview-ui/theme.scss';
    
    • 1

    九、uniapp小程序分包
    ①page.json中定义分包文件
    ②定义分包文件夹并创建分包文件

    "subPackages": [
    		{
    			"root": "subpkg",
    			"pages": [
    				{
    					"path": "search/search"
    				},{
                        "path" : "goods_list/goods_list"
                    }
                    ,{
                        "path" : "goods_detail/goods_detail",
                        "style" :                                                                                    
                    {
                        "navigationBarTitleText": "",
                        "enablePullDownRefresh": false
                    }
                    
                    }
                ]
    		}
    	],
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    数据库中间MyCat最新硬核教程,主从复制,分库分表
    基于PHP+MySQL的个人博客系统毕设
    speedoffice中Word文件如何加密
    sql处理重复的列,更好理清分组和分区
    gerrit部署使用
    chrome实用插件分享
    京东内网遭开源的“顶级”SpringCloud实战手册,GitHub列为首推
    ES单节点部署
    【python初学者日记】selenium初体验——“秒杀商品”、“清空购物车”技能养成记(二)
    vue3 集成 tailwindcss
  • 原文地址:https://blog.csdn.net/m0_43584016/article/details/134525240