uni-app

549 阅读35分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Dcloud团队推出的跨平台应用前端框架,用的vue.js语法。可以用来开发几乎所有的前端应用。可以实现用一套代码,将项目部署到多个平台上面,包括IOS、Android、h5、小程序(微信/百度/头条/QQ/钉钉/淘宝)、快应用等

vue语法+微信小程序api

条件编译

尽管uni-app可以跨平台,但是每个平台之间的样式、支付接口有稍许不同,大约有百分之10的样式在各平台之间是不兼容的。这种情况,就需要用到条件编译了,针对每一平台的特性去做适配。

/*H5平台登陆按钮显示红色,微信小程序登录按钮显示蓝色*/
button{
    /* #ifdef H5 */
    background:red;
    /* #endif */
    
    /* #ifdef MP-WEIXIN */
    background:blue;
    /* #endif */
}
对ES6的支持

解构赋值、箭头函数、数组扩展、Promise、module

npm

支持用npm安装第三方包

创建一个uni-app项目

  1. HBuilder创建;编译器装在HBuilder的插件目录下面,HBbuilder版本更新,编译器就一起更新升级,对所有项目生效

  2. vue-cli命令行创建;编译器是安装在单独的项目下面的,升级时需要手动命令升级,只对这一个项目生效

    vue create -p dcloudio/uni-preset-vue uniAppProject
    

在创建项目时,选择不同的模板生成的项目目录是不一样的,常见的项目模板有uni-ui项目模板、Hello uni-app模板

全局配置和页面配置

包括项目的标题栏、底部Tab栏、窗口背景色等

主要通过操作项目根目录下面的pages.json文件,来进行项目的全局配置和页面配置

一些常用的配置项,项目创建完成后,会自动帮我们生成,我们需要了解每个配置项的含义,以及配置项对应的设置条件有哪些限制

比如导航栏标题色样式navigationBarTextStyle这个配置项,仅支持black/white这两个颜色的设置,设置为十六进制,系统就会识别不了

全局配置

全局配置作用于整个项目,即对项目中所有的页面都起作用。在项目根目录下面的pages.json文件中,找到globalStyle配置项,在这个配置项中进行项目的全局配置

{
    "globalStyle":{
        "navigationBarTextStyle":"black",// 导航栏标题颜色
        "navigationBarTitleText":"导航栏标题文字",
        "navigationBarBackgroundColor":"#f8f8f8",//导航栏背景颜色
        "backgroundColor":"#f8f8f8",// 下拉窗口背景颜色
        "backgroundTextStyle":light,// 下拉loading的样式
        "enablePullDownRefresh":true,// 开启下拉刷新
        "onReachBottomDistance":60,// 页面上拉触发距页面底部距离为60
        "usingComponents":{
            "collapse-tree-item":"/components/collapse-tree-item",// 引用小程序组件
        },
        "pageOrientation":"auto" // 支持屏幕旋转
    }
}
enablePullDownRefresh下拉刷新

想要实现页面下拉刷新的效果,需要先在配置文件中将enablePullDownRefresh设置为true,再在.vue文件中配合onPullDownRefresh函数进行页面下拉效果的实现,如果忘记enablePullDownRefresh配置项,会导致下拉效果失灵

uni.stopPullDownRefresh()结束下拉

pageOrientation屏幕旋转设置

这个属性可以设置为auto、portrait、landscape,分别代表着启用屏幕旋转、固定为竖屏显示、固定为横屏显示。默认值为portrait固定为竖屏显示

这个属性,通常可以使用js作为辅助,用js读取页面的显示区域尺寸,来进行屏幕方向的监听,每次屏幕旋转时都会调用这个方法。需要注意的是,在模拟器上不会触发这个方法,需要使用真机调试才能触发

Page({
    onResize(res){
        res.size.windowWidth // 新的显示区域宽度
        res.size.widnowHeight // 新的显示区域高度
    }
})

页面配置

页面配置只作用于单个页面,与全局配置冲突的地方,页面配置会覆盖全局配置。

在项目根目录下面的pages.json文件中,找到pages配置项里面的style来进行页面配置

page:页面路径

style:页面窗口表现

{
    "pages":[
        {
            "path":"pages/index/index",
            "style":{
                "navigationBarTitleText":"首页",
                "disableScroll":true,
                "enablePullDownRefresh":true,
                "navigationBarShadow":{
                    "colorType":"green"
                }// 导航栏阴影,仅支持grey、blue、green、orange、red、yellow
            }
        }
    ]
}

uni-app生命周期

uni-app生命周期包括应用生命周期和页面生命周期

应用生命周期

控制应用全局的生命周期,监听应用初始化、启动、报错等状态。只在App.vue文件中有效,App.vue文件是应用配置文件,用来配置App全局样式以及监听应用生命周期

onLaunch

当uni-app应用初始化完成时触发,全局只触发一次。一般用于查看用户是否授权、获取用户的设备信息等

onShow

当应用启动,或从后台进入前台显示时触发,可以触发多次。一般用于重新进入应用的消息提示或者数据刷新

onHide

