uni-app跨平台开发

一、简介

Uni-app是一个跨平台的应用程序框架,运用 Vue.js 开发的。通过它,我们可以将同一份代码发布并运行在多个平台上,包括 Android、iOS、Web、微信小程序、支付宝小程序、百度小程序、头条小程序、QQ 小程序和快应用等多个平台。Uni-app 框架使用 Vue.js 的语法和指令,同时也提供了许多平台原生 UI 控件和 API 的访问,方便开发跨平台应用程序。

在这篇文章里,我将分享我的 uni-app 学习心得,包括编程思路、技巧运用、软件工程类学习体会、项目分析或总结。

二、编程思路

  1. 了解各平台的特点

Uni-app 运行在多个平台上,每个平台的特点是不同的。因此,我们需要了解每种平台的特点,并针对性地进行开发。比如,微信小程序和支付宝小程序的 UI 设计和交互方式略有不同,因此在编写应用程序时,需要适应其特点,调整设计和交互。

  1. 注意兼容性问题

Uni-app 框架提供了许多平台原生的 UI 控件和 API 的访问,但是这些控件和 API 在不同平台之间的支持和表现情况会有所不同,因此我们需要注意在编写代码时尽量避免使用不同平台独有的 API 或特性,同时要特别关注不同平台之间的差异,以便在不同平台上运行时代码能够正确地工作。

  1. 组件模块化

在开发应用程序时,尤其是大型应用程序,我们需要将所使用的 UI 组件拆分成独立的模块,并对每个模块进行封装,以便在多个组件之间方便地进行调用和修改。有利于提高代码的重用性和可维护性。

三、技巧运用

  1. 使用内置组件

Uni-app 框架提供了许多内置组件,这些组件在不同平台之间具有良好的兼容性,并且具有一致的外观和行为。因此,在编写应用程序时,尽可能使用内置组件可以帮助我们简化代码并降低代码的维护难度。

  1. 条件渲染和循环渲染

条件渲染和循环渲染是 Uni-app 框架提供的两种常用的渲染方式。使用条件渲染可以根据不同的条件显示不同的组件或内容,而使用循环渲染可以从数据源中动态地渲染复杂的 UI 界面。这两种渲染方式对于构建复杂的 UI 界面非常有用。

  1. 使用 vuex 进行状态管理

vuex 是 Uni-app 提供的状态管理工具,它可以帮助我们集中管理应用程序的状态。使用 vuex 可以使我们对应用状态进行集中的管理,从而提高代码的可维护性和重用性。

  1. Flexbox 布局和 Grid 栅格布局

Flexbox 布局和 Grid 栅格布局是现代 Web 开发中常用的布局方式,它们使得页面设计更加方便和灵活。在 Uni-app 应用程序开发中,这两种布局方式同样也非常有用。

四、软件工程类学习体会

  1. 项目架构设计

在进行跨平台应用程序开发时,应该采用模块化开发的方式,将整个应用程序分为若干个独立的模块来开发,每个模块有独立的职责。同时,要根据不同的平台特点进行合理的组织和设计,从而提高应用程序性能和可维护性。

  1. 版本控制

应用程序开发过程中,要保持版本控制的意识,及时对代码进行提交和备份。同时使用 Git 作为版本控制工具,保证不同开发者之间的协同开发能更加方便高效。

  1. 故障排查和测试

应用程序开发过程中,要时刻关注程序的稳定性和安全性,要进行功能测试、白盒测试、代码静态分析和性能测试等多个方面的测试。一旦出现问题,要及时跟进并进行故障排查,从而保证应用程序的稳定性和可靠性。

五、项目总结

在我使用 Uni-app 进行开发的过程中,我对代码的组织和模块化设计、UI 页面的构建等方面进行了深入的学习和理解。我也更加认识到了跨平台开发的好处和挑战,能够更加灵活地进行 App 开发,并且可以将一个应用程序发布到多个平台上。但是在开发过程中,我也遇到了各种各样的问题,例如兼容性问题、布局问题等等,但是这些问题都得到了及时解决,从而最终成功地完成了应用程序的开发。

参考图例:

六、学习收获

  1. 学习了跨平台应用程序开发的思路和方法,了解了不同平台的特点以及开发规范。

  2. 理解和掌握了 Vue.js 的语法和指令,同时也学习了一些 Vuex、Flexbox 布局和 Grid 栅格布局等工具。

  3. 提高了对软件工程开发的理解,明确了项目架构设计、版本控制、故障排查和测试等方面的重要性和必要性。

六、UI-APP相关的学习资料

1.优购商城的接口文档

https://www.showdoc.com.cn/128719739414963/2516997897914014

2.帮助文档

uni-app官网:https://dcloud.io/

阿里巴巴字体图标官网:https://www.iconfont.cn/

菜鸟教程:https://www.runoob.com/

阮一峰的flex教程:https://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

Vue官网:https://cn.vuejs.org/v2/guide/

微信小程序官网:https://developers.weixin.qq.com/miniprogram/dev/framework/

最后,总体来说,Uni-app 的跨平台开发提供了许多可能性和便利性,但也需要在搭建过程中注意兼容性问题,同时进行版本控制和测试,从而确保应用程序能够稳定地运行。

历史Uniapp从诞生到目前,经历了3次重大变革,首先是最初借鉴了Mpvue的模板语法(非自定义组件模式)这个模式是性能最差且支持Vue语法有很多欠缺的版本,在当时我认为Uniapp开发APP是满足不了企业需要的,倒是做一款小程序开发框架很是不错。

在2018-2019这个时间段,也就是uniapp是模板编译模式的时代,网上对于uniapp也是褒贬不一,社区的完善度还有官方的UI支持都是非常落后的,唯一吹一吹的就是QQ群当时很火,官方的解答和处理BUG的速度还很快。我个人认为web前端跨平台框架受到了很多原生安卓&IOS开发者的排挤,拿生成的代码质量和性能说事,说不定自己也没有使用过。

在我接触uniapp不久之后(大概几个月)就出了自定义组件模式,这个组件模式相当于革命性的更新,支持用户编写的Vue组件转换成微信小程序的自定义组件,基于这个uniapp在安卓平台上放置了JS Core,从这个时候开始uniapp开始慢慢的被更多的原生开发者接受,因为跨平台开发的好处是在是太大了。

那么接下来的一次更新让我瞠目结舌,因为由于19年的年底这一段时间我没有从事uniapp开发,直到今年才继续开发uniapp,发现了uniapp的一次重大更新:“v3引擎”。

V3引擎同样也是Dcloud自研,我认为主要的更新在于安卓和IOS端,开始注重了启动速度和包体积大小,我们可以在V3更新说明中看到。

到此为止,我认为uniapp到此刻应该是推广的时候,让前端开发人员坐上跨平台开发的小车车。

踩坑经验(框架部分)

首先,uniapp绝大部分官网描述的API,比如设备信息,内存,蓝牙等等都是原生开发比较常用的,uniapp的优点就体现出来了,不同平台的各种API都会略微有差异,那么我们应该仔细看文档。

如果文档已经说明此API存在【平台差异】,那么我们应该注意API下方可能会有这样的【tips】

这也是文档的一个小坑,很多新手如果不仔细看文档,在调API的时候不考虑兼容问题,导致在小程序/APP中,比如出现安卓和ios功能不一致的问题,如果看仔细文档,那么百分之99以上的问题都会在tips中说明。

注释魔法:条件编译

其次uniapp还有一个非常强大的功能【条件编译】,这也是开发中非常常用的功能,如下,我们可以使用像C语言中核心注释,注释中的代码片段将在指定的平台出现,反之亦然;


代码片段,APP-PLUS代表着APP端,ifdef包含,ifndef不包含,多个平台可以用空格隔开  



编译多个平台

条件编译可以存在于任何地方,template css js;同样uniapp支持更强大的条件编译:比如支持在page.json中进行判断,达到不同端不同的分包功能;静态资源也可以进行条件编译,通过static下构建platform目录即可把不同的静态资源编译到不同的平台上去;那么同理也可以把页面进行条件编译,即不同平台不同页面;

onLoad&onShow

