React 介绍

  • React 是 facebook 推出的用于构建用户界面的前端 JavaScript 框架
  • https://reactjs.org/
  • React 使用组件构建用户界面

组件是什么

截屏2021-04-07 下午10.02.40.png
一块区域,包含了 html、css 及 JavaScript

组件开发的优势

  • 将一个庞大复杂的应用程序拆分成多个独立单元
  • 组件之间相互独立,有利于应用程序的维护
  • 组件可以重用,一次编写多地复用

搭建 React 开发环境

自定义 webpack 搭建 React 开发环境

  1. # 新建项目目录
  2. mkdir webpack-react-project
  3. # 进入项目目录
  4. cd webpack-react-project
  5. # 初始化
  6. npm init -y
  • 安装开发依赖

    1. "devDependencies": {
    2. "@babel/core": "^7.13.14",
    3. "@babel/preset-env": "^7.13.12",
    4. "@babel/preset-react": "^7.13.13",
    5. "babel-loader": "^8.2.2",
    6. "html-webpack-plugin": "^5.3.1",
    7. "react": "^17.0.2",
    8. "react-dom": "^17.0.2",
    9. "webpack": "^5.30.0",
    10. "webpack-cli": "^4.6.0",
    11. "webpack-dev-server": "^3.11.2"
    12. }
  • webpack.config.js ```javascript const path = require(‘path’) const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

module.exports = { mode: ‘development’, // devtool: ‘none’, entry: ‘./src/index.js’, output: { filename: ‘main.js’, path: path.resolve(‘dist’) }, devServer: { port: 2021, hot: true }, module: { rules: [ { test: /.js|jsx$/, exclude: /node_module/, use: [ { loader: ‘babel-loader’, options: { presets: [‘@babel/preset-env’, ‘@babel/preset-react’] } } ] } ] }, plugins: [ new HtmlWebpackPlugin({ template: ‘./src/index.html’ }) ] }

  1. - src/index.html
  2. ```html
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  8. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  9. <title>Document</title>
  10. </head>
  11. <body>
  12. <div id="root"></div>
  13. </body>
  14. </html>
  • src/index.js ```javascript import React from ‘react’ import { render } from ‘react-dom’

// 自定义组件 function App() { return

React
}

render(, document.getElementById(‘root’))

  1. - 运行 `npx webpack serve`
  2. - 通过 [http://localhost:2021/](http://localhost:2021/) 即可访问
  3. <a name="2TTbZ"></a>
  4. ### 脚手架初始化项目
  5. ```powershell
  6. # 全局安装reactCLI
  7. npm install create-react-app -g
  8. # 创建react 项目
  9. create-react-app react-project
  10. # 进入项目
  11. cd react-project
  12. # 启动项目
  13. npm start

JSX语法

  • JSX 可以看做是JS语言的扩展,它既不是一个字符串也不是一个HTML
  • 它具备了 JS 所有的功能,同时还可以被转为 HTML 在界面上进行展示(react react-dom)

动态显示数据

  1. const name= '拉钩教育'
  2. function App() {
  3. return (
  4. <div>
  5. <p>{name}</p>
  6. <p>name</p>
  7. </div>
  8. )
  9. }
  10. export default App;

调用方法:自定义 + 内置

  1. function sayHello () {
  2. return 'Hello'
  3. }
  4. function App() {
  5. return (
  6. <div>
  7. <p>{sayHello()}</p>
  8. <p>{console.log(111)}</p>
  9. <p>{Math.random()}</p>
  10. </div>
  11. )
  12. }
  13. export default App;

支持表达式,支持三元表达式

  1. const flag = true
  2. function App() {
  3. return (
  4. <div>
  5. <p>{1 + 2 + 3}</p>
  6. <p>{flag? '登陆' : '未登陆'}</p>
  7. </div>
  8. )
  9. }
  10. export default App;

模版字符串

  1. const name= '拉钩教育'
  2. function App() {
  3. return (
  4. <div>
  5. <p>{`hello, ${name}`}</p>
  6. </div>
  7. )
  8. }
  9. export default App;