监听应用从前台进入后台,一般用于退出应用时的消息提示

onError

应用报错时被触发,用于检测并处理错误

销毁应用

当应用进入后台超过一定时间,或者系统资源占用过高,应用才会被真正的销毁,再次打开就需要重新初始化启动应用

页面生命周期

控制单个页面的生命周期,监听页面渲染、加载、显示、下拉、滚动、分享等状态

onLoad

页面加载时触发,一个页面只会调用一次,可以传递参数

页面最先执行的生命周期,如果从上个页面跳转到本页面,可以通过参数option传递上个页面的数据

比如从首页(index.vue)跳转到个人中心页面(me.vue):

// index.vue
uni.reLaunch({
    url:'test?name=首页的数据'
})
// me.vue
export default{
    // options参数就是上个页面传递过来的数据
    onLoad:function(options){
        console.log(options.name)
    }
}
onShow

页面显示时触发,每次打开页面都会调用一次

onReady

页面初次渲染完成后触发,一个页面只会调用一次

onHide

页面隐藏时触发,每次隐藏页面都被触发

onUnload

页面卸载时触发

onResize

页面每次窗口尺寸变化时会被触发,仅支持App、微信小程序

onPullDownRefresh

用户下拉页面时触发,一般用于页面下拉刷新

普通页面下拉不会触发onPullDownRefresh函数,要先在pages.json里面,找到当前页面的pages节点,并在style选项中将enablePullDownRefresh设置为true,下拉页面才可以触发onPullDownRefresh函数

比如开启首页(index.vue)的下拉动作:

// pages.json
{
    "path":"pages/index/index.vue",
    "style":{
        "enablePullDownRefresh":true
    }
}

调用完成onPullDownRefresh函数后,欧阳那个stopPullDownRefresh函数可以停止当前页面的下拉状态

export default{
    onPullDownRefresh(){
        console.log("用户下拉时触发")
        uni.stopPullDownRefresh()
    }
}
onReachBottom

页面上拉滚动触底时触发

onTabItemTap

点击底部tab栏时触发,参数为object,支持微信小程序、百度小程序、H5、App

参数:

  • index - String,被点击tabItem的序号,从0开始
  • pagePath - String,被点击tabItem的页面路径
  • text - String,被点击tabItem的按钮文字
onShareAppMessage

点击右上角分享时触发。支持微信小程序、百度小程序、字跳小程序、支付宝小程序

onPageScroll

页面滚动时触发,只监听页面垂直滚动

onNavigationBarButtonTap

监听原生标题栏按钮点击事件。支持App、H5

参数:

index - Number,原生标题栏按钮数组的下标

export default{
    onNavigationBarButtonTap(options){
        console.log("index:",options.index)
    }
}
onBackPress

页面返回时触发。支持App、H5

返回结果的格式是这样的:event = {from:"backbutton/navigateBack"},其中backbutton表示来源是左上角返回按钮或android返回键;navigateBack表示来源是uni.navigateBack

onNavigationBarSearchInputChanged

监听原生标题栏搜索输入框输入内容变化事件。支持App、H5

onNavigationBarSearchInputConfirmed

监听原生标题栏搜索输入框搜索事件。支持App、H5

onNavigationBarSearchInputClicked

监听原生标题栏搜索输入框点击事件。支持App、H5

组件生命周期

vue的特性,可以配合uni-app中自带的应用生命周期和页面生命周期一起使用

有的页面生命周期函数与组件生命周期函数,在项目开发过程中,功能会有点重复,比如onLoad和created放的都是页面初始化时需要触发的代码;onReady和mounted里面放的都是页面加载完成后,只需要调用一次的代码,比如用户的登录信息。像这样比较重复的生命周期函数,推荐使用页面生命周期函数,比如,组件生命周期created可以替换为页面生命周期中的onLoad;组件生命周期中的mounted可以替换为页面生命周期中的onReady

uni-app基础组件

uni-app框架提供了一系列基础组件,与传统HTML中的基础标签元素类似,与小程序中的标签元素是一样的,更适合手机端使用。比如div会被view标签替代,类似的还有span转text、a转navigator等。如果开发过程中,不小心写了div这种不符合uni-app开发规范的标签,也不会报错,在编译到非H5平台时,编译器会帮我们转换为view标签。我们可以基于这些uni-app组件快速搭建页面的基础结构

view视图容器

属性:

  • hover-class:string,点击效果
  • hover-stop-propagation:Boolean,默认false,是否阻止本节点的祖先节点出现点击效果,默认不阻止
  • hover-start-time:Number,默认50,按住多久出现点击效果,单位毫秒
  • hover-stay-time:Number,默认400,手指松开后点击效果的保留事件,单位毫秒
<!-- 点击效果背景色改变,粉色背景效果保留1s;如果电脑网页版看不到点击效果,可以切换到手机页面试试 -->
<template>
    <view class="box" hover-class="click-active" :hover-start-time="1000"></view>
</template>
<style>
    .box{
        height:50px;
        background:black;
    }
    .click-active{
        background:pink;
    }
</style>

text文本组件

