# 常见问题
# 目录
- 一、如何解决微信小程序关于选择器的警告提示
- 二、文档右侧的演示demo有些功能不能操作
- 三、使用的ref与组件名重名,在vue3的setup语法糖中会报错
- 四、qinui-popup等组件怎么禁止滚动穿透
- 五、怎么隐藏组件的滚动条
- 六、避免部分扩展组件之间套娃,否则会造成错乱
- 七、为什么qinui-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>
# 四、qinui-popup等组件怎么禁止滚动穿透?
使用qinui-popup等弹出层组件时,会发现遮罩下方的内容可以滚动,这就是穿透滚动。
由于平台的自身原因,除H5之外,其他平台都不能在组件内禁止滚动穿透,所以在微信小程序、App 平台,页面内需要用户特殊处理一下。
# 解决方案:
# 微信小程序/App
以 qinui-popup 为例,需要在 data 中定义一个变量,用来表示 qinui-popup 的开启关闭状态,并通过这个变量修改 page-meta 的 overflow 属性。
在 qinui-popup 的 打开和关闭 事件中可以接受到 qinui-popup 的开启关闭状态 ,并赋值给上面的变量。
<template>
<page-meta :page-style="'overflow:'+(show?'hidden':'visible')"></page-meta>
<view class="container">
<!-- 普通弹窗 -->
<qinui-popup ref="popup" @open="change(true)" @close="change(false)">
<!-- ... -->
</qinui-popup>
</view>
</template>
<script>
export default {
data() {
return {
show:false
}
},
methods: {
change(show) {
this.show = show
}
}
}
</script>
# Tips
- h5 滚动穿透不需要处理,组件内部有处理。或者自己根据状态设置
body上面的overflow属性为hidden和visible,也可以达到这种效果。 - 其他平台无法阻止滚动穿透,建议使用
scroll-view滚动 ,手动设置overflow:hidden或设置scroll-y属性来禁止滚动。
# 五、怎么隐藏组件的滚动条?
组件使用了 scroll-view 标签,在 H5 等平台会出现滚动条,需要全局设置滚动条样式,局部设置不生效。
# 解决方案:
/* APP.vue */
<style lang="scss">
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
</style>
# 六、避免部分扩展组件之间套娃,否则会造成错乱
- 套娃的简单案例:
qinui-popup中嵌套uv-calendars。造成的后果可以复制下面的代码体验下。
<template>
<view>
<qinui-popup ref="popup" mode="top">
<view>
<uv-button :text="`选择时间${time}`" @click="openTime"></uv-button>
<!-- 套在了qinui-popup中...过分...,uv-calendars属于弹窗性质的组件,这样做的后果就是底层组件都不知道自己是啥娃子了 -->
<uv-calendars ref="calendars" @confirm="confirm" />
</view>
</qinui-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>
<qinui-popup ref="popup" mode="top">
<view>
<uv-button :text="`选择时间${time}`" @click="openTime"></uv-button>
</view>
</qinui-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%,你把它执行的范围给缩小到你指定的范围,那弹出来的效果肯定是不对的。
# 七、为什么qinui-popup等弹窗组件显示不使用show属性进行控制,而是使用ref控制
弹窗等组件中都会用到调用 open 方法去执行后续程序,使用监听 show 属性也可以做到,但是实际上使用 watch 监听 show 属性的变化,会比直接调方法执行的慢些,监听到去执行是需要时间的,所以 QinUi 推荐直接调用方法,这可能也是 QinUi 组件使用 ref 的原因,跟着官方对齐没毛病吧。
在 Vuejs 中, ref 方法和监听 show 变化都可以用来访问和操作 DOM 元素。但是,它们的执行顺序是不确定的,因为它们是由 Vuejs 内部处理的。通常情况下, ref 方法会先于监听 show 变化执行,因为它可以更早地访问和操作 DOM 元素。然而,在某些情况下,监听show 变化可能会先于 ref 方法执行。例如,当 show 属性在组件实例化之前发生变化时,监听 show 变化可能会先执行。
可以用一个简单示例来解释:可以看出下面的示例 show 的变化在前, open 方法执行在后,但是最后打印的结果是 open 中的程序在前,监听 show 变化程序在后。
总结:从性能和代码洁癖上来考虑,还是建议使用 ref 进行控制,这也正是 QinUi 深思熟虑的结果。
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>