笔记根据B站Uni-App从入门到实战-黑马程序员杭州校区出品视频教程整理
相关素材:https://pan.baidu.com/s/1Dkj5iuGRG6j2HzK_8MDxFA 提取码:7vm2,搬运来的链接,大家自取
案例的接口文档:https://www.showdoc.com.cn/128719739414963?page_id=2513235043485226
颜色对照表:https://destiny001.gitee.io/color/
p1 uniapp简介
uni-app上手简单,可快速开发小程序、h5、安卓、ios应用。学习本课程需有vue基础方可继续,当然了有想学习小程序的,也建议学习本课程,学会uni-app之后,原生小程序也可快速上手。
p2 uniapp环境搭建
下载HBuilderX即可:https://www.dcloud.io/hbuilderx.html
创建uniapp项目

运行到浏览器

运行到微信小程序

注意:需要先在微信小程序中 设置-安全设置 开启端口 否则启动不了。

运行到安卓手机
略
p3 uniapp项目结构和开发规范
项目结构
├─pages                 业务页面文件存放的目录
│  ├─index
│  │  └─index.vue       index页面
│  └─list
│     └─list.vue        list页面
├─static                存放应用引用的本地静态资源(如图片、视频等)的目录,注意:静态资源只能存放于此
├─unpackage             非工程代码,一般存放运行或发行的编译结果
├─main.js               Vue初始化入口文件
├─App.vue               应用配置,用来配置App全局样式以及监听 应用生命周期
├─manifest.json         配置应用名称、appid、logo、版本等打包信息,详见
├─pages.json            配置页面路由、导航条、选项卡等页面类信息,详见
└─uni.scss              这里是uni-app内置的常用样式变量 
开发规范
为了实现多端兼容,综合考虑编译速度、运行性能等因素,uni-app 约定了如下开发规范:
- 页面文件遵循 Vue 单文件组件 (SFC) 规范(opens new window)
 - 组件标签靠近小程序规范,详见uni-app 组件规范
 - 接口能力(JS API)靠近微信小程序规范,但需将前缀 
wx替换为uni,详见uni-app接口规范 - 数据绑定及事件处理同 
Vue.js规范,同时补充了App及页面的生命周期 - 为兼容多端运行,建议使用
flex布局进行开发 
总结:就是小程序的语法和vue的语法结合
P4 globalStyle全局配置
对应page.json文件中globalStyle节点
| 属性 | 类型 | 默认值 | 描述 | 平台差异说明 | 
|---|---|---|---|---|
| navigationBarBackgroundColor | HexColor | #F7F7F7 | 导航栏背景颜色(同状态栏背景色) | APP与H5为#F7F7F7,小程序平台请参考相应小程序文档 | 
| navigationBarTextStyle | String | white | 导航栏标题颜色及状态栏前景颜色,仅支持 black/white | |
| navigationBarTitleText | String | 导航栏标题文字内容 | ||
| navigationStyle | String | default | 导航栏样式,仅支持 default/custom。custom即取消默认的原生导航栏,需看使用注意 | 微信小程序 7.0+、百度小程序、H5、App(2.0.3+) | 
| backgroundColor | HexColor | #ffffff | 下拉显示出来的窗口的背景色 | 微信小程序 | 
| backgroundTextStyle | String | dark | 下拉 loading 的样式,仅支持 dark / light | 微信小程序 | 
| enablePullDownRefresh | Boolean | false | 是否开启下拉刷新,详见页面生命周期。 | |
| onReachBottomDistance | Number | 50 | 页面上拉触底事件触发时距页面底部距离,单位只支持px,详见页面生命周期 | 
更多属性配置可以参考文档:全局配置文档
P5 创建和配置页面
第一步:新建文件夹以及创建vue文件

message.vue的内容如下:
<template>
    <view>message页面</view>
</template>
<script>
</script>
<style>
</style>
第二步:在page.json文件中进行配置
注意:pages数组中第一项表示应用启动页

测试就可以看到页面了

