uni-app

一、框架简介
1、目录结构
┌─components 组件目录
├─common 公共资源
├─hybrid 本地网页
├─platforms 各平台专用页面
├─pages 业务页面文件
├─static 静态资源
├─wxcomponents 存放小程序组件的目录
├─main.js Vue初始化入口文件
├─App.vue 应用配置,用来配置App全局样式以及监听 应用生命周期
├─manifest.json 配置应用名称、appid、logo、版本等打包信息
└─pages.json 配置页面路由、导航条、选项卡等页面类信息
2、应用生命周期 App.vue

函数名 说明
onLaunch 当uni-app 初始化完成时触发(全局只触发一次)
onShow 当 uni-app 启动,或从后台进入前台显示
onHide 当 uni-app 从前台进入后台
onError 当 uni-app 报错时触发
onUniNViewMessage 对 nvue 页面发送的数据进行监听,可参考 nvue 向 vue 通讯

3、页面生命周期

函数名 说明 参数
onLoad 监听页面加载 上个页面传递的数据,Object
onReady 监听页面初次渲染完成。若渲染速度快,会在页面进入动画完成前触发 -
onResize 监听窗口尺寸变化 -
onPullDownRefresh 监听用户下拉动作 -
onReachBottom 页面上拉触底事件的处理函数 -
onTabItemTap 点击 tab 时触发 index,类型String,序号; pagePath,类型String,页面路径; text,类型String,按钮文字
onShareAppMessage 用户点击右上角分享 -
onPageScroll 监听页面滚动 scrollTop,类型Number,垂直方向已滚动的距离px
onNavigationBarButtonTap 监听原生标题栏 按钮点击事件 index,类型Number,标题栏按钮数组的下标
onBackPress 监听页面返回 from ,类型String,触发返回的来源:'backbutton':左上角导航栏按钮及安卓返回键;'navigateBack':uni.navigateBack() 方法。
onNavigationBarSearchInputChanged 监听原生标题栏 搜索输入框 内容变化事件 -
onNavigationBarSearchInputConfirmed 监听原生标题栏搜索框 搜索事件,用户点击软键盘上的“搜索”按钮时触发。 -
onNavigationBarSearchInputClicked 监听原生标题栏 搜索框点击事件 -
页面返回onBackPress:
onBackPress(options) {
        console.log('from:' + options.from)
    }

4、路由
两种路由跳转方式:使用navigator组件跳转、调用API跳转。
5、页面栈
框架以栈的形式管理当前所有页面, 当发生路由切换的时候,页面栈的表现如下:

路由方式 页面栈表现 触发时机
初始化 新页面入栈 uni-app 打开的第一个页面
打开新页面 新页面入栈 调用 API:uni.navigateTo、使用组件:< navigator open-type="navigate"/>
页面重定向 当前页面出栈,新页面入栈 调用 API:uni.redirectTo、使用组件:< navigator open-type="redirectTo"/>
页面返回 页面不断出栈,直到目标返回页 调用 API:uni.navigateBack、使用组件:< navigator open-type="navigateBack"/> 、用户按左上角返回按钮、安卓用户点击物理back按键
Tab 切换 页面全部出栈,只留下新的 Tab 页面 调用 API:uni.switchTab、使用组件 :< navigator open-type="switchTab"/> 、用户切换 Tab
重加载 页面全部出栈,只留下新的页面 调用 API:uni.reLaunch、使用组件:< navigator open-type="reLaunch"/>
6、运行环境判断 a.开发环境or生产环境 通过 process.env.NODE_ENV 判断当前环境是开发环境还是生产环境。一般用于连接测试服务器或生产服务器的动态切换。
if(process.env.NODE_ENV === 'development'){
    console.log('开发环境')
}else{
    console.log('生产环境')
}

b.判断平台
1.编译期判断,即条件编译,不同平台在编译出包后已经是不同的代码。
写法:以 #ifdef 或 #ifndef 加 %PLATFORM% 开头,以 #endif 结尾

#ifdef:仅在某平台存在
#ifndef:除了某平台均存在

