React Material-UI 中“makeStyles”的内部实现?

Posted

技术标签:

【中文标题】React Material-UI 中“makeStyles”的内部实现?【英文标题】:Internal implementation of "makeStyles" in React Material-UI? 【发布时间】:2019-12-04 19:11:49 【问题描述】:

这个问题的目的是了解幕后发生的事情。每次我找到makeStyles() 的代码时,我都觉得我只是在做一个纯粹的复制粘贴,而不了解引擎盖下发生的事情。所以我想在这里发布一个问题,以便有人可以帮助我。

我在许多 React 应用程序中看到过以下类型的代码。当我们打电话给makeStyles() 时,我很想知道发生了什么。所以我跳入了它的定义,但我无法理解它的含义。有人可以帮助我了解如何阅读/理解它。

我在这里理解的是我正在传递一个带有名为theme 的参数的函数。通过该功能后,我不知道发生了什么。如果有人也能帮助我解决这个问题,我将不胜感激。

// Calling makeStyles()
const useStyles = makeStyles(theme => (
  root: 
    display: 'flex',
  ,
  drawer: 
    [theme.breakpoints.up('sm')]: 
      width: drawerWidth,
      flexShrink: 0,
    ,
  ,
  appBar: 
    marginLeft: drawerWidth,
    [theme.breakpoints.up('sm')]: 
      width: `calc(100% - $drawerWidthpx)`,
    ,
  ,
  menuButton: 
    marginRight: theme.spacing(2),
    [theme.breakpoints.up('sm')]: 
      display: 'none',
    ,
  ,
  toolbar: theme.mixins.toolbar,
  drawerPaper: 
    width: drawerWidth,
  ,
  content: 
    flexGrow: 1,
    padding: theme.spacing(3),
  ,
));

//definition of makeStyles()
import  Theme as DefaultTheme  from './createMuiTheme';
import  Styles, WithStylesOptions  from '@material-ui/styles/withStyles';
import  StylesHook  from '@material-ui/styles/makeStyles';

export default function makeStyles<
  Theme = DefaultTheme,
  Props extends  = ,
  ClassKey extends string = string
>(
  styles: Styles<Theme, Props, ClassKey>,
  options?: WithStylesOptions<Theme>,
): StylesHook<Styles<Theme, Props, ClassKey>>;

【问题讨论】:

【参考方案1】:

输入/输出/副作用的高级图片

制作样式

概述:此函数通常在 javascript 文件的顶层调用(而不是从组件/函数内),它返回一个函数(通常称为 useStyles),该函数将在函数组件内使用. 输入:样式对象或样式对象创建函数 如果输入是一个对象,则假定该对象的每个属性都定义了一个样式规则。属性名称是规则名称,属性值是具有 CSS 属性和/或嵌套规则的对象。每个样式规则稍后将用于生成 CSS 类。 如果输入是一个函数,则假定它是一个函数,该函数接收主题作为参数,然后返回一个样式对象,该对象具有在输入为对象的情况下描述的结构。 在makeStyles function declaration 中,此输入称为stylesOrCreator。然后通过getStylesCreator function 将其标准化为具有create 属性的对象,该属性指向将返回样式对象的函数。 输出:useStyles函数 makeStyles 的函数returned 通常称为useStyles,是一个custom hook。这意味着它只能从函数组件和must be called unconditionally 中调用。 在返回此useStyles 函数时,几乎没有发生任何事情。该函数知道它的stylesCreator,但还没有使用它。通过stylesCreator's options,useStyles 函数知道index 稍后将用于确定这些样式相对于其他对@987654352 的调用生成的其他样式表在样式表的&lt;head&gt; 中的位置@/useStyles. 副作用:增加一个global counter,用于确定&lt;head&gt; 中由makeStyles/useStyles 生成的样式表的索引。

使用样式

概述:这是makeStyles返回的函数。应该从函数组件中调用它以获取如下所述的classes 对象。 可选输入:props对象 如果传递,这通常是函数组件的props。然后它将作为参数传递给值是函数的任何样式规则。 您可以在以下答案中看到使用此功能的示例: Send Variable to withStyles in Material UI? Using props to set '&:hover' background-color How to use 'theme' and 'props' in makeStyles? 输出:classes 对象 此对象将样式对象中的每个样式规则名称映射到生成的 CSS 类名称。然后,您可以在组件渲染中利用 classes.rulename 将该 CSS 类应用于元素。 副作用:将样式表添加到 &lt;head&gt; 中的 DOM,其中包含每个样式规则的 CSS 类。

主要工作发生在哪里

大部分魔法发生在您调用useStyles 函数时。函数的开头是here。以下是它执行的关键步骤:

致电attach。 attach function 执行以下关键步骤: 调用stylesCreator.create 获取您的样式对象。 根据您的样式对象利用JSS 到create a style sheet。 JSS 也在此处生成将在 classes 对象中的类名。 Attaches 将此样式表添加到 DOM 中的 &lt;head&gt; 内的适当位置。 Returns the classes object 如果发生触发重新创建 CSS 或组件卸载的情况,则调用 detach 以删除先前生成的样式表。

【讨论】:

是否可以在另一个组件中重用 useStyles?我的意思是,如果我导出这个钩子并在几个组件中使用它,可以吗? @MichaelGustus 是的,但有一些警告。在这里查看我的答案:***.com/questions/56929702/…。【参考方案2】:

makeStyles(styles, [options]) => 钩子 使用钩子模式将样式表与功能组件链接。

参数

    styles (Function | Object):生成样式或样式对象的函数。它将链接到组件。如果您需要访问主题,请使用函数签名。它作为第一个参数提供。

    选项(对象 [可选]): options.defaultTheme(对象 [可选]):

    1.如果主题不是通过主题提供者提供时使用的默认主题。

      options.name(字符串 [可选]):样式表的名称。对...有用 调试。如果未提供该值,它将尝试回退到该名称 组件。 options.flip (Boolean [optional]): 当设置为 false 时,此工作表将选择 - 退出 rtl 转换。设置为 true 时,样式会反转。什么时候 设置为null,它遵循theme.direction。

    其他键被转发到选项参数 jss.createStyleSheet([styles], [options]).。 退货 钩子:钩子。这个钩子可以在函数组件中使用。文档经常将此返回的钩子称为 useStyles。它接受一个参数:将用于样式表中“插值”的属性。

示例

import React from 'react';
import  makeStyles  from '@material-ui/styles';

const useStyles = makeStyles(
  root: 
    backgroundColor: 'red',
    color: props => props.color,
  ,
);

export default function MyComponent(props) 
   const classes = useStyles(props);
   return <div className=classes.root />;  

【讨论】:

以上是关于React Material-UI 中“makeStyles”的内部实现?的主要内容,如果未能解决你的问题,请参考以下文章

React & Material-UI 分页 - 将 Material-UI 的组件连接到 React-Router

如何在 React 测试库中获取 Material-UI 密码输入

在 Material-ui 中使用 mixins 自定义 React 中的组件

React + Jest单元测试中的Material-UI排版错误

为 SelectField 显示空白菜单项的正确方法是啥(material-ui,react)

React:如何组合 Material-UI 中标记的每个多个样式