参考:页面样式配置文档
p6-p7 tabBar 配置
属性说明:
| 属性 | 类型 | 必填 | 默认值 | 描述 | 平台差异说明 | 
|---|---|---|---|---|---|
| color | HexColor | 是 | tab 上的文字默认颜色 | ||
| selectedColor | HexColor | 是 | tab 上的文字选中时的颜色 | ||
| backgroundColor | HexColor | 是 | tab 的背景色 | ||
| borderStyle | String | 否 | black | tabbar 上边框的颜色,可选值 black/white | App 2.3.4+ 支持其他颜色值、H5 3.0.0+ | 
| blurEffect | String | 否 | none | iOS 高斯模糊效果,可选值 dark/extralight/light/none(参考:使用说明 (opens new window)) | App 2.4.0+ 支持、H5 3.0.0+(只有最新版浏览器才支持) | 
| list | Array | 是 | tab 的列表,详见 list 属性说明,最少2个、最多5个 tab | ||
| position | String | 否 | bottom | 可选值 bottom、top | top 值仅微信小程序支持 | 
第一步:新增contact页面,参考p5。建完之后别忘了在pages.json中的pages节点下配置路径

第二步:将图片拷贝的静态文件夹,有选中的图片和不选中的图片。可以用阿里图标库生成

第三步:page.json中配置一下tabbar
"tabBar": {
        "color": "#7A7E83",
        "selectedColor": "#3cc51f",
        "borderStyle": "black",
        "backgroundColor": "#ffffff",
        "list": [
            {
                "pagePath": "pages/index/index",
                "iconPath": "static/image/home.png",
                "selectedIconPath": "static/image/home-active.png",
                "text": "主页"
            }, 
            {
                "pagePath": "pages/message/message",
                "iconPath": "static/image/message.png",
                "selectedIconPath": "static/image/message-active.png",
                "text": "信息"
            },
            {
                "pagePath": "pages/contact/contact",
                "iconPath": "static/image/contact.png",
                "selectedIconPath": "static/image/contact-active.png",
                "text": "我们"
            }
        ]
    }
然后在界面就可以看到效果了,点击之后可以切换到对应的界面

p8 condition
启动模式配置,仅开发期间生效,用于模拟直达页面的场景,如:小程序转发后,用户点击所打开的页面。
属性说明:
| 属性 | 类型 | 是否必填 | 描述 | 
|---|---|---|---|
| current | Number | 是 | 当前激活的模式,list节点的索引值 | 
| list | Array | 是 | 启动模式列表 | 
list说明:
| 属性 | 类型 | 是否必填 | 描述 | 
|---|---|---|---|
| name | String | 是 | 启动模式名称 | 
| path | String | 是 | 启动页面路径 | 
| query | String | 否 | 启动参数,可在页面的 onLoad 函数里获得 | 
注意: 在 App 里真机运行可直接打开配置的页面,微信开发者工具里需要手动改变编译模式,如下图:

第一步:新增details页面
第二步:在pages.json中添加condition节点,配置如下
"condition" : { //模式配置,仅开发期间生效
        "current": 0, //当前激活的模式(list 的索引项)
        "list": [
            {
                "name": "详情页", //模式名称
                "path": "pages/details/details", //启动页面,必选
                "query": "id=10" //启动参数,在页面的onLoad函数里面得到
            }
        ]
    }
p9 text组件
文本组件。
用于包裹文本内容。
属性说明
| 属性名 | 类型 | 默认值 | 说明 | 平台差异说明 | 
|---|---|---|---|---|
| selectable | Boolean | false | 文本是否可选 | App、H5、快手小程序 | 
| user-select | Boolean | false | 文本是否可选 | 微信小程序 | 
| space | String | 显示连续空格 | App、H5、微信小程序 | |
| decode | Boolean | false | 是否解码 | App、H5、微信小程序 | 
space 值说明
| 值 | 说明 | 
|---|---|
| ensp | 中文字符空格一半大小 | 
| emsp | 中文字符空格大小 | 
| nbsp | 根据字体设置的空格大小 | 
修改detail.vue
<template>
    <view>
        <view><text>不可选文字(默认)</text></view>
        <view><text selectable>可选文字</text></view>
        <view><text>空格隔空    你搞个1</text></view>
        <view><text space="ensp">中文字符    空格一半大小</text></view>
        <view><text space="emsp">中文字符  空格大小</text></view>
        <view><text space="nbsp" style="font-size: 16px;">根据字体 设置的空格大小</text></view>
        <view><text>解码 & > </text></view>
    </view>
