当前位置: 首页 > 知识库问答 >
问题:

尝试用React State模拟Bootstrap导航栏的折叠/展开

丁宏浚
2023-03-14

我试图使用Bootstrap展开和折叠导航栏时,汉堡图标被点击。问题是我正在使用React,我非常确定Bootstrap的DOM操作与React的DOM操作相冲突。所以我试图从Bootstrap中删除所有的操作,纯粹依靠它们的样式,并使用React来更新类。我觉得这是正确的方式。现在我意识到像React Bootstrap这样的东西存在,但是我已经在整个项目中集成了香草Bootstrap,而且React Bootstrap似乎仍然在版本4上,我使用的是5。

据我所知,Bootstrap正在操作这个div上的类:

引导将转换时间设置为.35秒。下面是我的代码:

const handleNavCollapse = () => {
        if (isNavCollapsed) {
            setNavbarClasses('navbar-collapse collapsing');
            //setTimeout(  <-- I learned this way does not work correctly
            setTimeout(() => 
                setNavbarClasses('navbar-collapse collapse show'),
                350
            );
        } else {
            setNavbarClasses('navbar-collapse collapse');
        }
        setIsNavCollapsed(!isNavCollapsed);
    };

此外,如果这有助于某人找到答案,那么下面是Bootstrap在塌陷类中应用的CSS:

.collapsing {
    height: 0;
    overflow: hidden;
    transition: height 0.35s ease;
}

它在中途工作,因为当点击汉堡图标时,它会正确显示和隐藏导航栏菜单。但是没有过渡。当我像在Bootstrap站点上那样在检查器中查看DOM时,我没有看到折叠类被添加。我只看到它添加show并删除show。也许我没有做setTimeout的权利。

更新:所以我从这个答案中得出:https://stackoverflow.com/a/42650143/571723 事实上我做错了。我切换到箭头功能。现在我看到正在崩溃类立即被添加,然后在350毫秒超时后切换到show。问题是仍然没有过渡动画,它只是在350毫秒后显示菜单。


共有1个答案

易镜
2023-03-14

首先,让我们从一个小建议开始:不要将类存储为状态。您真正想要的是存储一些更原始的值,这些值可用于在渲染时派生最终UI(包括类)。

类似的东西:

const [isCollapsed, setCollapsed] = React.useState(false);

const className = `navbar-collapse ${isCollapsed ? '' : 'show'}`;

return <div className={className}> … </div>;

您还可以使用一个非常常见的实用程序,如clsx(通常是首选的)或类名来构建它。

如果浏览器通过转换在CSS属性(如高度)的自动和实际单位值(如12px)之间插值,那么开发可折叠组件将是微不足道的。但是它们没有,你不能从或到自动转换,但是你可以在单位值之间插值。

这确实是每个可折叠(或手风琴)UI小部件在幕后所做的,它在已知和显式单元维度之间进行动画处理。让我们看看Bootstrap v5. x的原始可折叠实现(它是Vanilla JS,没有jQuery)。

让我们重写那些show()hide()方法而不产生任何干扰,例如添加那些折叠的类(它们专门用于帮助进行一些额外的样式设置)。(以下内容是伪代码,绝对与React无关!)

class Collapsible extends BaseComponent {

  show() {
    this.element.style.height = '0px';
    this.element.style.transition = 'height 300ms';
    this.element.style.height = this.element.scrollHeight + 'px';
  }

  hide() {
    this.element.style.height = this.element.getBoundingClientRect().height + 'px';
    this.element.style.transition = 'height 300ms';
    this.element.style.height = '0px';
  }

}

首先,我们分析show()方法:

>

  • this.element.style.height='0px';

    该行强制可折叠元素的高度0px

    这对下一招很重要。

    this.element.style.transition='height 300ms'

    只是现在我们设置了转换配置。这允许转换仅在该行之后发生的高度更改时开始。(实际上这并不是那么容易,而且这段代码不应该像预期的那样工作,但这或多或少是个想法)。

    this.element.style.heightthis.element.scroll高度px

    我们现在使用HTMLElement.scrollHeight检索元素应该具有的高度。这是因为scrollHeight返回可用于滚动的总高度(从而返回“scroll”和“height”),对于具有overflow:hiddenheight:0px的元素,该值是内容的总高度。

    hide()

    >

  • this.element.style.height=this.element.getBoundingClientRect().height'px'

    设置初始高度,但是这次我们使用HTMLElement.getBoundingClientRect()来获取自访问以来元素的当前尺寸(宽度高度)。style.height会给我们简单的自动,我们需要一个单位值(其中包含px)。

    this.element.style.transition='height 300ms'

    启用转换。

    this.element.style.height='0px'

    通过“隐藏”元素开始转换。

    我们如何在反应中做到这一切?简单的回答是“这并不简单”。

    您可以完全通过状态转换来实现它,如果您要学习React,这将是一个非常好的练习。

    我可以建议的是实际使用一些转换/动画库来为您做这件事,代价是添加几个KB的依赖项(尽管要彻底评估它)。您需要检查库是否支持自动值之间的转换。

    符合描述的一个库是react spring,它还有一个与您想要实现的或多或少相同的示例:https://codesandbox.io/embed/q3ypxr5yp4

  •  类似资料:
    • 问题内容: 这是我简单的导航栏: 我只是想防止这种情况崩溃,因为我不需要它,怎么办? 我想避免编写30万行CSS来覆盖默认样式。 有什么建议吗? 问题答案: 经过仔细检查,没有30万行,但是您需要覆盖大约3-4个CSS属性: 这样,您的菜单就不会折叠。 说明 四个CSS属性分别执行以下操作: 引导程序中的默认属性隐藏平板电脑(风景)和电话菜单的右侧,而是显示一个切换按钮以隐藏/显示它。因此,此属性

    • 问题内容: 我在导航栏中做了一些修改,但是现在切换按钮在单击时没有响应。下面是我的代码。我哪里错了?? 码: 问题答案: 您需要更改此标记 改变 至 原因:的值是关联的nav div的任何类名。在这种情况下

    • 我使用Bootstrap4创建了这个可折叠的导航栏,它工作得很好,但我希望在用户单击链接时关闭它。有办法吗?谢谢 html导航栏: css用于。图标栏,因为引导程序4不使用图标栏类。

    • 主要内容:默认的导航栏,实例,响应式的导航栏,实例,导航栏中的表单,实例,导航栏中的按钮,实例,导航栏中的文本,实例,结合图标的导航链接,实例,组件对齐方式,实例,固定到顶部,实例,固定到底部,实例,静态的顶部,实例,反色的导航栏,实例导航栏是一个很好的功能,是 Bootstrap 网站的一个突出特点。导航栏在您的应用或网站中作为导航页头的响应式基础组件。导航栏在移动设备的视图中是折叠的,随着可用视口宽度的增加,导航栏也会水平展开。在 Bootstrap 导航栏的核心中,导航栏包括了站点名称和基

    • 问题内容: 我使用Bootstrap 4很好地创建了这个可折叠的导航栏,但是我希望当用户单击链接时将其关闭。有什么办法吗?谢谢 html导航栏: .icon-bar的css,因为Bootstrap 4不使用icon-bar类。 问题答案: 您可以像这样将组件添加到链接。 或者 ,(也许是一种更好的方法)像这样使用jQuery。

    • 问题内容: 在导航栏元素外部单击时,如何关闭打开的折叠导航栏?当前,打开或关闭它的唯一方法是单击按钮。 请参见示例和代码: 到目前为止,我已经尝试了以下似乎无效的方法: 问题答案: 看一下: 我知道,调用并不是很优雅,但对我也不起作用,而且我认为该动画比几乎很难添加和删除类更好。