初衷

近期公司要开发一个电商小程序,之前的mpvue已经停更别再选了,原生嘛 也没啥意思,因为是vue党所所以团队就选择了 uni-app来试试水,一周多使用下来使用感受 还是可以的。
会vue的 话简直就是无脑开发,看完这篇文章 直接上手撸。

小程序 分包加载:链接

底层实现原理:链接

uni-app runtime :
uniapp开发 - 图1

逻辑层和视图层分离,且非H5端通信有折损

uni-app 在非H5端运行时,从架构上分为逻辑层和视图层两个部分。逻辑层负责执行业务逻辑,也就是运行js代码,视图层负责页面渲染。

虽然开发者在一个vue页面里写js和css,但其实,编译时就已经将它们拆分了。

逻辑层详解

逻辑层是运行在一个独立的jscore里的,它不依赖于本机的webview,所以一方面它没有浏览器兼容问题,可以在Android4.4上跑es6代码,另一方面,它无法运行window、document、navigator、localstorage等浏览器专用的js API。

uni-app的App端和小程序端的js引擎,其实是在jscore上补充了一批手机端常用的JS API,比如扫码。

视图层详解

通常:h5和小程序平台,以及app-vue,视图层是webview。而app-nvue的视图层是基于weex改造的原生视图。

uni-app的js基本没有不同手机的兼容问题(因为js引擎自带了),而视图层的css,在app-vue上会有手机浏览器的css兼容问题。所以在app-vue的场景中尽量不要使用太新的css语法,除非你不打算支持低端机。

当然这样做也是有 利弊的 详情查看

项目创建

两种方式

1. 通过 HBuilderX 可视化界面

这个超级简单 开箱即用,无需配置nodejs。

下载好 IDE在点击工具栏里的文件 -> 新建 -> 项目 ,喜欢哪个模板选一个就完事儿了(推荐 hello uni-app)。

2. 通过vue-cli命令行 ( vue玩家推荐)

通过vuecli3.0+ 做为支持,所以 需要先安装 npm install -g @vue/cli
然后=》创建项目: vue create -p dcloudio/uni-preset-vue my-project

自带各种脚本,秀的不行啊!
通过这个方式,可以安装各种 你想要的 css预处理器、第三方插件等等,玩vue项目的都懂的。
uniapp开发 - 图2

关于NPM支持

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

关于页面配置

跟小程序一样放在 : pages.json

  1. {
  2. "pages": [{
  3. "path": "pages/component/index",
  4. "style": {
  5. "navigationBarTitleText": "组件"
  6. }
  7. }]
  8. }

开发规范

为了实现多端兼容,综合考虑编译速度、运行性能等因素,uni-app 约定了如下开发规范:

uniapp开发 - 图3

  • 组件标签靠近小程序规范,(比如基本的 view、text、image)详见uni-app 组件规范
  • 接口能力(JS API)靠近微信小程序规范,但需将前缀 wx 替换为 uni,详见uni-app接口规范
  • 数据绑定及事件处理同 Vue.js 规范,同时补充了App及页面的生命周期
  • 为兼容多端运行,建议使用flex布局进行开发

资源路径说明

  • @开头的绝对路径以及相对路径会经过base64转换规则校验

模板内引入静态资源

  1. <!-- 绝对路径,/static指根目录下的static目录,在cli项目中/static指src目录下的static目录 -->
  2. <image class="logo" src="/static/logo.png"></image>
  3. <image class="logo" src="@/static/logo.png"></image>
  4. <!-- 相对路径 -->
  5. <image class="logo" src="../../static/logo.png"></image>

js文件引入

  1. / 绝对路径,@指向项目根目录,在cli项目中@指向src目录
  2. import add from '@/common/add.js'
  3. // 相对路径
  4. import add from '../../common/add.js'

css引入静态资源

  1. /* 绝对路径 */
  2. @import url('/common/uni.css');
  3. @import url('@/common/uni.css');
  4. /* 相对路径 */
  5. @import url('../../common/uni.css');

页面

getCurrentPages() 函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。
最好 自己打印出来 看下 所需信息 const pages = getCurrentPages()

尺寸单位

uni-app 支持的通用 css 单位包括 px、rpx

  • px 即屏幕像素
  • rpx 即响应式px,一种根据屏幕宽度自适应的动态单位。以750宽的屏幕为基准,750rpx恰好为屏幕宽度。屏幕变宽,rpx 实际显示效果会等比放大。

生命周期

详情 链接

