uniapp相关记录

news/2025/2/12 4:10:12/

一、自定义我的物品组件 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>

二、自定义商品列表组件 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 = trueconst {data: res} = await uni.$http.get('/api/public/v1/goods/search', this.queryObj)// 关闭节流阀this.isLoading = falsecb && 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// 让页码值自增+1this.queryObj.pagenum++this.getGoodsList()},onPullDownRefresh() {// 重置关键数据this.queryObj.pagenum = 1this.total = 0this.isLoading = falsethis.goodsList = []// 重新发起数据请求this.getGoodsList(() => {uni.stopPullDownRefresh()})}}</script><style lang="scss"></style>

三、自定义商品详情组件 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_idthis.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(/<img /g,'<img style="display:block;" ').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>

四、自定义搜索组件 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>

五、小程序首页 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>

六、状态管理相关 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
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.goodsStatethis.commit('m_cart/saveToStorage')}},updateGoodsCount(state, goods) {const findResult = state.cart.find(x => x.goodsId === goods.goodsId)if (findResult) {findResult.goodsCount = goods.goodsCountthis.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 creturn 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)}}
}
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 = addressthis.commit('m_user/saveAddressToStorage')},// 持久化存储 addresssaveAddressToStorage(state) {uni.setStorageSync('address', JSON.stringify(state.address))},updateUserInfo(state, userinfo) {state.userinfo = userinfothis.commit('m_user/saveUserInfoToStorage')},saveUserInfoToStorage(state) {uni.setStorageSync('userinfo', JSON.stringify(state.userinfo))},updateToken(state, token) {state.token = tokenthis.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}}
}

七、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 = falseimport 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

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

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

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

"subPackages": [{"root": "subpkg","pages": [{"path": "search/search"},{"path" : "goods_list/goods_list"},{"path" : "goods_detail/goods_detail","style" :                                                                                    {"navigationBarTitleText": "","enablePullDownRefresh": false}}]}],

http://www.ppmy.cn/news/1233842.html

相关文章

NEJM一篇新文为例,聊聊孟德尔随机化研究mr 连锁不平衡(linkage disequilibrium)

2019年3月14日&#xff0c;新英格兰医学杂志发表了一篇论著&#xff0c;Mendelian Randomization Study of ACLY and Cardiovascular disease, 即《ACLY和心血管疾病的孟德尔随机化研究》。与小咖在2017年1月9日报道的一篇发表在新英格兰医学的孟德尔随机化研究——精读NEJM&am…

Axios使用方式

ajax是JQUERY封装的XMLHttprequest用来发送http请求 Axios简单点说它就是一个js库,支持ajax请求,发送axios请求功能更加丰富,丰富在哪不知道 1.npm使用方式 vue项目中 npm install axios 2.cdn方式 <script src"https://unpkg.com/axios/dist/axios.min.js">…

蓝桥等考C++组别八级001

第一部分:选择题 1、C++ L8 (15分) 整数12,18的最大公约数(公因数)是( )。 A. 3 B. 4 C. 6 D. 36 正确答案:C

golang 断点调试

1.碰见如下报错,调试器没有打印变量信息 Delve is too old for Go version 1.21.2 (maximum supported version 1.19) 2. 解决办法 升级delve delve是go语言的debug工具。 go install github.com/go-delve/delve/cmd/dlvlatest报错 Get “https://proxy.golang.org/github…

centos7安装MySQL—以MySQL5.7.30为例

centos7安装MySQL—以MySQL5.7.30为例 本文以MySQL5.7.30为例。 官网下载 进入MySQL官网&#xff1a;https://www.mysql.com/ 点击DOWNLOADS 点击链接&#xff1b; 点击如上链接&#xff1a; 选择对应版本&#xff1a; 点击下载。 安装 将下载后的安装包上传到/usr/local下…

【Python】用 dict 实现一个简单的 json 数据库

废话不看&#xff1a; 最近写了一个小项目&#xff0c;基本逻辑是通过定时任务轮询 API&#xff0c;检测 API 状态变化并执行对应的操作。该 API 一共有 3 种状态&#xff0c;假设每种状态的值分别为 1、2、3&#xff0c;在状态 2 的时候需要调用一次处理方法。 这里的问题是状…

第六章 SELinux

目录 1.概述 1.1.概念 1.2.作用: 1.3.SELinux与传统的权限区别 2.SELinux工作原理 2.1.名词解释 2.2文件安全上下文查看 3. SELinux的启动、关闭与查看 3.1.三种配置模式 3.2 原理图&#xff1a; 3.3 模式管理 3.4.selinux的状态 3.5.selinux配置文件 4.修改安全…