React

466 阅读5分钟

1.简介

  • 声明式
  • 组件化(基于组件)
  • 学习一次,随处使用

2.安装配置

1、安装React

安装命令 npm i react react-dom

  • react 包是核心,提供创建元素、组件等功能
  • react-dom 包提供DOM相关功能等

2、安装脚手架

npm i create-react-app -g   // 全局安装

3、初始化项目

create-react-app 项目名

4、启动项目

npm start

5、其他方式

image-20211106223700310

2.JSX

1.jsx简介

JSX 是 JavaScript 的简写,表示在JavaScript 代码中 写 XML(HTML)格式的代码。

优势: 声明式语法更加直观,与HTML结构相同,降低了学习成本,提升了开发效率

let h1 = <h1 id='title' className='box' >hello,React</h1>
/* jsx语法,h1是react元素 */   
ReactDOM.render(h1,document.getElementById('root'))

2.jsx插值语法

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
// import App from './App'// jsx语法,h1是react元素
// let h1 = <h1 id='title' className='box' >hello,React</h1>
// ReactDOM.render(h1,document.getElementById('root'))// JSX⭐⭐ 语法:
// 单表签必须闭合;布尔值不渲染; {}单括号
// 标签属性有所变化
// 1. class改成className
// 2. 多个单词组成的属性,需要变成小驼峰
let num = 50
let state = false
let message = 'Start'
let pic = 'https://img0.baidu.com/it/u=3927459320,2138990686&fm=26&fmt=auto'
let person = {
  name: 'zs',
  age: 50
}
let arr = ['zs', 'li']
let arr2 = [<li key="1">你好</li>, <li key="2">我好</li>]
let htmlStr = '<div>我是一个文字的内容</div><b>我是文章的段落</b>'
​
​
let tpl = (
  <div>
    <h1 id={'data' + num}>{message}</h1>
    <img src={pic} alt='' className='pic' />
    <h1>{state}</h1>
​
    {/* 不能直接渲染对象 */}
    <h2>{JSON.stringify(person)}</h2>
​
    {/* 数组 */}
    <div>{arr}</div>
    <div>{arr2}</div>
​
    {/* html字符串;插值语法+对象 */}
    <div dangerouslySetInnerHTML={{ __html: htmlStr }}></div>
  </div>
)
ReactDOM.render(tpl, document.getElementById('root'))
​

3.样式操作

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'// 样式操作:
// 1. 操作class
// 2. 操作style
let sty = { backgroundColor: 'red', color: '#fff' }
let tpl = (
  <div>
    <h1 className={200 > 2 ? 'success' : 'fail'}>hello!react</h1>
    <h1 style={sty}>hello!react</h1>
  </div>
)
​
​
ReactDOM.render(tpl, document.getElementById('root'))

4.条件渲染(三元表达式)

// 导入react
// 导入react-dom
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css'
// 条件渲染let tpl = (<div>
  {
    20 > 10 ?
      <ul>
        <li>111</li>
        <li>111</li>
        <li>111</li>
        <li>111</li>
      </ul>
      :
      <p>
        <span>暂无数据</span>
        <img src="" alt="" />
      </p>
  }
</div>)
​
ReactDOM.render(tpl, document.getElementById('root'))

5.列表渲染

// 导入react
// 导入react-dom
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css'// 列表渲染
let arr = ['铁娃', '二狗子', '翠花']
// 直接渲染数组的话,会把数组每个元素取出直接拿去渲染!
let arr2 = [<li key="1">铁娃</li>, <li key="2">二狗子</li>, <li key="3">翠花</li>]
// 处理arr变成像arr2一样
let arr3 = arr.map((item, index) => {
  return <li key={index}>{item}</li>
})
let tpl = (<div>
  {/* 1 */}
  {arr}
  <hr />
​
  {/* 2 */}
  <ol>
    {arr2}
  </ol>
​
  {/* 3 */}
  <ul>
    {arr3}
  </ul>
​
  <hr />
  {/* 最终写法 */}
  <ul>
    {arr.map((item, index) => (<li key={index}>{item}</li>))}
  </ul>
</div>)
​
ReactDOM.render(tpl, document.getElementById('root'))

3.组件

1.函数式组件

快捷键 rfc

import React from 'react';
// 函数式组件let Item = () => {
  return (
    <div className="item">
      <div className="title">测试</div>
      <div className="content">内容</div>
    </div>
  )
}
export default Item

2.类组件

快捷键 rcc