注释

  1. function App() {
  2. return (
  3. <div>
  4. <p>124{/*注释*/}</p>
  5. </div>
  6. )
  7. }
  8. export default App;

页面上不能直接打印对象

  1. const obj = {
  2. name: '拉勾教育',
  3. age: 100
  4. }
  5. function App() {
  6. return (
  7. <div>
  8. <p>{obj/*会报错*/}</p>
  9. <p>{JSON.stringify(obj)}</p>
  10. </div>
  11. )
  12. }
  13. export default App;

JSX 本身就是一个表达式

  1. const name = <h1>拉钩教育</h1>
  2. function App() {
  3. return (
  4. <div>
  5. {name}
  6. </div>
  7. )
  8. }
  9. export default App;

JSX 添加属性

  1. const num = 100
  2. function App() {
  3. return (
  4. <div>
  5. <p title='自定义标题'>添加属性</p>
  6. <p title={num}>添加动态属性</p>
  7. </div>
  8. )
  9. }
  10. export default App;

JSX 添加子元素

  1. function App() {
  2. return (
  3. <div>
  4. <p>子元素</p>
  5. <p>子元素</p>
  6. </div>
  7. )
  8. }
  9. export default App;

JSX 只能有一个根节点

  1. function App() {
  2. return (
  3. <div>根节点</div>
  4. )
  5. }
  6. export default App;

使用单标签时必须正确关闭

  1. function App() {
  2. return (
  3. <div>
  4. <img />
  5. </div>
  6. )
  7. }
  8. export default App;

事件操作

事件绑定

驼峰命名直接添加={事件监听的名称}

  1. const handler = () => {
  2. console.log(1111)
  3. }
  4. function App () {
  5. return (
  6. <div>
  7. <button onClick={handler}>点击触发事件</button>
  8. </div>
  9. )
  10. }
  11. export default App

事件监听传参

  • 利用箭头函数内部调用事件监听的时候传递实参
  • 利用 bind 方法返回一个新的函数在事件发生时调用,此时也可以传递参数 ```jsx const handler = (a,b) => { console.log(a,b) console.log(1111) }

function App () { return (

) }

export default App

  1. <a name="Bek8z"></a>
  2. ### 获取事件对象
  3. - 默认情况下不需要接收参数,且直接执行事件监听,此时它的第一个实参默认就是 ev
  4. - 利用箭头函数执行事件监听,需要通过箭头函数将 ev 对象 传递给事件监听函数进行使用
  5. - 利用 bind 方法执行时,如果有传递参数那么最后一个参数默认就接收到的就是 ev
  6. ```jsx
  7. const handler = (ev) => {
  8. console.log(ev)
  9. console.log(1111)
  10. }
  11. const handler2 = (a,b,ev) => {
  12. console.log(ev)
  13. console.log(1111)
  14. }
  15. function App () {
  16. return (
  17. <div>
  18. <button onClick={handler}>点击触发事件</button>
  19. <button onClick={(ev) => {handler(ev)}}>点击触发事件</button>
  20. <button onClick={handler2.bind(null,10,20)}>点击触发事件</button>
  21. <button onClick={handler.bind(null)}>点击触发事件</button>
  22. </div>
  23. )
  24. }
  25. export default App

循环数据

  • jsx 可以直接将数组中的数据解构 ```jsx const arr = [

    1

    ,

    2222

    ,

    3333

    ]

function App () { return(

{arr}
) }

export default App

  1. - 遍历数据
  2. ```jsx
  3. // const arr = [<p>1</p>, <p>2222</p>, <p>3333</p>]
  4. const arr = [
  5. {
  6. id: 1,
  7. name: 'zce',
  8. age: 40,
  9. salary: 1000000
  10. },
  11. {
  12. id: 2,
  13. name: 'zoe',
  14. age: 18,
  15. salary: 2000000
  16. }
  17. ]
  18. function App () {
  19. const ret = arr.map(item =>{
  20. return (
  21. <li key={item.id}>
  22. <span>{item.name}--</span>
  23. <span>{item.age}--</span>
  24. <span>{item.salary}</span>
  25. </li>
  26. )
  27. })
  28. return <ul>{ret}</ul>
  29. }
  30. export default App

样式