属性说明:

  • selectable:boolean,默认false,文本是否可选
  • space:string,默认“.”,显示连续空格,可选参数ensp、emsp、nbsp
  • decode:boolean,默认false,是否解码,可以解析的有< > & ''
<template>
    <view>
        <!-- 长按文本是否可选 -->
        <view>
            <text :selectable="true">长按文本可选</text>
        </view>
        <!-- 显示连续空格的方式 -->
        <view>
            <!-- 中文字符空格一半大小 -->
            <view space="ensp">空格 space</view>
        </view>
        <view>
            <!-- 中文字符空格大小 -->
            <view space="emsp">空格 space</view>
        </view>
        <view>
            <!-- 根据字体设置的空格大小 -->
            <view space="nbsp">空格 space</view>
        </view>
    </view>
</template>

Tips:如果用了span组件,编译时会被转换为;组件内只支持嵌套,不支持其他组件或自定义组件,否则不同平台会有渲染差异;除了文本节点以外,其他节点都无法长按选中

buttom按钮组件

属性说明:

  • size - String,默认default,按钮大小;按钮设置为mini时,可以在一行显示多个按钮,为默认值时,会独占一行
  • type - String,默认default,按钮样式类型
  • plain - Boolean,默认false,按钮是否镂空,背景色透明
  • disabled - Boolean,默认false,是否禁用
  • loading - Boolean,默认false,名称前是否带loading图标

navigator页面链接

属性说明:

  • url - String,应用内的跳转链接
  • open-type - String,默认navigate,跳转方式;navigate对应uni.navigateTo的功能;redirect对应redirectTo的功能;switchTab;reLaunch;navigateBack;
  • delta - Number,当open-type为navigateBack时有效,表示回退的层数
  • animation-type
  • animation-duration

image图片组件

属性说明:

  • src - String,图片资源地址
  • mode - String,默认值scaleToFill,图片裁剪、缩放的模式;aspectFit表示保持纵横比例缩放图片,使图片的长边适应容器的宽度或高度
  • image组件默认宽度300px,高度225px

以上是uni-app的一些常用基础组件,所有组件与属性名都是小写。 官网:uniapp.dcloud.io/component/R…

tips:如果成功引用了组件,但是组件却没有显示出来,并且也没有报错。这种情况往往是因为新创建的组件没有被重新编译,大多数情况下,重启编译器组件就可以正常显示了

条件编译实现跨端兼容

条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同的平台。写法是以#ifdef#ifdef加%PLATFORM%开头,以#endif`结尾

// 表示代码仅在H5平台上面执行,其他平台不执行
#ifdef H5
	需条件编译的代码
#endif

// 表示代码在H5平台上面不执行,其他平台上面不执行
#ifndef H5
	需条件编译的代码
#endif

// 表示代码在H5平台、App平台、微信小程序平台上面执行,其他平台上面不执行
#ifdef H5 || APP-PLUS || MP-WEIXIN
	需条件编译的代码
#endif

// demo 设置仅在H5平台显示登录弹窗
<!-- #ifdef H5 -->
	<Login/>
<!-- #endif -->

tips:条件编译是注释的状态

uni-app路由跳转和传参

配置路由

在pages.json文件中配置路由,一般配置path和style两个属性

路由跳转

navigator组件跳转
<!-- open-type表示跳转方式,如果不写,默认是navigate-->
<navigator :url="url" open-type="navigate">
    <button type="default">跳转到新页面</button>
</navigator>
<navigator :url="url" open-type="redirect">
    <button type="default">在当前页打开</button>
</navigator>
<navigator :url="url" open-type="switchTab">
    <button type="default">跳转到tab页面</button>
</navigator>
API跳转
<template>
    <button type="default" @tap="navigateTo">跳转到新页面</button>
    <button type="default" @tap="redirectTo">在当前页打开</button>
    <button type="default" @tap="switchTab">跳转到tab页面</button>
</template>
<script>
    export default{
        methods:{
            navigateTo(){
                uni.navigateTo({
                    url:this.url
                })
            },
            redirectTo(){
                uni.redirectTo({
                    url:this.url
                })
            },
            switchTab(){
                uni.switchTab({
                    url:this.url
                })
            }
        }
    }
</script>

路由传值

将要传递的值直接在跳转页面的URL路径后面拼接,然后再在接收页面的onload里面接收这个值

<!-- index.vue -->
<button type="default" @tap="navigateData">跳转到page1页面</button>
navigateData(){
    uni.navigateTo({
        url:this.url + "?data='从index.vue传过来的值'"
    })
}
<!-- page1.vue -->
onLoad(options){
    let data = options.data;
}

tips:url有长度限制,太长的字符串会传递失败,可以使用缓存、窗体通信等解决

uni-app页面栈

在做页面开发之前,一定要先了解页面栈的功能。不然uni.navigateTo、uni.redirectTo有时乱用,在需要连续跳转3层以上页面的功能,容易出现bug

