关于前端:一文了解react中定义样式csslesssass的常用方法

4次阅读

共计 4893 个字符,预计需要花费 13 分钟才能阅读完成。

react 中通过 jsx 的语法形式,将 html 标签和 js 语法分割在一起,而 css 的编写形式,没有明确的指定编写形式,目前就有很多不同办法,每个形式各有其优缺点,咱们一起来看看罕用的定义形式有哪些。

最根底也是最简略的形式就是如 html 当中编写款式一样,间接内联应用,区别在于 jsx 中内联应用款式须要用小驼峰命名,不可应用短横线 -,jsx 中编写 js 的表达式须要应用 {},而定义的款式是以对象的模式存在,也是通过 {},所以看起来 style 标签外面应用了两个大括号 {}

return(<div style={{color: 'blue'}}>
   hello react
</div>)

这样的形式长处是代码不会抵触,定义的代码都作用于以后元素,而且如果须要动静的获取 state 的值来设置款式也能够做到。毛病也很显著,当如果款式十分多的时候,即便把款式整体提炼进去,作为一个变量赋值给 style,但依然还是和业务逻辑混淆在一起,并且无奈编写伪类等一些语法。

第二种形式可能将 css 代码与业务逻辑代码拆散开来,在 jsx 的标签中定义 className 属性,自定义 css 的款式文件,再通过 import 引入 css/scss/less 等款式文件,就是应用的 css 的原生编写形式,定义伪类以及其它的高级选择器编写形式都能够反对。

return(<div className="title">
   hello react
</div>)

// 定义在独自的款式文件
.title {color: 'blue'}

这样能够让代码比拟清晰明了,css 款式和 jsx 文件分来到。

当须要应用多个 className,或者通过状态来变更 className 时,能够通过 + 来进行字符串拼接,或者应用数组,再通过 toString() 转成字符串

const isActive = true
<h2 className="active foo bar"> 我是题目 1 </h2>       
// active foo bar   
<h2 className={"foo", (isActive ? "active" : "") }> 我是题目 2 </h2>  
// active
<h2 className={"foo" + (isActive ? "active" : "") }> 我是题目 3 </h2> 
// foo, active
<h2 className={["foo",(isActive ? "active" : "")]}> 我是题目 4 </h2>  
// foo, active
<h2 className={["foo",(isActive ? "active" : "")].join(" ")}>
我是题目 5 </h2> 
// foo avtive

为了简便应用,能够间接应用 classnames 这个库来动静的应用类名,classnames 默认裸露了一个函数,传入参数的参数能够为字符串、对象和数组,传入 null/undefined/boolean 值也不会显示在页面上

import classNames from 'classnames'
const isShow = false
const list = ['foo', 'bar']
<h2 className={classNames({"active": isActive}, "foo")}>
我是题目 6 </h2>    
// active foo
<h2 className={classNames({"active": isActive, "bar": isShow})}>
我是题目 7 </h2> 
// active 
<h2 className={classNames({"active": isActive}, list)}>
我是题目 8 </h2>       
// active foo bar
<h2 className={classNames(null, undefined, 0, 10, '0', true, false)}>
我是题目 8 </h2> 
// 10 0

但 react 开发的页面都叫做单页面利用,整个我的项目只有一个页面,款式在 a 组件援用,b 组件即便没有援用,定义了同名的类名,也会有款式,这样导致如果 c 组件和 d 组件都定义了 className 属性,别离引入了 css 款式定义字体色彩,但最终两者呈现出的字体色彩为后引入的 css 文件里的字体色彩,即同名的款式会被笼罩掉。

为了解决这一问题,咱们就须要在跟标签处再定义一个 className,来包裹以后组件的所有标签,这样 css 款式的层级就比拟多,并且还可能因为选择器优先级的问题(在外层定义了 id 选择器),而产生款式抵触,同时它不反对获取 state 属性动静设置款式。

return(<div className="homeComponent">
    <div className="title">hello react</div>
</div>)

此时就产生了第三种编写形式,css 的模块化,这样的形式能够辨别各个组件的款式,不会互相笼罩,而且还能定义伪类,react 脚手架当中内置了 css modules 的配置,咱们能够间接将 css 的文件定义为 xxx.module.css,在 xxx.module.css 文件中,还是依照以前的 css 编写形式编写,不同点在于 jsx 页面中定义 className,先引入该 css 文件,而后定义类名以对象的模式定义