内联样式

  • 设置样式的时候应该将键值对放置于 {} ```jsx const styleObj = { width: 100, height: 100, backgroundColor: ‘pink’, }

function App () { return (

样式处理
) }

export default App

  1. - 内联样式默认无法支持伪类及媒询样式设置
  2. - 导入 Radium 函数将当前需要支持伪类操作的组件包裹之后再导出
  3. ```jsx
  4. //App.js
  5. import Radium from 'radium'
  6. const styleObj = {
  7. width: 100,
  8. height: 100,
  9. backgroundColor: 'pink',
  10. ":hover": {backgroundColor: 'skyblue'},
  11. "@media (max-width: 800px)": {width: 300}
  12. }
  13. function App () {
  14. return (
  15. <div style={styleObj}>样式处理</div>
  16. )
  17. }
  18. export default Radium(App)
  1. // index.js
  2. import React from 'react';
  3. import ReactDOM from 'react-dom';
  4. import App from './App'
  5. import {StyleRoot} from 'radium'
  6. ReactDOM.render(
  7. <React.StrictMode>
  8. <StyleRoot><App /></StyleRoot>
  9. </React.StrictMode>,
  10. document.getElementById('root')
  11. );
  • 多样式 ```jsx import Radium from ‘radium’

const ButtonStyle = { base: { width: 150, height: 40, fontSize: 20, background: ‘#ffff’ }, login: { background: ‘green’ }, logout: { background: ‘orange’ } }

const isLogin = false

function App () { return (

) }

export default Radium(App)

  1. <a name="RCz7t"></a>
  2. ### 外联样式
  3. - 全局外联样式--所有组件当中都可以直接进行使用
  4. ```css
  5. /* style.css */
  6. body{
  7. background-color: orange;
  8. }
  9. .box{
  10. width: 100px;
  11. height: 100px;
  12. background-color: seagreen;
  13. }
  1. // App.js
  2. function App() {
  3. return(
  4. <div className={'box'}>外联样式</div>
  5. )
  6. }
  7. export default App
  1. // Test.js
  2. function Test() {
  3. return (
  4. <div>
  5. <div className = {'box'}> Test 中的 div </div>
  6. </div>
  7. )
  8. }
  9. export default Test
  1. // index.js
  2. import React from 'react';
  3. import ReactDOM from 'react-dom';
  4. import App from './App'
  5. import test from './Test'
  6. import './style.css'
  7. ReactDOM.render(
  8. <React.StrictMode>
  9. <App />
  10. <Test />
  11. </React.StrictMode>,
  12. document.getElementById('root')
  13. );
  • 组件级别的外联样式
    • 只有某一个组件可以进行使用
    • 组件名.module.css
      1. /* Test.module.css */
      2. .item{
      3. width: 100px;
      4. height: 100px;
      5. background-color: red;
      6. }
      ```jsx // Test.js import style from ‘./Test.module.css’

function Test() { return (

Test中的P,使用自己的样式

) }

export default Test

  1. - CSS in JS
  2. - 安装 `styled-components`
  3. ```jsx
  4. import styled from 'styled-components'
  5. // 自定义标签
  6. const SectionDiv = styled.div.attrs({
  7. className: 'box1 box2'
  8. })`
  9. width: 100px;
  10. height: 100px;
  11. background-color: hotpink;
  12. `
  13. function Test () {
  14. return (
  15. <div>
  16. <SectionDiv />
  17. </div>
  18. )
  19. }
  20. export default Test

创建组件

函数组件

  • AboutFunc.js ```jsx function AboutFunc() { return (
    About Func 组件
    ) }

export default AboutFunc

  1. - App.js
  2. ```jsx
  3. import AboutFunc from './AboutFunc'
  4. function App() {
  5. return (
  6. <div>
  7. <AboutFunc />
  8. </div>
  9. )
  10. }
  11. export default App;

类组件

  • 必须继承 Component render
  • 组件名称的首字母必须是大写的,在 React 当中可以用于区分组件和普通的标记 ```jsx // AboutClass.js import React, {Component, Fragment} from ‘react’

class AboutClass extends Component { render() { return (

About Class 类组件
) } }

export default AboutClass

  1. ```jsx
  2. import AboutClass from './AboutClass'
  3. function App() {
  4. return (
  5. <div>
  6. <AboutClass />
  7. </div>
  8. )
  9. }
  10. export default App;

