我什么时候应该在 Material-UI 中使用 style 而不是 sx prop?

say*_*ode 27 javascript reactjs material-ui

MUI 组件中的 style 和 sx prop 几乎做同样的事情。sx 属性提供了一些简写语法,并允许您访问主题对象。但除此之外,它们看起来完全相同。你什么时候应该使用其中一种而不是另一种?

say*_*ode 41

要真正了解使用哪一个,我们需要了解幕后发生的情况。Material UI 使用情感(或您手动选择的任何样式引擎)来设置其组件的样式。从表面上看,以下两个似乎在做同样的事情:

<Box sx={{ height:'50px', width:'25px' }}/>
<div style={{ height:'50px', width:'25px' }}/>
Run Code Online (Sandbox Code Playgroud)

两者都将具有所需高度和宽度的 div 渲染到 DOM。但对于 div,样式以内联样式应用,而 Box 以类的形式将样式应用于 div 元素。类定义本身存储在 head 标记中,您可以检查该标记以查看以下内容 充满情感的 CSS 类声明 应用于 div 的 CSS 类

只要我们只声明一次样式,这一切都很好。但当你添加动态样式时,事情真的会变得疯狂。也许有一个状态变量控制你的 div 的高度。

function CustomComponent(){
  const [computedHeight,setComputedHeight]=useState();

  useEffect(()=>{
    window.addEventListener('resize',()=>setComputedHeight(window.innerWidth/2))
  },[]);

  return (
    <Box sx={{ height:computedHeight, width:'25px'}}/>
    <div style={{ height:computedHeight, width:'25px'}}/>
  )

Run Code Online (Sandbox Code Playgroud)

这是一种常见的情况,其中某些外部变量(例如浏览器窗口的宽度)决定了组件的某些属性。每当此状态更改为新值时,MUI 都会创建一个新类,将其设置为 Box 的类,并将定义添加到<head>您网站的标签中,作为一个全新的<style>标签。因此,在很短的时间内,head 标签就会填满数百个 style 标签,这显然是不可取的。

但是,对于 div 标签,样式位于内联。因此,无论值更改一次,还是一百次,样式都只有一个定义,并且它存在于元素本身上。无需担心。

编辑1:

MUI 仅为以前未使用过的样式创建新的样式标记。为了说明这一点,如果你的 sx prop 像这样动态地改变“红色”和“蓝色”之间的颜色,

sx={{
  color: dynamicValue ? 'red' : 'blue',
}}
Run Code Online (Sandbox Code Playgroud)

color无论您更改dynamicValue 的值多少次,MUI 都只会创建两个标签(针对 的两个可能值)。MUI 将只使用旧样式标签。

关于伪选择器的注意事项: 另一件事需要注意的是,内联样式不能使用伪元素(如::after、 或::before)或伪类(如:hover:focus),因为内联样式直接影响当前元素。您必须采用像 css 变量这样的解决方法才能更改伪元素/类的样式。

太长了;将动态样式(根据某些变量更改的样式)放在 style 属性中,并将所有静态样式放在 sx 属性中


San*_*ath 10

stylesxMUI 5 中的比较

沙盒链接

sxprop 仅适用于 MUI 组件Grid,例如Box、 等,而styleprop 则适用于 MUI 组件和类似 HTML 的元素 (JSX),例如、span等。articleh1

sx在某些情况下,与 prop 相比,prop 非常有用style,如下所述。它们之间可能存在很多差异,但这是我注意到的 3 个关键差异,您可能会经常遇到它们。

  • 定义媒体查询
  • 嵌套样式
  • 在对象内部使用theme参数(获取调色板),sx这是我们不能style这样做的 -color: (theme) => theme.palette.primary.main

1. 定义媒体查询

stylesx最流行的一个区别是,基于 Material UI 主题定义媒体查询

您将如何处理styleprop 中的媒体查询?您可以使用自己的断点并按照 CSS 中的方式进行操作,但不能使用 Material UI 断点。

这就是sxprop 派上用场的地方,您可以定义媒体查询和其他 MUI 提供的属性来改变您的样式。

例子


import { Typography, createTheme, ThemeProvider } from '@mui/material'

let theme = createTheme()

function Demo() {
  const stylePropCSS = {
    backgroundColor: 'lightblue',

    /* theme prop is not understood here,
       so this breakpoint will not work,
       and text will not turn into orange */

    [theme.breakpoints.down('xl')]: {
      backgroundColor: 'orange',
    },
  }

  /*   theme prop is understood here. 
     breakpoints can be applied here based on MUI theme
  */
  const sxPropCSS = {
    backgroundColor: 'lightgreen',
    [theme.breakpoints.up('xs')]: {
      backgroundColor: 'orange',
    },
  }

  return (
    <ThemeProvider theme={theme}>
      {/* style prop */}
      <Typography style={stylePropCSS}>
        This text will <b>NOT TURN</b> orange as 
        I am using style prop and MUI 'theme' is not understood
      </Typography>

      <br />
      {/* sx prop */}
      <Typography sx={sxPropCSS}>
         This text will <b>TURN</b> into orange as 
         I am using sx prop and MUI 'theme' is understood
      </Typography>
    </ThemeProvider>
  )
}

export default Demo

Run Code Online (Sandbox Code Playgroud)

2. 嵌套样式并在 sx prop 中使用主题

使用 prop 时可以嵌套样式sx,但使用 prop 时不能这样做style

带有 sx 道具

<Box sx={styles.post}>
  <Typography variant="h4">This is the title</Typography>
</Box>
Run Code Online (Sandbox Code Playgroud)

Boxdiv背景黑色,我需要h4是黄色或MUI primary colorsx有了这个要求,当我使用这样的 prop时,我可以嵌套我的样式,将其放置h4在内部postsx仅定义Box

const styles = {
  post: {
    backgroundColor: 'black',

    // nesting h4 inside post

    h4: {
      // color:'yellow' // OR
      color: (theme) => theme.palette.primary.main,

      /* I cannot use theme inside style object. Since I am going 
to apply styles.post to sx prop,I could make use of theme 
object here as an argument */

    },
  },
}
Run Code Online (Sandbox Code Playgroud)

带有风格道具

<Box style={styles.post}>
  <Typography variant="h4" style={style.heading}>
    This is the title
  </Typography>
</Box>

const styles = {
  post: {
    backgroundColor: 'black',
  },
  // I can't nest the heading inside post, so defining it outside post
  heading: {
    color: 'yellow',
    // color: (theme) => theme.palette.primary.main, // THIS WON'T WORK with style prop
  },
}
Run Code Online (Sandbox Code Playgroud)

编辑 现代-hooks-8wftwx