一、什么是 uni-app?

uni-app 这个框架是基于Vue.js开发的,通过uni-app可以开发出跨平台的产品,所以如果对vue有一定的了解,那么这套框架可以很快速的掌握,当然,如果你对微信小程序也了解的话,也能够迅速掌握的,因为Uni-App封装并且兼容了微信小程序的组件和api。开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉/淘宝)、快应用等多个平台。

浅析uniapp-LMLPHP

二、为什么要选择uni-app?

对比其他移动端跨平台框架(如Cordova/ReactNative/NativeJS),UniApp在跨端抹平度、扩展灵活性、性能体验、周边生态、开发成本等几个方面上拥有明显的优势。

(1)跨端数量多:一套代码,编译后可发布到iOS、Android、H5、小程序等多个平台,且跨端抹平度高,应用的显示效果接近一致,真正能落实到生产力。这一点是uniapp的最大优势,完胜其他跨平台框架。

(2)性能体验优秀:uniapp是体验更好的Hybrid框架,加载新页面速度更快。且App端支持weex原生渲染,可实现更流畅的动画效果。相比较而言,依赖于WebView的Cordova框架性能方面就有所欠缺了。

(3)生态开放丰富:uniapp的插件市场,集成了近千余第三方插件,各种轮子拿来即用;同时,由于uniapp的接口API采用了小程序规范,微信生态的各种SDK可直接用于跨平台App。在这个方面作对比,React Native框架的社区活跃度和资料文档都较为有限。

(4)开发成本低:以前由N个平台开发人员(IOS/安卓/H5)完成的开发任务,现在采用前端通用技术栈实现,研发、维护、测试各环节的成本都大幅下降。

同时,HBuilderX工具搭配uniapp可以免终端调试,可视化创建项目、可视化安装组件和扩展编译器,研发人员的开发体验也变得更好,从而能够更高效地编写代码。

三、uniapp发展史

uni是统一的意思。

很多人以为小程序是微信先推出的,其实,DCloud才是这个行业的开创者。

DCloud于2012年开始研发小程序技术,优化webview的功能和性能,并加入W3C和HTML5中国产业联盟,推出了HBuilder开发工具,为后续产业化做准备。

2015年,DCloud正式商用了自己的小程序,产品名为“流应用”,它不是B/S模式的轻应用,而是能接近原生功能、性能的动态App,并且即点即用。

为将该技术发扬光大,DCloud将技术标准捐献给工信部旗下的HTML5中国产业联盟,并推进各家流量巨头接入该标准,开展小程序业务。

随后DCloud推动大众点评、携程、京东、有道词典、唯品会等众多开发者为流应用平台提供应用。

在2015年9月,DCloud推进微信团队开展小程序业务,演示了流应用的秒开应用、扫码获取应用、分享链接获取应用等众多场景案例,以及分享了webview体验优化的经验。

微信团队经过分析,于2016年初决定上线小程序业务,但其没有接入联盟标准,而是订制了自己的标准。

DCloud持续在业内普及小程序理念,推进各大流量巨头,包括手机厂商,陆续上线类似小程序/快应用等业务。

部分公司接入了联盟标准,但更多公司因利益纷争严重,标准难以统一。

技术是纯粹的,不应该因为商业利益而分裂。开发者面对如此多的私有标准不是一件正确的事情。

造成混乱的局面非DCloud所愿。于是就决定开发一个免费开源的框架。

既然各巨头无法在标准上达成一致,官方希望通过这个框架为开发者抹平各平台差异。这就是uni-app的由来。

四、功能框架

下面是uni-app功能框架图,图中直观的表现了uniapp出色的跨平台能力和各平台特色。不多说,直接上图:

浅析uniapp-LMLPHP

从上面uni-app功能框架图可看出,uni-app在跨平台的过程中,不牺牲平台特色,可优雅的调用平台专有能力。用官方的话说就是:海纳百川、各取所长。

概念导入:

  • (1)什么是H5+?

HTML5plus Runtime,简称5+ Runtime,是运行于手机端的强化web引擎,除了支持标准HTML5外,还支持更多扩展的js api,使得js的能力不输于原生。5+ Runtime内置于HBuilder,在真机运行、打包时自动挂载。