</template>
<script>
</script>
<style>
</style>
测试就可以看到对应的效果
p10 view组件
视图容器。
它类似于传统html中的div,用于包裹各种元素内容。
如果使用nvue (opens new window),则需注意,包裹文字应该使用<text>组件。
属性说明
| 属性名 | 类型 | 默认值 | 说明 | 
|---|---|---|---|
| hover-class | String | none | 指定按下去的样式类。当 hover-class=”none” 时,没有点击态效果 | 
| hover-stop-propagation | Boolean | false | 指定是否阻止本节点的祖先节点出现点击态,App、H5、支付宝小程序、百度小程序不支持(支付宝小程序、百度小程序文档中都有此属性,实测未支持) | 
| hover-start-time | Number | 50 | 按住后多久出现点击态,单位毫秒 | 
| hover-stay-time | Number | 400 | 手指松开后点击态保留时间,单位毫秒 | 
在details.vue文件中加入下面的测试代码
<template>
    <view>
        <view class="box" hover-class="box-active" :hover-start-time="2000" :hover-stay-time="2000">
            <view class="childbox" hover-class="childbox-active" hover-stop-propagation></view>
        </view>
    </view>
</template>
<style>
    .box{
        width: 150px;
        height: 150px;
        background: green;
    }
    .box-active{
        background: deeppink;
    }
    .childbox{
        width: 50px;
        height: 50px;
        background: greenyellow;
    }
    .childbox-active{
        background: deepskyblue;
    }
</style>
p11 button组件
按钮组件
属性说明
| 属性名 | 类型 | 默认值 | 说明 | 平台差异说明 | 
|---|---|---|---|---|
| size | String | default | 按钮的大小 | |
| type | String | default | 按钮的样式类型 | |
| plain | Boolean | false | 按钮是否镂空,背景色透明 | |
| disabled | Boolean | false | 是否禁用 | |
| loading | Boolean | false | 名称前是否带 loading 图标 | H5、App(App-nvue 平台,在 ios 上为雪花,Android上为圆圈) | 
更多属性可以看button组件文档
在details.vue文件中加入下面的测试代码即可看到效果
<button>默认按钮</button>
<button size="mini">mini按钮</button>
<button type="primary">type=primary按钮</button>
<button type="primary" plain>type=primary的镂空按钮</button>
<button type="primary" disabled>type=primary的禁用按钮</button>
<button type="primary" loading>type=primary的loading按钮</button>
p12 image组件
图片组件
| 属性名 | 类型 | 默认值 | 说明 | 平台差异说明 | 
|---|---|---|---|---|
| src | String | 图片资源地址 | ||
| mode | String | ‘scaleToFill’ | 图片裁剪、缩放的模式 | 
Tips
<image>组件默认宽度 300px、高度 225px;app-nvue平台,暂时默认为屏幕宽度src仅支持相对路径、绝对路径,支持 base64 码;- 页面结构复杂,css样式太多的情况,使用 image 可能导致样式生效较慢,出现 “闪一下” 的情况,此时设置 
image{will-change: transform},可优化此问题。 - 自定义组件里面使用 
<image>时,若src使用相对路径可能出现路径查找失败的情况,故建议使用绝对路径。 
mode 有效值:
mode 有 14 种模式,其中 5 种是缩放模式,9 种是裁剪模式。
| 模式 | 值 | 说明 | 
|---|---|---|
| 缩放 | scaleToFill | 不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素 | 
| 缩放 | aspectFit | 保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。 | 
| 缩放 | aspectFill | 保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。 | 
更多参考图片组件文档
在details.vue中加入下面的代码
<image src="https://heliufang.gitee.io/2022/03/27/1513842928408203264/images/image-20220319113815361.png"></image>
        <image src="https://heliufang.gitee.io/2022/03/27/1513842928408203264/images/image-20220319113815361.png" mode="aspectFit"></image>
        <image src="https://heliufang.gitee.io/2022/03/27/1513842928408203264/images/image-20220319113815361.png" mode="aspectFill"></image>