栈是一种连续的数据结构,具有先进后出的特点。页面栈就是用来储存页面的栈,uni-app是通过页面栈来管理所有的页面,可以在onLoad中使用getCurrentPages()方法获取当前页面栈的实例,展现页面栈中页面存储的情况,返回的结果是数组形式,数组的第一个元素为初始化页面,数组的最后一个元素为当前页面。

打开新页面

当调用APIuni.navigateTo或者使用组件<navigator open-type='navigate'/>就会打开新的页面,这时就会有新的页面进入页面栈。

页面返回

当调用APIuni.navigateBack或使用组件<navigator open-type='navigateBack'>或者点击浏览器左上角的返回按钮,还有点击安卓物理back按键,都会进行页面返回,返回到上一级页面。进行这些操作时,页面会不断的出栈,直至回到第一个页面,也就是存放在页面栈中最底部的页面。

页面重定向

当调用APIuni.redirectTo,或者使用组件<navigator open-type='redirectTo'>时,就会进行页面重定向。这时当前页面会出页面栈,新打开的页面加入页面栈。

Tab切换

当调用APIuni.switchTab,或者使用组件<navigator open-type='switchTab'>,或者点击tab页面切换时,这种情况,所有的页面都会从页面栈内删除,只留下新的tab页面

重加载

调用APIuni.reLaunch,或者使用组件<navigator open-type='reLaunch'>,就会进行页面重加载,这时页面会全部出栈,只留下新的页面,页面栈的表现与tab切换是一样的

tips:1,navigateTo、redirectTo只能打开非tab页面;2,switchTab只能打开tab页面;3,reLaunch可以打开任意页面

uni-app页面样式

全局样式与局部样式

全局样式会作用再所有页面上,用来写一些页面的重复样式,方便后期对项目的优化和维护。在uni-app项目中,会将全局样式定义在App.vue文件中

局部样式会作用在特定的页面上面,当全局样式与局部样式冲突时,局部样式会覆盖掉全局样式,通常将局部样式定义在pages目录下的.vue文件中

选择器

uni-app支持的选择器有.class、#id、element、element,element、::after、::before这6个

动态样式建议写在style属性中,静态样式建议写在class属性中,这样可以提高渲染效果,尽可能的优化页面性能

<template>
    <view :style="{color:color}">文字颜色动态变化</view>
</template>
<script>
export default{
    data(){
        color:"",
        data:1
    }
    onLoad(){
        if(this.data < 0){
            this.color = "green"
        }else{
            this.color = "red"
        }
    }
}
</script>

网络请求

uni-request

在小程序中网络相关的API在使用前需要配置域名白名单

API参数

经常用到的大多是url、data、method、success这几个参数;method值必须大写,默认是GET;data参数支持object,但会被转成String类型;

运行环境判断及平台判断

在日常开发过程中,一般测试服务器和生产服务器是分开的,测试服务器和生产服务器之间的项目配置数据是不同的,每次切换运行环境还要修改这些配置数据非常麻烦,且不利于后期维护。所以,需要判断当前环境是开发环境还是生产环境,自动进行测试及生产服务器的动态切换。

由于平台之间也会有一定的差异性,所以也需要对当前的平台进行判断,以应对这种差异性。比如微信小程序自带了标题栏和返回键,但是原生app没有自带标题栏和返回键,就需要自己定义。

判断开发环境和生产环境

uni-app中打包了一个process.env.NODE_ENV方法,通过这个方法可以直接来判断当前环境。

if(process.env.NODE_ENV === "development"){
    // 开发环境的配置数据
}
if(process.env.NODE_ENV === "production"){
    // 生产环境的配置数据
}

运行平台判断

运行平台的判断可以在编译期判断,也可以在运行期判断

在编译器判断

通过条件编译使特定的代码只运行在对应的平台的发行包里,其他平台发行包不会包含条件编译的代码

在运行期判断

运行期判断是指代码已经编译到发行包里面,所以我们还是需要判断当前是在哪个平台上运行。这种情况可以用uni.getSystemInfoSync().platform方法来判断当前的平台是Android、ios还是小程序开发工具。在百度小程序开发工具、微信小程序开发工具、支付宝小程序开发工具中使用上述方法返回值都是devtools,所以只能判断是小程序开发工具,不能再细分。

自定义平台

如果有其他的开发需求,比如微信服务号开发,uni-app中没有对应的平台,就可以自定义一个,在package.json文件中增加uni-app扩展节点

{
    "uni-app":{
        "scripts":{
            "wx-platform":{ // 自定义编译平台配置,可通过cli方式调用
                "title":"微信服务号", // 自定义平台名称,
                "env":{ // 环境变量
                    "UNI_PLATFORM":"mp-weixin"
                },
                "define":{ // 自定义条件编译
                    "WX-PLATFORM":true // 自定义条件编译常量
                }
            }
        }
    }
}

tips:package.json文件中不允许出现注释,否则扩展配置无效;使用自定义平台功能,vue-cli需要更新到最新版,HBuilderX需升级到2.1.6+版本

// #ifdef WX-PLATFORM
console.log("微信服务号平台特有代码")
// #endif

uni-app的打包发布

