我一直认为文章是有时效性的。我在看别人写的文章或者博客的时候,会特别注意文章的发布日期。当文章发布的日期超过1年的时候,我就会开始警惕文章的内容是否"过期",时间越长越是如此(基础性的知识可以不受这个范围的约束)。
知识是不断更新的,被淘汰的知识本身的价值是很小的。在我们互联网的前端开发这个职业里面更是如此。所以这里给出文章编写的具体日期,供后面的人参考。
编写日期:2020/6/16
这篇文章主要目的是分享我个人在探索uniapp
期间的一些坑和整体感受,难免会有一些偏个人的主观意见,希望各位再看这篇文章之前先去看官方文档,以免先入为主。
官方文档并非同步更新的,需要同步着当前的uni-app v3版本升级 这篇文章看,这样才是比较完整的内容。
关于苹果下架H5 app 的相关新闻,请看这个官方说明 。想看更多新闻请看 公告 。
uniapp,由 Dcloud 公司推出。
因为app的开发依赖HbuilderX的app编译模块 , 所以HbuilderX这个开发工具的版本相当重要。
我们从HbuilderX更新日志可以看出,v3版本的编译器是从2.5.1版本加入正式版的,那时候是2020-01-03,直到现在过去2个月,v3版本还不算稳定,推荐是官方有推出更新就更新 (虽然每次更新填坑的时候也在挖坑)
目前的app
开发(整个流程)需要官方的开发工具HbuilderX
的支持。因为app的项目热开发、debug、真机运行、打包都需要这个HbuilderX
去做一个 “启动器”的角色。开发上面可以使用其他的编辑器,比如我们的vscode,保存代码HbuilderX会自动编译。
目前我使用的是最新的HbuilderX 2.6.1 ,这里有这个版本的 相关更新
开发插件相关
在菜单栏 => 工具栏下有插件安装,在这里基本能找到你想要的插件
开发app
必须要用HbuilderX ,所以项目的初始化我直接使用了官方提供的基础模板,从而走上了从零构建项目工程的道路…
第二种方式是通过vue-cli,这里官方文档 快速入手 有更加具体的说明,这里我不再赘述。
APP
打包 这里介绍了发布app 的大概资料。app的打包需要HbuilderX完成,这里面涉及到开发者证书相关的一块 ,正式打包需要原生这边的一些东西。可以需询问相关的开发人员,也可以问我。
我们自己开发测试可以使用官方提供的测试证书 (打包时候的默认选项)。
以往的从npm的地方的下载的插件通常只支持H5端, 插件市场则是uniapp相关插件主要获取来源,插件特性是能兼容多端。
插件安装方式
生态
uniapp已经出来这么多年了,而目前生态的状况在我看来,我是不满意的。或许是因为uniapp的稳定性不够或者其他原因,插件市场插件数量少同时质量也不够高(比起我们之前的要差上一个档次),没有一套其他第三方团队提供的比较完整地UI框架,大对数都是个人开发者在做。
文档
插件能否有效利用,文档是一个主要的因素。我个人在使用插件的时候发现大部分插件的文档并不友好(甚至连官方也不是很完善)
v3编译器带来的影响
其实自从V3编译器上线正式版之后,经历了一个月的疫情的影响和官方HbuilderX本身的各种小bug不断,目前插件市场的绝大多数组件都没有兼容v3 ,所以可以试着想想对于v3这个版本来说生态是很初始的一个状态的,生态的跟进还需要一定的时间(UI相关的插件会好很多,多半只是UI的布局受到影响)
JS API
发生了一个巨大的改变,开发方式相同,但是各项api
名字都不一样,但也就只是改了个名字。
出现了一系列对原生的html5+ api (加强版api)。这里会出现很多原生相关的知识点和小技巧,无疑是一大波知识点的补充。
也有部分js和vue的api无法使用,主要原因的一个功能在某个端不存在想对应的概念,或者说不支持这个特性。
比方说微信小程序的请求是不支持发送cookie凭证,而我们常用的H5是可以做到的,cookie凭证在我们的文件上传一类的接口中需要使用到
就是这样,可能是因为官方为了让多端的表现统一,所以在接口设计上就会统一砍掉,保持开发上的一致性。 这样的情况从我来看不在少数
但实际上如果 配置 发送cookie凭证 , 实际上是可以使用的(前提是那个端支持), 同时也不会报错 (注意使用条件编译), 但是官方文档并不会提到这一点
适配方案
尺寸单位。按照文档,直接使用rpx
,简单易用,使用750px
宽的的设计稿即可 (什么?给的是1242?自己用ps调)。
我目前99%都是使用rpx, 只有在做少部分比如一些边框的那种细线的时候才会使用到px,但并不是说px使用的场景就很少,这需要各位的挖掘。
并不是现在的所有第三方插件都使用了rpx, 因为有些组件有点年代了, 它们大量使用着upx和px。选择第三方插件的时候请多多注意。
布局和样式
官方首先推荐flex布局, 当然flex本身就是个很不错的选择,我个人也推荐这个,当然同时我们也能使用原本就有的布局方法,这些在vue页面都是支持的(nvue的布局是例外)。
每个页面的css自带作用域, 不用在style中额外声明scoped
样式重置相关
在 uni-app
中不能使用 *
选择器。样式重置是个问题, 比如我们常见的一些
*{
box-sizing:border-box
}
这个盒子模型贯穿我们整个项目的一个布局思路, 但目前我自己使用只能每个单独去处理, 比较不方便, 同时没有遇到较好的解决方法
多端UI库的基本认识 ,下面是介绍我所知道的大多数开发者会使用的UI库。
基础组件会是我们业务开发中很重要的组成部分。官方放在基础组件这个位置就说明了态度。
性能来说最好(官方),但UI上来说特别简单(这里input默认情况连边框都没有),需要自己的额外修饰
优点:官方团队维护的组件库, 稳定性和支持性有保证。
缺点:难看, 且业务型组件不够丰富, 有的组件甚至没有样式 (也可以侧面说可开发的部分很多)
这里附上 uniapp相关组件的在线预览
这里有个很奇妙的问题 , 下面这个是组件的引入方式, 在组件中单独引入没有问题, 但当在main.js中想做全局组件引入就会报错 , 目前没有探明原因
import { uniLoadMore } from '@dcloudio/uni-ui/'
css
库,为数不多的使用人数多的,比较好看的UI之一,没有使用文档! 使用纯靠复制粘贴我个人是及其不推荐使用这个库的,样式的写法可以作为参考
我个人没有使用,但是觉得还可以的一个很完善的有功能封装的UI框架,推荐尝试使用(踩坑)
不支持nvue
个人意见
开发上面我个人推荐是基础组件+ uni-ui + 任意一款第三方UI框架, 首选稳定的官方提供的框架,然后在部分需求去选择业务组件。
v3版本刚出的情况下,难免会出现比较多的问题。特别是那种个人开发者做的独立插件。从UI看来,nvue页面的业务开发速度上明显会落后于常规vue页面
webview
https://uniapp.dcloud.io/component/web-view
我个人总感觉这是个很关健的组件,使用这个组件能完全模仿出以前传统的webiview+ h5的方式。同时通讯各种的api都很齐全。
ps : 目前我使用方面主要是用来app内部打开外链使用。当时我遇到这个需求的时候,期望能找到api直接调用打开webview的方法,我个人认为uniapp的接口设计上是会有这么个接口的,但我寻找了很久都没有找到类似的接口,于是我只能单独做了个路由页面去做webview以处理app内部打开外链。
nvue,native vue,即原生的vue,这是这个文件后缀名的来源 。
相关资料
官方nvue文档
nvue不同编译模式介绍
坏处
好处
nvue
。个人感受:如丝般顺滑个人意见
我个人使用过nvue, 综合考虑下来是不推荐使用,原因如上面所述。个人是否承担nvue页面给整个项目带来的负担及后续的维护成本(还有面对各种无法难以形容的开发情况保持良好的心态)
http
请求我试用了插件市场中差不多三款http的插件,最终选择了 luch-request ,因为其余的插件封装不完整,还有细微的bug和不支持的功能。
使用方法与 axios
基本相似,少部分不同 , 需要自己对请求进行再封装 。
存在的问题
目前这个插件还不支持abort
个人意见
插件市场有好几个模仿axios的的http请求库, 在我的认识里面相似及其功能的插件对于大多数人来说只需要一款,绝对不会出现第二款。而目前在插件市场就出现了3款,且使用人数都相差不大。所以目前插件市场出现这种现象是比较令我感到奇怪,侧面证明uniapp的生态还不算稳定。
反馈
文件上传, 出现问题 自定义出现难度
使用方式基本没有差别
配置使用vuex
nvue使用vuex注意事项
pages.json, 文档明确说明了所有的页面路径都是需要在这里配的, 同时还可以在这里设置对应页面的导航栏的各种自定义按钮呀, 搜索栏, 透明等等。(注意每次配置完后你的热开发都是要重启的,这个不像我们的webpack这块能自动编译)
官方关于路由的使用相关文档
参数的接收
//钩子
onLoad(query){
//query 就是对象参数, 中文的参数需要使用 encodeURIComponent 和 decodeURIComponent转换处理
}
个人意见
我认为上述的这种做法并不是很好,因为我认为的这种中文转码应该内置处理了,就像vue-router本身不存在这样的问题。
插件市场的 vue-router 是个不错的选择,这个是插件是在uniapp中模拟vue-router,使用之后大致上能延续以往习惯的开发方式,包含了vue-router原本就比较丰富的api。但是目前还不能在v3版本使用,因为v3版本的部分问题没有修复,如果修复了可以尝试去跟进
我目前在这个作者群, 这是作者的相关项目 uni-simple-router ,如果方便的可以给作者点个star, 秋梨膏 ~
反馈
原生api用着还可以
资源路径说明 ,如果背景图片引用上出现问题,参考背景图片- 绝对路径 引用图片
背景图片相对路径引用失败可能是v3版本的一个暂时性的bug
反馈
少数有bug
iconfont
跟原本常规使用方式一致,使用icomoon即可。部分不适合/不能使用字体图标的场景使用图片代替即可
引入方式
不能像传统项目直接在main.js
中直接引用,HbuilderX会报出App平台 v3 模式暂不支持在 js 文件中引用***.css
关于这个暂不支持可能后续会有解决方案,这里将会持续关注
这里提供一个可用的引入方式,就是在App.vue
中引入,代码如下:
/* #ifndef APP-PLUS-NVUE*/
/*字图标片icomoon */
@import "static/icomoon/style.css";
/* #endif */
以我们常用的icomoon为例, 我们将icomoon放在static文件加下面并通过上述方式引用, 但是这时候会报错, 提示字体文件 ttf/eot找不到 , 我们需要对其中引用tff文件的引用路径做一下小小修改,下面是例子
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?8v7q4m');
src: url('fonts/icomoon.eot?8v7q4m#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?8v7q4m') format('truetype'),
url('fonts/icomoon.woff?8v7q4m') format('woff'),
url('fonts/icomoon.svg?8v7q4m#icomoon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
我们需要所有的路径改为绝对路径 , 也就是图中的fonts/icomoon
改成 ~@/static/icomoon/fonts/icomoon
(这里的路径请根据自己的文件结构自行调整), 修改完后就能够正确使用 。
当然这么做也有其缺点
icomoon
预览用的index.html
就失效了 , 因为~@
是uniapp特有的一个规则,在uniapp中才能正常编译使用,而index.html
的路径是常规的引用规则。这里实际上还有另外一个解决方式, 那就是字体文件转换成base64的方式,直接内联进去,这样就不会有字体文件引用的问题
此时或许有人注意到我在上面提供的例子中, 是通过条件编译来引入字体图标的css文件的 , 在nvue的页面中不引人这个css文件, 这么做的原因是主要因为下面这段
[class^='icon-'],
[class*=' icon-'] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'icomoon' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
这只是一个例子, 因为nvue
的 css
使用规则是基于weex
的, 在这套规则中不能识别属性选择器, 会提示报错。这意味着我们放弃了在nvue
文件中使用我们自定义的字体图标 ,目前没有找到比较方便的解决方法 ,在nvue页面推荐使用官方提供的icons 组件做字体图标。
调试相关文档 , 正常情况只需要在电脑浏览器上对H5进行调试即可, 基本上H5跟app的表现是一致的, 当遇到比较复杂的问题, 就可以考虑debug调试
普通H5调试
菜单栏 =>运行 => 运行到浏览器 (选择自己想要打开的浏览器)
真机调试vue!页面
菜单栏 => 视图 => 显示webview控制台 (其实很像 google 的 inspect)
真机调试Nvue页面
关于-app-的调试debug , 连接失败可以尝试关闭电脑防火墙,同时电脑和手机要处于同一wifi
下
https://uniapp.dcloud.io/cloud
app原生插件
目前这里讲的组件都是uni-ui, 看之前推荐去快速体验 下载app,边实时预览边看。
uni.showToast({
title: error_message,
duration: 2000,
icon: 'none', //不想要icon需要手动取消
position: 'bottom'//这个位置的显示会特殊点
})
icon: 'none'
(我很希望能找到一个全局设置的方法)position: 'bottom'
这里面比较特殊,显示的效果是特殊的轻提示 (用app能看出明显区别)这个侧边栏使用的场景不用我说, 一般首页普遍都会有。这里我想提醒的是这个组件的问题。
解决方法
我在项目中使用完这个组件之后,我意识到了为什么文档不友好体现在哪里。
首先我们进去一看 示例,这不就是我们移动端常见的cell吗?
如果认真看虽然很像cell,但是却没有提供插槽, 我不认为加入个简单的插槽都这么困难,这里面发生了什么,但原因我目前仍然没有查明
我们继续看文档, 看向使用方式会发现使用的时候需要同时引入uniList,uniListItem
这两个组件 ,很明显uniListItem
这个组件基本上就是cell, 同时你会发现当然文档并没有uni-list
的一个文档或者是相关说明。
我当时就裂开了, 官方文档竟然能这么写
为了解决这个疑问,我们首先来看源码
uni-list
<template>
<view class="uni-list">
<slot />
view>
<list class="uni-list" :enableBackToTop="enableBackToTop" loadmoreoffset="15" :scroll- y="scrollY" @loadmore="loadMore">
<slot />
list>
template>
uni-list-item
<template>
<cell>
<view :class="disabled ? 'uni-list-item--disabled' : ''" :hover-class="disabled || showSwitch ? '' : 'uni-list-item--hover'"
class="uni-list-item" @click="onClick">
view>
cell>
template>
可能这里放代码不合适,可以去npm地址 下载下来看源码会更适合。
这里我们应该把目光着重放在 其中的条件编译部分的代码,会发现这两个组件会在nvue页面中, 使用 list
、cell
这两个nvue专用的原生组件 , 文档明确说明了这两个组件之间的关系, 即
能作为list组件的一级子组件的组件只有cell、header、refresh、loading,而cell就是其中1个; 同样的能作为cell组件的父组件的只有list、recycler、waterfall,而list是其中一个
让我们尝试一下错误示范, 在nvue页面中,如果我们如下方这么写,那么就会提示报错,因为这是不符合规范的
<list>
<view>view>
list>
<view>
<cell>cell>
view>
至此我们能理解为什么uni-list
和uni-list-item
会在文档中成对出现了, 多半是不希望有人在nvue页面使用这个组件的时候出错。但文档并没有能对这个情况做一个很好的说明,能想象得出来,会出现这种情况并不会只是在这个组件中。
官方已经为所有的组件进行了nvue的适配,无论是否使用nvue,至少我们知道使用nvue的时候会遇到更多的障碍,各位在使用的时候要谨慎应对。
/*其实跟vant的方案是一样的, 通常的1px看起来是会有点粗,只需要设置1px再通过transform 之后就可以达到想要的细线条,这个方法在hbuilderx2.6.1.202002261 后证实有效*/
&::after {
content: " ";
position: absolute;
height: 1px;
top: 50%;
right: 0;
left: 0;
background-color: #d2d2d2;
transform: scaleY(0.5);
}
###富文本解决方案
这里是指类似v-html的过程
大部分情况下我们使用v-html, 替代方案 插件市场富文本
这个我认为也是比较重要的东西, 因为有些错误只会在特定情况下发生(app的确很容易这样),事后的问题重现难度大。应该要统一做个错误日志,好方面问题排查
比如用onError的钩子去处理
https://uniapp.dcloud.io/use?id=常见问题
https://uniapp.dcloud.io/frame?id=css%e5%8f%98%e9%87%8f
实际上官方提供的原生导航栏本身就很强大!包括了各种你想的到的常见需求,例如 常见搜索栏, 各种按钮 uni-app导航栏开发指南, 官网文档对应部分
但同时应该也要注意相关问题,避免开发上面出现比较大的问题。
当需求特别诡异的时候,可以考虑 前端模拟导航栏
官方文档- 下拉刷新
原生自带的下拉刷新我全局关掉了,目前我的做法是在需要地方单独做下拉刷新 (nvue页面),但并没有对下拉刷新进行抽象 (官方的示例中也不抽象)。
常用列表的下拉刷新方案 (vue)
应用生命周期 ,每个页面提供了对应的下拉刷新 onPullDownRefresh
和上拉刷新 onReachBottom
的 生命周期.
下拉刷新的更多妙用 , 这里你甚至能手动调用下拉刷新
###登录模块
实现方面可以参考HBuilderX新建uni-app项目时的登陆模板。 登录页不一定要设为首页
页面呢…及相关微信登录等其他第三方登录 , 可以参考登录模板或者插件市场的相关代码。
总体来说做起来不会太难
内嵌扫码
接口调用扫码
https://ask.dcloud.net.cn/article/35120
使用场景
常用是提交表单之后返回上个页面并刷新列表
uniapp社区相关解决方案
getCurrentPages文档
let page = getCurrentPages();//获取页面栈
let prevPage = pages[pages.length - 2];//获取你想操作的对应页面
// #ifdef APP-PLUS
prevPage.$vm.test();//app端写法
// #endif
// #ifndef APP-PLUS
prevPage.test();//调用列表页面方法
// #endif
uni.navigateBack();//跳转页面的操作,这个一定要放在后面不然page 这些就会失效
//test 是对应页面的对应方法
没有, 因为其他平台式并不一定有dom这个概念的
掘金-uni-app的开发经历
返回逻辑自定义
https://ask.dcloud.net.cn/article/35120
uniapp社区相关解决方案