动画
在一样平常开发中,页面切换时的转场动画是比力基础的一个场景
当一个组件在显示与消失过程中存在过渡动画,可以很好的增加用户的体验
在 react中实现过渡动画效果会有很多种选择,如 react-transition-group, react-motion,Animated,以及原生的 CSS 都能完成切换动画
在 react 中,react-transition-group 是一种很好的办理方案,其为元素添加 enter, enter-active, exit,exit-active 这一系列勾子
可以资助我们方便的实现组件的入场和离场动画其主要提供了三个主要的组件:
- CSSTransition:在前端开发中,团结 CSS 来完成过渡动画效果
- SwitchTransition:两个组件显示和隐藏切换时,使用该组件
- TransitionGroup:将多个动画组件包裹在其中,一样平常用于列表中元素的动画
基本概念
- 在开发中,我们想要给一个组件的显示和消失添加某种过渡动画,这样可以很好的增加用户体验
- 固然,我们可以通过原生的CSS来实现这些过渡动画,但是React社区为我们提供了react-transition-group用来完成过渡动画
- React曾为开发者提供过动画插件 react-addons-css-transition-group,后由社区维护,形成了现在的 react-transition-group
- 这个库可以资助我们方便的实现组件的 入场 和 离场 动画,使用时必要进行额外的安装
- # npm
- npm install react-transition-group --save
- # yarn
- yarn add react-transition-group
复制代码
react-transition-group自己非常小,不会为我们应用步伐增加过多的负担
react-transition-group主要组件:
◼ Transition
该组件是一个和平台无关的组件(不肯定要团结CSS);
在前端开发中,我们一样平常是团结CSS来完成样式,以是比力常用的是CSSTransition;
◼ CSSTransition
在前端开发中,通常使用CSSTransition来完成过渡动画效果
◼ SwitchTransition
两个组件显示和隐藏切换时,使用该组件
◼ TransitionGroup
将多个动画组件包裹在其中,一样平常用于列表中元素的动画;
CSSTransition使用
基本结构
- CSSTransition是基于Transition组件构建的:
- CSSTransition执行过程中,有三个状态:appear、enter、exit;
- 它们有三种状态,必要定义对应的CSS样式:
第一类,开始状态:对应的类是-appear、-enter、exit;
第二类:执举措画:对应的类是-appear-active、-enter-active、-exit-active;
第三类:执行结束:对应的类是-appear-done、-enter-done、-exit-done;
常见的属性设置
◼ in:触发进入或者退出状态
假如添加了unmountOnExit={true},那么该组件会在执行退出动画结束后被移撤除;
当in为true时,触发进入状态,会添加-enter、-enter-acitve的class开始执举措画,当动画执行结束后,会移除两个class,并且添加-enter-done的class;
当in为false时,触发退出状态,会添加-exit、-exit-active的class开始执举措画,当动画执行结束后,会移除两个class,并且添加-enter-done的class;
◼ classNames:动画class的名称
决定了在编写css时,对应的class名称:比如card-enter、card-enter-active、card-enter-done;
◼ timeout:
过渡动画的时间
◼ appear:
是否在初次进入添加动画(必要和in同时为true)
◼ unmountOnExit:退出后卸载组件
◼ 其他属性可以参考官网来学习:
https://reactcommunity.org/react-transition-group/transition
◼ CSSTransition对应的钩子函数:主要为了检测动画的执行过程,来完成一些JavaScript的操作
onEnter:在进入动画之前被触发;
onEntering:在应用进入动画时被触发;
onEntered:在应用进入动画结束后被触发;
onExit:在离开动画之前被触发;
onExiting:在应用离开动画时被触发;
onExited:在应用离开动画结束后被触发;
◼ nodeRef
用于在严酷模式下,过期报错问题
Index.jsx
- import React from 'react';
- import ReactDOM from 'react-dom/client';
- import './index.css';
- import App from './App';
- import reportWebVitals from './reportWebVitals';
- const root = ReactDOM.createRoot(document.getElementById('root'));
- root.render(
- <React.StrictMode>
- <App />
- </React.StrictMode>
- );
- // If you want to start measuring performance in your app, pass a function
- // to log results (for example: reportWebVitals(console.log))
- // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
- reportWebVitals();
复制代码 办理措施:
Demo.jsx
- import React, { PureComponent } from 'react'
- import { CSSTransition } from "react-transition-group"
- import '../style/style.css'
- export class classHello extends PureComponent {
- constructor() {
- super()
- this.state = {
- isShowTitle: true
- }
-
- // 解决严格模式下由于该css插件里的某些方法或者API由于过期报错问题
- this.sectionRef = createRef();
- }
- render() {
- const { isShowTitle } = this.state
- return (
- <div>
- {/** {isShowTitle && <h2>classHello</h2>} */}
- <CSSTransition
- nodeRef={this.sectionRef}
-
- in={isShowTitle}
- classNames="show"
- unmountOnExit={true}
- timeout={2000}
- appear
- onEnter={e => console.log("开始进入动画")}
- onEntering={e => console.log("执行进入动画")}
- onEntered={e => console.log("执行进入结束")}
- onExit={e => console.log("开始离开动画")}
- onExiting={e => console.log("执行离开动画")}
- onExited={e => console.log("执行离开结束")}
- >
- <h2 ref={this.sectionRef}>classHello</h2>
- </CSSTransition>
- <button onClick={e => this.setState({isShowTitle: !isShowTitle})}>切换</button>
- </div>
- )
- }
- }
- export default classHello
复制代码 或者直接关闭(注释)index.jsx里的严酷模式
- import React from 'react'
- import ReactDOM from 'react-dom/client'
- import './index.css'
- import App from './App'
- import reportWebVitals from './reportWebVitals'
- const root = ReactDOM.createRoot(document.getElementById('root'))
- root.render(
- // <React.StrictMode>
- // <App />
- // </React.StrictMode>
- <App />
- )
- reportWebVitals()
复制代码
演示示例
- unmountOnExit={true} timeout={2000}
- // 以上属性是必须要写的,不然会报警告
复制代码
- import React, { PureComponent } from 'react'
- import { CSSTransition } from "react-transition-group"
- import '../style/style.css'
- export class classHello extends PureComponent {
- constructor() {
- super()
- this.state = {
- isShowTitle: true
- }
- }
- render() {
- const { isShowTitle } = this.state
- return (
- <div>
- {/** {isShowTitle && <h2>classHello</h2>} */}
- <CSSTransition
- in={isShowTitle}
- classNames="show"
- unmountOnExit={true}
- timeout={2000}
- appear
- onEnter={e => console.log("开始进入动画")}
- onEntering={e => console.log("执行进入动画")}
- onEntered={e => console.log("执行进入结束")}
- onExit={e => console.log("开始离开动画")}
- onExiting={e => console.log("执行离开动画")}
- onExited={e => console.log("执行离开结束")}
- >
- <h2>classHello</h2>
- </CSSTransition>
- <button onClick={e => this.setState({isShowTitle: !isShowTitle})}>切换</button>
- </div>
- )
- }
- }
- export default classHello
复制代码
style.css
- /* 进入动画 */
- /* .show-appear {
- transform: translateX(-150px);
- }
- .show-appear-active {
- transform: translateX(0);
- transition: transform 2s ease;
- } */
- /*进入动画初识状态、真正进入状态*/
- .show-appear, .show-enter {
- opacity: 0;
- }
- .show-appear-active, .show-enter-active {
- opacity: 1;
- transition: opacity 2s ease;
- }
- /* 离开动画 */
- .show-exit {
- opacity: 1;
- }
- .show-exit-active {
- opacity: 0;
- transition: opacity 2s ease;
- }
复制代码
SwitchTransition
基本概念
SwitchTransition可以完成两个组件之间切换的炫酷动画:
比如我们有一个按钮必要在on和off之间切换,我们希望看到on先从左侧退出,off再从右侧进入;
这个动画在vue中被称之为 vue transition modes;
react-transition-group中使用SwitchTransition来实现该动画;
SwitchTransition中主要有一个属性:mode(动画的模式),有两个值
in-out:表现新组件先进入,旧组件再移除;
out-in:表现旧组件先移除,新组建再进入;
怎样使用SwitchTransition呢?
SwitchTransition组件内里要有CSSTransition或者Transition组件,不能直接包裹你想要切换的组件;
SwitchTransition内里的CSSTransition或Transition组件不再像以前那样接受in属性来判断元素是何种状态,取而代之的是key属性;
演示示例
- /* 进入初始状态 */
- .login-enter {
- transform: translateX(100px);
- opacity: 0;
- }
- /* 进入过程 */
- .login-enter-active {
- transform: translateX(0);
- opacity: 1;
- transition: all 1s ease;
- }
- /* 离开初识状态 */
- .login-exit {
- transform: translateX(0);
- opacity: 1;
- }
- /* 离开过程 */
- .login-exit-active {
- transform: translateX(-100px);
- opacity: 0;
- transition: all 1s ease;
- }
复制代码
- import React, { PureComponent } from 'react'
- import { CSSTransition, SwitchTransition } from "react-transition-group"
- import '../style/style.css'
- export class classHello extends PureComponent {
- constructor() {
- super()
- this.state = {
- isLogin: true
- }
- }
- render() {
- const { isLogin } = this.state
- return (
- <div>
- <SwitchTransition mode='out-in'>
- <CSSTransition
- key={isLogin ? "exit": "login"}
- classNames="login"
- timeout={1000}
- >
- <button onClick={e => this.setState({ isLogin: !isLogin })}>
- { isLogin ? "退出": "登录" }
- </button>
- </CSSTransition>
- </SwitchTransition>
- </div>
- )
- }
- }
- export default classHello
复制代码
TransitionGroup
当我们有一组动画时,必要将这些CSSTransition放入到一个TransitionGroup中来完成动画:
演示示例
- .book-enter {
- transform: translateX(150px);
- opacity: 0;
- }
- .book-enter-active {
- transform: translateX(0);
- opacity: 1;
- transition: all 1s ease;
- }
- .book-exit {
- transform: translateX(0);
- opacity: 1;
- }
- .book-exit-active {
- transform: translateX(150px);
- opacity: 0;
- transition: all 1s ease;
- }
复制代码
- import React, { PureComponent } from 'react'
- import { CSSTransition, TransitionGroup } from "react-transition-group"
- import '../style/style.css'
- export class classHello extends PureComponent {
- constructor() {
- super()
- this.state = {
- books: [
- { id: 111, name: "你不知道JS", price: 99 },
- { id: 222, name: "JS高级程序设计", price: 88 },
- { id: 333, name: "Vuejs高级设计", price: 77 },
- ]
- }
- }
- addNewBook() {
- const books = [...this.state.books]
- books.push({ id: new Date().getTime(), name: "React高级程序设计", price: 99 })
- this.setState({ books })
- }
- removeBook(index) {
- const books = [...this.state.books]
- books.splice(index, 1)
- this.setState({ books })
- }
- render() {
- const { books } = this.state
- return (
- <div>
- <h2>书籍列表:</h2>
- <TransitionGroup component="ul">
- {
- books.map((item, index) => {
- return (
- <CSSTransition key={item.id} classNames="book" timeout={1000}>
- <li>
- <span>{item.name}-{item.price}</span>
- <button onClick={e => this.removeBook(index)}>删除</button>
- </li>
- </CSSTransition>
- )
- })
- }
- </TransitionGroup>
- <button onClick={e => this.addNewBook()}>添加新书籍</button>
- </div>
- )
- }
- }
- export default classHello
复制代码

