使用bslib时Shiny自定义JavaScript滚动事件监听器失效问题
解决bslib Shiny应用中滚动事件监听器无响应问题
我开发了一个Shiny应用,希望用户滚动时修改导航栏的CSS类。用原生JS添加scroll事件监听器实现,代码能执行(控制台打印"START")但滚动时无响应;手动执行DOM操作可生效,纯Shiny版本正常,但用bslib的版本失效。
解决方案
问题出在两个核心点:bslib的页面滚动容器并非document,且原JS代码存在逻辑运算符错误。以下是修复后的完整代码:
修复后的bslib示例代码
library(shiny) library(bslib) js <- 'let attop = true console.log("START") // 获取bslib的内容滚动容器 const contentContainer = document.querySelector(".bslib-page-content"); // 监听内容容器的滚动事件 contentContainer.addEventListener("scroll", (event) => { console.log("SCROLL"); // 用容器的scrollTop代替window.scrollY判断滚动位置 const scrollPos = contentContainer.scrollTop; // 修正逻辑与运算符:将位运算符&改为逻辑与&& if (scrollPos != 0 && attop) { attop = false; let col = document.getElementsByClassName("navbar"); for (let i = 0; i < col.length; i++) { col[i].classList.add("navbar-red"); } console.log("Not At Top"); } else if (scrollPos == 0) { attop = true; let col = document.getElementsByClassName("navbar"); for (let i = 0; i < col.length; i++) { col[i].classList.remove("navbar-red"); } console.log("At Top!"); } }); ' ui <- page_navbar( theme = bs_theme() |> bs_add_rules(".navbar.navbar-red { background-color: red !important; }"), id = "navbar", title = "NAVBAR", tabPanel( title = "hello", tags$head(tags$script(HTML(js))), h2("header"), div(style = "height: 200vh; background-color: lightgray;") ) ) shinyApp(ui, server = function(input, output, session) {})
关键修改说明
- 滚动容器切换:bslib的
page_navbar将页面内容包裹在.bslib-page-content容器中,滚动行为发生在这个容器上而非document,因此需要监听该容器的scroll事件,同时用容器的scrollTop属性判断滚动位置。 - 逻辑运算符修正:原代码中使用的
&是位运算符,而非逻辑与运算符,会导致逻辑判断异常,需改为&&。 - CSS选择器优化:简化CSS选择器,适配bslib导航栏的类结构,确保样式正常生效。
纯Shiny版本正常的原因
纯Shiny的navbarPage使用固定导航栏(position = fixed-top),页面滚动行为直接作用于document,因此绑定document的scroll事件可正常触发;同时原代码的&错误在部分浏览器环境下未暴露,但仍是潜在问题。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