%PLATFORM% 可取值如下:

平台
APP-PLUS 5+App(参考HTML5+ 规范)
APP-PLUS-NVUE 5+App nvue(参考Weex 规范)
H5 H5
MP-WEIXIN 微信小程序
MP-ALIPAY 支付宝小程序
MP-BAIDU 百度小程序
MP-TOUTIAO 头条小程序
MP-QQ QQ小程序(目前仅cli版支持)
MP 微信小程序/支付宝小程序/百度小程序/头条小程序/QQ小程序

Android 和 iOS 平台不支持通过条件编译来区分,如果需要区分 Android、iOS 平台,请通过调用 uni.getSystemInfo 获取平台信息
注意: 条件编译是利用注释实现的,在不同语法里注释写法不一样,js使用 // 注释、css 使用 /* 注释 */、vue/nvue 模板里使用 < !-- 注释 -->;

除了支持单个平台的条件编译外,还支持多平台同时编译,使用 || 来分隔平台名称。
uni-app_第1张图片
不同平台下的特有功能,以及小程序平台的分包,都可以通过 pages.json 的条件编译来更好地实现。这样,就不会在其它平台产生多余的资源,进而减小包体积。

static 目录的条件编译
在不同平台,引用的静态资源可能也存在差异,通过 static 的的条件编译可以解决此问题,static 目录下新建不同平台的专有目录(目录名称同 %PLATFORM% 值域,但字母均为小写),专有目录下的静态资源只有在特定平台才会编译进去。
如以下目录结构,a.png 只有在微信小程序平台才会编译进去,b.png 在所有平台都会被编译。
┌─static
│ ├─mp-weixin
│ │ └─a.png
│ └─b.png
├─main.js
├─App.vue
├─manifest.json
└─pages.json

整体目录条件编译
如果想把各平台的页面文件更彻底的分开,也可以在uni-app项目根目录下创建platforms目录,然后在下面进一步创建APP-PLUS、MP-WEIXIN等子目录,存放不同平台的文件

在项目里,正常都是复用的代码多,所以应该使用多端。而个性的代码可以放到不同平台的目录下,差异化维护。

2.运行期判断,代码已经打入包中,仍然需要在运行期判断平台,此时可使用 uni.getSystemInfoSync().platform 判断客户端环境。小程序返回值均为 devtools。

switch(uni.getSystemInfoSync().platform){
    case 'android':
       console.log('运行Android上')
       break;
    case 'ios':
       console.log('运行iOS上')
       break;
    default:
       console.log('运行在开发者工具上')
       break;
}

二、页面样式与布局
1、尺寸单位
uni-app 支持的通用 css 单位包括 px、rpx

rpx 即响应式px。以750宽的屏幕为基准,屏幕变宽,rpx 实际显示效果会等比放大。
rem 默认根字体大小为 屏幕宽度/20(微信小程序、头条小程序、App、H5)。

nvue不支持百分比单位、rem、vh、vw。

App端,在 pages.json 里的 titleNView 或页面里写的 plus api 中涉及的单位,只支持 px。

nvue中,uni-app 模式可以使用 px 、rpx,表现与 vue 中一致。

weex 模式目前遵循weex的单位,它的单位比较特殊:
px:,以750宽的屏幕为基准动态计算的长度单位,与 vue 页面中的 rpx 理念相同。
wx:与设备屏幕宽度无关的长度单位,与 vue 页面中的 px 理念相同。

开发者可以通过设计稿基准宽度计算页面元素 rpx 值,设计稿 1px 与框架样式 1rpx 转换公式如下:
设计稿 1px / 设计稿基准宽度 = 框架样式 1rpx / 750rpx
换言之,页面元素宽度在 uni-app 中的宽度计算公式:
750 * 元素在设计稿中的宽度 / 设计稿基准宽度
举例说明:
若设计稿宽度为 750px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在 uni-app 里面的宽度应该设为:750 * 100 / 750,结果为:100rpx。
若设计稿宽度为 640px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在 uni-app 里面的宽度应该设为:750 * 100 / 640,结果为:117rpx。
若设计稿宽度为 375px,元素 B 在设计稿上的宽度为 200px,那么元素 B 在 uni-app 里面的宽度应该设为:750 * 200 / 375,结果为:400rpx。

