我正在实现一个菜单,当用户单击头像时该菜单将打开。问题在于菜单在完全不同的位置呈现:
化身是右边的绿色“ OB”按钮。没有控制台错误,没有检查Popover
元素,它正在接收anchorEl
道具:
化身右侧的语言菜单呈现得很好,可以在应打开的位置打开。我的代码看起来不错,我真的不确定为什么位置错误:
export function DashboardNavbar({ setDrawer }) {
// translation hook
const { i18n } = useTranslation("navbar");
// config drawer state
const [configDrawer, setConfigDrawer] = useState(false);
// config menu state
const configMenuState = usePopupState({
variant: "popover",
popupId: "configMenu"
});
// avatar id
const [cookie] = useCookies("userInfo");
const decodedToken = decodeToken(cookie.userInfo.token);
const avatarId =
decodedToken.firstName.charAt(0) + decodedToken.lastName.charAt(0);
function DesktopNavbar() {
return (
<>
<StyledDashboardNavbar>
<Container maxWidth="lg">
<div
style={{
display: "flex",
justifyContent: "flex-end"
}}
>
<Avatar
style={{
backgroundColor:
theme.palette.secondary.main
}}
{...bindTrigger(configMenuState)}
>
{avatarId}
</Avatar>
<DashboardMenu
bindMenu={bindMenu}
menuState={configMenuState}
/>
<LanguageMenu i18n={i18n} />
</div>
</Container>
</StyledDashboardNavbar>
</>
);
}
function MobileNavbar() {
return (
<>
<StyledDashboardNavbar>
<Container maxWidth="md">
<div className="navbar">
<div
style={{
display: "flex",
alignItems: "center"
}}
>
<MenuIcon
color="secondary"
onClick={() => setDrawer(true)}
/>
</div>
<div
className="logo"
onClick={() => setConfigDrawer(true)}
>
<Avatar
style={{
backgroundColor:
theme.palette.secondary.main
}}
>
{avatarId}
</Avatar>
</div>
</div>
</Container>
</StyledDashboardNavbar>
<AvatarDrawer
drawer={configDrawer}
setDrawer={setConfigDrawer}
/>
</>
);
}
return window.innerWidth > 480 ? <DesktopNavbar /> : <MobileNavbar />;
}
我正在使用material-ui-popup-state
,但是我尝试在没有此程序包的情况下“现场”实现,结果是相同的。
在这方面的任何帮助表示赞赏。提前致谢
问题是DesktopNavbar
内部嵌套DashboardNavbar
。这意味着每次DashboardNavbar
重新渲染时,DesktopNavbar
都将被重新定义。由于DesktopNavbar
与以前的渲染相比,它将是一个新功能DashboardNavbar
,因此React不会将其识别为相同的组件类型,DesktopNavbar
而是将重新安装而不是仅重新渲染。由于菜单状态保持在内DashboardNavbar
,因此打开菜单会导致菜单的重新渲染,DashboardNavbar
因此DesktopNavbar
,由于DesktopNavbar
菜单的重新安装及其内部的所有内容,传递给菜单的锚元素将不再是该菜单元素的一部分。的DOM。
嵌套组件的定义几乎总是一个坏主意,因为每次重新渲染包含的组件时,嵌套的组件都会被视为新的元素类型。
来自https://reactjs.org/docs/reconciliation.html#elements-of-different-
types
:
每当根元素具有不同类型时,React都会拆开旧树并从头开始构建新树。从
<a>
到<img>
或从<Article>
到<Comment>
或从<Button>
到<div>
-这些都将导致完全重建。
当您重新定义DesktopNavbar
并MobileNavbar
重新渲染时DashboardNavbar
,其中的DOM元素的整个树将从DOM中删除并重新创建,而不仅仅是对现有DOM元素进行更改。这会对性能产生重大影响,并且还会引起行为问题,例如您所遇到的行为问题,即您所引用的元素意外地不再是DOM的一部分。
如果改为移动DesktopNavbar
,并MobileNavbar
在顶层,并通过从任何依赖DashboardNavbar
作为道具,这将导致DesktopNavbar
被认可作出反应,一致的组件类型的跨重新呈现DashboardNavbar
。LanguageMenu
不会出现相同的问题,因为大概是在内部对其状态进行管理,因此打开它不会导致重新呈现DashboardNavbar
。
代码示例重组(未执行,因此可能会有小错误):
function DesktopNavbar({configMenuState, i18n}) {
return (
<>
<StyledDashboardNavbar>
<Container maxWidth="lg">
<div
style={{
display: "flex",
justifyContent: "flex-end"
}}
>
<Avatar
style={{
backgroundColor:
theme.palette.secondary.main
}}
{...bindTrigger(configMenuState)}
>
{avatarId}
</Avatar>
<DashboardMenu
bindMenu={bindMenu}
menuState={configMenuState}
/>
<LanguageMenu i18n={i18n} />
</div>
</Container>
</StyledDashboardNavbar>
</>
);
}
function MobileNavbar({setDrawer, configDrawer, setConfigDrawer, avatarId}) {
return (
<>
<StyledDashboardNavbar>
<Container maxWidth="md">
<div className="navbar">
<div
style={{
display: "flex",
alignItems: "center"
}}
>
<MenuIcon
color="secondary"
onClick={() => setDrawer(true)}
/>
</div>
<div
className="logo"
onClick={() => setConfigDrawer(true)}
>
<Avatar
style={{
backgroundColor:
theme.palette.secondary.main
}}
>
{avatarId}
</Avatar>
</div>
</div>
</Container>
</StyledDashboardNavbar>
<AvatarDrawer
drawer={configDrawer}
setDrawer={setConfigDrawer}
/>
</>
);
}
export function DashboardNavbar({ setDrawer }) {
// translation hook
const { i18n } = useTranslation("navbar");
// config drawer state
const [configDrawer, setConfigDrawer] = useState(false);
// config menu state
const configMenuState = usePopupState({
variant: "popover",
popupId: "configMenu"
});
// avatar id
const [cookie] = useCookies("userInfo");
const decodedToken = decodeToken(cookie.userInfo.token);
const avatarId =
decodedToken.firstName.charAt(0) + decodedToken.lastName.charAt(0);
return window.innerWidth > 480 ? <DesktopNavbar configMenuState={configMenuState} i18n={i18n} /> : <MobileNavbar setDrawer={setDrawer} configDrawer={configDrawer} setConfigDrawer={setConfigDrawer} avatarId={avatarId} />;
}
解决此问题的另一种方法是只消除嵌套的组件,因此DashboardNavbar
是单个组件:
export function DashboardNavbar({ setDrawer }) {
// translation hook
const { i18n } = useTranslation("navbar");
// config drawer state
const [configDrawer, setConfigDrawer] = useState(false);
// config menu state
const configMenuState = usePopupState({
variant: "popover",
popupId: "configMenu"
});
// avatar id
const [cookie] = useCookies("userInfo");
const decodedToken = decodeToken(cookie.userInfo.token);
const avatarId =
decodedToken.firstName.charAt(0) + decodedToken.lastName.charAt(0);
const useDesktopLayout = window.innerWidth > 480;
return <>
{useDesktopLayout &&
<StyledDashboardNavbar>
<Container maxWidth="lg">
<div
style={{
display: "flex",
justifyContent: "flex-end"
}}
>
<Avatar
style={{
backgroundColor:
theme.palette.secondary.main
}}
{...bindTrigger(configMenuState)}
>
{avatarId}
</Avatar>
<DashboardMenu
bindMenu={bindMenu}
menuState={configMenuState}
/>
<LanguageMenu i18n={i18n} />
</div>
</Container>
</StyledDashboardNavbar>
}
{!useDesktopLayout &&
<>
<StyledDashboardNavbar>
<Container maxWidth="md">
<div className="navbar">
<div
style={{
display: "flex",
alignItems: "center"
}}
>
<MenuIcon
color="secondary"
onClick={() => setDrawer(true)}
/>
</div>
<div
className="logo"
onClick={() => setConfigDrawer(true)}
>
<Avatar
style={{
backgroundColor:
theme.palette.secondary.main
}}
>
{avatarId}
</Avatar>
</div>
</div>
</Container>
</StyledDashboardNavbar>
<AvatarDrawer
drawer={configDrawer}
setDrawer={setConfigDrawer}
/>
</>
}
</>;
}
主要内容:实例,实例,实例,实例元素是构成 React 应用的最小单位,它用于描述屏幕上输出的内容。 与浏览器的 DOM 元素不同,React 当中的元素事实上是普通的对象,React DOM 可以确保 浏览器 DOM 的数据内容与 React 元素保持一致。 将元素渲染到 DOM 中 首先我们在一个 HTML 页面中添加一个 id="example" 的 <div>: 在此 div 中的所有内容都将由 React DOM 来管
我想知道HTML代码是否有效: 如果它无效,还能做什么?
我有一个弹出窗口,其中包含不同种类的内容,分为几个部分,点击一个按钮就会触发。我试图在此实现中公开适当的可访问性/aria语义。(它不是一个模式对话框,而是一个简单的就地弹出窗口)。根据我目前的研究,我认为这是有意义的: 触发按钮上的咏叹调展开 在触发按钮上 其他可选键盘可访问性 此菜单按钮实现示例:https://www.w3.org/TR/wai-aria-practices/examples
mui框架内置了弹出菜单插件,弹出菜单显示内容不限,但必须包裹在一个含.mui-popover类的div中,如下即为一个弹出菜单内容: <div id="popover" class="mui-popover"> <ul class="mui-table-view"> <li class="mui-table-view-cell"><a href="#">Item1</a></li
我使用onCreateOptionsMenu创建了一个溢出菜单,但该菜单几乎完全位于屏幕之外。我尝试过显式设置(如操作栏菜单显示屏幕中的建议),但这并没有解决我的问题。我也不想遵循使用旧主题的建议(如在ICS-Menu item text Cutoff?)。 XML是 我做错了什么?
因此,我试图用几个HTML输入创建一个动态表单。我有一个对象数组,其中包含应该呈现的的。目前,我能够呈现两个输入,如文本区域,但我如何处理收音机,复选框,选择连同他们的选项?任何帮助都将不胜感激。 请参见此CodeSandBox。