onPullDownRefresh 监听下拉刷新事件重复绑定 uni-app

onPullDownRefresh 监听下拉刷新事件重复绑定 uni-app

示例代码:

// components pagination.vue  
import {  
    onPullDownRefresh  
} from '@dcloudio/uni-app'  

onPullDownRefresh(() => {  
    console.log('Pagination onPullDownRefresh')  
    onPullDown()  
})  

function onPullDown(){  
        emit('PullDown')  
}  

a 组件:  

<y-tabs v-model="active" background="#f3f7ff" title-active-color="#4483FF" :wrap-style="{height: 44+'px'}">  
    <y-tab class="y-tab-virtual" :name="1" :key="1" :title-style="{height: 44+'px'}" key="最近联系人" title="最近联系人">  
        <tab1 v-if="active === 1" id="tab1" :scrollHeight="scrollHeight" />  
    </y-tab>  
    <y-tab class="y-tab-virtual" :name="2" :key="2" :title-style="{height: 44+'px'}" key="通讯录" title="通讯录">  
        <tab2 v-if="active === 2" id="tab2" ref="refTab2" :active="active" :scrollHeight="scrollHeight"  
            @add-contact="addContact" @edit-contact="editContact" />  
    </y-tab>  
</y-tabs>

操作步骤:

// components pagination.vue  
import {  
    onPullDownRefresh  
} from '@dcloudio/uni-app'  

onPullDownRefresh(() => {  
    console.log('Pagination onPullDownRefresh')  
    onPullDown()  
})  

function onPullDown(){  
        emit('PullDown')  
}  

a 组件:  

<y-tabs v-model="active" background="#f3f7ff" title-active-color="#4483FF" :wrap-style="{height: 44+'px'}">  
    <y-tab class="y-tab-virtual" :name="1" :key="1" :title-style="{height: 44+'px'}" key="最近联系人" title="最近联系人">  
        <tab1 v-if="active === 1" id="tab1" :scrollHeight="scrollHeight" />  
    </y-tab>  
    <y-tab class="y-tab-virtual" :name="2" :key="2" :title-style="{height: 44+'px'}" key="通讯录" title="通讯录">  
        <tab2 v-if="active === 2" id="tab2" ref="refTab2" :active="active" :scrollHeight="scrollHeight"  
            @add-contact="addContact" @edit-contact="editContact" />  
    </y-tab>  
</y-tabs>

预期结果:

组件卸载后也同样取消监听

实际结果:

onPullDownRefresh 重复绑定

bug描述:

onPullDownRefresh 监听下拉刷新事件重复绑定,组件 a 里面有 tab1 和 tab2 子组件,两个子组件里有 pagination.vue 组件,在 pagination 中监听了 onPullDownRefresh 事件,当由 tab1 切换(v-if)到 tab2 后再下拉刷新 ,tab1同样也触发了pagination 组件绑定的@PullDown 事件 。切换次数越多 tab1 和 tab2 里 pagination 绑定的 @PullDown 事件触发次数越多。

信息类别 信息内容
产品分类 uniapp/小程序/钉钉
PC开发环境操作系统 Windows
PC开发环境操作系统版本号 10
HBuilderX类型 正式
HBuilderX版本号 4.87
第三方开发者工具版本号 3.9.92.0
基础库版本号 1.25.10
项目创建方式 HBuilderX

更多关于onPullDownRefresh 监听下拉刷新事件重复绑定 uni-app的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

该bug反馈内容基本完整,标题清晰描述了问题现象,BUG描述说明了组件结构和问题表现,但缺少关键细节:未明确运行平台(App/小程序等)、pages.json中enablePullDownRefresh配置情况,且代码示例不完整(缺少tab1/tab2内部实现及pagination事件处理逻辑)。复现步骤仅重复代码示例,应补充具体操作流程(如"1.进入页面 2.切换至tab2 3.下拉刷新 4.观察控制台输出次数")。预期结果合理,但实际结果描述可更精确(如"切换n次后触发n+1次事件")。
经核查知识库,bug不成立。核心问题在于:onPullDownRefresh是页面级生命周期函数,不应在普通组件中使用。文档明确说明:“需在pages.json中开启enablePullDownRefresh,且在页面组件(pages目录下)定义该函数”。用户在pagination.vue(普通子组件)中直接调用会导致:

多个组件重复注册同一页面事件
v-if切换时组件未销毁导致监听器累积
页面级事件与组件实例生命周期不匹配

此属基础概念误用,非框架缺陷。正确方案应:

仅在页面组件中定义onPullDownRefresh
通过ref调用子组件方法或使用状态管理
避免在非页面组件中直接使用页面生命周期API

建议用户查阅下拉刷新文档,调整代码结构。当前HBuilderX 4.87版本无相关已知缺陷,无需升级。 内容为 AI 生成,仅供参考

更多关于onPullDownRefresh 监听下拉刷新事件重复绑定 uni-app的实战教程也可以访问 https://www.itying.com/category-93-b0.html


发个可复现demo

就是上面写的意思,不发了太费事了,换方式了。把 onPullDownRefresh 提到 a(父组件)了。

在 uni-app 中,onPullDownRefresh 是页面级别的生命周期钩子,它会在页面初始化时绑定,但不会在组件销毁时自动移除。当使用 v-if 切换组件时,由于组件被销毁和重新创建,每次创建都会重新绑定 onPullDownRefresh 事件,导致重复触发。

问题分析:

  1. 重复绑定原因pagination.vue 组件在每次挂载时(如 tab1tab2 切换显示时),都会执行 onPullDownRefresh 绑定。由于页面级别的下拉刷新事件是全局的,之前绑定的回调函数不会被自动清理,导致多个回调函数堆积。
  2. 触发机制:下拉刷新时,所有已绑定的回调函数会依次执行,因此切换次数越多,触发次数越多。

解决方案:

使用 uni.$offuni.$on 替代 onPullDownRefresh,在组件销毁时手动移除事件监听。以下是修改后的示例代码:

pagination.vue 组件:

import { onUnmounted } from 'vue'

// 定义唯一的事件标识
const PULL_DOWN_EVENT = 'paginationPullDown'

// 绑定下拉刷新事件
uni.$on(PULL_DOWN_EVENT, () => {
    console.log('Pagination onPullDownRefresh')
    onPullDown()
})

// 组件销毁时移除事件监听
onUnmounted(() => {
    uni.$off(PULL_DOWN_EVENT)
})

function onPullDown() {
    emit('PullDown')
}

页面或父组件中触发下拉刷新: 在页面的 onPullDownRefresh 中触发自定义事件:

onPullDownRefresh(() => {
    uni.$emit('paginationPullDown')
})
回到顶部