可以直接在HBuilderX工具中将项目进行打包,操作可视化,并且可以将开发的项目打包成能够发布在多个平台上面的文件。需要先注册登录到HBuilderX工具中,再对uni-app项目进行打包

打包为原生App

在工具栏,点击发行,选择原生app-本地打包,会在本地配置中生成安装包apk/ipa,可以参考官网原生app-本地打包文档。Android包名至少分为两段,并且每段开头必须是小写字母。

打包为H5手机版

在工具栏,点击发行,选择网站-H5手机版。出现弹框,我们填写网站标题和网站域名之后,点击发行就可以了。编译成功后,会显示打包文件的保存地址。uni-app在打包成H5项目时,如果根据默认的配置,项目一般是打不开的,需要在打包之前,将vue.config配置文件中的publicPath选项配置成(./),这样编译出来的html文件还有引用js、css文件的路径会自动变成cdn上的地址。不然打包出来是(/xxx/xxx)这种路径格式,编译出来的html文件找不到正确的路径,是打不开的。

打包为小程序
  1. 注册微信小程序账号,获取到AppID,配置的时候会用到
  2. 在HBuilderX工具栏,点击发行,选择小程序-微信,输入小程序名称和AppID,单击发行就可以了。
  3. 这样我们就会获得一个微信小程序的打包文件,接下来要发布微信小程序,打开微信小程序开发者工具,导入刚刚生成的微信小程序项目的打包文件,在微信小程序开发者工具中先测试一下,项目是否正常运行。测试没问题之后,点击右上角按钮,上传代码就可以发布微信小程序了,最后等待微信团队审核通过,别人就可以在线上访问到我们发布的小程序了
打包为百度小程序
  1. 入驻百度小程序并注册申请百度小程序的AppID
  2. 在HBuilderX工具栏,点击发行,选择小程序-百度
  3. 输入小程序名称和百度小程序的AppID,单击发行就可以了

uni-app中使用Vue.js的注意事项

uni-app框架可以开发几乎所有的前端应用,并且只需要一套代码就可以将项目部署到多个平台。这是因为uni-app框架用的是vue.js语法和微信小程序的api。但是这样的组合也有一些限制,由于各个平台的特性,有些vue语法在个别平台上没办法实现,所以有一些需要注意的事项

生命周期

uni-app有应用生命周期和页面生命周期,同时还支持vue组件生命周期。其中页面生命周期和组件生命周期,在开发的过程中会有点重复,通常选择其中一个使用就可以了。需要注意的是,应用生命周期函数仅在page页面有效,在单独封装的组件中无效。但是组件生命周期函数在page页面和单独封装的组件中都有效。

列表渲染key

在实际开发过程中,列表渲染如果没有指定key,会报一个warning警告。如果列表是静态的,里面的数据不会因为页面的情况改变而改变,可以忽略这个warning。如果列表会随着页面情况的改变而改变,那必须要指定key,不然会降低渲染效率,这是因为渲染层重新渲染的时候,会校正带有key的组件,提高列表渲染时的效率。key指定的数据必须是唯一的字母或者是数字,且不能动态改变

uni-app配置文件

uni-app支持的全局配置包括:pages.json、manifest.json、package.json、vue.config.js、uni.scss

pages.json配置文件

配置页面路由、进行页面的全局配置和页面配置都可以在pages.json文件中配置,是开发过程中经常操作的文件。

condition是与pages同级的配置项,意义是启动模式配置,只在开发期间生效,主要是方便我们进行多层级页面测试时看到预览效果

tabBar是与condition、pages同级的配置项,当应用需要显示tab栏时,只需要通过配置pages.json配置文件中的tabBar属性,就可以控制项目中tab栏的显示。tab项至少配置2个,最多配置5个。tab栏从左到右的显示顺序与tabBar中list数组中tab项的排序有关

{
    "tabBar":{
        "color":"#eee",// 必须设置的选项,表示tab文字默认的颜色,也是没有选中tab时文字显示的颜色
        "selectedColor":"#ea5149",// 必须设置的选项,表示选中tab时文字显示的颜色,仅支持十六进制
        "backgroundColor":"#fff",// 必须设置的选项,表示tab背景色
        "borderStyle":"black",// 可选设置,表示tab上边框的颜色,目前只支持black/white
        "list":[
            {
                "text":"首页",// tab项显示的文字
                "pagePath":"pages/index/main",// tab项的页面路径,必须要先在pages配置项中定义不然会报错
                "iconPath":"static/images/default.png",// tab项未选中时所显示的图标路径
                "selectedIconPath":"static/images/active.png"// tab项被选中时显示的图标路径
            },
            {
                "text":"我的",
                "pagePath":"pages/index/main",
                "iconPath":"static/images/default.png",
                "selectedIconPath":"static/images/active.png"
            }
        ]
    }
}

将图标文件放到项目根目录的static文件夹下面,然后就可以在pages.json配置文件中引用了,引用的时候static前面不要加/,不然图片显示不出来,比如"iconPath":"static/images/logo.png"