我们已经了解了uniapp极具特色的条件编译之后,我们可以了解一下uniapp必不可少的生命周期,uniapp在目前版本支持vue的所有生命周期以及绝大多数API;比较重要的nextTickcompile不支持,组件选项中比较重要的是render函数不支持,具体更多的支持特性表请移步官网查看(https://uniapp.dcloud.io/use?id=vue%e7%89%b9%e6%80%a7%e6%94%af%e6%8c%81%e8%a1%a8),下面我们将推荐开发中常用的生命周期以及应用场景:

onLoad(e){
  // 组件渲染未完成但是已创建的钩子,与Vue的create同理,这里推荐使用onLoad代替create
  // 行参e可以获取当前路径的参数,比如当前页面是b,如果a跳转到b页面是如下url:
  // /pages/index/a?type=1
}
onShow(){
  // 用于监听:页面在屏幕上显示时触发,从APP应用后台到APP前台也会触发
  // 通常我们可以使用这个钩子做一些非列表页面的数据刷新(比如从上一个页面返回,然后此页面刷新)
}

触底加载&下拉加载的实践

APP中有一个非常常见的场景叫做触底加载,那么针对APP页面级别的滚动触底回调就是onReachBottom

onReachBottom(){
  // 在这里进行当前页加1
  this.listConfig.nowPage ++;
  // 调用加载列表的方法
  this.initList();
}
methods: {
  async initList(){
    const toList = await getALLTodoList({
      limit: this.listConfig.pageSize,
      offset: (this.listConfig.nowPage - 1) * this.listConfig.pageSize),
    })
  }
}

那么下拉加载这个功能在APP中非常常见,我们需要在page.json中对应的节点style下开启下拉加载

"enablePullDownRefresh": true

那么对应页面的监听钩子将会触发

onPullDownRefresh(){
  // 用户下拉了页面
}

【注意事项】不管是触底加载和下拉刷新此实例都是针对页面级别,如果你不知道何为页面级,那么请耐心看完uniapp的组件相关内容,在uniapp组件中有一个,它提供一个滚动视图,在这个滚动视图中有着自己的下拉加载和触底加载方法,因此如果页面中存在此组件,开发者应该妥善处理组件级别的滚动和页面级别的滚动,这是非常重要的。

在开发中,我们经常会出现一些列表的场景,那么在uniapp中处理长列表,我们不应该使用scroll-view组件级别的滚动,而应该使用页面级别的滚动,这样性能会更好

如何操作DOM?

我们通常在开发Vue应用时,很少直接操作DOM,在uniapp中没有暴漏DOM这个概念,但是我们可以通过指定的API去操作DOM,尽管这是非常不建议的,但是在某些业务场景不得不说

它是很方便的;

let tabInfo = uni.createSelectorQuery().select("#tab");
tabInfo.boundingClientRect((data) => {
  // 目标区域的信息
}).exec();

文件的选择

uniapp在文件的选择上非常丰富,举一个例子比如说图片,我们可以在文档中很清楚的查询到对应的API,通过封装的API我们可以通过配置参数来chooseImage,然后拿到临时路径再继续上传;

uni.chooseImage({
    count: 6, //默认9
    sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
    sourceType: ['album'], //从相册选择
    success: function (res) {
       // 临时路径 res.tempFilePaths
       uni.uploadFile({
            url: '', //仅为示例,非真实的接口地址
            filePath: tempFilePaths[0],
            name: 'file',
            formData: {
                'user': 'test'
            },
            success: (uploadFileRes) => {
                console.log(uploadFileRes.data);
            }
        });
    }
});

重点来了,我们上传图片固然简单,但是上传文件是非常难的,我们如果在APP端想做一个上传文件的功能,就要尽量使用html的帮助,由html的input type=“file”来做上传,那么首先得简单了解一下利用html如何上传文件。

1. 首先我们需要使用h5+API中的webview相关的API

let wv = plus.webview.create("", "/hybrid/html/index.html", {
  'uni-app': 'none', //不加载uni-app渲染层框架,避免样式冲突
  top: 0,
  height: '100%',
  background: 'transparent'
  }, {
    url,
    header,
    key: name,
    ...formData,
  });
wv.loadURL("/hybrid/html/index.html"); // 加载本地的html文件
currentWebview.append(wv); // 把html追加到当前页面中

把本地的HTML加载到APP之上之后,我们在本地编写的HTML文件中引入对应uni.webview文件以及需要的业务JS文件,我们在HTML是这样做的(核心代码)


我们在本地编写的业务JS