rpx不支持动态横竖屏切换计算,使用rpx建议锁定屏幕方向。
如果设计稿不是750px,HBuilderX提供了自动换算的工具,详见:https://ask.dcloud.net.cn/article/35445。
早期 uni-app 提供了 upx ,目前已经推荐统一改为 rpx 。

2、css选择器

选择器 样例 样例描述
element view 选择所有 view 组件
::after view::after 在 view 组件后边插入内容
::before view::before 在 view 组件前边插入内容

在 uni-app 中不能使用 * 选择器。page 相当于 body 节点。nvue页面暂不支持全局样式。

3、内置 CSS 变量

CSS变量 描述 5+App 小程序 H5
--status-bar-height 系统状态栏高度 系统状态栏高度、nvue不支持 25px 0
--window-top 内容区域距顶部的距离 0 0 NavigationBar 的高度44px
--window-bottom 内容区域距底部的距离 0 0 TabBar 的高度50px
注意: 当设置 "navigationStyle":"custom" 取消原生导航栏后,由于窗体为沉浸式,占据了状态栏位置。此时可以使用一个高度为 var(--status-bar-height) 的 view 放在页面顶部,避免页面内容出现在状态栏。
.status_bar {
        height: var(--status-bar-height);/*状态栏*/
        width: 100%;
    }

由于在H5端,不存在原生导航栏和tabbar,也是前端div模拟。如果设置了一个固定位置的居底view,在小程序和App端是在tabbar上方,但在H5端会与tabbar重叠。此时可使用–window-bottom,不管在哪个端,都是固定在tabbar上方。

.toTop {
        bottom: calc(var(--window-bottom) + 10px)/*距离底部tabbar上浮10px*/
    }

目前 nvue 在App端,还不支持 --status-bar-height变量,替代方案是在页面onLoad时通过uni.getSystemInfoSync().statusBarHeight获取状态栏高度,然后通过style绑定方式给占位view设定高度。

<template>
    <view class="content">
        <view :style="{ height: iStatusBarHeight + 'px'}"></view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                iStatusBarHeight:0
            }
        },
        onLoad() {
            this.iStatusBarHeight = uni.getSystemInfoSync().statusBarHeight
        }
    }
</script>

4、背景图片
使用本地路径背景图片需注意:
图片小于 40kb,uni-app 会自动将其转化为 base64 格式
图片大于等于 40kb, 需开发者自己将其转换为 base64 格式使用,或将其挪到服务器上,从网络地址引用。
uni-app v3版本设定为不自动将图片转 base64 格式。

本地背景图片的引用路径推荐使用以 ~@ 开头的绝对路径。

 .test2 {
     background-image: url('~@/static/logo.png');
 }

注意:
微信小程序不支持相对路径(真机不支持,开发工具支持)
其他端使用本地背景图片作为背景图没有限制

5、字体图标
uni-app 支持使用字体图标,使用方式与普通 web 项目相同,需要注意以下几点:
网络路径必须加协议头 https。
从 http://www.iconfont.cn 上拷贝的代码,默认是没加协议头的。

uni-app 本地路径图标字体支持情况:
字体文件小于 40kb,uni-app 会自动将其转化为 base64 格式;
字体文件大于等于 40kb, 需开发者自己转换,否则使用将不生效;

 @font-face {
        font-family: 'iconfont';
        src: url('https://at.alicdn.com/t/font_865816_17gjspmmrkti.ttf') format('truetype');
    }
    .test {
        font-family: iconfont;
        margin-left: 20rpx;
    }

6、< template/> 和< block/>
uni-app 支持在 template 模板中嵌套 < template/>< block/>,用来进行 列表渲染条件渲染。它们仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。

<template>
    <view>
        <template v-if="test">
            <view>test 为 true 时显示</view>
        </template>
        <template v-else>
            <view>test 为 false 时显示</view>
        </template>
    </view>