p13 uniapp样式-字体图片-sass
css单位
uni-app 支持的通用 css 单位包括 px、rpx
- px 即屏幕像素
 - rpx 即响应式 px,一种根据屏幕宽度自适应的动态单位。以 750 宽的屏幕为基准,750rpx 恰好为屏幕宽度。屏幕变宽,rpx 实际显示效果会等比放大,但在 App(vue2 不含 nvue) 端和 H5(vue2) 端屏幕宽度达到 960px 时,默认将按照 375px 的屏幕宽度进行计算,具体配置参考:rpx 计算配置 。
 
举例说明:
- 若设计稿宽度为 750px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在
 uni-app里面的宽度应该设为:750 * 100 / 750,结果为:100rpx。- 若设计稿宽度为 640px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在
 uni-app里面的宽度应该设为:750 * 100 / 640,结果为:117rpx。
vue 页面支持下面这些普通 H5 单位,但在 nvue 里不支持:
- rem 根字体大小可以通过 page-meta 配置
 - vh viewpoint height,视窗高度,1vh 等于视窗高度的 1%
 - vw viewpoint width,视窗宽度,1vw 等于视窗宽度的 1%
 
新建uniapp-style.vue页面
假设设计稿的宽度为375px ,盒子的宽度为100px。那么根据公式 750*100/375=200rpx
<template>
    <view>
        <view class="box">
            <text>uniapp</text>
        </view>
    </view>
</template>
<script>
</script>
<style>
    .box{
        width: 200rpx;
        height: 200rpx;
        background: red;
        font-size: 32rpx;
    }
</style>
打开页面调试工具发现切换到宽度为375px的设备,发现盒子的像素确实是100px
样式导入
使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。
在uniapp-style.vue页面的同级目录下新建a.css文件,文件内容如下
.box{
    border: 1rpx solid;
}
然后再uniapp-style.vue页面引入
<style>
    @import url(./a.css);
    .box{
        width: 200rpx;
        height: 200rpx;
        background: red;
        font-size: 32rpx;
    }
</style>
测试发现给盒子加上边框了。
选择器
目前支持的选择器有:
| 选择器 | 样例 | 样例描述 | 
|---|---|---|
| .class | .intro | 选择所有拥有 class=”intro” 的组件 | 
| #id | #firstname | 选择拥有 id=”firstname” 的组件 | 
| element | view | 选择所有 view 组件 | 
| element, element | view, checkbox | 选择所有文档的 view 组件和所有的 checkbox 组件 | 
| ::after | view::after | 在 view 组件后边插入内容,仅 vue 页面生效 | 
| ::before | view::before | 在 view 组件前边插入内容,仅 vue 页面生效 | 
注意:
- 在 
uni-app中不能使用*选择器。 - 微信小程序自定义组件中仅支持 class 选择器
 page相当于body节点,例如:
<!-- 设置页面背景颜色,使用 scoped 会导致失效 -- > 
  page {
    background-color: #ccc;
}
全局样式与局部样式
定义在 App.vue 中的样式为全局样式,作用于每一个页面。在 pages 目录下 的 vue 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 App.vue 中相同的选择器。
注意:
- App.vue 中通过 
@import语句可以导入外联样式,一样作用于每一个页面。 - nvue 页面暂不支持全局样式
 
使用scss
在页面加上 lang=”scss” 会自动安装scss插件
<style lang="scss">
    @import url(./a.css);
    .box{
        width: 200rpx;
        height: 200rpx;
        background: red;
        text{
            font-size: 16rpx;
            color: aqua;
        }
    }
</style>
字体图标
uni-app 支持使用字体图标,使用方式与普通 web 项目相同,需要注意以下几点:
- 支持 base64 格式字体图标。
 - 支持网络路径字体图标。
 - 小程序不支持在 css 中使用本地文件,包括本地的背景图和字体文件。需以 base64 方式方可使用。
 - 网络路径必须加协议头 
https。 - 从 http://www.iconfont.cn (opens new window)上拷贝的代码,默认是没加协议头的。
 - 从 http://www.iconfont.cn (opens new window)上下载的字体文件,都是同名字体(字体名都叫 iconfont,安装字体文件时可以看到),在 nvue 内使用时需要注意,此字体名重复可能会显示不正常,可以使用工具修改。
 - 使用本地路径图标字体需注意:
- 为方便开发者,在字体文件小于 40kb 时,
uni-app会自动将其转化为 base64 格式; - 字体文件大于等于 40kb,仍转换为 base64 方式使用的话可能有性能问题,如开发者必须使用,则需自己将其转换为 base64 格式使用,或将其挪到服务器上,从网络地址引用;
 - 字体文件的引用路径推荐使用以 ~@ 开头的绝对路径。
 
 - 为方便开发者,在字体文件小于 40kb 时,
 
@font-face {
    font-family: test1-icon;
    src: url('~@/static/iconfont.ttf');
}
第一步:将字体图标文件拷贝到static文件夹下

第二步:修改iconfont.css路径,都加上~@路径

第三步:使用
<text class="iconfont icon-shipin"></text>
p14 -16数据绑定和事件绑定
和vue一模一样 uniapp官网上的vue文档
新建一个home.vue文件用来测试
<template>
    <view>
        <view>数据绑定学习(和vue一样)</view>
        <!-- 插值表达式和三目运算符 -->
        <view>{{msg}}</view>
        <view>{{"1"+"uniapp"}}</view>
        <view>{{1+1}}</view>
        <view>{{flag?'真的':'假的'}}</view>
        <!-- v-bind绑定数据 -->
        <image :src="imgurl"></image>
        <!-- v-for循环 -->
        <view v-for="(item,index) in arr" :key="item.id">
            序号:{{index}},ID:{{item.id}},姓名:{{item.name}},年龄:{{item.age}}
        </view>
        <button @click="clickHandle1">注册1</button>
        <button type="primary" @click="clickHandle2(10,$event)">注册2</button>
    </view>
</template>
<script>
    export default{
        data(){
            return {
                msg: '你好',
                flag: false,
                imgurl: 'https://heliufang.gitee.io/2022/03/27/1513842928408203264/images/image-20220319113815361.png',
                arr: [
                    {id: 1,name: '赵云',age: 18},
                    {id: 2,name: '马超',age: 28},
                    {id: 3,name: '关羽',age: 38},
                ]
            }
        },
        methods: {
            clickHandle1(e){//不传参数获取事件对象
                console.log(e)
            },
            clickHandle2(num,e){//传参
                console.log(num,e)
            }
        }
    }
</script>
<style>
</style>
p17 应用和页面的生命周期函数
应用的生命周期函数–App.vue文件中
<script>
    export default {
        onLaunch: function() {
            console.log('应用加载完毕-只执行一次')
        },
        onShow: function() {
            console.log('应用显示')
        },
        onHide: function() {
            console.log('应用隐藏')
        }
    }
</script>
<style>
    @import url(./static/fonts/iconfont.css);
    /*每个页面公共css */
</style>
页面的生命周期函数–每个页面中 页面生命周期文档
| 函数名 | 说明 | 
|---|---|
| onLoad | 监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参),参考示例 | 
| onShow | 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面 | 
| onReady | 监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发 | 
| onHide | 监听页面隐藏 | 
例如在message.vue页面中加上页面的生命周期函数
<template>
    <view>message页面</view>
</template>
<script>
    export default{
        onLoad(obj){
            //页面加载完毕,obj是上个页面传递的数据
            console.log('页面加载完毕',obj)
        },
        onShow(){
            console.log('页面显示')
        },
        onReady(){
            console.log('页面初次渲染完毕')
        },
        onHide(){
            console.log('页面隐藏,通过切换tabbar可以看到我')
        }
    }
</script>
p18 下拉刷新
在 js 中定义 onPullDownRefresh 处理函数(和onLoad等生命周期函数同级),监听该页面用户下拉刷新事件。
- 需要在 
pages.json里,找到的当前页面的pages节点,并在style选项中开启enablePullDownRefresh。 

- 当处理完数据刷新后,
uni.stopPullDownRefresh可以停止当前页面的下拉刷新。 
message.vue代码
<template>
    <view>
        message页面
        <view v-for="(item) in arr" :key="item.id">{{item}}</view>
        <button type="primary" @click="refreshArr">按钮触发下拉刷新</button>
    </view>
</template>
<script>
    export default{
        data(){
            return {
                arr: ['java','前端','UI','测试']
            }
        },
        methods: {
            refreshArr(){
                uni.startPullDownRefresh()
            }
        },
        onPullDownRefresh(){
            setTimeout(() => {
                this.arr = ['UI','测试','java','前端']
                uni.stopPullDownRefresh() //关闭下拉刷新
            },2000)
        },
    }
