uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉)等多个平台。
uni-app开发参考文档:https://uniapp.dcloud.io/README
uni-app开发工具:HBuilderX:官方IDE下载地址使用uni-app创建项目
页面配置
1.pages.json页面配置
pages.json 文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path" : "pages/home/home",
"style" : {
"navigationBarTitleText": "首页",
"enablePullDownRefresh" : true
}
}
,{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "好购物-app"
}
}
,{
"path" : "pages/kind/kind",
"style" : {"navigationBarTitleText": "分类"}
}
,{
"path" : "pages/cart/cart",
"style" : {"navigationBarTitleText": "购物车"}
}
,{
"path" : "pages/users/users",
"style" : {"navigationBarTitleText": "我的"}
}
,{
"path" : "pages/detail/detail"
}
,{
"path" : "pages/login/login",
"style" : {}
}
,{
"path" : "pages/register/register",
"style" : {}
}
],
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "好购物",
"navigationBarBackgroundColor": "#f66",
"backgroundColor": "#F8F8F8"
},
"tabBar":{
"color": "#333",
"selectedColor": "#f66",
"backgroundColor":"#efefef",
"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/users/users",
"text": "我的",
"iconPath": "static/resources/mine.png",
"selectedIconPath": "static/resources/mine-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/users/users"
}
]
}
}
pages
uni-app 通过 pages 节点配置应用由哪些页面组成,pages 节点接收一个数组,数组每个项都是一个对象,其属性值如下:
通过新建页面,可以创建其他普通页面
2.运行uni-app
浏览器运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到浏览器 -> 选择浏览器,即可在浏览器里面体验uni-app 的 H5 版。
3.App.vue文件
App.vue是uni-app的主组件,所有页面都是在App.vue下进行切换的,是页面入口文件。但App.vue本身不是页面,这里不能编写视图元素。
这个文件的作用包括:调用应用生命周期函数、配置全局样式、配置全局的存储globalData
应用生命周期仅可在App.vue中监听,在页面监听无效。
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
/*每个页面公共css */
</style>
onLaunch 当uni-app 初始化完成时触发(全局只触发一次)
onShow 当 uni-app 启动,或从后台进入前台显示
onHide 当 uni-app 从前台进入后台
onError 当 uni-app 报错时触发
封装数据库的请求
uni.request(OBJECT)
发起网络请求。
uni.showToast(OBJECT)
显示消息提示框。
const baseUrl = ' https://www.xxxx.xx' //你的接口地址
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
})
}
首页轮播图数据请求
<template>
<view class="container">
<swiper :indicator-dots="true" :autoplay="true" :circular="true">
<swiper-item v-for="(item, index) of bannerlist" :key="index">
<image :lazy-load="true" mode="aspectFit" :src="'http://daxun.kuboy.top' + item" ></image>
</swiper-item>
</swiper>
<view class="iconfont" @click="backtop">↑</view>
</view>
</template>
<script>
import { request } from '../../utils/index.js'
export default {
data() {
return {
bannerlist: []
}
},
components: {
},
mounted () {
request({
url: '/pro/banner'
}).then(res => {
console.log(res.data)
this.bannerlist = res.data.data
})
},
methods: {
backtop () {
uni.pageScrollTo({
scrollTop: 0,
duration: 200
})
}
}
}
</script>
<style>
image {
width: 100%;
}
.iconfont {
position: fixed;
bottom: 60px;
right: 10px;
width: 40px;
height: 40px;
background-color: #f66;
}
</style>
自定义商品列表组件
<template>
<view class="prolist">
<!-- <view class="proitem" v-for="(item, index) of prolist" :key="index">
<view class="itemimg">
<image :src="item.proimg" mode=""></image>
</view>
<view class="iteminfo">
<view class="title">{{ item.proname }}</view>
</view>
</view> -->
<!-- 声明式跳转 -->
<!-- <navigator :url="'/pages/detail/detail?proid=' + item.proid" class="proitem" v-for="(item, index) of prolist" :key="index">
<view class="itemimg">
<image :src="item.proimg" mode=""></image>
</view>
<view class="iteminfo">
<view class="title">{{ item.proname }}</view>
</view>
</navigator> -->
<!-- 编程式跳转 -->
<view @click="toDetail(item.proid)" class="proitem" v-for="(item, index) of prolist" :key="index">
<view class="itemimg">
<image :src="item.proimg" mode=""></image>
</view>
<view class="iteminfo">
<view class="title">{{ item.proname }}</view>
</view>
</view>
</view>
</template>
<script>
/*
子组件定义的地方,添加一个props选项,props选项的值是一个数组或者对象
1.如果是数组,数组的元素就是自定义的属性名,可以在组件中通过此自定义属性名访问数据
2.如果是对象,有两种形式,
2.1 key值为自定义的属性名,value值为数据类型
2.2 key值为自定义的属性名,value为一个对象,该对象有两个选项,一个为type(数据类型),一个未default(默认值),如果默认值是对象或者数组,需要把default写为一个函数,返回对象和数组
*/
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
})
}
}
}
</script>
<style>
.prolist .proitem {
width: 100%;
height: 100px;
display: flex;
box-sizing: border-box;
border-bottom: 1upx solid #ccc;
}
/* gulp */
.prolist .proitem .itemimg {
width: 100px;
height: 100px;
}
.prolist .proitem .itemimg image{
width: 90px;
height: 90px;
box-sizing: border-box;
/* 如果是网页开发,需要写一个物理像素 ---- scss库 ---- 1px边框 */
border: 1upx solid #ccc;
margin: 5px;
}
.prolist .proitem .iteminfo {
flex: 1;
padding: 3px 5px;
}
</style>
在首页设置自定义组件
<template>
<view class="container">
<swiper :indicator-dots="true" :autoplay="true" :circular="true">
<swiper-item v-for="(item, index) of bannerlist" :key="index">
<image :lazy-load="true" mode="aspectFit" :src="'http://daxun.kuboy.top' + item" ></image>
</swiper-item>
</swiper>
<prolist :prolist="prolist"/>
<view class="tip" v-if="flag">没有更多数据了</view>
<view class="iconfont" @click="backtop">↑</view>
</view>
</template>
<script>
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
})
}
}
}
</script>
<style>
....
</style>