样式处置惩罚
概述
前面说过,整个前端已经是组件化的天下:
- 而CSS的计划就不是为组件化而生的,以是在现在组件化的框架中都在必要一种符合的CSS办理方案
在组件化中选择符合的CSS办理方案应该符合以下条件:
可以编写局部css:css具备自己的局部作用域,不会随意污染其他组件内的元素;
可以编写动态的css:可以获取当前组件的一些状态,根据状态的变革天生差异的css样式;
支持所有的css特性:伪类、动画、媒体查询等;
编写起来简便方便、最好符合一贯的css风格特点;
等等...
事实上,css一直是React的痛点,也是被很多开发者吐槽、诟病的一个点
在这一点上,Vue做的要好于React:
Vue通过在.vue文件中编写 <style><style> 标签来编写自己的样式;
通过是否添加 scoped 属性来决定编写的样式是全局有效还是局部有效;
通过 lang 属性来设置你喜欢的 less、sass等预处置惩罚器;
通过内联样式风格的方式来根据最新状态设置和改变css;
等等...
Vue在CSS上虽然不能称之为完美,但是已经充足简便、天然、方便了,至少统一的样式风格不会出现多个开发人员、多个项目采用不一样的样式风格
相比而言,React官方并没有给出在React中统一的样式风格:
由此,从普通的css,到css modules,再到css in js,有几十种差异的办理方案,上百个差异的库;
各人划一在探求最好的或者说最适合自己的CSS方案,但是到现在为止也没有统一的方案;
组件式开发选择符合的 css 办理方案尤为紧张
通常会遵循以下规则:
常见的 CSS引入方式有以下:
行内样式-style
基本概念
◼ 内联样式是官方推荐的一种css样式的写法:
style 接受一个采用小驼峰命名属性的 JavaScript 对象,而不是 CSS 字符串;
并且可以引用state中的状态来设置相干的样式;
◼ 内联样式的长处:
1.内联样式, 样式之间不会有辩说
2.可以动态获取当前state中的状态
◼ 内联样式的缺点:
1.写法上都必要使用驼峰标识
2.某些样式没有提示
3.大量的样式, 代码混乱
4.某些样式无法编写(比如伪类/伪元素)
◼ 以是官方依然是希望内团结适和普通的css来团结编写;
使用示例
- import React, { PureComponent } from 'react'
- export class App extends PureComponent {
- constructor() {
- super()
- this.state = {
- titleSize: 30
- }
- }
- addTitleSize() {
- this.setState({ titleSize: this.state.titleSize + 2 })
- }
- render() {
- const { titleSize } = this.state
- return (
- <div>
- <button onClick={e => this.addTitleSize()}>增加titleSize</button>
- <h2 style={{color: "red", fontSize: `${titleSize}px`}}>我是标题</h2>
- <p style={{color: "blue", fontSize: "20px"}}>我是内容, 哈哈哈</p>
- </div>
- )
- }
- }
- export default App
复制代码
或者如下写法:
注意:
- 行内样式写法style={{key: value}}
- 在style样式中,假如样式带有横岗-,应使用小驼峰的方式去书写
外部样式
基本概念
普通的css我们通常会编写到一个单独的文件,之后再进行引入。
◼ 这样的编写方式和普通的网页开发中编写方式是划一的:
假如我们按照普通的网页尺度去编写,那么也不会有太大的问题;
但是组件化开发中我们总是希望组件是一个独立的模块,即便是样式也只是在自己内部见效,不会相互影响;
但是普通的css都属于全局的css,样式之间会相互影响;
◼ 这种编写方式最大的问题是样式之间会相互层叠掉;
使用示例
示例1:
- .color {
- color: red;
- }
- .bg-color {
- background-color: blue;
- }
复制代码
- import './App.css';
- let title = 'hahaha'
- function App() {
- return (
- <div className='color bg-color'>
- {title}
- </div>
- );
- }
- export default App;
复制代码 注意:绑定class样式时应该使用className,不要使用class,由于class是js中的关键字。
示例2:
- // 导入样式
- import './base.css'
- const dv = <div className="title">style样式</div>
复制代码
base.css样式文件
- .title {
- text-align: center;
- color: red;
- background-color: pink;
- }
复制代码
示例3:
- const list = [
- { id: 1, name: "刘德华", content: "给我一杯忘情水" },
- { id: 2, name: "五月天", content: "不打扰,是我的温柔" },
- { id: 3, name: "毛不易", content: "像我这样优秀的人" }
- ];
复制代码
参考示例:
App.js
- import './base.css'
- const list = [{
- id: 1,
- name: "刘德华",
- content: "给我一杯忘情水"
- },
- {
- id: 2,
- name: "五月天",
- content: "不打扰,是我的温柔"
- },
- {
- id: 3,
- name: "毛不易",
- content: "像我这样优秀的人"
- }
- ];
- function render() {
- if(list.length === 0){
- return <div>暂无数据</div>;
- }
- return (
- <div>
- <ul>
- {
- list.map(item => (
- <li style={{listStyle: 'none'}} key={item.id}>
- <h3>评论人:{item.name}</h3>
- <p className='text_content'>评论内容:{item.content}</p>
- </li>
- ))
- }
- </ul>
- </div>
- )
- }
- function App() {
- return (
- <div>{render()}</div>
- )
- }
- export default App
复制代码 以上这种方式存在不好的地方在于样式是全局见效,样式之间会互相影响
css modules
◼ css modules并不是React特有的办理方案,而是所有使用了类似于webpack配置的情况下都可以使用的。
假如在其他项目中使用它,那么我们必要自己来进行配置,比如配置webpack.config.js中的modules: true等。
◼ React的脚手架已经内置了css modules的配置:
.css/.less/.scss 等样式文件都必要修改成 .module.css/.module.less/.module.scss 等;
之后就可以引用并且进行使用了;
◼ css modules确实办理了局部作用域的问题,将 css文件作为一个模块引入,这个模块中的所有 css,只作用于当前组件。不会影响当前组件的后代组件,也是很多人喜欢在React中使用的一种方案。
◼ 但是这种方案也有自己的缺陷:
引用的类名,不能使用连接符(.home-title),在JavaScript中是不辨认的;
- // base.css
- .home-title {
- color: red;
- }
- // App/jsx
- import appStyle from "./App.module.css"
- <div className={appStyle.home-title}></div> // 以上这种写法是不支持的,在js里会报错
复制代码 所有的className都必须使用{style.className} 的形式来编写;
不方便动态来修改某些样式,依然必要使用内联样式的方式;
◼ 假如你觉得上面的缺陷还算OK,那么你在开发中完全可以选择使用css modules来编写,并且也是在React中很受欢迎的一种方式
app.module.css
- .title {
- font-size: 20px;
- font-weight: 700;
- color: red;
- }
复制代码
App.jsx
- import React, { PureComponent } from 'react'
- import appStyle from '../style/app.module.css'
- export class classHello extends PureComponent {
- render() {
- return (
- <div className={appStyle.title}>classHello</div>
- )
- }
- }
- export default classHello
复制代码
CSS in JS-推荐
CsS-in-JS,是指一种模式,其中 CSS由 JavaScript 天生而不是在外部文件中定义此功能并不是 React 的一部分,而是由第三方库提供,例如:
- styled-components
- emotion/react
- glamorous
下面主要看看 styled-components 的基本使用
可在 VsCode 里安装 styled-components 插件,就会有提示了当输入代码的时间
本质是通过函数的调用,最终创建出一个组件:
- 这个组件会被自动添加上一个不重复的class
- styled-components会给该class添加相干的样式
概述
◼ 官方文档也有提到过CSS in JS这种方案:
“CSS-in-JS” 是指一种模式,其中 CSS 由 JavaScript 天生而不是在外部文件中定义;
注意此功能并不是 React 的一部分,而是由第三方库提供;
React 对样式怎样定义并没有明确态度;
◼ 在传统的前端开发中,我们通常会将结构(HTML)、样式(CSS)、逻辑(JavaScript)进行分离。
但是在前面的学习中,我们就提到过,React的头脑中以为逻辑自己和UI是无法分离的,以是才会有了JSX的语法。
样式呢?样式也是属于UI的一部分;
事实上CSS-in-JS的模式就是一种将样式(CSS)也写入到JavaScript中的方式,并且可以方便的使用JavaScript的状态;
以是React有被人称之为 All in JS;
◼ 固然,这种开发的方式也受到了很多的批评:
Stop using CSS in JavaScript for web development
Stop using CSS in JavaScript for web development | HackerNoon
◼ 批评声音虽然有,但是在我们看来很多优秀的CSS-in-JS的库依然非常强大、方便:
CSS-in-JS通过JavaScript来为CSS赋予一些能力,包罗类似于CSS预处置惩罚器一样的样式嵌套、函数定义、逻辑复用、动态修改状态等等;
虽然CSS预处置惩罚器也具备某些能力,但是获取动态状态依然是一个不好处置惩罚的点;
以是,现在可以说CSS-in-JS是React编写CSS最为受欢迎的一种办理方案;
◼ 现在比力盛行的CSS-in-JS的库有哪些呢?
styled-components
emotion
glamorous
◼ 现在可以说styled-components依然是社区最盛行的CSS-in-JS库,以是我们以styled-components的讲解为主;
◼ 安装styled-components:
- yarn add styled-components
- # 或者
- npm install styled-components
复制代码 可参考:https://www.npmjs.com/package/styled-components
◼ ES6中增加了模板字符串的语法,这个对于很多人来说都会使用。
◼ 但是模板字符串还有另外一种用法:标签模板字符串(Tagged Template Literals)。
◼ 我们一起来看一个普通的JavaScript的函数:
正常情况下,我们都是通过 函数名() 方式来进行调用的,其实函数还有另外一种调用方式:
◼ 假如我们在调用的时间插入其他的变量:
模板字符串被拆分了;
第一个元素是数组,是被模块字符串拆分的字符串组合;
反面的元素是一个个模块字符串传入的内容;
- // 标签模板字符串
- // 1. 基本使用
- const age = 14
- console.log(`age is ${age}`);
- // 2. 标签模板字符串
- function foo(...args) {
- console.log(args);
- }
- // foo`` // 直接调用函数
- foo`my age is ${age}` // 调用函数并传参
复制代码 ◼ 在styled component中,就是通过这种方式来解析模块字符串,最终天生我们想要的样式的
基本使用
◼ styled-components的本质是通过函数的调用,最终创建出一个组件:
这个组件会被自动添加上一个不重复的class;
styled-components会给该class添加相干的样式;
◼ 另外,它支持类似于CSS预处置惩罚器一样的样式嵌套:
支持直接子代选择器或后代选择器,并且直接编写样式;
可以通过&符号获取当前元素;
支持伪类选择器、伪元素等;
示例:
- import styled from 'styled-components'
- export const AppWrapper = styled.div`
- .section {
- border: 1px solid #eee;
- width: 500px;
- padding: 20px;
- .title {
- color: blue;
- &:hover {
- background-color: purple;
- }
- }
- .content {
- font-size: 25px;
- }
- }
- .footer {
- margin-top: 20px;
- padding: 10px;
- width: 500px;
- border: 1px solid pink;
- }
- `
复制代码
- import React, { PureComponent } from 'react'
- import { AppWrapper } from '../style/style.js'
- export class classHello extends PureComponent {
- render() {
- return (
- <AppWrapper>
- <div className="section">
- <h2 className="title">标题</h2>
- <div className="content">内容区域</div>
- </div>
- <div className="footer">
- <div>免责声明</div>
- <div>版权声明</div>
- </div>
- </AppWrapper>
- )
- }
- }
- export default classHello
复制代码
props、attrs属性
◼ props可以被传递给styled组件
获取props必要通过${}传入一个插值函数,props会作为该函数的参数;
这种方式可以有效的办理动态样式的问题;
◼ 添加attrs属性
添加默认值,不传的时间显示默认值
variable.js
- export const primaryColor = '#ff8800';
- export const secondPrimary = '#ff7788';
- export const smallSize = '12px'
- export const middleSize = '14px'
- export const largeSize = '16px'
复制代码
- import styled from 'styled-components'
- import * as vars from './variable'
- // 默认值写法1--接收传递进来的数据
- // export const AppWrapper = styled.div.attrs({
- // tColor: (props => props.color) || 'blue'
- // })``
- // 默认值写法2--接收传递进来的数据
- //export const AppWrapper = styled.div.attrs(props => {
- // return {
- // tColor: props.color || 'blue'
- // }
- //})``
- export const AppWrapper = styled.div.attrs(props => ({
- tColor: props.color || 'blue',
- }))
- `
- .section {
- border: 1px solid #eee;
- width: 500px;
- padding: 20px;
- .title {
- color: ${props => props.tColor};
- font-size: ${props => props.size}px;
- &:hover {
- background-color: purple;
- }
- }
- .content {
- font-size: ${vars.largeSize};
- color: ${vars.primaryColor};
- }
- }
- .footer {
- margin-top: 20px;
- padding: 10px;
- width: 500px;
- border: 1px solid pink;
- }
- `
复制代码
- import React, { PureComponent } from 'react'
- import { AppWrapper } from '../style/style.js'
- export class classHello extends PureComponent {
- constructor(){
- super()
- this.state = {
- size: 25,
- color: "orange"
- }
- }
- render() {
- const { size, color } = this.state
- return (
- // 将 size 和 color 传递给了 AppWrapper 组件
- <AppWrapper size={size} color={color}>
- <div className="section">
- <h2 className="title">标题</h2>
- <div className="content">内容区域</div>
- <button onClick={e => this.setState({color: 'red'})}>修改颜色</button>
- </div>
- <div className="footer">
- <div>免责声明</div>
- <div>版权声明</div>
- </div>
- </AppWrapper>
- )
- }
- }
- export default classHello
复制代码
高级特性
样式的继承
- import styled from 'styled-components'
- const LwjButton = styled.button`
- border: 1px solid red;
- border-radius: 5px;
- `
- export const LwjButtonWrapper = styled(LwjButton)`
- background-color: #0f0;
- color: #fff;
- `
- export const HomeWrapper = styled.div`
- `
复制代码
- import React, { PureComponent } from 'react'
- import { HomeWrapper, LwjButtonWrapper } from '../style/home'
- export class Home extends PureComponent {
- render() {
- return (
- <HomeWrapper>
- <LwjButtonWrapper>按钮</LwjButtonWrapper>
- </HomeWrapper>
- )
- }
- }
- export default Home
复制代码
设置主题
index.js
- import React from 'react';
- import ReactDOM from 'react-dom/client';
- import './index.css';
- import App from './App';
- import reportWebVitals from './reportWebVitals';
- import { ThemeProvider } from 'styled-components';
- const root = ReactDOM.createRoot(document.getElementById('root'));
- root.render(
- <ThemeProvider theme = {{color: 'purple', size: '50px'}}>
- <App />
- </ThemeProvider>
- );
- reportWebVitals();
复制代码
Home.js
- import styled from 'styled-components'
- export const HomeWrapper = styled.div`
- .top {
- .banner {
- font-size: ${props => props.theme.size};
- }
- }
- .bottom {
- .title {
- color: ${props => props.theme.color};
- }
- ul {
- li {
- color: blue;
- }
- }
- }
- `
复制代码
Home.jsx
- import React, { PureComponent } from 'react'
- import { HomeWrapper } from '../style/fun'
- export class funHello extends PureComponent {
- render() {
- return (
- <HomeWrapper>
- <div className="top">
- <div className="banner">bannercontent</div>
- </div>
- <div className="bottom">
- <h2 className="title">标题</h2>
- <ul>
- <li>商品列表1</li>
- <li>商品列表2</li>
- </ul>
- </div>
- </HomeWrapper>
- )
- }
- }
- export default funHello
复制代码
classnames库
基本概念
安装:npm install classnames
使用示例
- import React, { PureComponent } from 'react'
- import classNames from 'classnames'
- export class App extends PureComponent {
- constructor() {
- super()
- this.state = {
- isbbb: true,
- isccc: true
- }
- }
- render() {
- const { isbbb, isccc } = this.state
- const classList = ["aaa"]
- if (isbbb) classList.push("bbb")
- if (isccc) classList.push("ccc")
- const classname = classList.join(" ")
- return (
- <div>
- <h2 className={`aaa ${isbbb ? 'bbb': ''} ${isccc ? 'ccc': ''}`}>哈哈哈</h2>
- <h2 className={classname}>呵呵呵</h2>
- {/*使用classnames库*/}
- <h2 className={classNames("aaa", { bbb:isbbb, ccc:isccc })}>嘿嘿嘿</h2>
- <h2 className={classNames(["aaa", { bbb: isbbb, ccc: isccc }])}>嘻嘻嘻</h2>
- </div>
- )
- }
- }
- export default App
复制代码
总结
- JSX表现在JS代码中书写HTML结构,是React声明式的表现
- 使用JSX配合嵌入的JS表达式,条件渲染,列表渲染,可以渲染恣意的UI结构
- 结果使用className和style的方式给JSX添加样式
- React完全利用JS的语言自身的能力来编写UI,而不是造轮子增强HTML的功能。(对比VUE)
至于使用 react 用哪种方案引入 Css,并没有一个绝对的答案,可以根据各自情况选择符合的方案
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |