uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉)等多个平台。
相对开发者来说,减少了学习成本,因为只学会 uni-app 之后,即可开发出 iOS、Android、H5、以及各种小程序的应用,不需要再去学习开发其他应用的框架,相对开发而言,也大大减少了开发成本。
环境搭建
利用 HbuilderX 初始化项目
点击 HbuilderX 菜单栏文件>项目>新建
选择 uni-app,填写项目名称,项目创建的目录
运行项目
- 浏览器运行 进入 hello-uniapp 项目,点击工具栏的运行 -> 运行到浏览器 -> 选择浏览器,即可在浏览器里面体验 uni-app 的 H5 版。
- 真机运行 连接手机,开启 USB 调试,进入 hello-uniapp 项目,点击工具栏的运行 -> 真机运行 -> 选择运行的设备,即可在该设备里面体验 uni-app。
如手机无法识别,请点击菜单运行-运行到手机或模拟器-真机运行常见故障排查指南。
- 在微信开发者工具里运行 进入 hello-uniapp 项目,点击工具栏的运行 -> 运行到小程序模拟器 -> 微信开发者工具,即可在微信开发者工具里面体验 uni-app。
注意:如果是第一次使用,需要先配置小程序 ide 的相关路径,才能运行成功。如下图,需在输入框输入微信开发者工具的安装路径。 若 HBuilderX 不能正常启动微信开发者工具,需要开发者手动启动,然后将 uni-app 生成小程序工程的路径拷贝到微信开发者工具里面,在 HBuilderX 里面开发,在微信开发者工具里面就可看到实时的效果。 uni-app 默认把项目编译到根目录的 unpackage 目录。
- 在支付宝小程序开发者工具里运行 进入 hello-uniapp 项目,点击工具栏的运行 -> 运行到小程序模拟器 -> 支付宝小程序开发者工具,即可在支付宝小程序开发者工具里面体验 uni-app。
- 其他小程序开发工具里运行 内容同上,不再重复。
介绍项目目录和文件作用
pages.json 文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生 tabbar 等
manifest.json 文件是应用的配置文件,用于指定应用的名称、图标、权限等。
App.vue 是我们的跟组件,所有页面都是在 App.vue 下进行切换的,是页面入口文件,可以调用应用的生命周期函数。
main.js 是我们的项目入口文件,主要作用是初始化 vue 实例并使用需要的插件。
uni.scss 文件的用途是为了方便整体控制应用的风格。比如按钮颜色、边框风格,uni.scss 文件里预置了一批 scss 变量预置。
unpackage 就是打包目录,在这里有各个平台的打包文件
pages 所有的页面存放目录
static 静态资源目录,例如图片等
components 组件存放目录
为了实现多端兼容,综合考虑编译速度、运行性能等因素,uni-app 约定了如下开发规范:
页面文件遵循 Vue单文件组件 (SFC) 规范
组件标签靠近小程序规范,详见 uni-app 组件规范
接口能力(JS API)靠近微信小程序规范,但需将前缀 wx 替换为 uni,详见 uni-app 接口规范
数据绑定及事件处理同 Vue.js 规范,同时补充了 App 及页面的生命周期
为兼容多端运行,建议使用 flex 布局进行开发
全局配置和页面配置
通过 globalStyle 进行全局配置
用于设置应用的状态栏、导航条、标题、窗口背景色等。详细文档页面生命周期
<style> td {white-space:nowrap;border:1px solid #dee0e3;font-size:10pt;font-style:normal;font-weight:normal;vertical-align:middle;word-break:normal;word-wrap:normal;}</style> <byte-sheet-html-origin data-id="" data-version="4" data-is-embed="true" data-grid-line-hidden="false" data-copy-type="col"><colgroup><col width="213"><col width="105"><col width="105"><col width="398"></colgroup>
| 属性 | 类型 | 默认值 | 描述 |
| navigationBarBackgroundColor | HexColor | #F7F7F7 | 导航栏背景颜色(同状态栏背景色) |
| navigationBarTextStyle | String | white | 导航栏标题颜色及状态栏前景颜色,仅支持 black/white |
| navigationBarTitleText | String | | 导航栏标题文字内容 |
| backgroundColor | HexColor | #ffffff | 窗口的背景色 |
| backgroundTextStyle | String | dark | 下拉 loading 的样式,仅支持 dark / light |
| enablePullDownRefresh | Boolean | FALSE | 是否开启下拉刷新 |
| onReachBottomDistance | Number | 50 | 页面上拉触底事件触发时距页面底部距离,单位只支持px |</byte-sheet-html-origin>
创建新的 message 页面
右键 pages 新建 message 目录,在 message 目录下右键新建。vue 文件,并选择基本模板,uni-app 里不使用 div 标签,而使用 view 标签;图片标签不使用 img,而使用 image
<template>
<view>
这是信息页面
</view>
</template>
<script>
</script>
<style>
</style>
通过 pages 来配置页面
<style> td {white-space:nowrap;border:1px solid #dee0e3;font-size:10pt;font-style:normal;font-weight:normal;vertical-align:middle;word-break:normal;word-wrap:normal;}</style> <byte-sheet-html-origin data-id="" data-version="4" data-is-embed="true" data-grid-line-hidden="false" data-copy-type="col"><colgroup><col width="105"><col width="105"><col width="105"><col width="504"></colgroup>
| 属性 | 类型 | 默认值 | 描述 |
| path | String | | 配置页面路径 |
| style | Object | | 配置页面窗口表现,配置项参考 pageStyle |</byte-sheet-html-origin>
pages 数组数组中第一项表示应用启动页
"pages": [
{
"path": "pages/tabBar/component/component",
"style": {
"navigationBarTitleText": "首页",
"app-plus": {
"bounce": "vertical",
"titleNView": {
"buttons": [{
"text": "\ue6e3",
"fontSrc": "/static/iconfont.ttf",
"fontSize": "22px",
"color": "#FFFFFF"
}]
}
}
}
},
{
"path": "pages/tabBar/API/API",
"style": {
"navigationBarTitleText": "信息",
"app-plus": {
"titleNView": {
"buttons": [{
"text": "\ue534",
"fontSrc": "/static/uni.ttf",
"fontSize": "22px",
"color": "#FFFFFF"
}]
}
}
}
},
{
"path": "pages/tabBar/template/template",
"style": {
"navigationBarTitleText": "我的",
"app-plus": {
"titleNView": {
"buttons": [{
"text": "\ue534",
"fontSrc": "/static/uni.ttf",
"fontSize": "22px",
"color": "#FFFFFF"
}]
}
}
}
}
]
配置 tabbar
如果应用是一个多 tab 应用,可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页。
Tips
当设置 position 为 top 时,将不会显示 icon
tabBar 中的 list 是一个数组,只能配置最少 2 个、最多 5 个 tab,tab 按数组的顺序排序。
属性说明:
<style> td {white-space:nowrap;border:1px solid #dee0e3;font-size:10pt;font-style:normal;font-weight:normal;vertical-align:middle;word-break:normal;word-wrap:normal;}</style> <byte-sheet-html-origin data-id="" data-version="4" data-is-embed="true" data-grid-line-hidden="false" data-copy-type="col"><colgroup><col width="105"><col width="105"><col width="105"><col width="105"><col width="171"><col width="230"></colgroup>
| 属性 | 类型 | 必填 | 默认值 | 描述 | 平台差异说明 |
| color | HexColor | 是 | | tab 上的文字默认颜色 | |
| selectedColor | HexColor | 是 | | tab 上的文字选中时的颜色 | |
| backgroundColor | HexColor | 是 | | tab 的背景色 | |
| borderStyle | String | 否 | black | tabbar 上边框的颜色,仅支持 black/white | |
| list | Array | 是 | | tab 的列表,详见 list 属性说明,最少2个、最多5个 tab | |
| position | String | 否 | bottom | 可选值 bottom、top | top 值仅微信小程序支持 |</byte-sheet-html-origin>
其中 list 接收一个数组,数组中的每个项都是一个对象,其属性值如下:
<style> td {white-space:nowrap;border:1px solid #dee0e3;font-size:10pt;font-style:normal;font-weight:normal;vertical-align:middle;word-break:normal;word-wrap:normal;}</style> <byte-sheet-html-origin data-id="" data-version="4" data-is-embed="true" data-grid-line-hidden="false" data-copy-type="col"><colgroup><col width="105"><col width="105"><col width="105"><col width="516"></colgroup>
| 属性 | 类型 | 必填 | 说明 |
| pagePath | String | 是 | 页面路径,必须在 pages 中先定义 |
| text | String | 是 | tab 上按钮文字,在 5+APP 和 H5 平台为非必填。例如中间可放一个没有文字的+号图标 |
| iconPath | String | 否 | 图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px,当 postion 为 top 时,此参数无效,不支持网络图片,不支持字体图标 |
| selectedIconPath | String | 否 | 选中时的图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px ,当 postion 为 top 时,此参数无效 |</byte-sheet-html-origin>
案例代码:
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#007AFF",
"borderStyle": "black",
"backgroundColor": "#F8F8F8",
"list": [{
"pagePath": "pages/tabBar/component/component",
"iconPath": "static/component.png",
"selectedIconPath": "static/componentHL.png",
"text": "首页"
},
{
"pagePath": "pages/tabBar/API/API",
"iconPath": "static/api.png",
"selectedIconPath": "static/apiHL.png",
"text": "信息"
}, {
"pagePath": "pages/tabBar/extUI/extUI",
"iconPath": "static/extui.png",
"selectedIconPath": "static/extuiHL.png",
"text": "我的"
}
]
}
uni 的生命周期
应用的生命周期
生命周期函数:在生命周期中每个阶段会伴随着每一个函数的触发,这些函数被称为生命周期函数
uni-app 支持如下应用生命周期函数:
<style> td {white-space:nowrap;border:1px solid #dee0e3;font-size:10pt;font-style:normal;font-weight:normal;vertical-align:middle;word-break:normal;word-wrap:normal;}</style> <byte-sheet-html-origin data-id="" data-version="4" data-is-embed="true" data-grid-line-hidden="false" data-copy-type="col"><colgroup><col width="105"><col width="723"></colgroup>
| 函数名 | 说明 |
| onLaunch | 当uni-app 初始化完成时触发(全局只触发一次) |
| onShow | 当 uni-app 启动,或从后台进入前台显示 |
| onHide | 当 uni-app 从前台进入后台 |
| onError | 当 uni-app 报错时触发 |</byte-sheet-html-origin>
页面的生命周期
uni-app 支持如下页面生命周期函数:
<style> td {white-space:nowrap;border:1px solid #dee0e3;font-size:10pt;font-style:normal;font-weight:normal;vertical-align:middle;word-break:normal;word-wrap:normal;}</style> <byte-sheet-html-origin data-id="" data-version="4" data-is-embed="true" data-grid-line-hidden="false" data-copy-type="col"><colgroup><col width="163"><col width="408"><col width="147"><col width="107"></colgroup>
| 函数名 | 说明 | 平台差异说明 | 最低版本 |
| onLoad | 监听页面加载,其参数为上个页面传递的数据,参数类型为Object(用于页面传参),参考示例 | | |
| onShow | 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面 | | |
| onReady | 监听页面初次渲染完成。 | | |
| onHide | 监听页面隐藏 | | |
| onUnload | 监听页面卸载 | | |</byte-sheet-html-origin>
下拉刷新
开启下拉刷新
在 uni-app 中有两种方式开启下拉刷新
需要在 pages.json 里,找到的当前页面的 pages 节点,并在 style 选项中开启 enablePullDownRefresh
通过调用 uni.startPullDownRefresh 方法来开启下拉刷新
创建 list 页面进行演示
<template>
<view>
<view v-for="(item,index) in arr" :key="index">
{{item}}
</view>
</view>
</template>
<script>
export default {
data () {
return {
arr: ['前端','java','ui','大数据']
}
}
}
</script>
<style>
</style>
通过 pages.json 文件中找到当前页面的 pages 节点,并在 style 选项中开启 enablePullDownRefresh
{
"path":"pages/list/list",
"style":{
"enablePullDownRefresh": true
}
}
监听下拉刷新
通过 onPullDownRefresh 可以监听到下拉刷新的动作
export default {
data () {
return {
arr: ['前端','java','ui','大数据']
}
},
methods: {
startPull () {
uni.startPullDownRefresh()
}
},
onPullDownRefresh () {
console.log('触发下拉刷新了')
}
}
关闭下拉刷新
uni.stopPullDownRefresh()
停止当前页面下拉刷新。
<template>
<view>
<button type="primary" @click="startPull">开启下拉刷新</button>
<view v-for="(item,index) in arr" :key="index">
{{item}}
</view>
</view>
</template>
<script>
export default {
data () {
return {
arr: ['前端','java','ui','大数据']
}
},
methods: {
startPull () {
uni.startPullDownRefresh()
}
},
onPullDownRefresh () {
this.arr = []
setTimeout(()=> {
this.arr = ['前端','java','ui','大数据']
uni.stopPullDownRefresh()
}, 1000);
}
}
</script>
上拉加载
通过在 pages.json 文件中找到当前页面的 pages 节点下 style 中配置 onReachBottomDistance 可以设置距离底部开启加载的距离,默认为 50px
通过 onReachBottom 监听到触底的行为
<template>
<view>
<view v-for="(item,index) in arr" :key="index">
{{item}}
</view>
</view>
</template>
<script>
export default {
data () {
return {
arr: ['前端','java','ui','大数据','前端','java','ui','大数据']
}
},
onReachBottom () {
console.log('触底了')
}
}
</script>
<style>
view{
height: 100px;
line-height: 100px;
}
</style>
网络请求
在 uni 中可以调用 uni.request 方法进行请求网络请求
<template>
<view>
<button @click="send">发送请求</button>
</view>
</template>
<script>
export default {
methods: {
send () {
//method 可以配置POST/GET
uni.request({
method: "GET",
url: '...........',
success(res) {
console.log(res)
}
})
}
}
}
</script>
数据缓存
uni.setStorage
将数据存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个异步接口。
代码演示
<template>
<view>
<button type="primary" @click="setStor">存储数据</button>
</view>
</template>
<script>
export default {
methods: {
setStor () {
uni.setStorage({
key: 'id',
data: 100,
success () {
console.log('存储成功')
}
})
}
}
}
</script>
<style>
</style>
uni.setStorageSync
将 data 存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。
代码演示
<template>
<view>
<button type="primary" @click="setStor">存储数据</button>
</view>
</template>
<script>
export default {
methods: {
setStor () {
uni.setStorageSync('id',100)
}
}
}
</script>
<style>
</style>
uni.getStorage
从本地缓存中异步获取指定 key 对应的内容。
代码演示
<template>
<view>
<button type="primary" @click="getStorage">获取数据</button>
</view>
</template>
<script>
export default {
data () {
return {
id: ''
}
},
methods: {
getStorage () {
uni.getStorage({
key: 'id',
success: res=>{
this.id = res.data
}
})
}
}
}
</script>
uni.getStorageSync
从本地缓存中同步获取指定 key 对应的内容。
代码演示
<template>
<view>
<button type="primary" @click="getStorage">获取数据</button>
</view>
</template>
<script>
export default {
methods: {
getStorage () {
const id = uni.getStorageSync('id')
console.log(id)
}
}
}
</script>
uni.removeStorage
从本地缓存中异步移除指定 key。
代码演示
<template>
<view>
<button type="primary" @click="removeStorage">删除数据</button>
</view>
</template>
<script>
export default {
methods: {
removeStorage () {
uni.removeStorage({
key: 'id',
success: function () {
console.log('删除成功')
}
})
}
}
}
</script>
uni.removeStorageSync
从本地缓存中同步移除指定 key。
代码演示
<template>
<view>
<button type="primary" @click="removeStorage">删除数据</button>
</view>
</template>
<script>
export default {
methods: {
removeStorage () {
uni.removeStorageSync('id')
}
}
}
</script>
上传图片、预览图片
上传图片
uni.chooseImage 方法从本地相册选择图片或使用相机拍照。
案例代码
<template>
<view>
<button @click="chooseImg" type="primary">上传图片</button>
<view>
<image v-for="item in imgArr" :src="item" :key="index"></image>
</view>
</view>
</template>
<script>
export default {
data () {
return {
imgArr: []
}
},
methods: {
chooseImg () {
uni.chooseImage({
count: 9,
success: res=>{
this.imgArr = res.tempFilePaths
}
})
}
}
}
</script>
预览图片
结构
<view>
<image v-for="item in imgArr" :src="item" @click="previewImg(item)" :key="item"></image>
</view>
预览图片的方法
previewImg (current) {
uni.previewImage({
urls: this.imgArr,
current
})
}
条件注释实现跨段兼容
条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。
写法:以 #ifdef 加平台标识 开头,以 #endif 结尾。
平台标识
<style> td {white-space:nowrap;border:1px solid #dee0e3;font-size:10pt;font-style:normal;font-weight:normal;vertical-align:middle;word-break:normal;word-wrap:normal;}</style> <byte-sheet-html-origin data-id="" data-version="4" data-is-embed="true" data-grid-line-hidden="false" data-copy-type="col"><colgroup><col width="164"><col width="243"><col width="414"></colgroup>
| 值 | 平台 | 参考文档 |
| APP-PLUS | 5+App | HTML5+ 规范 |
| H5 | H5 | |
| MP-WEIXIN | 微信小程序 | 微信小程序 |
| MP-ALIPAY | 支付宝小程序 | 支付宝小程序 |
| MP-BAIDU | 百度小程序 | 百度小程序 |
| MP-TOUTIAO | 头条小程序 | 头条小程序 |
| MP-QQ | QQ小程序 | |
| MP | 微信小程序/支付宝小程序/百度小程序/头条小程序/QQ小程序 | |</byte-sheet-html-origin>
组件的条件注释
代码演示
<!-- #ifdef H5 -->
<view>
h5页面会显示
</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<view>
微信小程序会显示
</view>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<view>
app会显示
</view>
<!-- #endif -->
api 的条件注释
代码演示
onLoad () {
//#ifdef MP-WEIXIN
console.log('微信小程序')
//#endif
//#ifdef H5
console.log('h5页面')
//#endif
}
样式的条件注释
代码演示
/* #ifdef H5 /
view{
height: 100px;
line-height: 100px;
background: red;
}
/ #endif /
/ #ifdef MP-WEIXIN /
view{
height: 100px;
line-height: 100px;
background: green;
}
/ #endif */
uni 中的导航跳转
利用 navigator 进行跳转
navigator 详细文档:文档地址
跳转到普通页面
<navigator url="/pages/about/about" hover-class="navigator-hover">
<button type="default">跳转到关于页面</button>
</navigator>
跳转到 tabbar 页面
<navigator url="/pages/message/message" open-type="switchTab">
<button type="default">跳转到message页面</button>
</navigator>
利用编程式导航进行跳转
利用 navigateTo 进行导航跳转
保留当前页面,跳转到应用内的某个页面,使用 uni.navigateBack 可以返回到原页面。
<button type="primary" @click="goAbout">跳转到关于页面</button>
通过 navigateTo 方法进行跳转到普通页面
goAbout () {
uni.navigateTo({
url: '/pages/about/about',
})
}
通过 switchTab 跳转到 tabbar 页面
跳转到 tabbar 页面
<button type="primary" @click="goMessage">跳转到message页面</button>
通过 switchTab 方法进行跳转
goMessage () {
uni.switchTab({
url: '/pages/message/message'
})
}
redirectTo 进行跳转
关闭当前页面,跳转到应用内的某个页面。
<!-- template -->
<button type="primary" @click="goMessage">跳转到message页面</button>
<!-- js -->
goMessage () {
uni.switchTab({
url: '/pages/message/message'
})
}
通过 onUnload 测试当前组件确实卸载
onUnload () {
console.log('组件卸载了')
}
导航跳转传递参数
在导航进行跳转到下一个页面的同时,可以给下一个页面传递相应的参数,接收参数的页面可以通过 onLoad 生命周期进行接收
传递参数的页面
goAbout () {
uni.navigateTo({
url: '/pages/about/about?id=80',
});
}
接收参数的页面
<script>
export default {
onLoad (options) {
console.log(options)
}
}
</script>
结语
以上是我对uniApp的简单了解,介绍了初始项目搭建,运行方式,相关配置及方法的使用,有何不解欢迎私下一起探讨。