Material-ui: تحويل ListItem متوافق مع جهاز التوجيه المتفاعل

تم إنشاؤها على ٣٠ أغسطس ٢٠١٧  ·  21تعليقات  ·  مصدر: mui-org/material-ui

أريد أن أجعل كل ListItem في List إلى Link .

لدي مكون Drawer مكون من List ،
هذه القائمة تتكون من 4 ListItem s.
ما أريد تحقيقه هو تحويل كل ListItem إلى جهاز توجيه React Link .
حاولت تعديل طريقة onClick للدرج ، والحصول على معرف عنصر القائمة الذي تم النقر عليه ثم تغيير موقع النافذة برمجيًا بناءً على المعرف.
لكنني أعتقد أن هذا النهج أكثر استفزازًا من مفاهيم التفاعل.
حاولت أيضًا إضافة Link إلى component prop في ListItem ، لكن نتج عن ذلك خطأ. (لقد رأيت أنك استخدمت خاصية في component في المستندات).
ما هي الطريقة الموصى بها لتحقيق هذا المطلب؟

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Drawer from 'material-ui/Drawer';
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List';
import Face from 'material-ui-icons/Face';
import Person from 'material-ui-icons/Person';
import Assignment from 'material-ui-icons/Assignment';
import Link from 'react-router-dom/Link';
import { FormattedMessage } from 'react-intl';

const styles = {
   list: {
      width: 250,
      flex: 'initial',
    },
};

 class UndockedDrawer extends Component {

   constructor() {
      super();
      this.onClick = this.onClick.bind(this);
    }

    onClick(e, data) {
       console.log(data);
       this.props.onRequestClose();
     }

   render() {
       const classes = this.props.classes;
        const sidebarListItems = (
     <div>
         <ListItem button >
            <ListItemIcon>
               <Person />
           </ListItemIcon>
            <ListItemText primary={<FormattedMessage id="user" />} />
          </ListItem>
    <ListItem button>
      <ListItemIcon>
        <Assignment />
      </ListItemIcon>
      <ListItemText primary={<FormattedMessage id="consultant" />} />
    </ListItem>
    <ListItem button>
      <ListItemIcon>
        <Face />
      </ListItemIcon>
      <ListItemText primary={<FormattedMessage id="student" />} />
    </ListItem>
  </div>
);

const sidebarList = (
  <div>
    <List className={classes.list} >
      {sidebarListItems}
    </List>
  </div>
);

return (
  <div>
    <Drawer
      anchor="right"
      open={this.props.open}
      onRequestClose={this.props.onRequestClose}
      onClick={this.onClick}
    >
      {sidebarList}
    </Drawer>
   </div>
   );
   }
 }

  UndockedDrawer.propTypes = {
     classes: PropTypes.shape({}).isRequired,
     open: PropTypes.bool.isRequired,
     onRequestClose: PropTypes.func.isRequired,
    };

   export default withStyles(styles)(UndockedDrawer);
  • واجهة المستخدم المادية: 1.0.6 بيتا
  • رد الفعل: ^ 15.6.1
  • المتصفح: كروم: 60
  • رد فعل جهاز التوجيه دوم: ^ 4.1.2
question

التعليق الأكثر فائدة

هذا مغطى في الوثائق: https://material-ui.com/components/buttons/#third -party-routing-library.

import React from 'react';
import { MemoryRouter as Router } from 'react-router';
import { Link, LinkProps } from 'react-router-dom';
import ListItem from '@material-ui/core/ListItem';
import { Omit } from '@material-ui/types';

// The usage of React.forwardRef will no longer be required for react-router-dom v6.
// see https://github.com/ReactTraining/react-router/issues/6056
const AdapterLink = React.forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => (
  <Link innerRef={ref as any} {...props} />
));

const CollisionLink = React.forwardRef<HTMLAnchorElement, Omit<LinkProps, 'innerRef' | 'to'>>(
  (props, ref) => <Link innerRef={ref as any} to="/getting-started/installation/" {...props} />,
);

export default function ButtonRouter() {
  return (
    <Router>
      <ListItem color="primary" component={AdapterLink} to="/">
        Simple case
      </ListItem>
      <ListItem component={CollisionLink}>Avoids props collision</ListItem>
    </Router>
  );
}

ال 21 كومينتر

لقد اكتشفت أنه يمكنني تغليف ListItem بـ Link النحو التالي:

<Link to="users" style={{ textDecoration: 'none' }}>
      <ListItem button >
        <ListItemIcon>
          <Person />
        </ListItemIcon>
        <ListItemText primary={<FormattedMessage id="user" />} />
      </ListItem>
    </Link>

مع هذا النهج ، سيتم تشغيل طريقة onClick أيضًا.
أي اقتراحات أو إهمال؟

اكتشفت ذلك ، يمكنني تغليف عنصر القائمة في رابط على النحو التالي

هذا الحل ليس صالحًا من الناحية الدلالية. ألق نظرة على كيفية تعاملنا مع المشكلة في الوثائق:

https://github.com/callemall/material-ui/blob/92bd073015b9cc0dff3a26195fcb49153ddaab78/docs/src/modules/components/AppDrawerNavItem.js#L71 -L83

