# 常见问题

# 目录

# 一、如何解决微信小程序关于选择器的警告提示?(谨慎使用)

微信小程序组件警告提示

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-metaoverflow 属性。
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 属性为 hiddenvisible,也可以达到这种效果。
  • wxapp 需要 使用 page-meta 组件配合阻止滚动穿透,page-meta 组件,一个页面只能存在一个。
  • 其他平台无法阻止滚动穿透,建议使用 scroll-view 滚动 ,手动设置 overflow:hidden或设置 scroll-y属性来禁止滚动。

# 五、为什么部分组件在弹出层中显示异常或功能异常?

在弹出层 uv-popup 中使用 uv-subsectionuv-tabsuv-rate 等组件时,可能会显示异常或功能异常。

# 原因:

uv-subsectionuv-tabsuv-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-imageuv-tags等组件。
  • uv-listuv-waterfall等组件在Android平台使用了<list><cell>封装,所以在该组件中仍然不能使用uv-imageuv-tags等组件。

# 七、uv-row、uv-grid等组件在百度小程序、抖音小程序等平台显示异常

  • uv-rowuv-griduv-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-pickeruv-notice-bar且设置竖向滚动时,然后再使用uv-picker时候,可能会出现选择时闪动的情况,如果不介意可以忽略。
  • 可能影响的组件eg2: 在 app-nvue 项目同一个页面中,使用 listuv-notice-bar且设置竖向自动滚动时,在 list 下拉刷下时,uv-notice-bar会出现拉回到第一个。

# 解决方案:

  1. 在 picker 组件打开时,禁止 uv-notice-bar 自动滚动,有属性可以设置,自行查看文档。
  2. 在 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控制

  1. 弹窗等组件中都会用到调用open方法去执行后续程序,使用监听show属性也可以做到,但是实际上使用watch监听show属性的变化,会比直接调方法执行的慢些,监听到去执行是需要时间的,所以uv-ui推荐直接调用方法,这可能也是uni-ui组件使用ref的原因,跟着官方对齐没毛病吧。

  2. 在Vuejs 中,ref 方法和监听show变化都可以用来访问和操作DOM元素。但是,它们的执行顺序是不确定的,因为它们是由 Vuejs 内部处理的。通常情况下,ref方法会先于监听show变化执行,因为它可以更早地访问和操作DOM元素。然而,在某些情况下,监听show变化可能会先于ref方法执行。例如,当show属性在组件实例化之前发生变化时,监听show变化可能会先执行。

  3. 可以用一个简单示例来解释:可以看出下面的示例show的变化在前,open方法执行在后,但是最后打印的结果是open中的程序在前,监听show变化程序在后。

  4. 总结:从性能和代码洁癖上来考虑,还是建议使用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>