Привет, я просматривал текущую реализацию пунктов меню и заметил, что на самом деле нет ссылки (имеется в виду тег html <a>
). В результате, например, даже в панели навигации нет фактической ссылки, а переходы на другие страницы управляются через события onclick.
Я думаю, что наличие ссылок было бы улучшением, особенно учитывая страницы, отображаемые на стороне сервера.
Как вы думаете, есть ли в этом смысл, или у вас есть конкретные причины не идти в этом направлении?
Я тоже думаю об этом. Я использую рендеринг на стороне сервера в своем приложении, это то, на что стоит обратить внимание.
Использование элементов привязки с атрибутами href
также улучшит доступность и позволит людям использовать поведение браузера, к которому они привыкли (например, ⌘-Щелкните, чтобы открыть в новой вкладке).
+1
+1
+1
+1
+1
+1
+1
@ecesena Как вы думаете, это все еще будет проблемой с новым компонентом MenuItem
? Смотрите здесь . MenuItem
могут быть окружены <a>..</a>
, не так ли?
это возможно с тем, что предложил @shaurya947 .
Я пытаюсь использовать MenuItems
в моем LeftNav следующим образом:
let menuItems = (
<div>
<MenuItem primaryText="Doors" leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} /></a>
<MenuItem primaryText="Load" leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
<MenuItem primaryText="Notes" leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
<MenuItem primaryText="Alerts" leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
<MenuItem primaryText="Admin" leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
</div>
);
return (
<LeftNav
ref="leftNav"
docked={false}
onChange={this._onLeftNavChange}
>
{menuItems}
</LeftNav>
)
Оборачивая <a>
вокруг тега <MenuItem>
выдается предупреждение validateDOMNesting(...): <a> cannot appear as a descendant of <a>. See MainLayout > a > ... > MenuItem > ListItem > EnhancedButton > a"
Если вы сделаете проверку вывода React, вы получите следующее.
<a href="/">
<MenuItem..>
<ListItem..>
<div>
<EnhancedButton..>
<a>
<TouchRipple ..>
</a>
</EnhancedButton>
</div>
</ListItem>
</MenuItem>
</a>
который с вложенными элементами <a>
является оскорбительным.
<MenuItems>
генерирует элементы <a>
в объявлении Button. Какая опора используется из MenuItem
для заполнения атрибута href в сгенерированном <EnhancedButton>
?
Использование объекта MenuItem в качестве опоры для LeftNav позволяет связать работу, но я не смог понять, как таким образом добавлять левые/правые значки.
то есть:
let menuItems = [
{ route: '/load_areas/'+ this.state.area + '/doors', text: 'Doors' },
{ route: '/load_areas/'+ this.state.area + '/trailer_loads', text: 'Load' },
{ route: 'notes', text: 'Notes' },
{ route: 'alerts', text: 'Alerts' },
{ route: 'admin', text: 'Admin' }
];
<LeftNav
ref="leftNav"
docked={false}
menuItems={menuItems}
onChange={this._onLeftNavChange}
/>
это отдельная проблема, пожалуйста, откройте ее, чтобы мы могли пометить ее и добавить к вехам, tnx :grin:
Используйте реквизит containerElement
!
видеть:
http://stackoverflow.com/questions/32106513/material-ui-menu-using-routes/34507786#34507786
<MenuItem
containerElement={<Link to="/profile" />}
primaryText="Profile"
leftIcon={
<FontIcon className="material-icons">people</FontIcon>
} />
Теперь реквизит linkButton
EnhancedButton
устарел. LinkButton больше не требуется, если указано свойство href
. Он будет удален с v0.16.0.
Например:
<MenuItem primaryText="Primary Text" href="/your/link" />
href перезагружает страницу. как насчет того, если я хочу использовать реагирующий маршрутизатор
@cezarneaga попробуй href="#/your/link"
<MenuItem
containerElement={<Link to="/profile" />}
.../>
в документации упоминается, что вам также необходимо ввести linkButton
. если это убрать, то работает без ошибок.
@DaxChen Я видел ваш обновленный ответ stackoverflow за декабрь 2016 года (крайне недавний, ха-ха), и мне было интересно, знаете ли вы, работает ли это для элемента меню в ящике? Я пытаюсь сделать следующее ниже, и мне совершенно не удалось заставить Link работать с MenuItem, поскольку containerElement, похоже, ничего не делает.
<Drawer
docked={false}
width={300}
onRequestChange={this.closeDrawer}
open={this.state.open}>
<AppBar title="Title"
/>
<MenuItem primaryText="home" containerElement={<Link to="/home" />} />
</Drawer>
containerElement работает, но не задокументирован, поэтому я думаю, что эта тема пока должна служить официальной документацией. Спасибо!
Привет @Faolain !
Искренне извиняюсь за поздний ответ...
Я попробовал ваш код в чистом приложении с помощью create-react-app
, но все вроде работало нормально?!
Может вы по другому настроили react-router
или версия другая?
В любом случае, вот пример репозитория и живая демонстрация здесь .
Если вы все еще не можете найти причину своей проблемы, можете ли вы предоставить образец репозитория для воспроизведения?
Ни одно из приведенных выше решений не работало в Safari и iOS. Итак, вот что я сделал в качестве обходного пути для react-router
<MenuItem
onTouchTap={() => {
this._yourMethod()
browserHistory.push('/howItWorks')
}}
primaryText="Menu Link"
/>
@janzenz этот пример не работает в вашем браузере?
Я попробовал это в Safari на macOS и Safari на iOS, и все они работают. Это не работает для вас?
Хотя ваш обходной путь работает, он может привести к ухудшению SEO, и вы потеряете некоторые собственные функции, такие как предварительный просмотр ссылки и нажатие опции, чтобы открыть в новой вкладке.
@DaxChen спасибо за понимание. Я не уверен, что моя проблема связана с вашей первой ссылкой. Я уже пробовал второй, но как только я добавляю реквизит onTouchTap
<Link />
больше не работает.
@janzenz Я добавил реквизит onTouchTap
в свой предыдущий пример, и он все еще работает.
Не знаю, отличается ли где-то ваша настройка или что-то в этом роде... 😢
Вы можете проверить обновленный код и посмотреть, работает ли он для вас?
@DaxChen Я вижу, вы используете material-ui
в версии ~0.16.0
. Пробовали ли вы последнюю версию ~0.17.0
и посмотрите, не проблема ли это?
@janzenz Я использовал более старую версию, только что обновил ее до последней 0.17.4
и она все еще работает!
Туше! Тогда, наверное, моя установка. Спасибо, что подтвердили, что @DaxChen я вернусь к этой теме, если
@DaxChen , я попробовал пример, который вы мне дали, но он не работает
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of `EnhancedButton`.
at invariant (invariant.js:44)
at ReactCompositeComponentWrapper.instantiateReactComponent [as _instantiateReactComponent] (instantiateReactComponent.js:74)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:367)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at mountComponentIntoNode (ReactMount.js:104)
at ReactReconcileTransaction.perform (Transaction.js:140)
at batchedMountComponentIntoNode (ReactMount.js:126)
at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:140)
at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:62)
at Object.batchedUpdates (ReactUpdates.js:97)
at Object._renderNewRootComponent (ReactMount.js:320)
at Object._renderSubtreeIntoContainer (ReactMount.js:401)
at Object.render (ReactMount.js:422)
at Object.<anonymous> (index.js:36)
at __webpack_require__ (bootstrap e3e2367…:555)
at fn (bootstrap e3e2367…:86)
at Object.<anonymous> (bootstrap e3e2367…:578)
at __webpack_require__ (bootstrap e3e2367…:555)
at bootstrap e3e2367…:578
at bootstrap e3e2367…:578
Мой код доступен по адресу https://github.com/hhimanshu/spicyveggie/tree/cards (ветка cards
)
Я не уверен, что отличается, но это просто не работает
@janzenz
Я также пробовал browserHistory.push('/howItWorks')
и импортировал import browserHistory from 'react-router-dom'
, но получил undefuned
.
@Oduig ,
Я пробовал #/your/link
, но это никуда не ведет
Я пробовал /your/link
, но страница перезагружается, и я теряю Drawer
из Material-UI
Ни одна из этих вещей не работала для меня. Мой код доступен по адресу https://github.com/hhimanshu/spicyveggie/tree/cards (ветвь cards
), конкретная фиксация https://github.com/hhimanshu/spicyveggie/commit/844b7b7cddf9102995cd2680a783df3b6ef48537 , может кто-нибудь, пожалуйста, помогите?
@DaxChen , спасибо. Вот и все. Однако не тогда, когда моя страница загружается с {<Link to="/menu"/>}
, она загружает всю страницу, а мой Drawer
исчезает.
@hhimanshu это потому , что вы использовали только Menu
компонента в вашем \menu
маршрута , так что App
не будут оказаны.
Вложите свои Menu
и Summary
внутрь App
или некоторых компонентов макета и передайте соответствующие дочерние элементы.
Вы можете использовать react-devtools для проверки иерархии отображаемых компонентов и их состояний!
Это не связано с material-ui, пожалуйста, читайте больше в учебниках/документах по реакции-маршрутизатору.
Спасибо @DaxChen , я решил это как https://github.com/hhimanshu/spicyveggie/blob/master/src/index.js#L20.
+1
Обходные пути для ссылок, ОБРАБАТЫВАЕМЫХ И НЕ ОБРАБАТЫВАЕМЫХ React Router.
Если целевая ссылка обрабатывается React Router
MenuItemLink.js
import React from 'react';
import { MenuItem } from 'material-ui/Menu';
import { Route } from 'react-router-dom';
class MenuItemLink extends React.Component {
render() {
const {
to, also,
...rest
} = this.props;
return (
<Route
render={({ history, location }) => (
<MenuItem
onClick={() => {
history.push(to);
if (typeof also === 'function') {
also();
}
}}
{...rest}
/>
)}
/>
);
}
}
MenuItemLink.muiName = 'MenuItem';
export default MenuItemLink;
Образец кода:
import MenuItemLink from './MenuItemLink';
<Menu ... >
<MenuItemLink to="/users"
also={this.handleRequestClose}>Users</MenuItemLink>
</Menu>
Если целевая ссылка НЕ обрабатывается React Router, то есть: запрос перенаправляется на сервер API или что-то еще
Функция onClick:
function facebookLoginRedirect () {
if (window) window.location.href = "/api/auth/facebook"
return true;
}
Образец кода:
<MenuItem onClick={ facebookLoginRedirect }>Login with Facebook</MenuItem>
Я собираюсь добавить к этому, на случай, если кто-то еще наткнулся на это.
В v3.4 вы можете добиться этого следующим образом:
import { Link } from 'react-router-dom';
import MenuItem from '@material-ui/core/MenuItem';
...
<MenuItem component={Link} to="/your-path">...</MenuItem>
Единственное решение, которое сработало для меня без нарушения макета меню, было:
```javascript
Единственное решение, которое сработало для меня без нарушения макета меню, было:
<MenuList> <Link to='/your-path' style={{ textDecoration: 'none' }}> <MenuItem> Notifications </MenuItem> </Link> <Link to='/your-path' style={{ textDecoration: 'none' }}> <MenuItem> Profile </MenuItem> </Link> </MenuList>
@eladlevy Это приведет к плохой семантике HTML.
<ul>
<a><li/></a>
<a><li/></a>
</ul>
Оставьте это здесь на случай, если это кому-нибудь поможет (под управлением версии 3.9.0). Мне нужно <Select>
чтобы действовать как меню из react-router-dom
<Link>
s. Каждая ссылка соответствовала настройке языка, поэтому в раскрывающемся списке отображалось значение текущего языка из параметра запроса.
<Select value={currentLanguage}>
{languages.map(language => (
<ListItem
button
component={btnProps => (
<Link
to={ `/things?lang=${ language }` }
{...btnProps as any}
/>
)}
value={language}
key={language}
>
{language}
</ListItem>
))}
</Select>
Это было самое чистое решение, которое я мог найти, которое требовало минимального приведения TypeScript и поддерживало визуальные эффекты, соответствующие пользовательскому интерфейсу материалов.
У @goyney есть решение, спасибо
Я собираюсь добавить к этому, на случай, если кто-то еще наткнулся на это.
В v3.4 вы можете добиться этого следующим образом:
import { Link } from 'react-router-dom'; import MenuItem from '@material-ui/core/MenuItem'; ... <MenuItem component={Link} to="/your-path">...</MenuItem>
Рабочее и чистое решение, спасибо ❤️
Для внешних ссылок вы захотите использовать component="a"
, но также окружите MenuItem
<li>
:
<MenuList>
<li>
<MenuItem
component="a"
href="https://google.com"
target="_blank"
>Google</MenuItem>
</li>
</MenuList>
Это генерирует следующий HTML:
<ul class="MuiList-root MuiList-padding" role="menu" tabindex="-1">
<li>
<a class="[...]" tabindex="-1" aria-disabled="false" role="menuitem" href="https://google.com" target="_blank">Google</a>
</li>
</ul>
Предположим, у меня есть всплывающее меню и я использую
импортировать {Link} из 'react-router-dom';
импортировать MenuItem из '@material-ui/core/MenuItem';
\
Ссылка откроет страницу /your-path, как закрыть всплывающее меню?
Самый полезный комментарий
Используйте реквизит
containerElement
!видеть:
http://stackoverflow.com/questions/32106513/material-ui-menu-using-routes/34507786#34507786