يمكنك أيضًا تجربة هذا

https://github.com/callemall/material-ui/blob/92bd073015b9cc0dff3a26195fcb49153ddaab78/docs/src/pages/demos/buttons/FlatButtons.js#L40 -L42

هذا مغطى في الوثائق: https://material-ui.com/components/buttons/#third -party-routing-library.

import React from 'react';
import { MemoryRouter as Router } from 'react-router';
import { Link, LinkProps } from 'react-router-dom';
import ListItem from '@material-ui/core/ListItem';
import { Omit } from '@material-ui/types';

// The usage of React.forwardRef will no longer be required for react-router-dom v6.
// see https://github.com/ReactTraining/react-router/issues/6056
const AdapterLink = React.forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => (
  <Link innerRef={ref as any} {...props} />
));

const CollisionLink = React.forwardRef<HTMLAnchorElement, Omit<LinkProps, 'innerRef' | 'to'>>(
  (props, ref) => <Link innerRef={ref as any} to="/getting-started/installation/" {...props} />,
);

export default function ButtonRouter() {
  return (
    <Router>
      <ListItem color="primary" component={AdapterLink} to="/">
        Simple case
      </ListItem>
      <ListItem component={CollisionLink}>Avoids props collision</ListItem>
    </Router>
  );
}

لا أراه في المستندات:
https://material-ui-next.com/demos/lists/
https://material-ui-next.com/demos/drawers/

هذا أمر شائع عند استخدام React Router ، لكن ليس من الواضح كيفية استخدام NavLink في ListItem .
A Button مع component ؟
وهل يتم مزج دعامات الأزرار ودعائم المكون معًا في علامة JSX نفسها؟
ما هو هذا النوع من mixin؟
لماذا معقدة للغاية؟

عند استخدام حل mehrdaad ، تبدو الروابط مثل قائمة MUI العادية ، ولكن عند استخدام component={Link} كما اقترح oliviertassinari ، يتم
(في الصورة ، يحوم الماوس فوق "إنشاء" ولكن العنصر الثاني يحصل على التسطير ...)

screen shot 2017-11-16 at 12 09 05

ilyador تم حل مشكلة نمط ارتباط واجهة المستخدم هذه.

@ zhangwei900808 لا ، لا يزال هذا خطأ من الناحية اللغوية ، فهو يولد <ul><a ..>...
https://codesandbox.io/s/lpwq74p30m

فقط استخدم الإجابة الواردة أعلاه

oliviertassinari هل هناك طريقة أسهل للقيام بذلك:

const styles = {
    li: {
        '&:hover': {
            backgroundColor: 'transparent',
        },
    },
};
// ...
<MenuItem disableGutters className={classes.li}>
    <Button component={Link} to="/logout" ...

لتجنب تأثير التمرير المزدوج ، على MenuItem وعلى Button (التي لا تزال تحتوي على هامش / حشوة طفيفة ، مشكلة أخرى)
لأن هذا مرهق

العرض التوضيحي: https://codesandbox.io/s/nk834yk5pl (لا تستخدم component={Link} to="/..." لكن هذا هو نفسه)

caub لماذا تقوم بإدخال مكون زر إضافي؟ يمكنك استخدام خاصية المكون في MenuItem.

oliviertassinari لأن ul > a غير صالح html5 https://codesandbox.io/s/lpwq74p30m

caub nav > a صالح.

حسنًا ، شكرًا ، جيد https://codesandbox.io/s/lpwq74p30m

هذا هو الحل الذي حل مشكلتي

<List>
        {menus.map((menu: any, index: any) => {
          return (
            <ListItem
              key={index}
              {...{ to: menu.link }}
              component={Link}
              button={true}
            >
              <ListItemIcon>{menu.icon}</ListItemIcon>
              <ListItemText primary={menu.text} />
            </ListItem>
          );
        })}
      </List>

وبالتالي فقط استخدم ListItem كـ
مفتاح = {فهرس}
** {... {to: menu.link}} **
المكون = {Link}
زر = {صحيح}
>

import {Link} from 'react-router-dom'

<ListItem component={Link} to="/" button>

// or
<ListItem component={props => <Link to="/" {...props} />} button>

mehrdaadoliviertassinari لقد نجحت ^ _ ^

كان هذا مثاليا بالنسبة لي. شكر!

فشلت الإجابة الأكثر تصويتًا بعد ترحيل MUI v4 (أنا على 4.3.1) بسبب "لا يمكن إعطاء المراجع لمكونات الوظيفة. ستفشل محاولات الوصول إلى هذا المرجع. هل تقصد استخدام React.forwardRef ()؟"

لقد استبدلت المكون NavLink بغلاف مثل:

import React, { Component } from "react"
import { NavLink } from "react-router-dom"

/**
 * React Router Nav Link wrapper to forward the ref to fix "Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?"
 *
 * From https://material-ui.com/guides/composition/#caveat-with-refs
 */
class NavLinkMui extends Component {
    render() {
        const { forwardedRef, ...props } = this.props
        return <NavLink {...props} ref={forwardedRef} />
    }
}