</template>
<template>
    <view>
        <block v-for="(item,index) in list" :key="index">
            <view>{{item}} - {{index}}</view>
        </block>
    </view>
</template>

三、npm支持
1、初始化npm工程

若项目之前未使用npm管理依赖(项目根目录下无package.json文件),先在项目根目录执行命令初始化npm工程:

npm init -y

cli项目默认已经有package.json了。HBuilderX创建的项目默认没有,需要通过初始化命令来创建。

2、安装依赖
在项目根目录执行命令安装npm包:

npm install packageName --save

3、使用
安装完即可使用npm包,js中引入npm包:

import package from 'packageName'
const package = require('packageName')

注意:
为多端兼容考虑,建议优先从 uni-app插件市场 获取插件。直接从 npm 下载库很容易只兼容H5端。
非 H5 端不支持使用含有 dom、window 等操作的 vue 组件和 js 模块,安装的模块及其依赖的模块使用的 API 必须是 uni-app 已有的 API(兼容小程序 API),比如:支持高德地图微信小程序 SDK。类似jQuery 等库只能用于H5端。
支持安装 mpvue 组件,但npm方式不支持小程序自定义组件(如 wxml格式的vant-weapp)。
四、TypeScript 、小程序组件支持
1、TypeScript 支持
在 vue 文件的 script 节点声明 lang=“ts”
声明 lang=“ts” 后,该 vue 文件 import 进来的所有 vue 组件,均需要使用 ts 编写。

2、小程序组件支持
uni-app 支持在 App 和 小程序 中使用小程序自定义组件。

平台 支持情况 小程序组件存放目录
H5 不支持 -
App(不含nvue) 支持微信小程序组件 wxcomponents
微信小程序 支持微信小程序组件 wxcomponents
支付宝小程序 支持支付宝小程序组件 mycomponents
百度小程序 支持百度小程序组件 swancomponents
头条小程序 支持头条小程序组件 ttcomponents
QQ小程序 支持QQ小程序组件 wxcomponents

使用方式:
在 pages.json 对应页面的 style -> usingComponents 引入组件:

{
    "pages": [
        {
            "path": "index/index",
            "style": {
                "usingComponents": {
                    // #ifdef APP-PLUS || MP-WEIXIN || MP-QQ
                     "custom": "/wxcomponents/custom/index"
                    // #endif
                    // #ifdef MP-BAIDU
                     "custom": "/swancomponents/custom/index"
                    // #endif
                    // #ifdef MP-ALIPAY
                     "custom": "/mycomponents/custom/index"
                    // #endif
                }
            }
        }
    ]
}

在页面中使用:


<view>
    
    <custom name="uni-app">custom>
view>

注意:
1、小程序组件,HBuilderX 建立的工程 文件夹在 项目根目录下。vue-cli 建立的工程 文件夹在 src 目录下。可在 vue.config.js 中自定义其他目录。
2、小程序组件的性能,不如vue组件。使用小程序组件,需要自己手动setData,很难自动管理差量数据更新。而使用vue组件会自动diff更新差量数据。所以如无明显必要,建议使用vue组件而不是小程序组件。比如某些小程序ui组件,完全可以用更高性能的uni ui替代。
3、当需要在 vue 组件中使用小程序组件时,注意在 pages.json 的 globalStyle 中配置 usingComponents,而不是页面级配置。
4、注意数据和事件绑定的差异,使用时应按照 vue 的数据和事件绑定方式:例如,阻止事件冒泡 从 catch:tap=“xx” 改为 @tap.native.stop=“xx”
5、事件命名用驼峰命名

五、使用vue.js注意事项
相比Web平台, Vue.js 在 uni-app 中使用差异主要集中在两个方面:
新增:uni-app除了支持Vue实例的生命周期,还支持应用启动、页面显示等生命周期。
受限:相比web平台,在小程序和App端部分功能受限。

支持vue模板语法:https://cn.vuejs.org/v2/guide/syntax.html

1、class style
非H5端不支持 Vue Class 与 Style 绑定 中的 classObject 和 styleObject 语法。
class:

<view :class="{ active: isActive }">111view>
<view :class="{ active: isActive, 'text-danger': hasError }">222view>
<view :class="[activeClass, errorClass]">333view>
<view :class="[isActive ? activeClass : '', errorClass]">444view>
<view :class="[{ active: isActive }, errorClass]">555view>

style:

<view :style="{ color: activeColor, fontSize: fontSize + 'px' }">666view>
<view :style="[{ color: activeColor, fontSize: fontSize + 'px' }]">777view>

以:style=""这样的方式设置px像素值,其值为实际像素,不会被编译器转换

可用 computed 方法生成 class 或者 style 字符串,插入到页面中

<template>
    <!-- 支持 -->
    <view class="container" :class="computedClassStr"></view>
    <view class="container" :class="{active: isActive}"></view>

    <!-- 不支持 -->
    <view class="container" :class="computedClassObject"></view>
</template>
<script>
    export default {
        data () {
            return {
                isActive: true
            }
        },
        computed: {
            computedClassStr () {
                return this.isActive ? 'active' : ''
            },
            computedClassObject () {
                return { active: this.isActive }
            }
        }
    }
</script>

2、v-for
在H5平台,使用 v-for 循环整数时和其他平台存在差异,如 v-for="(item, index) in 10" 中,在H5平台 item 从 1 开始,其他平台 item 从 0 开始,可使用第二个参数 index 来保持一致。
非H5平台,循环对象时不支持第三个参数

3、事件处理器

// 事件映射表,左侧为 WEB 事件,右侧为 ``uni-app`` 对应事件
{
    click: 'tap',
    touchstart: 'touchstart',
    touchmove: 'touchmove',
    touchcancel: 'touchcancel',
    touchend: 'touchend',
    tap: 'tap',
    longtap: 'longtap',
    input: 'input',
    change: 'change',
    submit: 'submit',
    blur: 'blur',
    focus: 'focus',
    reset: 'reset',
    confirm: 'confirm',
    columnchange: 'columnchange',
    linechange: 'linechange',
    error: 'error',
    scrolltoupper: 'scrolltoupper',
    scrolltolower: 'scrolltolower',
    scroll: 'scroll'
}

注意:
1、为兼容各端,事件需使用 v-on 或 @ 的方式绑定,请勿使用小程序端的bind 和 catch 进行事件绑定。
2、事件修饰符:
.stop:各平台均支持, 阻止事件冒泡,在非 H5 端同时也会阻止事件的默认行为
.prevent 仅在 H5 平台支持
.self:仅在 H5 平台支持
.once:仅在 H5 平台支持
.capture:仅在 H5 平台支持
.passive:仅在 H5 平台支持
3、若需要禁止蒙版下的页面滚动,可使用 @touchmove.stop.prevent=“moveHandle”,moveHandle 可以用来处理 touchmove 的事件,也可以是一个空函数。
< view class=“mask” @touchmove.stop.prevent=“moveHandle”>< /view>
4、按键修饰符:uni-app运行在手机端,没有键盘事件,所以不支持按键修饰符

4、表单控件绑定
支持 Vue官方文档:表单控件绑定。
建议开发过程中直接使用 uni-app表单组件。eg:
H5 的select 标签用 picker 组件进行代替。
表单元素 radio 用 radio-group 组件进行代替

5、组件
uni-app只支持vue单文件组件(.vue 组件)。其他的诸如:动态组件,自定义 render,和< script type=“text/x-template”> 字符串模版等,在非H5端不支持。
详细的非H5端不支持列表:
slot(scoped 暂时还没做支持)
动态组件
异步组件
inline-template
X-Templates
keep-alive
transition (可使用 animation 或 CSS 动画替代)

全局组件:
支持配置全局组件,在 main.js 里进行全局注册,注册后就可在所有页面里使用该组件。
注意:
Vue.component 的第一个参数必须是静态的字符串
nvue页面暂不支持全局组件。

import Vue from 'vue'
import pageHead from './components/page-head.vue'
Vue.component('page-head',pageHead)

你可能感兴趣的:(统一多端开发)