Uni 开发常见问题
使用 uni 开发一段时间了,一份代码提交了AppStore + 安卓各市场 + 百度小程序 + 微信小程序,记录下常用的知识点和问题,比较杂,但是效果好。
1. 布局相关
1.1 控制文本行数显示
控制显示指定行数文本:
.content{
overflow: hidden;
text-overflow: ellipsis; // 文本溢出显示省略号
display: -webkit-box;
-webkit-line-clamp: 2; // 指定控制的行数
-webkit-box-orient: vertical;
}
控制显示单行文本:
.content{
overflow: hidden;
text-overflow: ellipsis; // 文本溢出显示省略号
white-space: nowrap; // 文本不会换行(单行文本溢出)
background-color: red;
}
1.2 指定元素填满父元素剩余空间
![](https://img.haomeiwen.com/i10432329/192c0d224c3d0a70.png)
.parent{
padding: 20rpx;
display: flex;
flex-direction: row;
align-items: center;
background-color: #EDEDED;
}
.title{
flex: 1; // 控制占据剩余所有空间
// 控制单行显示
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.status{
// 这个正常写就行,
background-color: #007AFF;
color: #FFFFFF;
padding: 10rpx;
font-size: 24rpx;
}
1.3 文本中有长数字/字母时换行
![](https://img.haomeiwen.com/i10432329/4cd4a8de421e4191.png)
设置
word-break: break-all;
.p2{
word-break: break-all;
}
1.4 显示html文本
v-html
在小程序中不显示,可以使用rich-text
组件:
<template>
<view class="content">
<!-- APP & H5中可以显示,小程序中不会显示 -->
<text v-html="msg"></text>
<!-- 推荐使用rich-text -->
<rich-text :nodes="msg"></rich-text>
</view>
</template>
...
data() {
return {
msg : "<h1>这是一个h1元素内容</h1>"
}
}
...
1.5 顶部有fixed元素时的布局
顶部筛选元素为fixed
,底部list
布局仍然从·顶部·
开始:
- 设置list的
padding-top
为筛选元素的高度 - 在
list
顶部设置一个和筛选元素同高度的占位视图
1.6 View底部添加分割线
可以只设置view的底部边框,不用再去写一个view当做分割线:
.item{
padding: 20rpx 0rpx;
border-bottom: solid 1rpx #ededed;
}
1.7 导航栏添加按钮(小程序不支持)
自定义性较差,不支持自定义图片按钮,可以通过自定义导航栏实现。
官方文档:https://uniapp.dcloud.io/collocation/pages?id=app-titlenview-buttons
/* pages.json中对页面增加导航栏按钮 */
{
"path": "pages/tabbar/found/index",
"style": {
"navigationBarTitleText": "页面标题",
/* 关键代码,添加右上角按钮 */
"titleNView": {
"buttons": [{
"text": "收藏",
"float": "right", // 控制左右
"width": "auto",
"fontSize": 14,
"color": "#333333"
}]
}
}
}
/* 页面中监听按钮点击事件 */
onNavigationBarButtonTap(val) {
if (val.index == 0) {
console.log("第1个按钮");
}
}
/* 页面中动态改变按钮 --> !!!前提是pages.json中已经添加按钮,只能动态修改,如果想要隐藏,可以设置width=0,text="" !!! */
// #ifdef APP-PLUS
let webView = this.$mp.page.$getAppWebview();
// 0 是指定修改的按钮的下标
webView.setTitleNViewButtonStyle(0, {
"float": "right",
"text": '已收藏',
"fontSize": "16",
"width": "0",
"color": "#313c5d"
});
// #endif
页面中动态改变按钮的前提是pages.json中已经添加按钮
,只能动态修改,如果想要隐藏,可以设置width=0,text=""
1.8 设置rpx最大支持设备宽度
比如Pad,使用rpx单位时对元素按设备宽度比例放大,元素显示会非常大,此时可以设置rpxCalcMaxDeviceWidth,按照基准宽度计算:
/* pages.json中设置 */
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"rpxCalcMaxDeviceWidth": 500, // 计算所支持的最大设备宽度,单位 px,默认值为 960
"rpxCalcBaseDeviceWidth": 375, // 计算使用的基准设备宽度,设备实际宽度超出 rpx 计算所支持的最大设备宽度时将按基准宽度计算,单位 px,默认值为 375
"rpxCalcIncludeWidth": 750 // 计算特殊处理的值,始终按实际的设备宽度计算,单位 rpx,默认值为 750
},
2. 功能相关
2.1 下拉刷新&上拉加载
单列表页面,推荐使用页面级滚动 ( webview渲染的页面中,区域滚动的性能不及页面滚动 )。
2.1.1 下拉刷新
官网地址:https://uniapp.dcloud.io/api/ui/pulldown?id=onpulldownrefresh
/* 1.pages.json中为页面开启下拉刷新 */
{
...
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "导航栏",
"enablePullDownRefresh": true
}
}
],
...
}
/* 2.页面中监听下拉刷新事件 */
onPullDownRefresh() {
// 刷新逻辑
if(loadSuccess){
// 结束刷新
uni.stopPullDownRefresh(); => 对应的手动开始下拉刷新:uni.startPullDownRefresh({});
}
}
仅APP端
可以动态控制页面是否支持下拉刷新:
// #ifdef APP-PLUS
const pages = getCurrentPages();
const page = pages[pages.length - 1];
const currentWebview = page.$getAppWebview();
currentWebview.setStyle({
pullToRefresh: {
support: !this.isSupport, // 是否支持,这里用变量来控制
style: plus.os.name === 'Android' ? 'circle' : 'default'
}
});
// 变量改变,控制页面是否支持下拉刷新
this.isSupport = !this.isSupport;
// #endif
2.1.2 上拉加载更多
需自己在列表底部添加上拉加载更多显示控件,通过变量状态控制控件的状态显示:loading前,loading中,没有更多数据:
上拉加载更多控件:https://ext.dcloud.net.cn/plugin?id=29
<uni-load-more v-if="compositionList.length > 0" :status="moreStatus"></uni-load-more>
// moreStatus 对应:more(loading前)、loading(loading中)、noMore(没有更多了)
监听页面滚动到底部事件:
onReachBottom() {
this.moreStatus = "loading" // 改为加载中状态
if(加载成功){
this.moreStatus = "more"
/* this.moreStatus = "noMore" */
}
}
2.2 图片加载时&加载失败显示占位图片
使用image标签提供的两个方法:
![](https://img.haomeiwen.com/i10432329/a47f3a62119bc0a0.png)
// 使用
<view v-for="(item, index) in list" :key="index">
<image v-show="item.imgLoaded" :src="item.logo" mode="aspectFit" @error="onErrorImg(item)" @load="onSuccessImg(item)"/>
<image v-show="!item.imgLoaded" src="/static/images/login-grey.png" mode="aspectFit"/>
</view>
// js代码
onSuccessImg(item) {
this.$set(item, 'imgLoaded', true)
},
onErrorImg(item) {
this.$set(item, 'imgLoaded', false)
}
2.3 全局弹窗
例如升级弹窗,可覆盖任何页面,实现方式:跳转到一个透明背景的页面,并且修改页面展现动画。(仅支持APP)
/************* pages.json 中对页面的style做修改 *************/
{
"path" : "pages/index/popup",
"style" :
{
"navigationStyle":"custom", // 隐藏导航栏
"disableScroll":true, // 禁止页面滑动
"backgroundColor":"transparent", // 背景透明
"app-plus":{
"animationType": "fade-in", // 动画方式
"background": "transparent",
"popGesture": "none" // 禁用侧滑返回
}
}
}
/************* 页面样式 *************/
<style>
page{
background: transparent;
}
/* 根view,给了一个黑色蒙版 */
.content{
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.4); /* 设置背景色,黑色蒙版 */
display: flex;
align-items: center;
justify-content: center;
}
</style>
/************* 禁用安卓物理返回 *************/
onBackPress(options) {
// 禁止安卓返回按钮
if(options.from == "backbutton"){
return true;
}
}
使用时,直接通过普通的uni.navigationTo()方法跳转即可,隐藏时调用uni.navigateBack({})。
2.4 开屏广告页/引导页
pages.json 中将广告页/引导页放在pages对应数组的首位,说明它是应用启动页:
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
// #ifdef APP-PLUS || H5 -> 这里也可以使用判断,只有在APP端和H5端,这个页面才会被编译
{
"path": "pages/lunchad/index",
"style": {
"navigationStyle": "custom",
"disableScroll": true
}
}
// #endif
...省略...
]
在广告页/引导页onLoad()方法中,判断是否需要展示,如果不需要则跳转到home页面,此时用uni.switchTab():
onLoad(){
if(showAd){
...展示
}else{
// 跳转时使用switchTab方法
uni.switchTab({
url: '../tabbar/home/index'
})
}
}
3. 其它
3.1 for...in.. 问题
百度小程序不支持 v-for="(item,index) in 5",改为 v-for="(item,index) in [0,1,2,3,4]"
<view v-for="(item,index) in 5" :key="index">
第{{index}}项
</view>
3.2 页面跳转时传多个参数
/* 页面跳转传参 */
let params = {
"paramA":"A",
"paramB":"B"
}
let paramsStr = encodeURIComponent(JSON.stringify(params))
uni.navigateTo({
url: './preview?params=' + paramsStr
})
/* 跳转后接收参数 */
onLoad(options) {
if (options.params) {
let params = JSON.parse(decodeURIComponent(options. params));
}
}