组件传值

  • App.js ```jsx import About from ‘./About’ import Header from ‘./Header’

const obj = { name:’zce’, age: 18 } function App() { return (

{/在组件身上添加属性然后传递数据/} {/
/}

  1. {/*将数据统一管理,然后利用 ... 操作直接传递给相应的组件*/}
  2. <Header {...obj}/>
  3. <About {...obj} />
  4. </div>

) }

export default App;

  1. - 函数组件:在函数组件内可以接上到外部的数据,内部直接访问即可{ name:xxx, age:xxxx }
  2. ```jsx
  3. function About ({a,b}) {
  4. return (
  5. <div>
  6. <p>{a}</p>
  7. <p>{b}</p>
  8. </div>
  9. )
  10. }
  11. export default About
  • 类组件: 在类组件的内部存在一个 props 属性,外部传递的数据都放在这里保存,我们可以直接进行使用
    ```jsx import {Component} from ‘react’

class Header extends Component {

render() { const {name, age} = this.props

  1. return (
  2. <div>
  3. <p>{name}</p>
  4. <p>{age}</p>
  5. </div>
  6. )

} }

export default Header

  1. <a name="BQqcY"></a>
  2. ### 默认值及类型校验
  3. - 针对于函数组件来说,如果想要设置默认的 props 属性值,则直接通过 组件名称.defaultProps 来设置一个对象
  4. - 安装第三方校验插件 `npm install props-type`
  5. - [https://github.com/facebook/prop-types](https://github.com/facebook/prop-types)
  6. ```jsx
  7. import PropTypes from 'prop-types'
  8. function About ({name,age}) {
  9. return (
  10. <div>
  11. <p>{name}</p>
  12. <p>{age}</p>
  13. </div>
  14. )
  15. }
  16. About.defaultProps = {
  17. name: 'zzz',
  18. age: 10
  19. }
  20. About.propTypes = {
  21. name: PropTypes.string.isRequired,
  22. age: PropTypes.number
  23. }
  24. export default About
  • 针对于类组件来说,我们可以直接定义 static defaultProps 来管理需要设置默认值的属性即可 ```jsx import {Component} from ‘react’

class Header extends Component {

static defaultProps = { name: ‘拉钩教育’, age: 100 } render() { const {name, age} = this.props

  1. return (
  2. <div>
  3. <p>{name}</p>
  4. <p>{age}</p>
  5. </div>
  6. )

} }

export default Header

  1. <a name="hRumf"></a>
  2. ### 向组件传递 JSX
  3. - App.js
  4. ```jsx
  5. import About from './About'
  6. import Header from './Header'
  7. const obj = {
  8. name:'zce',
  9. age: 18
  10. }
  11. function App() {
  12. return (
  13. <div>
  14. <Header>
  15. <p>Header组中的 P标签</p>
  16. <span>Header组件中的 span标签</span>
  17. </Header>
  18. <About>
  19. <p>About 中p标签</p>
  20. </About>
  21. </div>
  22. )
  23. }
  24. export default App;
  • 函数组件 About.js ```jsx import PropTypes from ‘prop-types’

function About (props) { return (

{props.name}

{props.age}

{props.children}

) } About.defaultProps = { name: ‘zzz’, age: 10 }

About.propTypes = { name: PropTypes.string.isRequired, age: PropTypes.number } export default About

  1. - 类组件 Header.js
  2. ```jsx
  3. import {Component} from 'react'
  4. class Header extends Component {
  5. static defaultProps = {
  6. name: '拉钩教育',
  7. age: 100
  8. }
  9. render() {
  10. const {name, age} = this.props
  11. return (
  12. <div>
  13. <p>{name}</p>
  14. <p>{age}</p>
  15. {this.props.children}
  16. </div>
  17. )
  18. }
  19. }
  20. export default Header

组件布局

