# 常见问题
# 目录
- 一、如何解决微信小程序关于选择器的警告提示
- 二、文档右侧的演示demo有些功能不能操作
- 三、使用的ref与组件名重名,在vue3的setup语法糖中会报错
- 四、uv-popup等组件怎么禁止滚动穿透
- 五、为什么部分组件在弹出层中显示异常或功能异常
- 六、Android端list中为什么不能使用uv-image等组件
- 七、uv-row、uv-grid等组件在百度小程序、抖音小程序等平台显示异常
- 八、在同页面使用picker-view和swiper且设置竖向自动滚动时,选择时会存在bug
- 九、怎么隐藏uv-tabs等组件的滚动条
- 十、避免部分扩展组件之间套娃,否则会造成错乱
- 十一、为什么uv-popup等弹窗组件显示不使用show属性进行控制,而是使用ref控制
# 一、如何解决微信小程序关于选择器的警告提示?(谨慎使用)
微信小程序组件警告提示
Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors...
# 解决方案:
暂时无需解决,不影响使用
# 二、文档右侧的演示demo有些功能不能操作?
因为演示demo是iframe
嵌入的H5
,所以组件中的@touchstart
等事件会失效。
# 解决方案:
直接访问https://h5.uvui.cn (opens new window)的手机模式进行体验
# 三、使用的ref与组件名重名,在vue3的setup语法糖中会报错
<!-- 错误示例 -->
<template>
<view style="padding-top: 100px;">
<uv-demo ref="uvDemo"></uv-demo>
</view>
</template>
<script setup>
import { ref } from 'vue'
const uvDemo = ref(null);
</script>
报错
上述代码会报错导致不能正常显示
Invalid vnode type when creating vnode: null.
Component is missing template or render function.
# 解决方案:将ref改成其他名字即可,如下:
<template>
<view style="padding-top: 100px;">
<uv-demo ref="uvDemo1"></uv-demo>
</view>
</template>
<script setup>
import { ref } from 'vue'
const uvDemo1 = ref(null);
</script>
# 四、uv-popup等组件怎么禁止滚动穿透?
使用uv-popup等弹出层组件时,会发现遮罩下方的内容可以滚动,这就是穿透滚动。
由于平台的自身原因,除H5之外,其他平台都不能在组件内禁止滚动穿透,所以在微信小程序、App 平台,页面内需要用户特殊处理一下。
# 解决方案:
# 微信小程序/App
在 微信小程序/App
平台可使用 page-meta
组件动态修改页面样式,
以 uv-popup
为例,需要在 data
中定义一个变量,用来表示 uv-popup
的开启关闭状态,并通过这个变量修改 page-meta
的 overflow
属性。
在 uv-popup
的 打开和关闭 事件中可以接受到 uv-popup
的开启关闭状态 ,并赋值给上面的变量。
<template>
<page-meta :page-style="'overflow:'+(show?'hidden':'visible')"></page-meta>
<view class="container">
<!-- 普通弹窗 -->
<uv-popup ref="popup" @open="change(true)" @close="change(false)">
<!-- ... -->
</uv-popup>
</view>
</template>
<script>
export default {
data() {
return {
show:false
}
},
methods: {
change(show) {
this.show = show
}
}
}
</script>
# Tips
- h5 滚动穿透不需要处理,组件内部有处理。或者自己根据状态设置
body
上面的overflow
属性为hidden
和visible
,也可以达到这种效果。 wx
、app
需要 使用page-meta
组件配合阻止滚动穿透,page-meta
组件,一个页面只能存在一个。- 其他平台无法阻止滚动穿透,建议使用
scroll-view
滚动 ,手动设置overflow:hidden
或设置scroll-y
属性来禁止滚动。
# 五、为什么部分组件在弹出层中显示异常或功能异常?
在弹出层 uv-popup
中使用 uv-subsection
、uv-tabs
、uv-rate
等组件时,可能会显示异常或功能异常。
# 原因:
在uv-subsection
、uv-tabs
、uv-rate
等组件中,使用了 js
去计算相应的节点参数,弹窗未显示的时候组件内部计算的值可能存在偏差,所以导致异常。
# 解决方案:
使用v-if
进行控制,在弹窗弹出后,再去使用v-if = "true"
达到重新创建组件的效果,案例如下:
<template>
<view class="uv-content">
<uv-popup :show="show1" mode="center" @open="open">
<view class="content" style="width: 600rpx;height: 300px;background-color: #fff;">
<uv-subsection :list="list" v-if="show2" :current="current" @change="index=>current = index"></uv-subsection>
</view>
</uv-popup>
</view>
</template>
<script>
export default {
data() {
return {
show1: false,
show2: false,
current: 1,
list: ['未付款', '待评价', '已付款']
}
},
onLoad() {
this.show1 = true;
},
methods: {
open(){
// 弹窗弹出后,给一点延迟再去显示分段器组件,建议设置的值大点
setTimeout(()=>{
this.show2 = true
},200)
}
}
}
</script>
# 六、Android端list中为什么不能使用uv-image等组件?
Android
平台,因<list>
高效内存回收机制,不在屏幕可见区域的组件不会被创建,导致一些内部需要计算宽高的组件无法正常工作。Android
平台,因<list>
高效内存回收机制,不在屏幕可见区域的组件不会被创建,组件如果使用animation.transition
在内容回收后会导致显示异常,所以与uv-transition
相关的组件不能使用,例如:uv-image
、uv-tags
等组件。uv-list
、uv-waterfall
等组件在Android
平台使用了<list>
、<cell>
封装,所以在该组件中仍然不能使用uv-image
、uv-tags
等组件。
# 七、uv-row、uv-grid等组件在百度小程序、抖音小程序等平台显示异常
uv-row
、uv-grid
、uv-tabbar
等组件是由父组件和子组件组合而成,并且在父组件进行flex
布局,但是在百度小程序、抖音小程序等平台不支持将自定义节点设置成虚拟 (opens new window),即virtualHost: true
不生效。
# 八、在同页面使用picker-view和swiper且设置竖向自动滚动时,选择时会存在bug
- 该BUG是
uniapp
官方就存在的,已经反馈了此问题:https://ask.dcloud.net.cn/question/174410 (opens new window) - 可能影响的组件eg:在一个页面同时使用
uv-picker
和uv-notice-bar
且设置竖向滚动时,然后再使用uv-picker
时候,可能会出现选择时闪动的情况,如果不介意可以忽略。 - 可能影响的组件eg2: 在 app-nvue 项目同一个页面中,使用
list
和uv-notice-bar
且设置竖向自动滚动时,在list
下拉刷下时,uv-notice-bar
会出现拉回到第一个。
# 解决方案:
- 在 picker 组件打开时,禁止 uv-notice-bar 自动滚动,有属性可以设置,自行查看文档。
- 在 list 组件滚动时,禁止 uv-notice-bar 自动滚动,有属性可以设置,自行查看文档。
# 九、怎么隐藏uv-tabs等组件的滚动条?
uv-tabs
等组件使用了scroll-view
标签,在H5
等平台会出现滚动条,需要全局设置滚动条样式,局部设置不生效。
# 解决方案:
/* APP.vue */
<style lang="scss">
@import '@/uni_modules/uv-ui-tools/index.scss';
</style>
或
/* APP.vue */
<style lang="scss">
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
</style>
# 十、避免部分扩展组件之间套娃,否则会造成错乱
- 套娃的简单案例:
uv-popup
中嵌套uv-calendars
。造成的后果可以复制下面的代码体验下。
<template>
<view>
<uv-popup ref="popup" mode="top">
<view>
<uv-button :text="`选择时间${time}`" @click="openTime"></uv-button>
<!-- 套在了uv-popup中...过分...,uv-calendars属于弹窗性质的组件,这样做的后果就是底层组件都不知道自己是啥娃子了 -->
<uv-calendars ref="calendars" @confirm="confirm" />
</view>
</uv-popup>
<button @click="open">打开</button>
</view>
</template>
<script>
export default {
data() {
return {
time: ''
}
},
methods: {
open() {
this.$refs.popup.open('top');
},
openTime() {
this.$refs.calendars.open();
},
confirm(e) {
this.time = e.fulldate;
}
}
}
</script>
- 正确的做法:弹窗类等组件避免套在其他扩展组件里面,要放在根节点下面使用,且根节点不能设置宽高等属性。
<template>
<view>
<uv-popup ref="popup" mode="top">
<view>
<uv-button :text="`选择时间${time}`" @click="openTime"></uv-button>
</view>
</uv-popup>
<button @click="open">打开</button>
<uv-calendars ref="calendars" @confirm="confirm" />
</view>
</template>
<script>
export default {
data() {
return {
time: ''
}
},
methods: {
open() {
this.$refs.popup.open('top');
},
openTime() {
this.$refs.calendars.open();
},
confirm(e) {
this.time = e.fulldate;
}
}
}
</script>
- 总结:一些套娃的行为是不利于前端开发的!大家要谨记,特别是扩展组件,与原生组件有本质上的区别。为啥不能这样做,比如弹窗组件底层使用了动画组件,动画的开始执行位置是-100%,你把它执行的范围给缩小到你指定的范围,那弹出来的效果肯定是不对的。
# 十一、为什么uv-popup等弹窗组件显示不使用show属性进行控制,而是使用ref控制
弹窗等组件中都会用到调用open方法去执行后续程序,使用监听show属性也可以做到,但是实际上使用watch监听show属性的变化,会比直接调方法执行的慢些,监听到去执行是需要时间的,所以uv-ui推荐直接调用方法,这可能也是uni-ui组件使用ref的原因,跟着官方对齐没毛病吧。
在Vuejs 中,ref 方法和监听show变化都可以用来访问和操作DOM元素。但是,它们的执行顺序是不确定的,因为它们是由 Vuejs 内部处理的。通常情况下,ref方法会先于监听show变化执行,因为它可以更早地访问和操作DOM元素。然而,在某些情况下,监听show变化可能会先于ref方法执行。例如,当show属性在组件实例化之前发生变化时,监听show变化可能会先执行。
可以用一个简单示例来解释:可以看出下面的示例show的变化在前,open方法执行在后,但是最后打印的结果是open中的程序在前,监听show变化程序在后。
总结:从性能和代码洁癖上来考虑,还是建议使用ref进行控制,这也正是uv-ui深思熟虑的结果。
index.vue
<template>
<view class="content">
<demo ref="demoRef" :show="show"></demo>
<button @click="handle">执行</button>
</view>
</template>
<script>
export default {
data() {
return {
show: false
}
},
methods: {
handle() {
this.show = true;
this.$refs.demoRef.open();
}
}
}
</script>
demo组件:
<template></template>
<script>
export default {
props: {
show: {
type: Boolean,
default: false
}
},
watch: {
show(n) {
console.log('监听show变化', n);
}
},
methods: {
open() {
console.log('监听open方法执行');
}
}
}
</script>