import React, { Component } from 'react';
​
/*
class 组件名 extends Component/React.Component {
  render(){
    return jsx片段
  }
}
*/class Box extends Component {
  render () {
    return (
      <div className="box">
        我是Box组件
      </div>
    );
  }
}
​
export default Box;

3.补充

// 函数式组件没有状态,没有生命周期,必须依赖Hook钩子才可以获取到状态以及生命周期钩子
// 类组件有状态,有生命周期!// 组件名首字母必须大写

4.事件绑定

1.函数式组件事件绑定

// 函数式组件
import React from 'react';
​
function click (str) {
  console.log('aa' + str);
}
​
const App = () => {
  return (
    <div>
      {/*事件函数是click, 不可以写()*/}
      <button onClick={click}>触发事件</button>
​
      {/* 事件函数是箭头函数 */}
      <button onClick={() => click('点击了')}>触发事件,并且传参</button>
​
    </div>
  );
}
​
export default App;

2.类组件事件绑定

import React, { Component } from 'react'class App extends Component {
  fn (event) {
    console.log(111)
    console.log(this) //undefined
    console.log(event);
  }
  constructor() {
    super()
    this.fn3 = this.fn3.bind(this)
  }
  fn3 (event) {
    console.log(333)
    console.log(this)
    console.log(event);
  }
  fn4 (event) {
    console.log(444)
    console.log(this)
    console.log(event);
  }
  fn5 = (event) => {
    console.log(555)
    console.log(this)
    console.log(event);
  }
  render () {
    return (
      <div>
        {/* ⭐⭐缺点:没有this指向,且不能传参 */}
        <button onClick={this.fn}>事件绑定1</button>
        {/* ⭐以下均是解决this指向丢失问题 */}
        {/* 最常用⭐⭐⭐每一次模板更新都重新绑定 */}
        <button onClick={this.fn.bind(this)}>事件绑定2</button>
        {/* 只绑定一次 ,性能更优*/}
        {/* <button onClick={this.fn3}>事件绑定3</button> */}
        {/* 最常用⭐⭐⭐箭头函数可以留住this指向 */}
        <button onClick={(event) => this.fn4(event)}>事件绑定4</button>
        {/* <button onClick={this.fn5}>事件绑定5</button> */}
      </div>
    )
  }
}
export default App
// 类组件传值
import React, { Component } from 'react'class App extends Component {
  fn (num, event) {
    console.log(num);
    console.log(event);
    console.log(this) //undefined
  }
  fn4 (num, event) {
    console.log(num);
    console.log(event);
    console.log(this)
  }
  render () {
    return (
      <div>
        <button onClick={this.fn.bind(this, 60)}>事件绑定2</button>
​
        <button onClick={(event) => this.fn4(60, event)}>事件绑定4</button>
      </div>
    )
  }
}
​
export default App

5.组件状态(state和setState)

函数组件叫无状态组件,类组件叫做有状态组件

负责展示 负责更新ui

import React, { Component } from 'react'class App extends Component {
  constructor() {
    super()
    // 类似于vue中的data
    this.state = {
      num: 10,
      age: 20,
    }
  }
  changeNum = () => {
    //⭐ 修改state必须使用setState,setState会调用render方法更新视图
    // this.setState(修改对象,回调函数)
    // this.setState(函数,回调函数),修改的值依赖之前的值
    // ⭐⭐this.setState是异步的
    this.setState({
      num: this.state.num + 1,
    })
    console.log(this.state.num)
  }
  changeAge = () => {
    this.setState((state, props) => ({
      age: state.age + 1,
    }), () => {
      console.log(this.state.age)//⭐⭐获取到的还是新值
    })
    console.log(this.state.age) //⭐⭐获取到的还是老值
  }
  render () {
    return (
      <div>
        <button onClick={this.changeNum}>{this.state.num}</button>
        <button onClick={this.changeAge}>年龄加一</button>
      </div>
    )
  }
}
​
export default App

6.表单处理