业内之前有phonegap/Cordova方案,但是他们自带js api太少了,扩展api需要用原生语言开发,更致命的是这类方案的性能不足。
封装成跨平台的HTML5plus规范,并将规范公开于www.HTML5plus.org,不做厂商私有API。包括二维码、摇一摇、语音输入、地图、支付、分享、文件系统、通讯录等常用API,可以方便简单的编写,并且可跨平台。

注意:uni-app不需要 plus ready

在html中使用plus的api,需要等待plus ready。 而uni-app不需要等,可以直接使用。而且如果你调用plus ready,反而不会触发。

小程序及 H5 等平台是没有 HTML5+ 扩展规范的,因此在 uni-app 调用 HTML5+ 的扩展规范时,需要注意使用条件编译。否则运行到h5、小程序等平台会出现 plus is not defined错误。

  • (2)什么是条件编译?

条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。

写法:以 #ifdef 或 #ifndef 加 %PLATFORM% 开头,以 #endif 结尾。

  • · #ifdef:if defined 仅在某平台存在
  • · #ifndef:if not defined 除了某平台均存在
  • · %PLATFORM%:平台名称

%PLATFORM% 可取值如下:

注意:

  • · 条件编译是利用注释实现的,在不同语法里注释写法不一样,js使用 // 注释、css 使用 /* 注释 */、vue/nvue 模板里使用 <!-- 注释 -->;
  • · 条件编译APP-PLUS包含APP-NVUE和APP-VUE,APP-PLUS-NVUE和APP-NVUE没什么区别,为了简写后面出了APP-NVUE ;

API 的条件编译

// #ifdef  %PLATFORM%

平台特有的API实现


// #endif

  • (3)什么是nvue?

uni-app App端内置了一个基于 weex 改进的原生渲染引擎,提供了原生渲染能力。

在App端,如果使用vue页面,则使用webview渲染;如果使用nvue页面(native vue的缩写),则使用原生渲染。一个App中可以同时使用两种页面,比如首页使用nvue,二级页使用vue页面。

注意:虽然nvue也可以多端编译,输出H5和小程序,但nvue的css写法受限,所以如果你不开发App,那么不需要使用nvue。

  • (4)Uniapp编译模式是怎样的?

最初uni-app仅支持模板编译模式和自定义组件模式,在后来的升级中逐渐用V3编译模式取代,v3是针对App的改进,尤其是vue页面的改进。与其他平台无关。目前V3已成为默认的编译模式。此外uni-app还支持对nvue编译模式的选择,分为weex编译模式和uni-app编译模式,这里不做详细解读,有兴趣的同学可以自行学习。

五. 如何使用uni-app?

(1) 下载开发工具:HBuilderX

打开dcloud官网 http://www.dcloud.io/hbuilderx.html 推荐直接下载App开发版本,可以免去后续配置及安装插件等的烦恼

(2) 安装并打开HBuilderX

之后,在点击工具栏里的文件 -> 新建 -> 项目

浅析uniapp-LMLPHP

  • (3) 选择uni-app,输入工程名,如:uni-test,点击创建,成功创建 UniApp应用。点击模板里的 Hello uni-app 即可体验官方示例。
  • (4) 随着官方的不断迭代升级,现已支持创建多套模板,可以便捷的搭建项目框架,已内置大量常用组件,免去了搭建项目的大部分前期工作,这点非常方便。如下是 uni ui项目模板的常见例子,供大家参考。

浅析uniapp-LMLPHP

(4)创建DCloud appid(以后简称 appid)。appid是 DCloud 应用的唯一标识,在 DCloud 提供的所有服务中,都会以 appid 来标记一个应用。注意这和各家小程序的appid以及Apple的appid(其实就是iOS的包名)是两套体系。

  • l 登录开发者中心,申请创建 uniapp、5+app 等类型应用的 appid;
  • l 在 HBuilderX登录的情况下, 创建项目时,HBuilderX 也会自动联网生成 appid, 并将该 appid 保存在 manifest 文件中的 appid 字段;

(5)工程目录结构

浅析uniapp-LMLPHP 