export default NavLinkMui

استعمال:

<ListItem
    button
    component={NavLinkMui}
    to='/'
>
    <ListItemIcon>
        <SlideshowIcon />
    </ListItemIcon>
</ListItem>

HugoGresse نعم ، أنت بحاجة إلى استخدام واجهة برمجة تطبيقات المرجع الأمامي. يجب أن تكون قادرًا على العثور على أمثلة في الوثائق. لقد قمت بتحديث https://github.com/mui-org/material-ui/issues/7956#issuecomment -326908167 بإجابة محدثة. أخبرنا إذا كان الأمر جيدًا.

oliviertassinari فعلت.

ما زلت أواجه بعض المشكلات مع حل forwardRef أو حل مكون حيث لا يأخذ لون نص الزر في الاعتبار لون لوحة السمات. يجب أن يكون لون النص أبيض ليطابق palette.type: 'dark' ، لكنه أبيض.

ربما يكون مرتبطًا بتغيير على MUI لأنه بدون الدعائم component ما زلت أواجه المشكلة.
Capture d'écran 2019-08-06 16 54 51

لأولئك الذين يقرؤون هنا ، يمكنك تمرير دعامات إضافية إلى ListItemText ...

<ListItemText
    primaryTypographyProps={{
        color: 'textPrimary'
    }}
    primary="Dashboard"
/>

راجع للشغل ، المثال الخاص بك الآن في TS.

هذا هو الحل الذي حل مشكلتي

<List>
        {menus.map((menu: any, index: any) => {
          return (
            <ListItem
              key={index}
              {...{ to: menu.link }}
              component={Link}
              button={true}
            >
              <ListItemIcon>{menu.icon}</ListItemIcon>
              <ListItemText primary={menu.text} />
            </ListItem>
          );
        })}
      </List>

وبالتالي فقط استخدم ListItem كـ
مفتاح = {فهرس}
** {... {to: menu.link}} **
المكون = {Link}
زر = {صحيح}
>

button={true} ببساطة يجعل سلوك واجهة المستخدم للأدراج هو نفسه سلوك عدم وجود رابط.

بالنسبة للآخرين الذين يحاولون القيام بذلك في نسخة مطبوعة:

مثال بسيط باستخدام خاصية مكون ListItem لتحديد ملفعنصر كتطبيق ListItem. تكمن الحيلة في Typescript في استخدام عامل تشغيل الانتشار (...) في خصائص عنصر القائمة للتسلل إلى أخطاء التنضيد غير المرغوب فيها وغير الضرورية التي يؤدي تحديد هذا النوع من المكونات وخصائص "إلى" لعنصر القائمة عادةً إلى حدوث (Typescript خطأ TS2769 الخاصية 'مكون' غير موجودة في النوع 'IntrinsicAttributes ...)

import { NavLink } from "react-router-dom";

        <List>
            <ListItem button={true} {...{ component: NavLink, to: "/Somewhere" }}>
                <ListItemIcon>
                    <ShoppingCartIcon />
                </ListItemIcon>
                <ListItemText primary="Orders" />
            </ListItem>
        </List>

أو بدلاً من ذلك إذا كنت تريد فقط استخدام وظيفة onClick في ListItem على سبيل المثال:


    <List>
        <ListItem button={true} {...{ onClick: () => alert("foo") }}>
            <ListItemIcon>
                <DashboardIcon />
            </ListItemIcon>
            <ListItemText primary="Dashboard" />
        </ListItem>
    </List>

""

هذا عمل معي

const NavLinkMui = React.forwardRef((props, ref) => (
  <NavLink {...props} activeClassName="Mui-selected" ref={ref} />
))
<ListItem button component={NavLinkMui} to={to}>{text}</ListItem>

فشلت الإجابة الأكثر تصويتًا بعد ترحيل MUI v4 (أنا على 4.3.1) بسبب "لا يمكن إعطاء المراجع لمكونات الوظيفة. ستفشل محاولات الوصول إلى هذا المرجع. هل تقصد استخدام React.forwardRef ()؟"

لقد استبدلت المكون NavLink بغلاف مثل:

import React, { Component } from "react"
import { NavLink } from "react-router-dom"

/**
 * React Router Nav Link wrapper to forward the ref to fix "Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?"
 *
 * From https://material-ui.com/guides/composition/#caveat-with-refs
 */
class NavLinkMui extends Component {
    render() {
        const { forwardedRef, ...props } = this.props
        return <NavLink {...props} ref={forwardedRef} />
    }
}

export default NavLinkMui

استعمال:

<ListItem
    button
    component={NavLinkMui}
    to='/'
>
    <ListItemIcon>
        <SlideshowIcon />
    </ListItemIcon>
</ListItem>

شكرا HugoGresse هذا يعمل بشكل جيد :-)

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

ghost picture ghost  ·  3تعليقات

mb-copart picture mb-copart  ·  3تعليقات

ryanflorence picture ryanflorence  ·  3تعليقات

reflog picture reflog  ·  3تعليقات

iamzhouyi picture iamzhouyi  ·  3تعليقات