截屏2021-04-09 下午9.28.25.png

  • components/Header.js ```jsx function Header() { return ( <>
    1. <div className={'header'}>Header组件</div>
    </> ) }

export default Header

  1. - components/Footer.js
  2. ```jsx
  3. function Footer() {
  4. return (
  5. <>
  6. <div className={'footer'}>Footer组件</div>
  7. </>
  8. )
  9. }
  10. export default Footer
  • components/Layout.js

    • 当前组件的作用就是将 header 与 footer 显示出来,同时中的 main 内容空出来,
    • 将来我们传入什么样的 JSX 那么 main 里就显示什么样的 DOM ```jsx import Header from ‘./Header’ import Footer from ‘./Footer’

    function Layout(props) { return ( <>

    1. <Header />
    2. <div className="main">
    3. {props.children}
    4. </div>
    5. <Footer />

    </> ) }

    export default Layout ```

  • components/Home.js ```jsx import Layout from ‘./Layout’

function Home() { return (

当前是home界面

) }

export default Home

  1. - components/List.js
  2. ```jsx
  3. import Layout from './Layout'
  4. function List() {
  5. return (
  6. <Layout>
  7. <p>当前是List界面</p>
  8. </Layout>
  9. )
  10. }
  11. export default List
  • App.js ```jsx import Home from ‘./components/Home’ import List from ‘./components/List’

function App() { return ( {//} ) }

export default App

  1. <a name="kIi2K"></a>
  2. ## 组件状态
  3. - 组件状态: 状态就数据,因此组件状态指的就是某一个组件自己的数据
  4. - 数据驱动 DOM : 当我们修改某一个数据的时候,界面上的DOM中数据展示也会自动更新
  5. ```jsx
  6. import React, { Component } from 'react'
  7. class Header extends Component {
  8. // 在类组件当中默认就存在一个 state 属性,它是一个对象,可以用于保存当前组件的数据
  9. // 之后还可以通过 setState 方法来修改数据的值,最后修改之后结状态会自动展示在 DOM 界面上
  10. state = {
  11. name: 'zce',
  12. age: 40
  13. }
  14. handler = () => {
  15. // 在 react 当中是不能够直接来修改 state 值的
  16. // this.state.name = 'zoe'
  17. this.setState({
  18. name: 'zoe'
  19. })
  20. }
  21. render() {
  22. return (
  23. <>
  24. {this.state.name}
  25. {this.state.age}
  26. <button onClick={this.handler}>点击</button>
  27. </>
  28. )
  29. }
  30. }
  31. export default Header

setState 使用

setState 是异步函数

  • 可以使用 async 与 await 来解决 setState异步执行的问题

    1. handler = async () => {
    2. await this.setState({
    3. name: 'Zoe'
    4. })
    5. console.log(this.state.name, 22222)
    6. }
  • 调用 setState 的时候可以传入回调函数,在它里面就可以使用修改之后的数据

    1. handler = () => {
    2. this.setState({
    3. name: 'zoe'
    4. }, () => {
    5. console.log(this.state.name, 22222)
    6. })
    7. }

传入函数

  • setState 在使用的时候除了可以传入对象之外还能够传入一个函数

    1. state = {
    2. count: 0
    3. }
    4. handler = () => {
    5. this.setState((state) => ({
    6. count: state.count + 1
    7. }))
    8. }

传入函数与传入对象的不同点

  1. state = {
  2. count: 0
  3. }
  • 传入函数

    • 会依次执行 ```jsx handler = () => { this.setState((state) => ({

      1. count: state.count + 1

      }))

      this.setState((state) => ({ count: state.count + 5 })) }

  1. - 传入对象
  2. - 之后执行最后一个 setState
  3. ```jsx
  4. handler = () => {
  5. this.setState({
  6. count: this.state.count + 1
  7. })
  8. this.setState({
  9. count: this.state.count + 5
  10. })
  11. }

组件中的 this

  1. import React, { Component } from 'react'
  2. class Header extends Component {
  3. handler = function () {
  4. console.log(this)
  5. }
  6. render() {
  7. return (
  8. <>
  9. <div>
  10. {/*<button onClick={this.handler}>点击</button>*/}
  11. {/*<button onClick={() => { this.handler }}>点击</button>*/}
  12. <button onClick={this.handler.bind(this)}>点击</button>
  13. </div>
  14. </>
  15. )
  16. }
  17. }
  18. export default Header