</script>
p19 上拉(触底)加载
页面的可以配置触底的距离,也就是距离底部多少距离触发,默认是50

页面生命周期中有个onReachBottom方法,用来监听触底。
<template>
    <view>
        message页面
        <view class="item-class" v-for="(item) in arr" :key="item.id">{{item}}</view>
        <button type="primary" @click="refreshArr">按钮触发下拉刷新</button>
    </view>
</template>
<script>
    export default{
        data(){
            return {
                arr: ['java','前端','UI','测试']
            }
        },
        methods: {
            refreshArr(){
                uni.startPullDownRefresh()
            }
        },
        onPullDownRefresh(){
            setTimeout(() => {
                this.arr = ['UI','测试','java','前端']
                uni.stopPullDownRefresh() //关闭下拉刷新
            },2000)
        },
        onReachBottom(){//触底的方法
            //es6的语法扩展数组
            this.arr = [...this.arr,...['UI','测试','java','前端']]
            console.log('触底',this.arr)
        }
    }
</script>
<style>
    .item-class{
        height: 200px;
    }
</style>
p20 发送get请求
搭建本地的node服务
第一步,根据dtcmsdb4.sql文件来恢复数据库
第二步, npm i 安装依赖
第三步,node ./src/app.js 来启动服务,注意:默认数据库账号密码都是root,如果本地不是请修改好
第四步,浏览器输入 http://localhost:8082/api/getlunbo 来访问接口 出现下面这样表示成功

uniapp中通过uni.request(OBJECT) 发起网络请求。uni.request文档
<template>
    <view>
        <button type="primary" @click="getlunbo">发起请求</button>
    </view>
</template>
<script>
    export default{
        methods: {
            getlunbo(){
                uni.request({
                    url: 'http://localhost:8082/api/getlunbo',
                    success(resp){
                        console.log(resp)
                    }
                })
            }
        }
    }
</script>
p21 数据缓存
uni.setStorage
将数据存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个异步接口。
uni.setStorageSync
将 data 存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。
uni.getStorage
从本地缓存中异步获取指定 key 对应的内容。
uni.getStorageSync
从本地缓存中同步获取指定 key 对应的内容。
uni.removeStorage
从本地缓存中异步移除指定 key。
uni.removeStorageSync
从本地缓存中同步移除指定 key。
测试代码如下
<template>
    <view>
        <button type="primary" @click="saveData">保存数据</button>
        <button type="primary" @click="getData">获取数据</button>
        <button type="primary" @click="removeData">删除数据</button>
    </view>
</template>
<script>
    export default{
        methods: {
            saveData(){
                // uni.setStorage({
                //     key: 'id',
                //     data: 80,
                //     success(){
                //         console.log('保存成功')
                //     }
                // })
                uni.setStorageSync('id',100)
            },
            getData(){
                // uni.getStorage({
                //     key: 'id',
                //     success(resp){
                //         console.log('获取成功:',resp.data)
                //     }
                // })
                let resp = uni.getStorageSync('id')
                console.log('获取成功:',resp)
            },
            removeData(){
                // uni.removeStorage({
                //     key: 'id',
                //     success() {
                //         console.log('删除成功')
                //     }
                // })
                uni.removeStorageSync('id')
            }
        }
    }
</script>
p22 图片的上传和预览
- uni.chooseImage(OBJECT)
 
从本地相册选择图片或使用相机拍照。
App端如需要更丰富的相机拍照API(如直接调用前置摄像头),参考plus.camera
- uni.previewImage(OBJECT)
 
预览图片。
代码如下
<template>
    <view>
        <button type="warn" @click="uploadImg">上传图片</button>
        <image v-for="item in imgList" :src="item" @click="previewImg(item)"></image>
    </view>
</template>
<script>
    export default{
        data(){
            return{
                imgList: []
            }
        },
        methods: {
            uploadImg(){
                uni.chooseImage({
                    success: res => {
                        this.imgList = res.tempFilePaths
                        //console.log(res)
                    }
                })
            },
            previewImg(current){
                console.log('预览图片')
                uni.previewImage({
                    current,//current 为当前显示图片的链接/索引值
                    urls: this.imgList //需要预览的图片链接列表
                })
            }
        }
    }