import style from './index.module.css'
return(<div className={style.title}>
    hello react
</div>)

这样定义的款式是一个不会反复的字符

这样一种定义款式的形式可能比拟无效的解决款式重叠的问题,麻烦之处就是每次编写款式的时候须要通过对象的语法来定义,并且不反对动静的设置款式。

那么就有了第四种形式,css in js,这是一种代码的理念,react 中 html 和 js 没有拆散,那么 css 也能够不拆散,以 js 的形式来编写 css,使 css 的编写更加的灵便,既能够像之前写 css 一样编写,又能够动静的获取属性。这种编写形式须要依赖其它库,这里应用罕用的 styled-components 来演示。

应用 styled-components 之前须要对 es6 模板字符串的一种语法有理解,咱们能够应用模板字符串来对字符串和属性进行拼接,在此之前的拼接可能都须要应用 +

const name = 'kiki'
const age = '18'
const user = `my name is ${name}, age is ${age}`
console.log(user) // my name is kiki, age is 18

但模板字符串还有一种用法,就是它能够像小括号一样调用函数,并且参数以肯定的规定传递给函数

let name = 'kiki', age = 18
function foo(...args){console.log(args)
}
foo`hello`
foo`my name is ${name}, age is ${age} `

基于模板字符串的这种应用形式,咱们来看看 styled-components 如何应用,先从 styled-components 的默认裸露中引入函数,创立一个 div 标签,并在模板字符串中定义款式,最初将创立的组件替换 div 标签,通过 js 定义的组件都能够抽取到一个独自的 js 文件当中,这里为了演示不便,就写在了一起。

import React, {PureComponent} from 'react'
import styled from 'styled-components'

const DivStyle = styled.div`
  background-color: gray;
  color: #fff;
  font-size: 20px;
`

export default class Profile extends PureComponent{render(){
    return(<div>
      <DivStyle> 我是 Profile 组件的内容 </DivStyle>
    </div>)
  }
}

这样看起来编写形式更为简单了,但其实它还有很多好用的形式,除了应用款式,咱们可能还对有些标签要做一些别的属性设置,以及咱们须要通过以后页面保护的 state 属性来辨别款式的展现,在定义款式的时候,value 值以函数的模式从 props 中获取属性

import React, {PureComponent} from 'react'
import styled from 'styled-components'

const InputStyle = styled.input.attrs({
  type: 'text',
  placeholder: '请输出内容',
})`
  color: ${props => props.color}
`

export default class Deliver extends PureComponent{constructor(props){super(props)
    this.state = {color: 'purple'}
  }

  render(){
    return(<p>
      <InputStyle type="password" color={this.state.color}/>
    </p>)
  }
}

款式当中,如果有反复的定义款式形式,要么须要定义多个 className,要么就得反复定义,styled-components 提供了继承的形式使款式能够复用,通过 styled-components 中默认裸露的导出函数,间接传入已定义好款式的组件

import React, {PureComponent} from 'react'

import styled from 'styled-components'

const DivStyle = styled.div`
  background-color: gray;
  color: #fff;
  font-size: 14px;
`
const RecommondStyle = styled(DivStyle)`
  font-size: 20px;
`

export default class Profile extends PureComponent{render(){
    return(<div>
        <DivStyle>    
          hello styled-components
        </DivStyle>
        <RecommondStyle>
          style 属性的继承
        </RecommondStyle>
      </div>
    )
  }
}

另外,还能够给最外层的组件定义一个主题,这样它定义的款式子元素都能够从 props 中获取到

// 父组件
import {ThemeProvider} from 'styled-components'

export default class Home extends PureComponent{render(){return(<ThemeProvider theme={{color: 'brown'}}>
      <About/>
    </ThemeProvider>)
  }
}

// 子组件
import React, {PureComponent} from 'react'
import styled from 'styled-components'

const DivStyle = styled.div`
  color: ${props => props.theme.color};
`

export default class About extends PureComponent{render(){
    return(<DivStyle>
        style 设置主题
      </DivStyle>   
    )
  }
}

这样一种 css 的编写形式使得 css 的代码更像 js,十分的灵便,也更具备复用性。

以上四种款式在 react 当中的定义形式是比拟罕用的,能够依据状况联合应用~

正文完
 0