单向数据流动

  • 单向数据流的设计原则要求我们将不同组件之前需要共享的数据都定义在上层
  1. //App.js
  2. import C1 from './C1'
  3. import React, { Component } from 'react'
  4. class App extends Component {
  5. // 在类组件当中就可以使用 state 定义状态
  6. state = {
  7. name: 'zce',
  8. age: 40
  9. }
  10. // 定义状态的更新方法, 当前外只负责定义,在想要修改数据的地方会进行调用
  11. handler = ({ name, age }) => {
  12. this.setState({ name, age })
  13. }
  14. render() {
  15. return (
  16. <div>
  17. 单向数据流
  18. <C1 {...this.state} change={this.handler} />
  19. </div>
  20. )
  21. }
  22. }
  23. export default App
  1. // C1.js
  2. import React from 'react'
  3. import C2 from './C2'
  4. function C1(props) {
  5. console.log(props)
  6. return (
  7. <div>
  8. C1组件
  9. <C2 {...props} />
  10. {props.name}
  11. </div>
  12. )
  13. }
  14. export default C1
  1. // C2.js
  2. import React from 'react'
  3. import C3 from './C3'
  4. function C2(props) {
  5. console.log(props)
  6. return (
  7. <div>
  8. C2组件
  9. <C3 {...props} />
  10. </div>
  11. )
  12. }
  13. export default C2
  1. // C3.js
  2. import React from 'react'
  3. function C3(props) {
  4. console.log(props)
  5. return (
  6. <div>
  7. C3组件
  8. <button onClick={() => { props.change({ name: 'zoe', age: 100 }) }}>点击修改数据</button>
  9. </div>
  10. )
  11. }
  12. export default C3

特点

  • 单向数据流动,自顶向下,从父组件传到子组件
  • 基于单向数据流动,要求我们将共享的数据定义在上层组件
  • 子组件通过调用父组件传递过来的方法可以更改数据
  • 当数据发生更改之后,React 会重新渲染组件树

受控表单

  • 表单元素的值全部由 react 来进行管理,此时表单元素中的值都放在 state 中,所以表单元素里的值需要从 state 当中进行获取

    单值绑定与更新

  • 将 state 中的状态与表单的 value 值进行绑定 value = {this.state.xxx}

  • 更状态值 onChange={方法} ev.target.value
  • ev.target.name === [prop]:this.setState({})

只进行数据展示:

  • readOnly
  • defaultValue ```jsx import React, {Component} from ‘react’

class App extends Component { // 组件中的状态 state ={ name: ‘zzz’, age: 10, test:’只读’ } // 用于处理状态信息的方法 handler = (ev) => { const prop = ev.target.name this.setState({

  1. [prop]: ev.target.value})

}

render () { return (

{/ /} {/ this.setState({age: ev.target.age})}/> /}

  1. <input name='name' value={this.state.name} onChange={this.handler}/>
  2. <input name='age' value={this.state.age} onChange={this.handler}/>
  3. {/* <input type='text' value={this.state.test} readOnly /> */}
  4. <input type='text' defaultValue={this.state.test} />
  5. </div>
  6. )

} }

export default App

  1. <a name="f7bDS"></a>
  2. ### 下拉菜单
  3. ```jsx
  4. import React, {Component} from 'react'
  5. class App extends Component {
  6. // 状态
  7. state = {
  8. subject: 'JavaScript'
  9. }
  10. render () {
  11. return (
  12. <div>
  13. <select value={this.state.subject} onChange={ev => {this.setState({subject: ev.target.value})}}>
  14. <option value='大前端'>大前端</option>
  15. <option value='JavaScript'>JavaScript</option>
  16. <option value='python'>python</option>
  17. </select>
  18. <hr />
  19. <button onClick={() => {console.log(this.state)}}>点击获取状态</button>
  20. </div>
  21. )
  22. }
  23. }
  24. export default App