onLoad 监听页面加载,主要通过这个获取页面参数 onLoad(option)}{},参考示例
onShow 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
onReady 监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发
onHide 监听页面隐藏
onUnload 监听页面卸载

全局页面通讯

链接

触发全局的自定事件

uni.$emit(eventName,OBJECT) 附加参数都会传给监听器回调。栗子: uni.$emit('update',{msg:'页面更新'})

监听全局的自定义事件

uni.$on(eventName,callback)事件可以由 uni.$emit 触发,回调函数会接收所有传入事件触发函数的额外参数。

  1. uni.$on('update',function(data){
  2. console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
  3. })

注意事项

  • uni.$emit、 uni.$on 、 uni.$once 、uni.$off 触发的事件都是 App 全局级别的,跨任意组件,页面,nvue,vue 等
  • 使用时,注意及时销毁事件监听,比如,页面 onLoad 里边 uni.$on 注册监听,onUnload 里边 uni.$off 移除,或者一次性的事件,直接使用 uni.$once 监听

样式

使用 uni-app 组件的时候 有时候修改内部组件样式 无效,需要使用 /deep/ .xxx { } 才可以生效。

页面通用模式

  1. <template>
  2. <view class="container">
  3. <view class="user-section">
  4. <image class="bg" src="/static/user-bg.jpg"></image>
  5. </view>
  6. <view class="info-box">
  7. <text class="username">{{userInfo.nickname || '游客'}}</text>
  8. </view>
  9. </view>
  10. </template>
  11. // 基本上和vue一摸一样
  12. <script>
  13. import { getMyInfo } from '@/api/my.js'
  14. import { mapState } from 'vuex';
  15. import mixins_share from '@/mixins/share.js'
  16. export default {
  17. mixins: [mixins_share],
  18. data() {
  19. return {
  20. userInfo: {},
  21. vipTheme: {
  22. },
  23. };
  24. },
  25. computed: {
  26. ...mapState(['accessToken'])
  27. },
  28. onLoad(option) {
  29. this.nickName = option.nickName
  30. },
  31. onShow() {
  32. },
  33. methods: {
  34. scroll: function(e) {
  35. console.log(e);
  36. },
  37. goOrderList() {
  38. uni.navigateTo({
  39. url: '/pages/orderList/list'
  40. })
  41. }
  42. }
  43. };
  44. </script>
  45. // 使用 css插件需要安装
  46. <style lang="scss" scoped>
  47. .mine {
  48. min-height: 100vh;
  49. background-color: #f5f5f5;
  50. .mine-header {
  51. }
  52. }
  53. </style>

注意事项:

  • 页面生命周期 优先使用 小程序那一套, onLoad(option) {} 获取参数, onShow() {} 页面显示.

页面跳转方式

保留当前页面,跳转到某个页面

使用uni.navigateBack可以返回到原页面。

  1. /在起始页面跳转到test.vue页面并传递参数
  2. uni.navigateTo({
  3. url: 'test?id=1&name=uniapp'
  4. });

注意: 跳转到 tabBar 页面只能使用 switchTab 跳转

关闭当前页面,跳转到应用内的某个页面。

uni.redirectTo(OBJECT)

跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。

uni.switchTab(OBJECT)

关闭当前页面,返回上一页面或多级页面

uni.navigateBack(OBJECT)可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层。

  1. // 在C页面内 navigateBack,将返回A页面
  2. uni.navigateBack({
  3. delta: 2
  4. });

想了解更多?那点我官方走起

数据缓存

同步的话 在后面+Sync 例如:uni.setStorageSync

数据存储在本地缓存(异步接口)

uni.setStorage(OBJECT)指定的 key 中,会覆盖掉原来该 key 对应的内容

  1. uni.setStorage({
  2. key: 'storage_key',
  3. data: JSON.stringify(data), // 需要存储的内容,只支持原生类型、及能够通过 JSON.stringify 序列化的对象
  4. success: function () {
  5. console.log('success');
  6. }
  7. });

从本地缓存中异步获取指定 key 对应的内容

  1. uni.getStorage({
  2. key: 'storage_key',
  3. success: function (res) {
  4. console.log(res.data);
  5. }
  6. });

异步移除指定 key

  1. uni.removeStorage({
  2. key: 'storage_key',
  3. success: function (res) {
  4. console.log('success');
  5. }
  6. });

清理本地数据缓存。

uni.clearStorage()

注意:

uni-app的Storage在不同端的实现不同:

  • H5端为localStorage,浏览器限制5M大小,是缓存概念,可能会被清理
  • App端为原生的plus.storage,无大小限制,不是缓存,是持久化的
  • 各个小程序端为其自带的storage api,数据存储生命周期跟小程序本身一致,即除用户主动删除或超过一定时间被自动清理,否则数据都一直可用。
  • 微信小程序单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。
  • 支付宝小程序单条数据转换成字符串后,字符串长度最大200*1024。同一个支付宝用户,同一个小程序缓存总上限为10MB。
  • 百度、字节跳动小程序文档未说明大小限制

想了解更多?那点我官方走起

网络请求

发起网络请求: 官网介绍

  1. uni.request({
  2. url: 'https://www.example.com/request', //仅为示例,并非真实接口地址。
  3. data: {
  4. text: 'uni.request'
  5. },
  6. header: {
  7. 'custom-header': 'hello' //自定义请求头信息
  8. },
  9. success: (res) => {
  10. console.log(res.data);
  11. this.text = 'request success';
  12. }
  13. });
  • 单次网络请求数据量建议控制在50K以下(仅指json数据,不含图片),过多数据应分页获取,以提升应用体验。

上传文件(图片)

uni.uploadFile(OBJECT)

如页面通过 uni.chooseImage 等接口获取到一个本地资源的临时文件路径后,可通过此接口将本地资源上传到指定服务器。另外选择和上传非图像、视频文件参考:https://ask.dcloud.net.cn/article/35547

  1. uni.chooseImage({
  2. success: (chooseImageRes) => {
  3. const tempFilePaths = chooseImageRes.tempFilePaths;
  4. uni.uploadFile({
  5. url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
  6. filePath: tempFilePaths[0],
  7. name: 'file',
  8. formData: {
  9. 'user': 'test'
  10. },
  11. success: (uploadFileRes) => {
  12. console.log(uploadFileRes.data);
  13. }
  14. });
  15. }
  16. });

媒体文件操作 官网介绍

uniapp开发 - 图4

常用界面操作 官网介绍

uniapp开发 - 图5

其他辅助功能 官网介绍

uniapp开发 - 图6

使用cli创建项目和使用HBuilderX可视化界面创建项目有什么区别

编译器的区别

  • cli创建的项目,编译器安装在项目下。并且不会跟随HBuilderX升级。如需升级编译器,执行npm update
  • HBuilderX可视化界面创建的项目,编译器在HBuilderX的安装目录下的plugin目录,随着HBuilderX的升级会自动升级编译器。
  • 已经使用cli创建的项目,如果想继续在HBuilderX里使用,可以把工程拖到HBuilderX中。注意如果是把整个项目拖入HBuilderX,则编译时走的是项目下的编译器。如果是把src目录拖入到HBuilderX中,则走的是HBuilderX安装目录下plugin目录下的编译器
  • cli版如果想安装less、scss、ts等编译器,需自己手动npm安装。在HBuilderX的插件管理界面安装无效,那个只作用于HBuilderX创建的项目。

结语

所有的评测都只是提供决策依据,最后的结果还是要依赖开发者的团队技术栈、业务诉求、未来规划等。
不过作为一篇评测文章的结语,我们还是要给出自己的建议:

  • 如果你熟悉React,不懂Vue.js,推荐Taro;
  • 如果你熟悉Vue.js,则推荐 uni-app;
  • 如果你已经有H5代码,只想增加微信小程序平台,并且对性能要求不高,可以考虑kbone;
  • 如果你的业务涉及多端,更推荐 uni-app;
  • 如果你希望通过 serverless 方案快速上线业务,推荐 uni-app。

此结语摘自隔壁大佬:作者:CHB 链接:https://juejin.im/post/5e8e8d5a6fb9a03c6d3d9f42

先到这里了,关注 后期慢慢更新更多~

问题记录

1、需求描述:小程序页面分享带参数 u=userid,别人打开的时候 第一次会走 onLaunch 来获取参数并存储。如果 再打开 另一个人分享的 userid是不同的,此时 onLaunch不在走了,怎么获取参数?

解决方案: 在main.js 里 混入 onLoad

  1. Vue.mixin({
  2. onLoad(options){
  3. // 获取到参数 操作
  4. }
  5. }

2、全局 添加 分享功能,实现每个页面都可以 进行特性模式 分享。
解决方案:

  1. Vue.mixin({
  2. onShareAppMessage(e) {
  3. const merchant = this.$store.getters.merchant
  4. return {
  5. title: merchant.subName,
  6. path: `/pages/tabBar/vhome${'?refId='+this.$store.getters.userInfo.uid}`,
  7. imageUrl: merchant.posterImg
  8. }
  9. }
  10. })