现在是特殊时期,但是进步无止境,我们的战斗就永不停息。这种不断战胜困难和自己的战斗就是逆战。本篇是在了解了一些微信小程序开发后,用uni-app开发的一个商城类小程序项目。
可以参考网址 https://uniapp.dcloud.io/quickstart?id=%e5%88%9b%e5%bb%bauni-app官网中推荐了两种,个人觉得第一种比较简单
pages.json 文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。
它类似微信小程序中app.json的页面管理部分。注意定位权限申请等原属于app.json的内容,在uni-app中是在manifest中配置
属性 | 类型 | 必填 | 描述 | 平台兼容 |
---|---|---|---|---|
globalStyle | Object | 否 | 设置默认页面的窗口表现 | |
pages | Object Array | 是 | 设置页面路径及窗口表现 | |
easycom | Object | 否 | 组件自动引入规则 | 2.5.0+ |
tabBar | Object | 否 | 设置底部 tab 的表现 | |
condition | Object | 否 | 启动模式配置 | |
subPackages | Object Array | 否 | 分包加载配置 | |
preloadRule | Object | 否 | 分包预下载规则 | 微信小程序 |
workers | String | 否 | Worker 代码放置的目录 |
微信小程序 |
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path" : "pages/home/home",
"style" : {
"navigationBarTitleText": "嗨购-首页",
"enablePullDownRefresh": true
}
},
{
"path": "pages/index/index",
"style": {
}
},
{
"path" : "pages/kind/kind",
"style" : {
"navigationBarTitleText": "嗨购-分类"
}
},
{
"path" : "pages/cart/cart",
"style" : {
"navigationBarTitleText": "嗨购-购物车"
}
},
{
"path" : "pages/user/user",
"style" : {
"navigationBarTitleText": "嗨购-我的"
}
},
{
"path" : "pages/detail/detail",
"style" : {}
}
,{
"path" : "pages/login/login",
"style" : {}
}
,{
"path" : "pages/register/register",
"style" : {}
}
],
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "嗨购",
"navigationBarBackgroundColor": "#ff6666",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"color": "#333",
"selectedColor": "#f66",
"backgroundColor": "#efefef",
"borderStyle": "white",
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "static/resources/home.png",
"selectedIconPath": "static/resources/home_active.png"
},
{
"pagePath": "pages/kind/kind",
"text": "分类",
"iconPath": "static/resources/kind.png",
"selectedIconPath": "static/resources/kind_active.png"
},
{
"pagePath": "pages/cart/cart",
"text": "购物车",
"iconPath": "static/resources/cart.png",
"selectedIconPath": "static/resources/cart_active.png"
},
{
"pagePath": "pages/user/user",
"text": "我的",
"iconPath": "static/resources/user.png",
"selectedIconPath": "static/resources/user_active.png"
}
]
},
"condition": { //模式配置,仅开发期间生效 ---- 设置小程序的编译模式
"current": 0, //当前激活的模式(list 的索引项)
"list": [{
"name": "首页",
"path": "pages/home/home"
},{
"name": "分类",
"path": "pages/kind/kind"
},{
"name": "购物车",
"path": "pages/cart/cart"
},{
"name": "我的",
"path": "pages/user/user"
},{
"name": "登陆",
"path": "pages/login/login"
}]
}
}
应用生命周期
函数名 | 说明 |
---|---|
onLaunch | 当uni-app 初始化完成时触发(全局只触发一次) |
onShow | 当 uni-app 启动,或从后台进入前台显示 |
onHide | 当 uni-app 从前台进入后台 |
onError | 当 uni-app 报错时触发 |
onUniNViewMessage | 对 nvue 页面发送的数据进行监听,可参考 nvue 向 vue 通讯 |
函数名 | 说明 | 平台差异说明 | 最低版本 |
---|---|---|---|
onLoad | 监听页面加载,其参数为上个页面传递的数据,参数类型为Object(用于页面传参),参考示例 | ||
onShow | 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面 | ||
onReady | 监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发 | ||
onHide | 监听页面隐藏 | ||
onUnload | 监听页面卸载 | ||
onResize | 监听窗口尺寸变化 | App、微信小程序 | |
onPullDownRefresh | 监听用户下拉动作,一般用于下拉刷新,参考示例 | ||
onReachBottom | 页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据。具体见下方注意事项 | ||
onTabItemTap | 点击 tab 时触发,参数为Object,具体见下方注意事项 | 微信小程序、支付宝小程序、百度小程序、H5、App(自定义组件模式) | |
onShareAppMessage | 用户点击右上角分享 | 微信小程序、百度小程序、头条小程序、支付宝小程序 | |
onPageScroll | 监听页面滚动,参数为Object | nvue暂不支持 | |
onNavigationBarButtonTap | 监听原生标题栏按钮点击事件,参数为Object | App、H5 | |
onBackPress | 监听页面返回,返回 event = {from:backbutton、 navigateBack} ,backbutton 表示来源是左上角返回按钮或 android 返回键;navigateBack表示来源是 uni.navigateBack ;详细说明及使用:onBackPress 详解 | app、H5、支付宝小程序 | |
onNavigationBarSearchInputChanged | 监听原生标题栏搜索输入框输入内容变化事件 | App、H5 | 1.6.0 |
onNavigationBarSearchInputConfirmed | 监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的“搜索”按钮时触发。 | App、H5 | 1.6.0 |
onNavigationBarSearchInputClicked | 监听原生标题栏搜索输入框点击事件 | App、H5 | 1.6.0 |
组件生命周期
函数名 | 说明 | 平台差异说明 | 最低版本 |
---|---|---|---|
beforeCreate | 在实例初始化之后被调用。详见 | ||
created | 在实例创建完成后被立即调用。详见 | ||
beforeMount | 在挂载开始之前被调用。详见 | ||
mounted | 挂载到实例上去之后调用。详见 注意:此处并不能确定子组件被全部挂载,如果需要子组件完全挂载之后在执行操作可以使用$nextTick Vue官方文档 |
||
beforeUpdate | 数据更新时调用,发生在虚拟 DOM 打补丁之前。详见 | 仅H5平台支持 | |
updated | 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。详见 | 仅H5平台支持 | |
beforeDestroy | 实例销毁之前调用。在这一步,实例仍然完全可用。详见 | ||
destroyed | Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。详见 |
(轮播图状态、生命周期钩子中请求数据、修改状态、渲染数据)
//
没有更多数据了
↑
import prolist from '../../components/prolist/prolist.vue'
import { request } from '../../utils/index.js'
export default {
data() {
return {
bannerlist: [],
prolist: [],
pageCode: 1,
flag: false // 表示有无数据的标识
}
},
components: {
prolist
},
mounted () {
request({
url: '/pro/banner'
}).then(res => {
console.log(res.data)
this.bannerlist = res.data.data
})
request({
url: '/pro'
}).then(res => {
console.log(res.data)
this.prolist = res.data.data
})
},
onPullDownRefresh () { // 下拉刷新
console.log('下拉刷新')
request({
url: '/pro'
}).then(res => {
console.log(res.data)
this.prolist = res.data.data
this.pageCode = 1 // 重置页码
this.flag = false // 有无数据标识隐藏
// 当处理完数据刷新后,uni.stopPullDownRefresh 可以停止当前页面的下拉刷新。
uni.stopPullDownRefresh()
})
},
onReachBottom () { // 上拉加载
request({
url: '/pro',
data: {
pageCode: this.pageCode,
limitNum: 10
}
}).then(res => {
this.pageCode++
if (res.data.code === '10000') {
this.flag = true
} else {
this.prolist = [...this.prolist, ...res.data.data]
}
})
},
methods: {
backtop () {
uni.pageScrollTo({
scrollTop: 0,
duration: 200
})
}
}
}
const baseUrl = "http://xxx.xxx"
export function request (options) {
const { url, method, data, header } = options
uni.showLoading({
title: '加载中'
});
return new Promise((resolve, reject) => {
uni.request({
url: baseUrl + url,
data: data || {},
method: method || 'GET',
header: header || {},
timeout: 6000, // 请求超时时间设置
success: (res) => {
resolve(res)
},
fail: (err) => {
reject(err)
},
complete: () => {
uni.hideLoading()
}
})
})
}
export function toast (options) {
const { title, icon, duration } = options
uni.showToast({
title: title,
icon: icon || 'none',
duration: duration || 5000
})
}
{
{ item.proname }}
export default {
// props: ['prolist'],
props: {
// prolist: Array
prolist: {
type: Array,
default: function () {
return []
}
}
},
data() {
return {
};
},
methods: {
toDetail (proid) {
uni.navigateTo({
url: '/pages/detail/detail?proid=' + proid
})
}
}
}
{
{ teltip }}
{
{ passwordtip }}
import { request, toast } from '../../utils/index.js'
export default {
data() {
return {
tel: '18813007814',
password: '123456'
}
},
computed: {
teltip () {
if (this.tel.length !== 11) {
return '手机号码格式不正确'
} else {
return '手机号码ok'
}
},
passwordtip () {
if (this.password.length < 6) {
return '密码格式不正确'
} else {
return '密码ok'
}
}
},
methods: {
// 上面进行过 表单的检验,此处可以直接提交数据
login () {
request({
url: '/users/login',
method: 'POST',
data: {
tel: this.tel,
password: this.password
}
}).then(res => {
console.log(res.data)
const { code } = res.data
if (code === '10006') {
toast({title: '该用户还未注册'})
} else if (code === '10007') {
toast({title: '密码错误'})
} else {
// 登陆成功
toast({title: '登陆成功'})
try {
uni.setStorageSync('token', res.data.data.token)
uni.setStorageSync('userid', res.data.data.userid)
uni.navigateBack()
} catch (e) {
console.log(e)
}
}
})
}
}
}
{
{proname}}
{
{price}}
import { request, toast } from '../../utils/index.js'
export default {
data() {
return {
proname: '',
proid: '',
proimg: '',
price: 0
}
},
onLoad (options) {
// console.log(options)
const { proid } = options
request({
url: `/pro/detail?proid=${proid}`
}).then(res => {
console.log(res.data.data)
const { proname, proimg, price } = res.data.data
this.proname = proname
this.proimg = proimg
this.price = price
this.proid = proid
uni.setNavigationBarTitle({
title: proname
})
})
},
methods: {
addCart () {
// 获取本地存储的信息 token userid
try {
const token = uni.getStorageSync('token');
const userid = uni.getStorageSync('userid');
if (token && userid) { // 前端校验登陆
// 加入购物车判断用户是不是登陆状态 ---- 登陆 ---- 继续加入购物车
request({
url: '/cart/add',
method: 'POST',
data: {
token, userid, num: 1, proid: this.proid
}
}).then(res => {
if (res.data.code === '10119') { // 后端校验登陆状态
toast({title:'请先登录'})
uni.navigateTo({
url: '/pages/login/login'
})
} else {
toast({title:'加入购物车成功'})
}
})
} else {
toast({title:'请先登录'})
uni.navigateTo({
url: '/pages/login/login'
})
}
} catch (e) {
// error
}
}
}
}
购物车空空如也,请选购
{
{item.proname}}
¥{
{item.price}}
-
{
{item.num}}
+
删除
全选
总数:{
{totalNum}}
总价:{
{totalPrice}}