(6)进入项目,点击工具栏的运行 -> 运行到浏览器/真机下运行/模拟器运行,也可以选择小程序在微信开发者工具里运行,如下是项目运行的示例。

浏览器运行:进入hello-uniapp项目,点击工具栏的运行 -> 运行到浏览器 -> 选择浏览器,即可在浏览器里面体验uni-app 的 H5 版。

浅析uniapp-LMLPHP

真机运行:连接手机,开启USB调试,进入hello-uniapp项目,点击工具栏的运行 -> 真机运行 -> 选择运行的设备,即可在该设备里面体验uni-app。

如手机无法识别,请点击菜单运行-运行到手机或模拟器-真机运行常见故障排查指南。 注意开发App也需要安装微信开发者工具。

(7)发布uni-app

Unapp有两种发布形式:打包为原生App(云端)打包为原生App(离线)。由于离线打包需要一定原生基础,且sdk不能随官方升级,实时更新,一般采用app-云端打包的形式。

在HBuilderX工具栏,点击发行,选择原生app-云端打包,如下图:

浅析uniapp-LMLPHP

出现如下界面,点击打包即可。

浅析uniapp-LMLPHP

打包为原生App(离线)

uni-app 支持离线打包,在 HBuilderX 发行菜单里生成离线打包资源,然后参考离线打包文档操作,可以从HBuilderX的发行菜单里找到文档链接,也可以直接访问:https://nativesupport.dcloud.net.cn/AppDocs/README

在HBuilderX工具栏,点击发行,选择本地打包,如下图,点击即可生成离线打包资源。

浅析uniapp-LMLPHP

发布为H5

  • 1. 在 manifest.json 的可视化界面,进行如下配置(发行在网站根目录可不配置应用基本路径),此时发行网站路径是 www.xxx.com/h5,如:https://hellouniapp.dcloud.net.cn

浅析uniapp-LMLPHP

  • 2. 在HBuilderX工具栏,点击发行,选择网站-H5手机版,如下图,点击即可生成 H5 的相关资源文件,保存于 unpackage 目录。

浅析uniapp-LMLPHP

注意

  • l history 模式发行需要后台配置支持。
  • l 打包部署后,在服务器上开启 gzip 可以进一步压缩文件。

发布为小程序

发布为微信小程序:

  • 1. 申请微信小程序AppID,参考:微信教程
  • 2. 在HBuilderX中顶部菜单依次点击 "发行" => "小程序-微信",输入小程序名称和appid点击发行即可在 unpackage/dist/build/mp-weixin 生成微信小程序项目代码。

浅析uniapp-LMLPHP

  • 3. 在微信小程序开发者工具中,导入生成的微信小程序项目,测试项目代码运行正常后,点击“上传”按钮,之后按照 “提交审核” => “发布” 小程序标准流程,逐步操作即可,详细查看:微信官方教程

六、开发规范

(1)页面文件 遵循Vue单页面组件规范,Vue中的结构依然采用三大顶级代码块:vue-loader规范

(2)组件标签 VUE通用模板写法,编译后以IOS或Android原生UI控件渲染

(所以不能使用标准的HTML标签,JS对DOM操作也得尽量避免),示例:

浅析uniapp-LMLPHP

  • (3)接口能力: 基本遵循微信小程序规范,对于大部分接口地址前缀由wx修改为uni即可实现,也包括了uni特有的一些api,具体参考:https://uniapp.dcloud.io/api/README

随着severless的发展,uniapp还提供了基于unicloud的云函数、云数据库、云存储和CDN方案,uniCloud 是 DCloud 联合阿里云、腾讯云,为开发者提供的基于 serverless 模式和 js 编程的云开发平台。

此外,uniapp还提供了了很多

  • (4)样式控制:

uni-app 支持通用 css 单位包括 px;另外,针对屏幕宽度自适应的普遍需求,推出了响应式px的概念,最初,uniapp以upx为尺寸单位,在框架的升级过程中,借鉴了微信小程序rpx的设计理念,转为rpx。

rpx 是相对于基准宽度的单位,可以根据屏幕宽度进行自适应。uni-app 规定屏幕基准宽度 750rpx。

开发者可以通过设计稿基准宽度计算页面元素 rpx 值,设计稿 1px 与框架样式 1rpx 转换公式如下:

设计稿 1px / 设计稿基准宽度 = 框架样式 1rpx / 750rpx

换言之,页面元素宽度在 uni-app 中的宽度计算公式:

750 * 元素在设计稿中的宽度 / 设计稿基准宽度

(5)uniapp开发与传统前端开发的异同点:

传统的h5只有1端,即浏览器。而uni-app可跨多端,虽仍属前端,与传统h5有不同。

网络模型的变化

以前网页大多是b/s,服务端代码混合在页面里;

现在是c/s,前后端分离,通过js api(类似ajax的uni.request)获取json数据,把数据绑定在界面上渲染。

文件类型变化

以前是.html文件,开发也是html,运行也是html。
现在是.vue文件,开发是vue,经过编译后,运行时已经变成了js文件。
现代前端开发,很少直接使用HTML,基本都是开发、编译、运行。所以uni-app有编译器、运行时的概念。

文件内代码架构的变化

以前一个html大节点,里面有script和style节点;

现在template是一级节点,用于写tag组件,script和style是并列的一级节点,也就是有3个一级节点。

外部文件引用方式变化

以前通过script src、link href引入外部的js和css;

现在是es6的写法,import引入外部的js模块(注意不是文件)或css

示例

var dateUtils = require('../../../common/util.js').dateUtils; //直接使用js模块的属性。在hello uni-app有示例  


import * as echarts from '/components/echarts/echarts.simple.min.js'; //将js导入并重命名为echarts,然后使用echarts.来继续执行方法。在hello uni-app有示例

css外部文件导入

<style>  

    @import "./common/uni.css";  

    .uni-hello-text{  

        color:#7A7E83;  

    }  


</style>

全局样式,在根目录下的app.vue里写入,每个页面都会加载app.vue里的样式。

另外,vue支持组件导入,可以更方便的封装一个包括界面、js、样式的库。

如下是导入一个角标的组件库,在页面上显示一个abc并且右上角有个数字角标1,

<template>  

    <view>  

        <uni-badge text="abc" :inverted="true"></uni-badge><!--3.使用组件-->  

</view>  

</template>  

<script>  

    import uniBadge from "../../../components/uni-badge.vue";//1.导入组件(这步属于传统vue规范,但在uni-app的easycom下可以省略这步)  

    export default {  

        data() {  

            return {  

            }  

        },  

        components: {  

            uniBadge //2.注册组件(这步属于传统vue规范,但在uni-app的easycom下可以省略这步)  

        }  

}  

</script>

如需要全局导入vue组件,即每个页面都可以直接使用而不用引用和注册的话,在项目根目录下的main.js里处理。

组件/标签的变化

以前是html标签,比如<div>,现在是小程序组件,比如<view>。
那么标签和组件有什么区别,不都是用尖括号包围起来一段英文吗?
其实标签是老的概念,标签属于浏览器内置的东西。但组件,是可以自由扩展的。
类似你可以把一段js封装成函数或模块,你也可以把一个ui控件封装成一个组件。

uni-app参考小程序规范,提供了一批内置组件。

下为html标签和uni-app内置组件的映射表:

除了改动外,新增了一批手机端常用的新组件

cover-view需要多强调几句,uni-app的非h5端的video、map、canvas、textarea是原生组件,层级高于其他组件。如需覆盖原生组件,则需要使用cover-view组件。详见层级介绍

除了内置组件,还有很多开源的扩展组件,把常用操作都进行封装,DCloud建立了插件市场收录这些扩展组件,详见插件市场

js的变化

js的变化,分为运行环境变化、数据绑定模式变化、api变化3部分。

运行环境从浏览器变成v8引擎

标准js语法和api都支持,比如if、for、settimeout、indexOf等。

但浏览器专用的window、document、navigator、location对象,包括cookie等存储,只有在浏览器中才有,app和小程序都不支持。

js是ECMAScript组织管理的,浏览器中的js是w3c组织基于js规范补充了window、document、navigator、location等专用对象。

在uni-app的各个端中,除了h5端,其他端的js都运行在一个独立的v8引擎下,不是在浏览器中,所以浏览器的对象无法使用。如果你做过小程序开发,对此应当很了解。