</script>
p23 条件编译跨端兼容
条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。
| 条件编译写法 | 说明 | 
|---|---|
| #ifdef APP-PLUS 需条件编译的代码 #endif | 仅出现在 App 平台下的代码 | 
| #ifndef H5 需条件编译的代码 #endif | 除了 H5 平台,其它平台均存在的代码 | 
| #ifdef H5 || MP-WEIXIN 需条件编译的代码 #endif | 在 H5 平台或微信小程序平台存在的代码(这里只有||,不可能出现&&,因为没有交集) | 
HbuilderX中输入if关键字会有代码提示
<template>
    <view>
        <!-- #ifdef H5 -->
        <view>h5显示</view>
        <!-- #endif -->
        <!-- #ifdef MP-WEIXIN -->
        <view>微信小程序中显示</view>
        <!-- #endif -->
    </view>
</template>
<script>
    export default{
        onLoad() {
            // #ifdef H5
            console.log('h5打印')
            // #endif
            // #ifdef MP-WEIXIN
            console.log('wx打印')
            // #endif
            
        }
    }
</script>
<style>
    view{
        /* #ifdef H5 */
        color: red;
        /* #endif */
        /* #ifdef MP-WEIXIN */
        color: deepskyblue;
        /* #endif */
    }
</style>
p24 导航
navigator组件导航
页面跳转。 navigator文档
该组件类似HTML中的<a>组件,但只能跳转本地页面。目标页面必须在pages.json中注册。
该组件的功能有API方式,另见:https://uniapp.dcloud.io/api/router?id=navigateto(opens new window)
属性说明
| 属性名 | 类型 | 默认值 | 说明 | 平台差异说明 | 
|---|---|---|---|---|
| url | String | 应用内的跳转链接,值为相对路径或绝对路径,如:”../first/first”,”/pages/first/first”,注意不能加 .vue 后缀 | ||
| open-type | String | navigate | 跳转方式 | 
open-type 有效值
| 值 | 说明 | 备注 | 
|---|---|---|
| navigate | 对应 uni.navigateTo | 保留当前页面,跳转到应用内的某个页面。带返回按钮 | 
| redirect | 对应 uni.redirectTo | 关闭当前页面,跳转到应用内的某个页面。不带返回按钮 | 
| switchTab | 对应 uni.switchTab | 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。 | 
编程式导航
uni.navigateTo
uni.redirectTo
uni.switchTab
代码如下:
<template>
    <view>
        <navigator url="/pages/details/details">跳转到详情页(带返回按钮)</navigator>
        <navigator url="/pages/details/details" open-type="redirect">跳转到详情页redirect(不带返回按钮)</navigator>
        <navigator url="/pages/message/message" open-type="switchTab">到tabbar的消息页</navigator>
        <!-- 编程式导航 和上面三个是对应的 -->
        <button type="primary" @click="routerNavigate">跳转到详情页(带返回按钮)</button>
        <button type="primary" @click="routerRedirect">跳转到详情页(不带返回按钮)</button>
        <button type="primary" @click="routerSwichtab">到tabbar的消息页</button>
    </view>
</template>
<script>
    export default{
        onUnload() {
            console.log('页面卸载')
        },
        methods: {
            routerNavigate(){
                uni.navigateTo({
                    url: '/pages/details/details'
                })
            },
            routerRedirect(){
                uni.redirectTo({
                    url: '/pages/details/details'
                })
            },
            routerSwichtab(){
                uni.switchTab({
                    url: '/pages/message/message'
                })
            }
        }
    }
</script>
p25 组件的创建和组件生命周期函数
和vue的组件创建以及生命周期是一样的。
组件的创建和使用
新建components目录,并在目录下新建test组件

test组件的内容如下
<template>
    <view>
        test组件
    </view>
</template>
<script>
    export default {
        name:"test"
    }
</script>
然后在index.vue中应用test组件
<template>
    <view class="content">
        <test></test> 
    </view>
</template>
<script>
    import test from '../../components/test.vue' //导入test组件
    export default {
        components:{
            test//注册test组件
        }
    }