tips:1,iconfont免费矢量图平台(www.iconfont.cn);2,tab页面展示过一次以后就会保存在内存中,再次切换tab时,只会触发页面的onShow函数,不会再触发onLoad函数,这个需注意

manifest.json配置文件

manifest.json文件主要用来指定项目的基础配置、图标配置、启动页面配置等。使用HBuilderX创建的项目,manifest.json文件是在项目的根目录下,使用cli创建的项目,manifest.json文件是在项目的src目录下

App模块配置

HBuilderX中集成了很多常用的原生控件,比如Maps地图控件、Payment支付控件。开发时,建议直接使用这些HBuilderX中自带的原生控件就可以了,相比于其他控件,原生控件操作速度会更流畅一些,可以提高用户APP的使用体验

App权限配置

系统会帮我们开启一些权限,其中包括使用网络权限、读写SD卡权限、读取设备标识使用、安装apk需要的权限等,权限的设置可以参考官方文档

package.json配置文件

uni-app项目中的package.json文件,是用来帮我们扩展项目配置的,这个文件不是所有项目都有,通过HBuilderX创建的项目一般是不创建package.json文件的,通过vue-cli命令行方式创建的项目默认是有这个文件的。可以在package.json文件中增加uni-app扩展节点,可以实现钉钉小程序、微信服务号等这样的平台自定义条件编译平台

vue.config.js配置文件

vue.config.js是一个可选的配置文件,一般用于配置webpack等编译选项,如果项目的根目录中存在这个文件,那么它会被自动加载,可以与manifest.json文件搭配使用。如果vue.config.js和manifest.json文件中的配置冲突了,系统会以manifest.json文件中的配置为准,覆盖掉vue.config.js中的配置。

vue.config.js配置文件支持动态参数设置,但是每次更新此配置文件的参数,要记得重新编译程序配置才生效

uni.scss配置文件

uni.scss配置文件在项目根目录下可以找到,这个文件放了一些uni-app内置的常用样式变量,主要是用来控制项目的全局样式的,比如页面底色、按钮颜色等

可以通过修改uni.scss配置文件中的变量来定制自己需要的插件主题,实现自定义主题功能

当页面用到其他样式文件时,需要先import后再使用。而uni.scss文件比较特殊,不需要import这个文件,uni.scss中的样式变量就可以在该项目中的所有文件中使用

