目录
[2.1.1 HBuilderX](#2.1.1 HBuilderX)
[2.1.2 下载微信开发者工具](#2.1.2 下载微信开发者工具)
[2.2 创建uniapp项目](#2.2 创建uniapp项目)
[2.2.1 新建项目](#2.2.1 新建项目)
[2.2.2 项目基本结构](#2.2.2 项目基本结构)
[2.2.3 在微信开发者工具上运行](#2.2.3 在微信开发者工具上运行)
[2.2.4 发布微信小程序](#2.2.4 发布微信小程序)
[三、pages.json 页面路由](#三、pages.json 页面路由)
[4.1 视图容器](#4.1 视图容器)
[4.1.1 view:视图容器](#4.1.1 view:视图容器)
[4.1.2 scroll-view:可滚动视图](#4.1.2 scroll-view:可滚动视图)
[4.1.3 swiper:滑块视图容器](#4.1.3 swiper:滑块视图容器)
[4.1.4 match-media:匹配检测节点](#4.1.4 match-media:匹配检测节点)
[4.1.5 movable-area:可拖动区域](#4.1.5 movable-area:可拖动区域)
[4.1.6 movable-view:可移动的视图容器](#4.1.6 movable-view:可移动的视图容器)
[4.1.7 cover-view:覆盖在原生组件上的文本视图](#4.1.7 cover-view:覆盖在原生组件上的文本视图)
[4.1.8 cover-image:覆盖在原生组件上的图片视图](#4.1.8 cover-image:覆盖在原生组件上的图片视图)
[4.2 基础内容](#4.2 基础内容)
[4.2.1 text:文本](#4.2.1 text:文本)
[4.2.2 icon:图标](#4.2.2 icon:图标)
[4.2.3 rich-text:富文本](#4.2.3 rich-text:富文本)
[4.2.4 progress:进度条](#4.2.4 progress:进度条)
[4.3 表单组件](#4.3 表单组件)
[4.3.1 要点](#4.3.1 要点)
[4.3.2 form写法](#4.3.2 form写法)
[4.3.3 代码示例](#4.3.3 代码示例)
[4.4 媒体组件](#4.4 媒体组件)
[4.4.1 audio:音频](#4.4.1 audio:音频)
[4.4.2 camera:相机](#4.4.2 camera:相机)
[4.4.3 image:图片](#4.4.3 image:图片)
[4.4.4 video:视频](#4.4.4 video:视频)
[4.5 map地图](#4.5 map地图)
[4.5 扩展组件](#4.5 扩展组件)
[5.1 应用的生命周期](#5.1 应用的生命周期)
[5.2 页面的生命周期](#5.2 页面的生命周期)
[5.3 组件的生命周期](#5.3 组件的生命周期)
[6.1 网络请求](#6.1 网络请求)
[6.2 上传和下载](#6.2 上传和下载)
[7.1 异步存取指定键值对(对应的值)](#7.1 异步存取指定键值对(对应的值))
[7.2 同步存取指定键值对(对应的值)](#7.2 同步存取指定键值对(对应的值))
[7.3 移除指定键值对](#7.3 移除指定键值对)
[7.4 清理本地数据缓存](#7.4 清理本地数据缓存)
[8.1 路由跳转](#8.1 路由跳转)
[8.2 路由传参](#8.2 路由传参)
[8.3 事件传参](#8.3 事件传参)
[8.4 组件传值](#8.4 组件传值)
[8.4.1 父组件给子组件传值](#8.4.1 父组件给子组件传值)
[8.4.2 子组件给父组件传值](#8.4.2 子组件给父组件传值)
[9.1 获取位置](#9.1 获取位置)
[9.2 查看位置](#9.2 查看位置)
[10.1 图片](#10.1 图片)
[10.2 文件](#10.2 文件)
[10.3 视频](#10.3 视频)
[11.1 交互反馈(提示框)](#11.1 交互反馈(提示框))
[11.1 消息提示框](#11.1 消息提示框)
[11.2 loading 提示框](#11.2 loading 提示框)
[11.3 模态弹窗](#11.3 模态弹窗)
[11.4 从底部向上弹出操作菜单](#11.4 从底部向上弹出操作菜单)
[11.2 滚动:uni.pageScrollTo(OBJECT)](#11.2 滚动:uni.pageScrollTo(OBJECT))
[11.3 窗口:uni.onWindowResize(CALLBACK)](#11.3 窗口:uni.onWindowResize(CALLBACK))
[11.4 下拉刷新:onPullDownRefresh](#11.4 下拉刷新:onPullDownRefresh)
一、介绍
uni-app
是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。
本次章节也是博主从零开始搭建uniapp项目,在此过程进行记录,帮助后续查询同时为读者提供讲解,如有异议,欢迎留言。
更多详情可查看uni-app官网:uni-app官网
二、环境搭建
2.1.需要下载的软件
2.1.1 HBuilderX
下载地址:HBuilderX-高效极客技巧
2.1.2 下载微信开发者工具
下载地址:微信开发者工具(稳定版 Stable Build)下载地址与更新日志 | 微信开放文档
最好下载稳定版。
注意:
1.06后的版本不支持win10了,下载时需要注意。
2.2 创建uniapp项目
2.2.1 新建项目
打开HBuilderX,点击文件------>新建------>项目------>选择uni-app------>填写项目名,项目地址,选择模板------>点击创建。
如图所示:
2.2.2 项目基本结构
创建完成后,项目会生成默认的目录结构,如图所示:
2.2.3 在微信开发者工具上运行
然后启动测试一下,发现失败了。经过检查它报错的这两项,也没问题啊。
那么问题可能是出在微信开发者,我们需要进入微信开发者工具->设置->安全,然后把服务的端口号打开。
接着重新运行即可。
2.2.4 发布微信小程序
1.在浏览器中打开微信公众平台,注册信息,填写小程序相关信息,在"开发管理"模块中有AppID(小程序ID),将AppID填写在uniapp项目中。
2.点击"真机调试",会显示二维码,手机扫码即可查看。
3.点击"上传",输入版本号和项目备注,点击【上传】 。
4.在微信开发者工具中上传了小程序代码之后。
登录小程序管理后台(链接: 微信公众平台);
点击【版本管理】 -> 【开发版本】, 找到提交上传的版本;
点击【提交审核】 ,根据提示填写信息,即可提交审核。
5.发布
审核通过之后,管理员的微信中会收到小程序通过审核的通知。
此时登录小程序管理后台,在审核版本中可以看到通过审核的版本。
点击【发布】,即可发布小程序。
三、pages.json 页面路由
pages.json
文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。
配置项列表
属性 | 类型 | 必填 | 描述 | 平台兼容 |
---|---|---|---|---|
globalStyle | Object | 否 | 设置默认页面的窗口表现 | |
pages | Object Array | 是 | 设置页面路径及窗口表现 | |
easycom | Object | 否 | 组件自动引入规则 | 2.5.5+ |
tabBar | Object | 否 | 设置底部 tab 的表现 | |
condition | Object | 否 | 启动模式配置 | |
subPackages | Object Array | 否 | 分包加载配置 | H5 不支持 |
preloadRule | Object | 否 | 分包预下载规则 | 微信小程序 |
workers | String | 否 | Worker 代码放置的目录 |
微信小程序 |
leftWindow | Object | 否 | 大屏左侧窗口 | H5 |
topWindow | Object | 否 | 大屏顶部窗口 | H5 |
rightWindow | Object | 否 | 大屏右侧窗口 | H5 |
uniIdRouter | Object | 否 | 自动跳转相关配置,新增于HBuilderX 3.5.0 | |
entryPagePath | String | 否 | 默认启动首页,新增于HBuilderX 3.7.0 | 微信小程序、支付宝小程序 |
下面的page.json是个简单的 示例,标记了每个配置项的用法。
{
"pages": [
/* 主页面 */
{
"path": "pages/index/index",
"style": {
// 导航栏标题文字内容
"navigationBarTitleText": "首页"
// 是否开启下拉刷新
// "enablePullDownRefresh": true
}
}
],
//分包
"subPackages": [
/* 子页面 */
{
"root": "pages/practice/demo",
"pages": [
{
"path": "introduce",
"style": {
"navigationBarTitleText": "页面介绍", //设置页面标题文字
"enablePullDownRefresh": true //开启下拉刷新
}
}
]
}
],
// 全局样式
"globalStyle": {
// 导航栏标题颜色及状态栏前景颜色,仅支持 black/white
"navigationBarTextStyle": "black",
"enablePullDownRefresh": false,
// 定义页面底部的触发距离
"onReachBottomDistance": 50,
// 导航栏标题文字内容
"navigationBarTitleText": "uni-app",
// 导航栏背景颜色(同状态栏背景色)
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
/* 设置底部 tab 的表现 */
"tabBar": {
// 字体颜色
"color": "#cdcdcd",
// 选中字体颜色
"selectedColor": "#83b343",
"borderStyle": "black",
"backgroundColor": "#fff",
"fontSize": "16px",
"iconWidth": "18px",
"list": [{
"pagePath": "pages/index/index",
"text": "农事记录",
// 图标路径
"iconPath": "static/iconimg/icon_note.png",
// 选中图标路径
"selectedIconPath": "static/iconimg/icon_noteOp.png"
}
],
/* 这里设置的底部导航栏,中间图标凸起的效果 */。
//注意:目前仅在app,h5中显示,微信小程序不支持
"midButton":{
"iconPath": "static/iconimg/icon_tong.png",
"iconWidth":"70px",
// "text":"练习",
"width":"70px",
"height":"70px"
}
}
}
注意:
每新增一个页面,都要在page.json中配置,不然找不到。
或者分包,分包主要是因为有时候项目过大会影响打包,分包后减少内存。
四、组件
4.1 视图容器
所有的视图组件,包括view、swiper等,本身不显示任何可视化元素。它们的用途都是为了包裹其他真正显示的组件。
4.1.1 view:视图容器
类似于传统html中的div,用于包裹各种元素内容。
4.1.2 scroll-view:可滚动视图
用于区域滚动。
需注意在webview渲染的页面中,区域滚动的性能不及页面滚动。
使用竖向滚动时,需要给 <scroll-view>
一个固定高度,通过 css 设置 height;使用横向滚动时,需要给<scroll-view>
添加white-space: nowrap;
样式。
代码示例:
<view>
<!-- 纵向滚动 -->
<view class="area" style="border: 1rpx solid #000000;">
<scroll-view style="height: 200rpx;" scroll-y="true">
<view style="margin: 40px 0;">冯绍峰</view>
<view style="margin: 40px 0;">冯绍峰</view>
<view style="margin: 40px 0;">冯绍峰</view>
<view style="margin: 40px 0;">冯绍峰</view>
</scroll-view>
</view>
<!-- 横向滚动 -->
<view class="area" style="border: 1rpx solid #000000;">
<scroll-view scroll-x="true" style="width: 100%;height: 50px;white-space: nowrap;" @scroll="scroll"
scroll-left="120">
<view style="height: 50px;display: inline-block;width: 100%;">冯绍峰</view>
<view style="height: 50px;display: inline-block;width: 100%;">冯绍峰</view>
</scroll-view>
</view>
</view>
运行结果:
4.1.3 swiper:滑块视图容器
一般用于左右滑动或上下滑动,比如banner轮播图。
注意滑动切换和滚动的区别,滑动切换是一屏一屏的切换。swiper下的每个swiper-item是一个滑动切换区域,不能停留在2个滑动区域之间。
4.1.4 match-media:匹配检测节点
相当于
@media screen and (max-width: 1500px) {}
代码示例:
<template>
<view>
<match-media :min-width="375" :max-width="800" >
<view>当页面最小宽度 375px, 页面宽度最大 800px 时显示</view>
</match-media>
<match-media :min-height="400" :orientation="landscape">
<view>当页面高度不小于 400px 且屏幕方向为横向时展示这里</view>
</match-media>
</view>
</template>
4.1.5 movable-area:可拖动区域
由于app和小程序的架构是逻辑层与视图层分离,使用js监听拖动时会引发逻辑层和视图层的频繁通讯,影响性能。为了方便高性能的实现拖动,平台特封装了movable-area组件。
movable-area指代可拖动的范围,在其中内嵌movable-view组件用于指示可拖动的区域。
即手指/鼠标按住movable-view拖动或双指缩放,但拖不出movable-area规定的范围。
当然也可以不拖动,而使用代码来触发movable-view在movable-area里的移动缩放。
4.1.6 movable-view:可移动的视图容器
在页面中可以拖拽滑动或双指缩放。
movable-view必须在movable-area组件中,并且必须是直接子节点,否则不能移动。
4.1.7 cover-view:覆盖在原生组件上的文本视图
app-vue和小程序框架,渲染引擎是webview的。但为了优化体验,部分组件如map、video、textarea、canvas通过原生控件实现,原生组件层级高于前端组件(类似flash层级高于div)。为了能正常覆盖原生组件,设计了cover-view。
4.1.8 cover-image:覆盖在原生组件上的图片视图
可覆盖的原生组件同cover-view,支持嵌套在cover-view里。
4.2 基础内容
4.2.1 text:文本
行内元素,相当于<span>
<view class="area">
<h1>text</h1>
<text>沉醉不知归路</text>
<!-- 长按可选择 -->
<text selectable>沉醉不知归路</text>
</view>
4.2.2 icon:图标
这是uniapp自带的图标,还可以通过iconfont-阿里巴巴矢量图标库进行图标添加,可下载图片,可下载样式。
下载样式的步骤:
步骤一:
步骤二:
步骤三:
步骤四:
下载完成后解压:
步骤五:
步骤六:
引入iconfont.css
步骤七:
引入icon
<view class="area">
<view class="icon iconfont"></view>
</view>
运行后发现,icon显示出来了,但是,颜色是黑白的,如何改成彩色呢?
在阿里矢量图库中勾选彩色,并重新下载引用,即可得到彩色图标。
4.2.3 rich-text:富文本
4.2.4 progress:进度条
属性说明
属性名 | 类型 | 默认值 | 说明 | 平台差异说明 |
---|---|---|---|---|
percent | Number | 无 | 百分比0~100 | |
show-info | Boolean | false | 在进度条右侧显示百分比 | |
border-radius | Number/String | 0 | 圆角大小 | app-nvue、微信基础库2.3.1+、QQ小程序、快手小程序、京东小程序 |
font-size | Number/String | 16 | 右侧百分比字体大小 | app-nvue、微信基础库2.3.1+、QQ小程序、京东小程序 |
stroke-width | Number | 6 | 进度条线的宽度,单位px | |
activeColor | Color | #09BB07(百度为#E6E6E6) | 已选择的进度条的颜色 | |
backgroundColor | Color | #EBEBEB | 未选择的进度条的颜色 | |
active | Boolean | false | 进度条从左往右的动画 | |
active-mode | String | backwards | backwards: 动画从头播;forwards:动画从上次结束点接着播 | App、H5、微信小程序、QQ小程序、快手小程序、京东小程序 |
duration | Number | 30 | 进度增加1%所需毫秒数 | App-nvue2.6.1+、微信基础库2.8.2+、H5 3.1.11+、App-Vue 3.1.11+、快手小程序、京东小程序 |
@activeend | EventHandle | 动画完成事件 | 微信小程序、京东小程序 |
代码示例:
<view class="progress-box">
<progress percent="50" show-info stroke-width="3" activeColor="red" backgroundColor="blue"/>
</view>
4.3 表单组件
所用到的标签跟html的差不多,有几个不一样:
|-------------|-------|----------------|--------|-------------|--------|--------|--------|
| 外 | input | checkbox-group | picker | radio-group | slider | switch | editor |
| 内 | | checkbox | | radio | | | |
| 描述 | 单行输入框 | 多选框组 | 选择器 | 单项选择器 | 滑动选择器 | 开关选择器 | 富文本编辑器 |
| 是否支持 form表单 | 是 | 是 | 是 | 是 | 是 | 是 | 否 |
form表单:
4.3.1 要点
当点击 <form>
表单中 formType 为 submit 的 <button>
组件时,会将表单组件中的 value 值进行提交,需要在表单组件中加上 name 来作为 key。
也就是需要给支持form表单的组件上加name,不然提交的时候识别不到。例如:
注意:在表单中input只能写一个focus,不然也识别不到。
4.3.2 form写法
<template>
<view class="content">
<form @submit="formSubmit" @reset="formReset">
//这里写组件.....
<button type="primary" form-type="submit">Submit</button>
<button type="warn" form-type="reset">Reset</button>
</form>
</view>
</template>
<script>
export default {
methods: {
submit: function(e) {
var formdata = e.detail.value
console.log(formdata)
},
formReset: function(e) {
console.log('清空数据')
},
}
}
</script>
点击提交或重置,就能自动识别到所写组件的值。
4.3.3 代码示例
<template>
<view class="content">
<view class="area">
<form @submit="formSubmit" @reset="formReset">
<view>
<text>姓名</text>
<!-- @input 实时获取输入值-->
<input focus maxlength="10" name="name" @input="onKeyInput" placeholder="姓名" />
</view>
<view>
<!--
type:
1.text 文本输入键盘
2.number 数字输入键盘
3.idcard 身份证输入键盘
4.digit 带小数点的数字键盘
5.tel 电话输入键盘
6.safe-password 密码安全输入键盘
7.nickname 昵称输入键盘
-->
<text>年纪</text>
<input type="number" name="age" placeholder="年纪" />
</view>
<checkbox-group @change="checkboxChange" name="change">
<label class="label" v-for="(item,index) in checkbox">
<view>
<checkbox :value="item.value" :checked="item.checked" />
</view>
<view>{{item.name}}</view>
</label>
</checkbox-group>
<editor id="editor" class="ql-container" placeholder="开始输入..." show-img-size show-img-toolbar
style="width: 100%;height: 100rpx;min-height: 100rpx;border: 1px solid #000000;" name="editor">
</editor>
<picker @change="bindPickerChange" :value="index" :range="array" name="week">
<view class="uni-input">{{array[index]}}</view>
</picker>
<view>
<radio-group name="radioGroup">
<label class="uni-list-cell uni-list-cell-pd">
<view>
<radio value="r1" checked="true" />
</view>
<view>选中</view>
</label>
<label class="uni-list-cell uni-list-cell-pd">
<view>
<radio value="r2" />
</view>
<view>未选中</view>
</label>
</radio-group>
</view>
<view>
<!-- 滑块 -->
<slider value="80" min="50" max="200" activeColor="#FFCC33" backgroundColor="#000000"
block-color="#8A6DE9" block-size="20" show-value name="slider"/>
</view>
<view>
<!-- 开关选择器 修改样式大小是通过transform -->
<switch checked @change="switch1Change" color="#FFCC33" style="transform:scale(0.7)" name="switch"/>
</view>
<view>
<!-- 多行文本输入 其中auto-height 是否自动增高 -->
<textarea placeholder="占位符" style="border: 1px solid #000000;margin: 20rpx;" name="textarea1"/>
<textarea placeholder-style="color:#F76260" placeholder="占位符字体是红色的" auto-height
style="border: 1px solid #000000;margin: 20rpx;" name="textarea2"/>
</view>
<view class="buttonCon">
<!--
1.type:
1.primary: 默认 2.default:白色 3.warn:红色
2.loading:名称前是否带 loading 图标
3.disabled:是否禁用
4.size:大小
1.default:默认大小 2.mini:小尺寸
-->
<button type="primary" form-type="submit">Submit</button>
<button type="warn" form-type="reset" size="mini">Reset</button>
</view>
</form>
</view>
</view>
</template>
<script>
export default {
data() {
const date = new Date()
const years = []
const year = date.getFullYear()
const months = []
const month = date.getMonth() + 1
const days = []
const day = date.getDate()
for (let i = 1990; i <= date.getFullYear(); i++) {
years.push(i)
}
for (let i = 1; i <= 12; i++) {
months.push(i)
}
for (let i = 1; i <= 31; i++) {
days.push(i)
}
return {
checkbox: [{
value: 1,
name: "选项一"
},
{
value: 2,
name: "选项二",
checked: true
},
{
value: 3,
name: "选项三"
},
],
array: ['星期一', '星期二', '星期三'],
index: 0,
years,
year,
months,
month,
days,
day,
value: [9999, month - 1, day - 1],
visible: true,
indicatorStyle: `height: 50px;`
}
},
methods: {
checkboxChange: function(e) {
var items = this.items,
values = e.detail.value;
console.log(e)
},
formSubmit: function(e) {
var formdata = e.detail.value
console.log(formdata)
},
formReset: function(e) {
console.log('清空数据')
},
onKeyInput: function(event) {
console.log(event.target.value)
},
bindPickerChange: function(e) {
console.log('picker发送选择改变,携带值为', e.detail.value)
this.index = e.detail.value
},
bindChange: function(e) {
const val = e.detail.value
this.year = this.years[val[0]]
this.month = this.months[val[1]]
this.day = this.days[val[2]]
},
switch1Change: function(e) {
console.log(e.detail.value)
}
}
}
</script>
这里写了一些表单组件的简单示例和注解,运行结果:
点击Submit,打印结果:
4.4 媒体组件
4.4.1 audio:音频
<!-- 默认控件上的音频封面的图片资源地址,如果 controls 属性值为 false 则设置 poster 无效 -->
<audio style="text-align: left" src="https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3" poster="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/music-a.png" name="致爱丽丝" author="暂无" controls></audio>
4.4.2 camera:相机
页面内嵌的区域相机组件。注意这不是点击后全屏打开的相机。
<camera device-position="back" flash="off" @error="error" style="width: 100%; height: 300px;"></camera>
4.4.3 image:图片
mode:有效值
模式 | 值 | 说明 |
---|---|---|
缩放 | scaleToFill | 不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素 |
缩放 | aspectFit | 保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。 |
缩放 | aspectFill | 保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。 |
缩放 | widthFix | 宽度不变,高度自动变化,保持原图宽高比不变 |
缩放 | heightFix | 高度不变,宽度自动变化,保持原图宽高比不变 App 和 H5 平台 HBuilderX 2.9.3+ 支持、微信小程序需要基础库 2.10.3 |
裁剪 | top | 不缩放图片,只显示图片的顶部区域 |
裁剪 | bottom | 不缩放图片,只显示图片的底部区域 |
裁剪 | center | 不缩放图片,只显示图片的中间区域 |
裁剪 | left | 不缩放图片,只显示图片的左边区域 |
裁剪 | right | 不缩放图片,只显示图片的右边区域 |
裁剪 | top left | 不缩放图片,只显示图片的左上边区域 |
裁剪 | top right | 不缩放图片,只显示图片的右上边区域 |
裁剪 | bottom left | 不缩放图片,只显示图片的左下边区域 |
裁剪 | bottom right | 不缩放图片,只显示图片的右下边区域 |
<image style="width: 200px; height: 200px; background-color: #eeeeee;" mode="aspectFit"
src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/shuijiao.jpg"></image>
4.4.4 video:视频
<video id="myVideo" src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4" enable-danmu controls></video>
4.5 map地图
<template>
<view>
<view class="page-body">
<view class="page-section page-section-gap">
<map style="width: 100%; height: 300px;" :latitude="latitude" :longitude="longitude" :markers="covers">
</map>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
id: 0, // 使用 marker点击事件 需要填写id
title: 'map',
latitude: 39.909,
longitude: 116.39742,
covers: [{
latitude: 39.909,
longitude: 116.39742,
iconPath: '../../../static/pointer_orange.png',
//marker宽高
width:10,
height:15
}, {
latitude: 39.90,
longitude: 116.39,
iconPath: '../../../static/pointer_orange.png',
width:10,
height:15
}]
}
},
methods: {
}
}
</script>
4.5 扩展组件
当内置组件不能满足需求时,uniapp官网提供了一些扩展组件,uni-app官网
比如,想要引用日历,
现在好多好用的组件都需要打赏或者看广告,这里选择看广告 ,看完后:
点击确定后,该项目的uni_modules文件夹下会多出一个uni-calendar的文件,这个就是日历的相关文件。
引入:
<template>
<view class="content">
<view>
<uni-calendar ref="calendar" :insert="false" @confirm="confirm" range="true" />
<button @click="open">打开日历</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
open() {
this.$refs.calendar.open();
},
confirm(e) {
console.log(e);
}
}
}
</script>
效果:
其他扩展组件类似。
五、uniapp生命周期
5.1 应用的生命周期
uni-app
支持如下应用生命周期函数
函数名 | 说明 |
---|---|
onLauch | 当uni-app初始化完成时触发(全局只触发一次) |
onShow | 当uni-app启动,或从后台进入前台显示 |
onHide | 当uni-app从前台进入后台 |
onError | 当uni-app报错时触发 |
在创建项目时,App.vue已经写好了。
打印结果:
5.2 页面的生命周期
详情请看:页面 | uni-app官网
简单的示例:
(tabbar页面)
第一次进入当前页面的打印结果(由此可看运行顺序):
离开当前页面的打印结果:
再次进入当前页面的打印结果:
由此可见,在tabbar页面onLoad和onReady只在初始化执行一次。而onShow和onHide只要显示/隐藏当前页都会执行。
(非tabbar页面)
每次进入非tabbar页面都会执行onLoad和onShow**。** 非 tabbar 页面,每次打开都会执行 onLoad
方法,因为这些页面会在每次打开时重新初始化。
5.3 组件的生命周期
与vue标准组件的生命周期相同
详情请看官网:页面 | uni-app官网
六、网络
uni.request(OBJECT) | uni-app官网
6.1 网络请求
发起网络请求。uni.request
data 数据说明
最终发送给服务器的数据是 String 类型,如果传入的 data 不是 String 类型,会被转换成 String。转换规则如下:
1.对于 GET 方法,会将数据转换为 query string。例如 { name: 'name', age: 18 } 转换后的结果是 name=name&age=18。
2.对于 POST 方法且 header['content-type'] 为 application/json 的数据,会进行 JSON 序列化。
3.对于 POST 方法且 header['content-type'] 为 application/x-www-form-urlencoded 的数据,会将数据转换为 query string。
//网络请求api
uni.request({
url:url, // 请求路径
data:{}, // 参数
header:{}, // 请求头
method:'GET', // 请求方法
timeout:10000, // 超时请求
dataType:'json',// 默认json,请求数据类型
success: (res) =>{ // 成功时的回调
console.log(res);
},
fail: (err) => { // 失败时的回调
console.log(JSON.stringify(err));
}
})
我常用的(参考):
uni.request({
url: api.base + "/app/xx",
method: "POST",
data: {
id: id
},
header: {
"content-type": "application/x-www-form-urlencoded"
},
success: (res) => {
//...
}
})
如果微信开发者工具中,没有发送成功,可以试试如下方法。
6.2 上传和下载
- App支持多文件上传,微信小程序只支持单文件上传
1.文件上传chooseFile、下载downloadFile与打开openDocument
<button @click="onuploadFlie">文件上传</button>
<button @click="ondownloadFile">下载</button>
//上传文件
onuploadFlie(){
uni.chooseFile({
count: 1, //默认100
type:'file', //仅H5支持
extension:['.doc', '.docx', '.pdf', '.pptx', '.ppt', '.xls', '.xlsx','.zip'], //选择上传文件的格式
success: function (res) {
console.log(JSON.stringify(res.tempFilePaths));
}
});
}
//下载文件并打开文件
ondownloadFile(){
uni.downloadFile({
url: 'https://www.example.com/file/test', //下载文件的路径
success: (res) => {
var filePath = res.tempFilePath; //文件路径
uni.openDocument({ //打开下载完成的路径
filePath: filePath, //文件路径
showMenu: true,
success: function (res) {
console.log('打开文档成功');
}
});
}
});
}
2.图片上传
<button @click="onuploadphoto">图片上传</button>
<button @click="ondownload">下载</button>
<image :src="downloadfile" style="width: 300rpx;height: 270rpx;" mode="aspectFill"></image>
data() {
return {
downloadfile:''
}
},
onuploadphoto(){ //上传图片
uni.chooseImage({
count:1, // 上传图片的数量
sizeType:['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType:['album'], //从哪里选择图片(案例从相册选择)
success: (res) => {
console.log(JSON.stringify(res)); // 成功了查看图片信息
},
fail: () => {
console.log(JSON.stringify(err));
}
})
},
ondownload(){ //下载图片
uni.downloadFile({ url:'https://www.example.com/file/test', // 这里是图片接口地址 直接 url拼接参数可
timeout:30000, //超时
headers:{} , //是否需要携带请求头
methods:'GET'/'POST', //是否需要添加请求方法
success: (res) => {
console.log(JSON.stringify(res)); //显示图片的信息
this.downloadfile = res.tempFilePath; //显示图片
},
fail: (err)=>{
console.log(JSON.stringify(err));
}
})
}
七、数据缓存
|-----------------|------------------------------|-------|-------|
| 描述 | 写法 | 是否 异步 | 是否 同步 |
| 本地存储指定的键值对 | uni.setStorage(OBJECT) | √ | |
| 本地存储指定的键值对 | uni.setStorageSync(KEY,DATA) | | √ |
| 获取本地存储键对应的值 | uni.getStorage(OBJECT) | √ | |
| 获取本地存储键对应的值 | uni.getStorageSync(KEY,DATA) | | √ |
| 移除缓存 | uni.removeStorage(OBJECT) | √ | |
| 移除缓存 | uni.removeStorageSync(KEY) | | √ |
| 清空缓存 | uni.clearStorage() | √ | |
| 清空缓存 | uni.clearStorageSync() | | √ |
代码示例:
7.1 异步存取指定键值对(对应的值)
uni.setStorage({
key:'name',
data:'小童',
success() {
console.log('success');
}
})
uni.getStorage({
key: 'name',
success: function (res) {
console.log(res.data);
}
});
7.2 同步存取指定键值对(对应的值)
try {
uni.setStorageSync('name', '小童');
} catch (e) {
// error
}
try {
const value = uni.getStorageSync('name');
if (value) {
console.log(value);
}
} catch (e) {
// error
}
7.3 移除指定键值对
//异步
uni.removeStorage({
key: 'name',
success: function (res) {
console.log('success');
}
});
//同步
try {
uni.removeStorageSync('name');
} catch (e) {
// error
}
7.4 清理本地数据缓存
//异步
uni.clearStorage();
//同步
try {
uni.clearStorageSync();
} catch (e) {
// error
}
八、页面跳转、传参
8.1 路由跳转
|------------------|-----------------------------------------|------------------|
| | 描述 | 注意 |
| uni.navigateTo | 保留当前页面,跳转到应用内的某个页面 | 只能打开非 tabBar 页面 |
| uni.redirectTo | 关闭当前页面,跳转到应用内的某个页面 | 只能打开非 tabBar 页面 |
| uni.switchTab | 跳转到tabBar 页面,并关闭其他所有非 tabBar 页面 | 只能打开 tabBar
页面 |
| uni.reLaunch | 关闭所有页面,打开到应用内的某个页面 | 可以打开任意页面 |
| uni.navigateBack | 关闭当前页面,返回上一页面或多级页面 | |
uni.navigateBack写法示例:
uni.navigateBack({
delta: 2 //返回两级
});
uni.navigateBack() //默认delta回退1时不用写
可通过**getCurrentPages()
** 获取当前的页面栈,决定需要返回几层。
let pagearr = getCurrentPages(); //获取应用页面栈
console.log(pagearr)
let currentPage = pagearr[pagearr.length - 1]; //获取当前页面信息
//currentPage里面带有当前页面信息。如果要获取当前页的url:
//currentPage.options
代表当前页面是第二层。返回到第一层delta肯定是1。若当前是第三层, 返回到第一层delta则是2.
8.2 路由传参
1.通过URL携带参数
在跳转页面时,可以将参数附加到URL中,然后在目标页面通过this.$route.query
获取这些参数。例如:
uni.navigateTo({
url:'/pages/detail/detail?id=1&name=test'
})
2.在目标页面获取参数
export default{
onLoad:function(options){
console.log(options);
console.log(options.id); //输出 1
console.log(options.name); //输出test
}
}
打印options的结果:
8.3 事件传参
页面A:
// 页面A
uni.navigateTo({
url: '/pages/practice/demo/pageB',
events: {
// 事件名
customEvent: (data) => {
console.log(data.userId); // 1
console.log(data.userName); // JohnDoe
},
// ... 其他事件处理
},
success: (res) => {
// 向页面B传递参数
res.eventChannel.emit('customEvent', { userId: 1, userName: 'JohnDoe' });
}
});
页面B:
onShow() {
// 监听事件
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('customEvent', (data) => {
console.log(data.userId); // 1
console.log(data.userName); // JohnDoe
});
}
运行结果:
8.4 组件传值
8.4.1 父组件给子组件传值
- 在父组件elementFather.vue里面定义了title:"name"
- 在子组件中通过props来接收
- 子组件接收到父组件传递过来的值以后,可在页面显示
注意:若在子组件中同时定义title则会发生冲突
父组件(elementFather.vue):
<template>
<view class="content">
父页面
<element :title='name'></element>
</view>
</template>
<script>
import element from 'components/element.vue'
export default {
data(){
return{
name:'父页面的标题'
}
},
components:{
element
},
}
</script>
子组件(element.vue):
<template>
<view class="content">
子页面
<view>父组件传来的数据:{{title}}</view>
</view>
</template>
<script>
export default {
props:['title'],
}
</script>
运行结果:
ps:放一张之前学vue做的笔记
8.4.2 子组件给父组件传值
1.在子组件中通过emit方法给父组件传值this.emit('myEven','我是子组件的数据')
$emit('方法名字',参数名)
2.在父组件中通过@myEven方法接收数据
子组件(element.vue):
<template>
<view class="content">
子页面
<view>父组件传来的数据:{{title}}</view>
<button @click="giveFather">给父组件传值</button>
</view>
</template>
<script>
export default {
props:['title'],
methods:{
giveFather(){
this.$emit('myEven','我是子组件的数据')
}
},
}
</script>
<style>
</style>
父组件(elementFather.vue):
<template>
<view class="content">
父页面
<element :title='name' @myEven="gitTitle"></element>
<view>子组件传来的数据:{{father}}</view>
</view>
</template>
<script>
import element from 'components/element.vue'
export default {
data() {
return {
name: '父页面的标题',
father:''
}
},
components: {
element
},
methods: {
gitTitle(data) {
console.log(data)
this.father = data
}
},
}
</script>
<style>
</style>
运行结果:
ps:放一张之前学vue做的笔记
九、位置
|-------------------------|--------------------------|
| 获取位置 | 查看位置 |
| uni.getLocation(OBJECT) | uni.openLocation(OBJECT) |
| 获取当前的地理位置、速度。 | 使用应用内置地图查看位置。 |
要获取位置首先检查uniapp的manifest文件发现位置权限已经开启:
也就是这种效果
9.1 获取位置
代码如下:
//获取位置
uni.getLocation({
//默认为 wgs84 返回 gps 坐标,gcj02 返回国测局坐标
type: 'wgs84',
success: function (res) {
console.log('当前位置的经度:' + res.longitude);
console.log('当前位置的纬度:' + res.latitude);
}
});
打印结果:
9.2 查看位置
代码如下:
uni.getLocation({
type: 'gcj02', //返回可以用于uni.openLocation的经纬度
success: function (res) {
const latitude = res.latitude;
const longitude = res.longitude;
uni.openLocation({
latitude: latitude,
longitude: longitude,
success: function () {
console.log('success');
}
});
}
});
运行效果(微信开发者工具):
感觉位置有偏移。但是在微信开发者工具上用真机调试位置是准确的。
十、媒体
10.1 图片
代码如下:
uni.chooseImage({
count: 6, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], //从相册选择
success: function (res) {
console.log(res.tempFilePaths);
}
});
可多选图片,打印结果:
10.2 文件
代码如下:
uni.chooseFile({
count: 6, //默认100
extension:['.zip','.doc'],
success: function (res) {
console.log(JSON.stringify(res.tempFilePaths));
}
});
// 选择图片文件
uni.chooseFile({
count: 10,
type: 'image',
success (res) {
// tempFilePath可以作为img标签的src属性显示图片
const tempFilePaths = res.tempFiles
}
})
10.3 视频
代码如下:
uni.chooseVideo({
sourceType: ['camera', 'album'],
success: function (res) {
let src = res.tempFilePath;
}
});
十一、界面
11.1 交互反馈(提示框)
|--------------|-----------------------------|----------------------------------------------------------------------------|-------|
| 消息提示框 | uni.showToast(OBJECT) | | 显示 |
| 消息提示框 | uni.hideToast() | | 隐藏 |
| loading 提示框 | uni.showLoading(OBJECT) | | 显示 |
| loading 提示框 | uni.hideLoading() | | 隐藏 |
| 模态弹窗 | uni.showModal(OBJECT) | | 点击后隐藏 |
| 从底部向上弹出 操作菜单 | uni.showActionSheet(OBJECT) | | 点击后隐藏 |
11.1 消息提示框
代码示例:
//显示
uni.showToast({
title: '标题',
duration: 2000 //提示的延迟时间
});
//隐藏
uni.hideToast();
11.2 loading 提示框
代码示例:
//显示
uni.showLoading({
title: '加载中'
});
//2秒后隐藏
setTimeout(function () {
uni.hideLoading();
}, 2000);
11.3 模态弹窗
代码示例:
uni.showModal({
title: '提示',
content: '这是一个模态弹窗',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
11.4 从底部向上弹出操作菜单
代码示例:
uni.showActionSheet({
itemList: ['A', 'B', 'C'],
success: function (res) {
console.log('选中了第' + (res.tapIndex + 1) + '个按钮');
},
fail: function (res) {
console.log(res.errMsg);
}
});
11.2 滚动:uni.pageScrollTo(OBJECT)
将页面滚动到目标位置。可以指定滚动到具体的scrollTop数值,也可以指定滚动到某个元素的位置。
//滚到顶部
uni.pageScrollTo({
scrollTop: 0,
duration: 300 //滚动动画的时长 300ms
});
//滚动指定元素
uni.pageScrollTo({
selector:'.scroll', // 需要返回顶部的元素id或class名称
duration: 300 //滚动动画的时长 300ms
});
11.3 窗口:uni.onWindowResize(CALLBACK)
监听窗口尺寸变化事件
const windowResizeCallback = (res) => {
console.log('变化后的窗口宽度=' + res.size.windowWidth)
console.log('变化后的窗口高度=' + res.size.windowHeight)
}
uni.onWindowResize(windowResizeCallback)
11.4 下拉刷新:onPullDownRefresh
在 js 中定义 onPullDownRefresh 处理函数(和onLoad等生命周期函数同级),监听该页面用户下拉刷新事件。
- 需要在 **
pages.json
**里,找到的当前页面的pages节点,并在style
选项中开启enablePullDownRefresh
。 - 当处理完数据刷新后,
uni.stopPullDownRefresh
可以停止当前页面的下拉刷新。
uni.startPullDownRefresh(OBJECT)
开始下拉刷新,调用后触发下拉刷新动画,效果与用户手动下拉刷新一致
示例:
pages.json
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app",
"enablePullDownRefresh": true //是否开启下拉刷新
}
}
],
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#0faeff",
"backgroundColor": "#fbf9fe"
}
}
index.vue
// 仅做示例,实际开发中延时根据需求来使用。
export default {
data() {
return {
text: 'uni-app'
}
},
onLoad: function (options) {
setTimeout(function () {
console.log('start pulldown');
}, 1000);
uni.startPullDownRefresh();
},
onPullDownRefresh() {
console.log('refresh');
setTimeout(function () {
uni.stopPullDownRefresh();
}, 1000);
}
}
运行结果:
这是我复习一遍uniapp官网做的笔记,属于入门级教程,后续还会出关于uniapp在工作中遇到的问题,如有异议,欢迎留言改正。码字不易,给博主一个小小的赞吧~~~