import React, { Component, Fragment } from 'react';
​
// 表单分为俩类
// 受控组件 :能改
// input有事件绑定
// 非受控组件:只读
<input type="text" readOnly />
class App extends Component {
  state = {
    formData: {
      username: '123',
      sex: '1',
      hobby: ['lq', 'zq'],
      hometown: 'hz',
      notes: '451485'
    }
  }
  // 综合修改数据的方法
  changeInputValue (event, key) {
    // 获取新值
    let newVal = event.target.value
    console.log(event.target.value);
    // 键名
    console.log(key);
    // ⭐⭐⭐es6箭头函数语法,以及解构的不可重复性
    this.setState(state => ({
      formData: {
        ...state.formData,
        [key]: newVal
      }
    }))
  }
  // 修改复选框方法
  changeCheckboxValue (event, key) {
    let newVal = event.target.value
    console.log(event.target.value);
    // ⭐findIndex只能传入函数
    let idx = this.state.formData[key].findIndex(item => item === newVal)
    if (idx === -1) {
      this.state.formData[key].push(newVal)
    } else {
      this.state.formData[key].splice(idx, 1)
    }
    // ⭐更新视图
    this.setState({})
  }
  render () {
    let { username, sex, hobby, hometown, notes } = this.state.formData
    return (
      <>
        <p>姓名:<input onChange={(event) => this.changeInputValue(event, 'username')} typsexe="text" value={username} /> </p>
        <p>性别:
          <label htmlFor=""><input onChange={(event) => this.changeInputValue(event, 'sex')} type="radio" checked={sex === '1'} value='1' />男</label>
          <label htmlFor=""><input onChange={(event) => this.changeInputValue(event, 'sex')} type="radio" checked={sex === '0'} value='0' />女</label></p>
        <p>爱好
          <label htmlFor=""><input type="checkbox" onChange={(event) => this.changeCheckboxValue(event, 'hobby')} checked={hobby.includes('lq')} value='lq' />篮球</label>
          <label htmlFor=""><input type="checkbox" onChange={(event) => this.changeCheckboxValue(event, 'hobby')} checked={hobby.includes('zq')} value='zq' />足球</label>
          <label htmlFor=""><input type="checkbox" onChange={(event) => this.changeCheckboxValue(event, 'hobby')} checked={hobby.includes('qq')} value='qq' />铅球</label>
        </p>
        <p>家乡:
          <select value={hometown} onChange={(event) => this.changeInputValue(event, 'hometown')}>
            <option value="">请选择</option>
            <option value="hf">合肥</option>
            <option value="nj">南京</option>
            <option value="hz">杭州</option>
          </select>
        </p>
        <p>
          <textarea onChange={(event) => this.changeInputValue(event, 'notes')} value={notes} name="" id="" cols="30" rows="10"></textarea>
        </p>
      </>
    );
  }
}
​
export default App;

7.ref

import React, { Component } from 'react';
import Text from './text';
​
class App extends Component {
  constructor() {
    super()
    //创建ref引用
    this.fileRef = React.createRef()
    this.textRef = React.createRef()
  }
  showFile = () => {
    // ⭐获取dom节点
    console.log(this.fileRef.current);
  }
  changeNum = () => {
    this.textRef.current.setState({
      num: 50
    })
  }
  render () {
    return (
      <div>
        <Text ref={this.textRef} />
        <input ref={this.fileRef} type="file" />
        <hr />
        <button onClick={this.showFile}>获取文件信息</button>
        <button onClick={this.changeNum}>修改text中的num</button>
      </div>
    );
  }
}
​
export default App;

8.子父组件通信

1.父===> 子

image-20211108001904347

2.子===> 父

image-20211108002056145

3.context跨组件传递数据(provider/consumer)

image-20211111195650856

9.props校验

image-20211111204635967

4.路由

1.安装配置

react的路由核心思想 一切皆为组件!

this指向app实例对象

安装: npm install react-router-dom

2.图片引入方式

image-20211111221553469

3.路由实现

image-20211111222501917

                                                 往下||||

1.声明式导航

image-20211111232319478

往下|||||

2.编程式导航

image-20211111232735793

history.goback()

3.权限路由(路由拦截)

image-20211111234029489

image-20211112202929130

image-20211112203154267

5.调用请求

image-20211112193935945

6.生命周期

componentDidMount:生命周期:挂载完成之后

//组件将要被卸载 componentWillUnmount

// 组件是否应该更新!一定要返回布尔值,true表示组件要更新,false不会让组件更新 shouldComponentUpdate(newProps,newState){ return newProps.newMusic.length ? true :false } // 组件更新之后 componentDidUpdate

7.页面传值

image-20211112195756242

this.props.match.params

image-20211112200229016

image-20211112202408472

8.redux

三大原则

  • 单一数据源

  • state是只读

  • 使用纯函数进行修改

    • 一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数。

1.store.dispatch 触发action执行reducer函数

image-20211112201624412

2.store.getState() 获取state数据

3.store.subscribe() 监听数据的变化

image-20211112203348132

9.react-redux

image-20211112204512384

image-20211112204329863

10.hooks 钩子函数

blog.csdn.net/chenzhizhuo…

\