uni-app混合开发(uniapp.dcloud.io/hybird

有些功能仅仅使用uni-app框架是实现不了的,比如自定义扫码页面、自定义地图等,虽然uni-app框架中自带了这些功能,但是自带的功能没法有效的自定义,这时就需要用到APP的原生控件来进行组合开发,这个开发形式就是uni-app混合开发。uni-app的混合开发主要是为了实现一些uni-app框架无法实现的功能,或者扩展接入一些第三方的SDK。首先要确定用uni-app还是原生APP代码为主体

主体采用uni-app

如果主体是uni-app,只是部分功能的实现使用原生开发,这样可以找一些原生项目的插件来配合开发。这样uniapp就是通过调用原生API来实现代码的。

主体采用原生app代码

可以直接跳转uni-app编译为H5页面

uni-app原生插件开发

naitvesupport.dcloud.net.cn/NativePlugi…

原生插件开发就是用原生语言进行插件开发,对于uni-app原生插件来说,原生语言包括android和ios代码。使用android和ios代码开发的插件,可以在uni-app框架中通过vue代码调用,这就是uni-app原生插件。

uni-app原生插件包含两种扩展模式:module模式、component模式。

module模式

大部分插件都是属于module扩展模式,是非可视控件,不提供用户界面,只提供相应的能力,比如调用计步器API,只是调用计步器的能力,而不需要调用计步器的界面。module扩展方式的插件,在uni-app的vue、nvue页面都可以使用

component模式

component模式是原生UI控件扩展的,属于可视化控件,会提供用户界面。比如,调用某个地图厂商的Map组件,将地图组件插在页面中间,就需要把这个原生地图SDK封装为component模式,调用的时候与调用vue组件是差不多的,在template标签中写组件标签就可以了

component模式的插件只可以在nvue页面通过标签的方式进行使用

调用uni-app原生插件

调用之前,要在原生插件项目中先注册一下插件,具体位置在原生插件APP项目的module根目录下,assets/dcloud_uniplugins.json文件中

调用module模式的插件

通过uni.requireNativePlugin("插件名称")来调用的

const pluin = uni.requireNativePlugin('myPlugin')
调用component模式的插件
<view>
    <myPlugin></myPlugin>
</view>

uni-app关于nvue开发

uni-app框架是基于vue的前端解决方案,大部分的开发需求在vue页面基本都可以实现,但是还有部分功能需要结合nvue页面才能实现,比如map组件在vue页面中层级是最高的,即不能在map组件上添加任何的标签,这时就需要用nvue页面来开发map,来添加需要的标签到map上。

nvue是native vue的缩写,是uni-app的一种渲染方式。在app端,如果是vue页面,使用的是小程序方式的webview渲染,如果是nvue页面,则使用weex方式的原生渲染。

使用weex方式的原生渲染,其实就是在weex的基础上封装了uni-app框架的api,提供了App端的原生渲染能力。nvue常用于在App端给一些使用vue页面表现不佳的场景作为强化补充

weex

weex也是比较流行的一个web开发框架,也可以提供跨平台开发方案,实现一份代码同时在移动端、web端同时运行的效果。但是weex有一个很大的问题就是它只是一个高性能的渲染器,没有足够的API能力。nvue就解决了weex的这个问题,weex支持的东西,在nvue里大多都是支持的,并且nvue提供了丰富的插件生态,可以让前端工程师直接开发完整的app

vue、nvue页面开发区别

一个项目中可以同时存在vue和nvue页面,比如项目首页使用的是nvue页面,而二级页面则使用vue页面。如果一个页面路由下出现同名的vue和nvue文件,APP端会使用nvue页面,非APP端会使用vue页面。

nvue页面的组件和javascript的写法与vue页面是一样的,但是css写法有一些区别,nvue页面的css均采用flex布局,不支持其他布局方式。

在HBuilderX中进行页面创建时,可以选择创建vue页面还是nvue页面。大概有以下几点开发区别

nvue的css写法受限

虽然nvue也可以多端编译,但是在nvue页面编写css没有在vue页面中方便

  1. border不支持简写,在nvue中需要拆开写

    /* 不支持的写法 */
    .class-name{
        border:1px solid black;
    }
    /* 支持的写法 */
    .class-name{
        border-width:1px;
        border-style:solid;
        border-color:black;
    }
    
  2. 选择器只能选择单类

  3. 引入样式文件

    在nvue页面下不能直接使用import引入样式文件,并且在App.vue文件中定义的全局样式不会在nvue页面生效,nvue页面的全局样式需要我们手动引入

    /* 错误写法 */
    @import "@/main.css"
    /* 正确写法 */
    <style src="@/main.css"></style>
    
  4. 在nvue中,不支持使用scss、less等预编译语言

  5. 在nvue中,不能在style标签中直接引入字体文件,需要用weex来加载字体

    const domMoudule = weex.requireModule("dom")
    domMoudule.addRule("fontFace",{
        "fontFamily":"iconfont",
        "src":"url('./font.ttf')"
    })
    
  6. nvue和vue相互通讯

    如果使用vue就能实现需求,尽量只使用vue来进行开发,因为nvue除了css写法受限之外,在vue和nvue页面混用的项目中,通讯也是一个大问题

    • nvue向vue传值

      在nvue中使用uni.postMessage(data)发送数据,参数data只能是json数据,json数据的值只支持字符串。在vue中使用onUniNViewMessage函数监听数据

      // 在nvue页面定义方法,使用uni.postMessage发送数据
      export default{
          methods:{
              postMessage(item){
                  uni.postMessage({
                      name:'123',
                      data:item
                  })
              }
          }
      }
      
      // 在vue页面接收数据,对nvue页面发送的数据进行监听
      export default{
          onUniNViewMessage:(e)=>{
              const data = e.data
          }
      }
      
    • vue向nvue传值

      1,使用storage缓存的方式进行参数传递,在nvue页面获得缓存中的数据

      // 在vue页面打开nvue页面,并且通过setStorageSync方法将数据保存在缓存中
      export default{
          methods:{
              postMessage(item){
                  uni.setStorageSync("storageData","123")
              }
          }
      }
      
      // 在nvue页面获得缓存中的数据
      export default{
          created(){
              uni.getStorage({
                  key:'storageData',
                  success:(res)=>{
                      console.log("传过来的数据是:",res.data)
                  }
              })
          }
      }
      

      2,使用globalData全局数据的方式进行参数传递

      // 在vue中定义全局数据
      export default{
          globalData:{
              name:'123'
          }
      }
      
      // 在nvue页面获取全局数据
      export default{
          onLoad(){
              console.log(getApp().globalData.name)
          }
      }
      

tips:在使用nvue页面进行开发时,有个常见错误Uncaught Error,这种错误一般是因为没有创建vue页面。uni-app项目中必须要有一个vue页面,新建一个vue页面,再重新编译项目就不会报错了。

uni-app性能优化

uni-app项目的视图层和逻辑层是分离开的,虽然在开发项目过程中,将html、js代码写在同一个文件中,但是实际运行的时候是分离开的。视图层负责页面渲染,用来展示数据的,包括页面结构代码部分、页面样式代码部分。逻辑层负责执行后端的业务逻辑,用户看不到这部分的逻辑,用来处理数据的,包括页面逻辑代码script部分以及其他js文件。

视图层和逻辑层分离,减少了项目的耦合程度,并且逻辑层的运算不会影响到视图层的渲染,窗体动画会比较稳。而两层分离也有一个缺点,就是这两层互相通信会有损耗。

下面的一些性能优化,都是基于uni-app运行原理来操作的

长列表优化

循环长列表,将长列表中的数据逐一展示在项目中,但是在开发过程中,一旦数据过多,就会出现项目加载变慢的问题,具体需要注意如下几个方面

长列表差量数据更新

如果长列表的数据中,每个列表都有可能差量更新,则需要将长列表中的每个item都做成一个组件。不然,其中每个item更新,都会造成整个长列表的重新加载,严重浪费系统资源。比如博文的100条评论,每条都有点赞功能,如果每条评论没有做成单独的组件,用户每次给其中一条评论点赞,系统都会重新加载这100条评论,如果每条评论都做成了单独的组件,用户给其中一条评论点赞,系统只会重新加载点赞的这一条评论。

长列表无差量数据更新

如果长列表中,每个item不会单独去更新,那就没必要将每个item都做成一个组件了,直接循环长列表显示item就可以了。

在开发过程中,不需要每次都将长列表的item包装成组件,每个item需要差量数据更新的时候,才需要包装成组件。组件在页面初始化时会占用更多的内存,并且遍历节点也会更慢,每个组件渲染时都会触发一次通信,太多组件就会阻塞通信,所以,不分情况到处使用组件反而会适得其反。深层节点的嵌套也是同样的道理,开发的过程中要注意尽量避免深层节点嵌套。

在实际项目开发中,如果数据需要展示在页面上,就定义在data中,如果不需要展示在试图中,尽量将变量定于data外部。因为data中的数据每次发生变化,视图层都要重新渲染页面,这样做可以尽量避免浪费资源。

减少一次性加载的节点数量

页面初始化时,逻辑层如果一次性向视图层传递很多数据,不仅会造成逻辑层和视图层之间的通讯变化,由于视图层一次渲染的数据过多,还会造成页面的卡顿。所以,如果数据过多,建议进行分页加载,比如:服务端要返回1000条数据,可以一次加载100条,500ms后再进行下一次加载

尽量避免两层频繁通信

视图层和逻辑层分离造成的一个缺点,就是两层之间通讯的损耗,如果两层之间频繁通信,可能会造成通讯阻塞,影响项目的正常运行,主要有以下几点,尽量避免两层之间的频繁通信:

  1. scroll-view组件的使用

    • 使用scroll-view组件时,要尽量减少监听滚动事件,因为在监听scroll-view的滚动事件时,视图层会频繁的向逻辑层发送数据
    • 不要实时的改变scroll-top、scroll-left属性,可能会造成通讯卡顿
    • 如果要实现下拉刷新的功能,建议使用页面的滚动,而不是scroll-view
    • 不要在scroll-view组件中放长列表,会导致性能问题
  2. 图片、动画加载问题

    • 尽量使用压缩图片
    • 尽量使用css动画,而不是js定时器操作界面做动画
    • 如果项目中不可避免的需要加载大量的动画和图片,建议加载时进行延时处理,分批进行大量数据通讯,提高页面的流畅性。否则会造成页面切换卡顿、掉帧等问题
    • App-nvue和H5项目,还支持页面预加载,使用API uni.preloadPage,开发时可以使用提高用户的操作体验
  3. 使用nvue代替vue

    因为nvue页面开发限制比较多,一般不建议使用nvue来开发项目。但是,如果更加看重项目性能问题,可以使用nvue代替vue。因为nvue是基于weex的原生渲染,可以有效提高页面的流畅程度。如果对项目启动速度有更高要求,甚至可以将项目设置为纯nvue项目,这样整个应用都使用原生渲染,不加载webview框架,这样项目的启动速度会更快

登录流程

微信开放文档 > 小程序 > 开放能力

小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。

  1. wx.login()获取临时登录凭证code;

    • 通过凭证进而换取用户登录态信息,包括用户在当前小程序的唯一标识(openid)、微信开放平台账号下的唯一标识(unionid,若当前小程序已绑定到微信开放平台)及本次登录的会话密钥(sesson_key)等。用户数据的加解密通讯需要依赖会话密钥完成

    • 参数

      • timeout,超时时间,单位ms
      • success,接口调用成功的回调函数;接收wx.login返回的用户登录凭证code,有效期五分钟,开发者需要在开发者服务器后台调用auth.code2Session,使用code换取openid、unionid、session_key等信息
      • fail,接口调用失败的回调函数
      • complete,无论成功失败都会执行
  2. wx.request()发送临时登录凭证code回传到开发者服务器

  3. auth.code2Session登录凭证校验,通过wx.login接口获得临时登录凭证code后传到开发者服务器调用此接口完成登录流程

    • 参数

      • appid,必填,小程序appid
      • secret,必填,小程序appSecret
      • js_code,必填,登录时获取的code
      • grant_type,必填,授权类型,只需填authorization_code即可
    • 返回值

      • openid,用户唯一标识

      • session_key,会话密钥

      • unionid,用户在开发平台的唯一标识符,若当前小程序已绑定到微信开放平台账号下会返回。

        如果开发者拥有多个移动应用、网站应用、公众账号(包括小程序),可通过unionID来区分用户的唯一性,因为只要是同一个微信开放平台账号下的移动应用、网站应用和公众账号,用户的unioinID是唯一的,即用一用户,对同一个微信开放平台下的不同应用,unionID是相同的。一般通过wx.login+code2Session获取到该用户unionID,无需用户授权

  4. 开发者服务器