这意味着依赖document的很多HTML的库,比如jqurey无法使用。

当然app和小程序支持web-view组件,里面可以加载标准HTML,这种页面仍然支持浏览器专用对象window、document、navigator、location。

uni-app使用vue的数据绑定方式解决js和dom界面交互的问题。

在普通vue页面里的生命周期叫页面生命周期。在项目根目录的app.vue文件中的生命周期叫应用生命周期。
除了onload,还有onready等很多生命周期,具体见uni-app的生命周期

js api的变化

  • § 因为uni-app的api是参考小程序的,所以和浏览器的js api有很多不同,如
  • § alert,confirm 改成 uni.showmodel
  • § ajax 改成 uni.request
  • § cookie、session 没有了,local.storage 改成 uni.storage
  • § uni-app的js api还有很多,但基本就是小程序的api,把wx.xxx改为uni.xxx即可。

css的变化

  • § 标准的css基本都是支持的。
  • § 选择器有2个变化:*选择器不支持;元素选择器里没有body,改为了page。微信小程序即是如此。

page{  

}

注意css里背景图和字体文件,尽量不要大于40k,因为会影响性能。在小程序端,如果要大于40k,需放到服务器侧远程引用或base64后引入,不能放到本地作为独立文件引用。

工程结构和页面管理

uni-app的工程结构有单独的要求,上面例子中有讲到过:

浅析uniapp-LMLPHP

每个可显示的页面,都必须在 pages.json 中注册。如果你开发过小程序,那么pages.json类似app.json。如果你熟悉vue,这里没有vue的路由,都是在pages.json里管理。

原来工程的首页一般是index.html或default.html,是在web server里配的。而uni-app的首页,是在pages.json里配的,page节点下第一个页面就是首页。一般在/pages/xx的目录下。

app和小程序中,为了提升体验,页面提供了原生的导航栏和底部tabbar,注意这些配置是在pages.json中做,而不是在vue页面里创建。如果你熟悉小程序开发的话,对比变化如下:

  • § 原来app.json被一拆为二。页面管理,被挪入了uni-app的pages.json;非页面管理,挪入了manifest.json
  • § 原来的app.js和app.wxss被合并到了app.vue中

七、uni-app基本原理

技术的发展日新月异,各项新技术、新概念层出不穷。随着“微前端”理念发展,特别是微信小程序技术的“后发先至”,加速了uni-app的推出进程。结合实际项目中的使用分析来看,uniapp的实现更应该是文件预处理、编译技术和架构理念的更新,随着微信小程序的广为人知,及各家小程序的相互“借鉴”,uniapp迎合了这一趋势,为更好的发挥“流应用”框架的跨平台的能力,因此采用了近似小程序的项目架构。

实际上,不管是就跨平台、适配、还是条件编译等等,类比webpack预编译的实现方式和vue框架在vue-loader上的处理方式,我们不难理解uniapp在各平台先编译后运行的基本原理,其最终目的都是通过后期的编译,来实现各端在规范和格式上的统一。

  • 八、扩展能力和开发生态

uniapp支持混和开发和uni小程序开发。uni-app 积极拥抱社区,创建了开放、兼容的生态系统。

总结

uni-app从诞生至今,经过了uni官方和广大开发者长时间的打磨过程,“野蛮生长”的洪荒时代业已成为过去,如今,使用uni-app   在UI表现力、性能体验、生态成熟度几个维度都能经得起推敲。发展到现在,即便框架本身有着低成本的特性,uni-app仍然是一套相对完整的体系,还有很多方面很难一言蔽之。

综合来讲,uni-app在开发者数量、案例、灵活性、生态、开发成本等关键指标上有一定优势,能够满足大部分的基础需求,就学习成本而言,较容易上手,也为前端开发者提供了更多的可能,值得推荐。当然,任何框架都首先要服务于实际业务需求,技术的选型也需根据研发团队成员的技术方向和具体情况而定,对于项目建设而言技术框架没有最好的只有最适合的。

以上仅是我自己的一孔之见,这里抛砖引玉,欢迎大家积极交流意见和建议,共同学习和进步,谢谢大家!

06-29 23:19