单选框

  1. import React, {Component} from 'react'
  2. class App extends Component {
  3. // 状态
  4. state = {
  5. sex: '男'
  6. }
  7. render () {
  8. return (
  9. <div>
  10. <input
  11. type='radio'
  12. name='sex'
  13. value='男'
  14. defaultChecked={this.state.sex === '男'}
  15. onChange={ev => this.setState({sex: ev.target.value})} />男
  16. <input
  17. type='radio'
  18. name='sex'
  19. value='女'
  20. defaultChecked={this.state.sex === '女'}
  21. onChange={ev => this.setState({sex: ev.target.value})} />女
  22. <button onClick={() => {console.log(this.state)}}>Button</button>
  23. </div>
  24. )
  25. }
  26. }
  27. export default App

复选框

  1. import React, {Component} from 'react'
  2. class App extends Component {
  3. // 模拟数据源
  4. hobbies = [
  5. {
  6. id: 1,
  7. title: 'vue',
  8. isChecked: true
  9. },
  10. {
  11. id: 2,
  12. title: 'React',
  13. isChecked: false,
  14. },
  15. {
  16. id: 3,
  17. title: 'Angular',
  18. isChecked: false
  19. }
  20. ]
  21. handler (index, ev) {
  22. this.hobbies[index].isChecked = ev.target.checked
  23. }
  24. render () {
  25. return (
  26. <div>
  27. {
  28. this.hobbies.map((hobby,index) => {
  29. return (
  30. <label key={hobby.id}>
  31. <input
  32. type='checkbox'
  33. value={hobby.title}
  34. defaultChecked={hobby.isChecked}
  35. onChange={(ev) => {this.handler(index,ev)}} />{hobby.title}
  36. </label>
  37. )
  38. })
  39. }
  40. <hr />
  41. <button onClick={() => {console.log(this.hobbies)}}>Button</button>
  42. </div>
  43. )
  44. }
  45. }
  46. export default App

提交

  1. import React, {Component} from 'react'
  2. class App extends Component {
  3. // 状态
  4. state = {
  5. name: 'zzz',
  6. age: 10
  7. }
  8. // 模拟数据源
  9. hobbies = [
  10. {
  11. id: 1,
  12. title: 'vue',
  13. isChecked: true
  14. },
  15. {
  16. id: 2,
  17. title: 'React',
  18. isChecked: false,
  19. },
  20. {
  21. id: 3,
  22. title: 'Angular',
  23. isChecked: false
  24. }
  25. ]
  26. handler (index, ev) {
  27. this.hobbies[index].isChecked = ev.target.checked
  28. }
  29. submit(ev){
  30. ev.preventDefault()
  31. // 提交时拿到所有选择中的的 id 数组
  32. let ret = this.hobbies
  33. .filter(hobby => hobby.isChecked)
  34. .map(hobby => hobby.id)
  35. // 合并所有需要提交的数据
  36. ret = {
  37. ...this.state, ret
  38. }
  39. console.log(ret)
  40. }
  41. render () {
  42. return (
  43. <form onSubmit={(ev) => {this.submit(ev)}}>
  44. {
  45. this.hobbies.map((hobby,index) => {
  46. return (
  47. <label key={hobby.id}>
  48. <input
  49. type='checkbox'
  50. value={hobby.title}
  51. defaultChecked={hobby.isChecked}
  52. onChange={(ev) => {this.handler(index,ev)}} />{hobby.title}
  53. </label>
  54. )
  55. })
  56. }
  57. <hr />
  58. <button onClick={() => {console.log(this.hobbies)}}>Button</button>
  59. <input type='submit' />
  60. </form>
  61. )
  62. }
  63. }
  64. export default App

非受控表单

  • 不受 react 管理,表单元素的数据由 DOM 元素进行管理,表单元素的值也是存放在 DOM 元素里,获取的时候需要操作 DOM 元素
  • 该方法已不被推荐使用 ```jsx import React, {Component} from ‘react’

// 非受控表单 class App extends Component {

submit = (ev) => { ev.preventDefault()

  1. // 获取 DOM 元素
  2. console.log(this.refs.username)
  3. // 获取具体的值
  4. console.log(this.refs.username.value)

}

render () { return (

) } }

export default App

```