</script>
组件的生命周期函数
index.vue
<template>
    <view class="content">
        <test v-if="flag"></test>
        <button type="primary" @click="toggleTest">切换test组件</button>
    </view>
</template>
<script>
    import test from '../../components/test.vue'
    export default {
        components:{
            test
        },
        data(){
            return{
                flag: true
            }
        },
        methods: {
            toggleTest(){
                this.flag = !this.flag
            }
        }
    }
</script>
test.vue组件
<template>
    <view id="mout">
        test组件
    </view>
</template>
<script>
    export default {
        name:"test",
        data() {
            return {
                num: 10
            };
        },
        beforeCreate() {
            console.log('beforeCreate...',this.num)
        },
        created() {
            console.log('created',this.num) //页面渲染完毕
        },
        beforeMount() {
            console.log('beforeMount',document.getElementById('mout'))
        },
        mounted() { 
            console.log('mounted',document.getElementById('mout')) //dom挂载完毕
        },
        destroyed() {
            console.log('destroyed') //页面销毁
        }
    }
</script>
p26 组件之间的通信
父组件—子组件
父组件传递数据
<template>
    <view class="content">
        <!-- 通过v-bind给子组件传数据 -->
        <test v-if="flag" :msg='fmsg'></test>
    </view>
</template>
<script>
    import test from '../../components/test.vue'
    export default {
        components:{
            test
        },
        data(){
            return{
                flag: true,
                fmsg: '儿子你好!'
            }
        }
    }
</script>
子组件接收数据
<template>
    <view id="mout">
        test组件,父组件传来的数据为:--- {{msg}}
    </view>
</template>
<script>
    export default {
        name:"test"
        props: ['msg'],//接受父组件传来的数据
    }
</script>
子组件—父组件
父组件提供一个方法用来接收子组件的数据
<template>
    <view class="content">
        <!-- 将func方法传给子组件,子组件通过func方法给父组件传值 -->
        <test v-if="flag"  @func="receivedSon"></test>
    </view>
</template>
<script>
    import test from '../../components/test.vue'
    export default {
        components:{
            test
        }
        methods: {
            receivedSon(msg){
                //接收到子组件传来的数据
                console.log(msg)
            }
        }
    }
</script>
子组件通过this.$emit调用,来给父组件传值
<template>
    <view id="mout">
        test组件
        <button type="primary" @click="sendFather">给父组件传数据</button>
    </view>
</template>
<script>
    export default {
        name:"test",
        data() {
            return {
                num: 10
            };
        },
        methods: {
            sendFather(){
                //通过this.$emit调用,来给父组件传值
                this.$emit('func','爸爸你好,我是儿子')
            }
        }
    }
</script>
全局组件通信
uni.$emit(eventName,OBJECT)
触发全局的自定义事件,附加参数都会传给监听器回调函数。
| 属性 | 类型 | 描述 | 
|---|---|---|
| eventName | String | 事件名 | 
| OBJECT | Object | 触发事件携带的附加参数 | 
uni.$on(eventName,callback)
监听全局的自定义事件,事件由 uni.$emit 触发,回调函数会接收事件触发函数的传入参数。
| 属性 | 类型 | 描述 | 
|---|---|---|
| eventName | String | 事件名 | 
| callback | Function | 事件的回调函数 | 
【案例:a组件更新b组件的数据】
新建a组件
<template>
    <view>
        a组件<button type="primary" @click="updateB">修改b组件的数据</button>
    </view>
</template>
<script>
    export default {
        name:"a",
        methods: {
            updateB(){
                uni.$emit('updateNum',10) //触发全局的updateNum事件
            }
        }
    }
</script>
新建b组件
<template>
    <view>
        b组件的num={{num}}
    </view>
</template>
<script>
    export default {
        name:"b",
        data() {
            return {
                num: 0
            };
        },
        created() {
            uni.$on('updateNum',num =>{ //添加全局的事件
                this.num += num
            })
        }
    }
</script>
p27 uni-ui扩展组件
uni-ui是DCloud提供的一个跨端ui库,它是基于vue组件的、flex布局的、无dom的跨全端ui框架。
uni-ui不包括基础组件,它是基础组件的补充。
使用方法,登录后下载进入到Hbuilderx即可,默认已经全局注册,无需导入。
后端项目跟着老师的视频敲就好