xhr.onreadystatechange = (ev) => {
    if(xhr.readyState == 4) {
      if (xhr.status == 200) {
        progress.innerText = '成功'; 
        //  从这里可以看出,上传成功之后,我们通过改变html的title把信息返回
        title.innerText = `${file.name}|^$%^|${src}|^$%^|${suffix}`;
      }
      else {
        progress.innerText = '上传失败了';
      }
      setTimeout(()=>{
        tis.style.display = 'none';
        // 上传成功,关闭了上传webview的窗口
        plus.webview.currentWebview().close();
      },1000);
    }
  };
  xhr.send(formData);

当index.html的title变化之后,在vue组件创建webview的代码之后,我们可以在当前webview去监听标题的变化。

// wv就是plus.webview.create的返回,上述代码有举例子
wv.addEventListener('titleUpdate', ({
  title
}) => {
  console.log(title)
}

那vue组件拿到回调信息之后,就可以正常拿到图片信息去在页面中渲染。

顺便说一句,在文档的后面,会给大家介绍uniapp相关生态,一些业务组件插件都会在相关生态中查询到。

websocket

oh,又到了这个该死的东西了,今年的一段时间内,在uniapp上使用websocket可是真的太难了,先说一下事情的经过,我司开发的APP中本来使用了聊天相关功能,之后在部分业务中加入了websocket,前端需要根据websocket实时获取一些信息,在测试APP的时候发现,当2个websocket并行连接的时候,发现只有一个连接能有效的发送和接受消息,无奈只好去文档中寻找答案。

App平台自定义组件模式下,以及支付宝小程序下,所有 vue 页面只能使用一个 websocket 连接。App下可以使用 plus-websocket 插件替代实现多链接。App平台,2.2.6+起支持多个socket链接,数量没有限制。
uniapp-websocket文档
  import socket from 'plus-websocket'
  // #ifdef APP-PLUS
  Object.assign(uni, socket)
  // #endif

通过把依赖中的socket合并到uni中,把uni中原本封装的socket进行替换;

Nvue

uniapp支持用户编写.nvue的组件,那么此组件将会使用改进后的weex引擎进行渲染,提供了原生渲染的能力,那么如果你是weex用户如果用nvue写,那么全程和weex的写法无异,如果是普通的vue开发者使用nvue开发,那么将注意,nvue对于css和js的限制有非常多,尤其是css很多常用的简写都将不能支持,所以我们需要额外查询对应的weex框架的文档。

那么我们在APP中有必要全部使用nvue原生渲染么,使用普通vue组件进行webview渲染有什么缺点么?那么我建议APP中 核心/用户访问次数多/需要更强劲的性能的页面可以使用nvue,其余普通页面我们仍然可以使用vue页面。

那么如果是weex用户转uniapp,可以全项目使用nvue,uniapp支持纯原生渲染模式,可以减少APP包体积,也可以减少内存占用,因为此时webview相关依赖是不存在的。使用nvue开发,即保留了原weex开发者的习惯又可以提供强大的API能力,这是非常让人兴奋的开发体验。

SubNvue

subNvue本质上是一个nvue组件,支持在普通vue页面之上运行,subNvue能覆盖map,video等原生组件,uniapp有很多办法支持覆盖原生组件,subNvue是我认为最好的方法,因为相比组件,不能嵌套,而且写起来和原页面耦合;又和webview相比,需要原生h5+api做技术支撑,nvue相对来说更多vue开发者友好。

实例:由于首页有swiper那么悬浮的头部需要遮挡住swiper,在pages.json中注册即可

 "subNVues": [{
             "id": "indexTitle", // 唯一标识  
             "path": "pages/index/subNVue/indexTitle", // 页面路径  
             "style": {
               "position": "fixed",
               "dock": "top",
               "background": "transparent"
             }
           }]

uni全局通信

在uniapp中,vue,nvue组件中进行信息传递是很难的,尤其是vue和nvue中的信息传递我们可以通过全局通信的方式来做业务逻辑。

uni.$emit('update',{msg:'我是首页,用户下滑了'})
uni.$on('update',function(data){
    console.log("我是subnvue头部,你下滑了,那我就改变自身的透明度动画")
})

适用场景:

vue 与 nvue,nvue 与 vue 间的通讯
tabbar 页面之间的通讯
父页面与多级子页面间的通讯
uniapp-emit文档

你可能感兴趣的:(uni-app,小程序)