react

react

说明

此文全是在index.js中的文件,除了独立js文件那块

一、 组件

import React from 'react';
import ReactDOM from 'react-dom';
1.函数组件

大写字母开头,必须要有返回

function Hello(){
  return (
    <div>这是第一个函数组件Hello,平常函数</div>
  )
}
const Hello = () => <div>这是第一个函数组件Hello,箭头函数</div>

ReactDOM.render(<Hello />,document.getElementById('root'))
2.类组件:

大写开头,继承React.Component父类,必须提供render方法且有返回值

class Hello extends React.Component{
  render(){
    return (
      <div>这是第一个类组件</div>
    )
  }
}
ReactDOM.render(<Hello />,document.getElementById('root'))

3.独立js文件

抽离js文件到独立文件中,新建一个Hello.js

import React from 'react';

//创建组件
class Hello extends React.Component{
    render(){
      return (
        <div>这是第一个抽离到js文件中的类组件</div>
      )
    }
  }
// 导出组件
export default Hello

index.js先导入组件再使用

import Hello from './Hello';
ReactDOM.render(<Hello></Hello>, document.getElementById('root'))
4. React 事件绑定
方法一,通过类组件(有状态组件,动)
class App extends React.Component{
  //事件处理程序
  handleClick(){
    console.log('点我了,哈哈哈')
  }
    render(){
    return (
      <button onClick={this.handleClick}>点我 点我</button>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'))
方法二,通过函数组件(无状态组件,静)
function App(){
  function handleClick(){
    console.log('基于函数组件点击')
  }
  return (
    <button onClick={handleClick}>点我 点我</button>
  )
}
ReactDOM.render(<App />, document.getElementById('root'))
5.事件对象,e
class App extends React.Component{
  handleClick(e){
    //阻止浏览器默认行为
    e.preventDefault()

    console.log('a标签的单击事件触发了')
  }
  render(){
    return (
      <a href='http://lichee.top' onClick={this.handleClick}>lichee.top</a>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'))

6.state的基本使用
class App extends React.Component {
  // constructor(){
  //   super()
  //   // 初始化state
  //   this.state = {
  //     count:0
  //   }
  // }
  //简化写法
  state = {
    count:52
  }

 
  render(){
    return (
      <div>
        <h1>计数器:{this.state.count}</h1>
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'))
7.setState的修改

修改状态,更新UI

class App extends React.Component {
  state = {
    count:0
  }
  render(){
    return (
      <div>
        <h1>计数器:{this.state.count}</h1>
        <button onClick={()=>{
          this.setState({
            count:this.state.count+1
          })
        }}>+1</button>
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'))

8.解决this指向
class App extends React.Component {
  state = {
    count:0
  }
  constructor(){
    super()
    this.onIncrement = this.onIncrement.bind(this)
  }
  
  // onIncrement(){
  //   this.setState({
  //           count:this.state.count+1
  //         })
  // }

  // 3.class实例方法来解决this指向
  onIncrement =() =>{
    this.setState({
            count:this.state.count+1
          })
  }
  render(){
    return (
      <div>
        <h1>计数器:{this.state.count}</h1>
        {/* <button onClick={this.onIncrement}>+1</button> */}
         {/* 1.箭头函数解决this指向问题 */}
         {/* <button onClick={() =>this.onIncrement()}>+1</button> */}
         {/* 2.通过funcatopn.prototype.bind()解决 */}
        <button onClick={this.onIncrement}>+1</button>

        {/* <button onClick={()=>{
          this.setState({
            count:this.state.count+1
          })
        }}>+1</button> */}
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'))
9.表单受控组件
class App extends React.Component{
  state= {
    txt:''
  }
  handleChange = e =>{
    this.setState({
      txt: e.target.value
    })
  }
  render(){
    return (
      <div>
        <input type="text" value={this.state.txt} onChange={this.handleChange}></input>
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'))
多种表单

input、富文本、下拉框、多选框

class App extends React.Component{
  state= {
    txt:'',
    content:'',
    city:'bj',
    isChecked:false

  }
  handleChange = e =>{
    this.setState({
      txt: e.target.value
    })
  }
  //处理富文本框
  handleCondent = e =>{
    this.setState({
      content: e.target.value
    })
  }
  handleCity = e=>{
    this.setState({
      city: e.target.value
    })
  }
  handleChecked=e=>{
    this.setState({
      isChecked: e.target.checked
    })
  }
  render(){
    return (
      <div>
        <input type="text" value={this.state.txt} onChange={this.handleChange}></input>
        <br />
        <textarea value={this.state.content} onChange={this.handleCondent}></textarea>
        <br />
        <select value={this.state.city} onChange={this.handleCity}>
          <option value='sh'>上海</option>
          <option value='bj'>北京</option>
          <option value='gz'>广州</option>
        </select>
        <br />
        <input type="checkbox"  checked={this.state.isChecked} onChange={this.handleChecked}/>
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'))
优化
class App extends React.Component{
  state= {
    txt:'',
    content:'',
    city:'bj',
    isChecked:false
  }
  handleForm = e =>{
    //获取当前DOM对象
    const target = e.target
    const value = target.type === 'checkbox'
      ? target.defaultChecked
      : target.value
    const name = target.name
    this.setState({
      [name]: value
    })
  }
  render(){
    return (
      <div>
        <input type="text" name='txt' value={this.state.txt} onChange={this.handleForm}></input>
        <br />
        <textarea name='content' value={this.state.content} onChange={this.handleForm}></textarea>
        <br />
        <select name='city' value={this.state.city} onChange={this.handleForm}>
          <option value='sh'>上海</option>
          <option value='bj'>北京</option>
          <option value='gz'>广州</option>
        </select>
        <br />
        <input type="checkbox"  name='isChecked' defaultChecked={this.state.isChecked} onChange={this.handleChecked}/>
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'))

10.非受控组件
class App extends React.Component{
  constructor(){
    super()
    //创建ref
    this.txtRef = React.createRef()
  }
  getTxt = ()=>{
    console.log('文本框的值为:',this.txtRef.current.value)
  }
  render (){
    return(
      <div>
        <input type="text" ref={this.txtRef}/>
        <br />
        <button onClick={this.getTxt}>获取值</button>
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'))
11.综合案例(评论)
class  App extends React.Component{
  state = {
    comments:[
      {id:1,name:'jake',content:'沙发!!'},
      {id:2,name:'jake1',content:'沙发1!!'},
      {id:3,name:'jake3',content:'沙发2!!'},
      {id:4,name:'jake5',content:'沙发3!!'}
    ],

    //评论人
    userName:'',
    //评论内容
    userContent:''
  }
  renderList(){
    return this.state.comments.length === 0?(
      <div className="no-commit" >暂无评论,快去评论吧</div>
    ):(
      <ul>
        {this.state.comments.map(item => (
          <li key={item.id}>
            <h3>评论人 {item.name}</h3>
            <p>评论内容 {item.content}</p>
          </li>
      ))}
      </ul>
    )
  }
  //处理表单数据
  handleForm = (e) =>{
    const {name,value} = e.target
    this.setState({
      [name]:value
    })
  }
  //发表评论
  addcommit=()=>{
    const {comments,userName,userContent} = this.state

    if (userName.trim()==='' || userName.trim() === ''){
      alert("请输入内容!")
      return 
    }
    console.log(userName,userContent)
    const newComments = [{
      id : Math.random(),
      name: userName,
      content: userContent
    },
    ...comments
    ]

    this.setState({
      comments:newComments,
      userName:'',
      userContent:''
    })
  }
  render(){
    const {userName,userContent} = this.state
    return(
      <div className="app">
        <div>
          <input className='user' type='text' placeholder="请输入评论人"  value={userName} name='userName' onChange={this.handleForm}/>
          <br />
          <textarea
          className='content'
          cols = '30'
          rows = '10'
          placeholder="请输入评论内容"
          value={userContent}
          name='userContent'
          onChange={this.handleForm}
          />
          <br />
          <button onClick={this.addcommit}>发表评论</button>
        </div>

        {this.renderList()}
        {/* {this.state.comments.length === 0?(
          <div className="no-commit" >暂无评论</div>
        ):(
          <ul>
            {this.state.comments.map(item => (
              <li key={item.id}>
                <h3>评论人 {item.name}</h3>
                <p>评论内容 {item.content}</p>
              </li>
          ))}
          </ul>
        )} */}
        
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'))

二、组件进阶

1. props

函数组件接收

// 2.接收数据
const Hello = props =>{
  //props是一个对象
  console.log(props)
  return (
    <div>
      <h1>props:{props.name}</h1>
    </div>
  )
}

//1. 传递数据
ReactDOM.render(<Hello name="jack" age={19} />,document.getElementById('root'))

类组件接收

class Hello extends React.Component{
  render(){
    console.log(this.props)
    return (
      <div>
        <h1>props: {this.props.age}</h1>
      </div>
    )
  }
}

//1. 传递数据
ReactDOM.render(<Hello name="jack" age={19} />,document.getElementById('root'))

可以传任意类型数据

const Hello = props =>{
  console.log('props',props)
  props.fn()
  return(
    <div>
      <h1>props:</h1>
      {props.tag}
    </div>
  )
}

ReactDOM.render(
  <Hello 
  name="rose"
  age ={19}
  colors={['red','green','blue']}
  fn = {() =>console.log('这是一个函数')}
  tag = {<h1>HHH111</h1>}
  />,
  document.getElementById('root')
)
2.父组件–>子组件
//父组件
class Parent extends React.Component{
  state={
    lastName:"王"
  }
  render(){
    return (
      <div className="parent">
        父组件:
        <Child name={this.state.lastName}/>
      </div>
    )
  }
}

//子组件
const Child=(props)=>{
  console.log('子组件:',props);
  return(
    <div className="child">
      <p>子组件,接收到父组件的数据:{props.name}</p>
    </div>
  )
}
ReactDOM.render(<Parent />,document.getElementById('root'))
3.子组件–>父组件

思路:利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数。

//父组件
class Parent extends React.Component{
  state={
    parentMsg:''
  }
  //提供回调函数,用来接收数据
  getChildMsg = data =>{
    console.log("接收到子组件数据:",data)
    
    this.setState({
      parentMsg:data
    })
  }

  render(){
    return(
      <div className="parent">
        父组件:{this.state.parentMsg}
        <Child getMsg={this.getChildMsg}/>
      </div>
    )
  }
}
//子组件
class Child extends React.Component{
  state={
    msg:"play"
  }

  handleClick=()=>{
    //子组件调用度组件传过来的回调函数
    this.props.getMsg(this.state.msg)
  }
  render(){
    return(
    <div className="child">
      子组件:<button onClick={this.handleClick}>点我  点我</button>
    </div>
    )
  }
}

ReactDOM.render(<Parent />,document.getElementById('root'))
4.兄弟组件
class Counter extends React.Component{
  //提供共享状态
  state ={
    count:0
  }
  //提供修改状态的方法
  onIncrement = () =>{
    this.setState({
      count:this.state.count+1
    })
  }
  render(){
    return(
      <div>
        <Child1 count={this.state.count}/>
        <Child2 onIncrement={this.onIncrement}/>
      </div>
    )
  }
}
const Child1 = props =>{
  return <h1>计数器:{props.count}</h1>
}
const Child2 = props=>{
  return <button onClick={()=>props.onIncrement()}>+1</button>
}
ReactDOM.render(<Counter />,document.getElementById('root'))
5.context 跨组件传递

不用一层一层props

总结:

  1. 如果两个组件是远方亲戚(比如,嵌套多层)可以使用Context实现组件通讯

  2. Context提供 了两个组件: Provider和Consumer

  3. Provider组件 :用来提供数据

  4. Consumer组件 :用来消费数据

// 创建context得到两个组件
const {Provider, Consumer} = React.createContext()
class App extends React.Component{
  render(){
    return (
      <Provider value="pink">
        <div className="app">
          <Node />
        </div>
      </Provider>
    )
  }
}

const Node = props=>{
  return (
    <div className="node"> 
      <SubNode />
    </div>
  )
}

const SubNode = props =>{
  return (
    <div className='subnode'>
      <Child />
    </div>
  )
}

const Child = props =>{
  return (
  <div className='child'>
    <Consumer>
      {data =><span>我是子节点 -- {data}</span>}
    </Consumer>
  </div>
  )

}

ReactDOM.render(<App />,document.getElementById('root'))
6.props(chrildren)

我是子节点以这样子的会默认产生一个children

children属性:表示组件标签的子节点。当组件标签有子节点时, props就会有该属性
children属性与普通的props-样,值可以是任意值(文本、React元素、 组件,甚至是函数)

const App =props=>{
  console.log(props);
  return (
    <div>
      <h1>组件标签子节点:</h1>
      {props.children}
    </div>
  )
}
ReactDOM.render(<App>我是子节点</App> ,document.getElementById('root'))
7.props(校验)

使用步骤
1.安装包 prop-types ( yarn add prop-types / npm i props- types )
2.导入prop-types包

import PropTypes from 'prop-types'
const App =props=>{
  const arr = props.colors
  const lis = arr.map((item, index) =><li key={index}>{item}</li> )
  return <ul>{lis}</ul>
}
//添加propos校验
App.propTypes = {
  colors: PropTypes.array
}

ReactDOM.render(<App colors={19} />,document.getElementById('root'))

约束规则

  1. 常见类型: array、 bool、 func、 number. object. string
  2. React元素类型 : element
  3. 必填项: isRequired
  4. 特定结构的对象: shape({ })
8.props(默认值)
const App=props=>{
  console.log(props);
  return(
    <div>
      <h1>props默认值为:{props.pageSize}</h1>
    </div>
  )
}
App.defaultProps={
  pageSize:10
}
ReactDOM.render(<App  />,document.getElementById('root'))
9.生命周期

只有类组件才有生命周期。

class App extends React.Component {
  constructor(props) {
  super(props )
  console.warn( '生命周期钩子函数: constructor' ) 
  }
  componentDidMount(){
    console.warn( '生命周期钩子函数: componentDidMount' ) 
  }
  render() {
    console.warn( '生命周期钩子函数: render' ) 
    return (
    <div>
      <h1>统计豆豆被打的次数: </h1>
      <button id="btn">打豆豆</button>
    </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root' ))
10.props(获取鼠标位置)

组件复用

class Mouse extends React.Component{
  state ={
    x:0,
    y:0
  }
  //监听鼠标移动的事件处理
  handleMouseMove=e=>{
    this.setState({
      x:e.clientX,
      y:e.clientY

    })
  }

  //监听鼠标移动事件
  componentDidMount(){
    window.addEventListener('mousemove',this.handleMouseMove)
  }
  render(){
    return this.props.render(this.state)
  }
}


class App extends React.Component{
  render(){
    return (
      <div>
        <h1>render props 模式</h1>
        <Mouse render={(mouse)=><p>鼠标位置,{mouse.x},{mouse.y}</p>} />
      </div>
    )
  }
}
ReactDOM.render(<App/>,document.getElementById('root'))

猫捉老鼠

import img from './images/logo192.png'
class Mouse extends React.Component{
  state ={
    x:0,
    y:0
  }
  //监听鼠标移动的事件处理
  handleMouseMove=e=>{
    this.setState({
      x:e.clientX,
      y:e.clientY

    })
  }

  //监听鼠标移动事件
  componentDidMount(){
    window.addEventListener('mousemove',this.handleMouseMove)
  }
  render(){
    return this.props.render(this.state)
  }
}


class App extends React.Component{
  render(){
    return (
      <div>
        <h1>render props 模式</h1>
        <Mouse render={mouse=>{
          return(
            <p>
              鼠标位置,{mouse.x},{mouse.y}
            </p>)
          }} 
        />
        {/**猫捉老鼠 */}
        <Mouse render={mouse =>{
          return (
            <img src={img} alt="猫" style={{
              position:'absolute',
              top:mouse.y -96,
              left:mouse.x -96
            }}/>
          )
        }
        }/>
      </div>
    )
  }
}
ReactDOM.render(<App/>,document.getElementById('root'))
render props

chrildren实现render props

import img from './images/logo192.png'
import PropTypes from 'prop-types'
class Mouse extends React.Component{
  state ={
    x:0,
    y:0
  }
  //监听鼠标移动的事件处理
  handleMouseMove=e=>{
    this.setState({
      x:e.clientX,
      y:e.clientY

    })
  }
  //监听鼠标移动事件
  componentDidMount(){
    window.addEventListener('mousemove',this.handleMouseMove)
  }
  //卸载时解除事件绑定
  componentWillUnmount(){
    window.removeEventListener('mousemove',this.handleMouseMove)
  }
  render(){
    return this.props.children(this.state)
  }
  
}

Mouse.propTypes = {
  children:PropTypes.func.isRequired
}

class App extends React.Component{
  render(){
    return (
      <div>
        <h1>render props 模式</h1>
        {/* <Mouse render={mouse=>{
          return(
            <p>
              鼠标位置,{mouse.x},{mouse.y}
            </p>)
          }} 
        /> */}
        <Mouse>
          {
            mouse=>{
              return (
                <p>
                  鼠标位置,{mouse.x},{mouse.y}
              </p>
              )
            }
          }
        </Mouse>
        {/**猫捉老鼠 */}
        {/* <Mouse render={mouse =>{
          return (
            <img src={img} alt="猫" style={{
              position:'absolute',
              top:mouse.y -96,
              left:mouse.x -96
            }}/>
          )
        }
        }/> */}
        <Mouse>
          {
            mouse =>{
              return (
                <img src={img} alt="猫" style={{
                  position:'absolute',
                  top:mouse.y -96,
                  left:mouse.x -96
                }}/>
              )
            }
          }
        </Mouse>
      </div>
    )
  }
}
ReactDOM.render(<App/>,document.getElementById('root'))
2.高阶组件

三、React原理

1.setState()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XJhaDEiB-1624269396777)(https://github.com/Lichee-cpu/images/raw/master/images/images20210621111745.png)]

2.JSX转化过程

3.组件更新

4.性能优化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PgdrZd6P-1624269396791)(https://github.com/Lichee-cpu/images/raw/master/images/images20210621133749.png)]

5.虚拟DOM和Diff算法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i8hAZDoI-1624269396803)(https://github.com/Lichee-cpu/images/raw/master/images/images20210621134852.png)]

四、路由

1.基本使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VxmSf0B7-1624269396804)(https://github.com/Lichee-cpu/images/raw/master/images/images20210621170906.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z2FOLrPC-1624269396807)(https://github.com/Lichee-cpu/images/raw/master/images/images20210621170958.png)]

import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter as Router,Route,Link} from 'react-router-dom'

const First= ()=><p>页面一内容</p>

const App=()=>(
  <Router>
    <div>
      <h1>React 路由基础</h1>
      {/* 指定入口 */}
      <Link to='/first'>页面一</Link>
      {/* 指定出口 */}
      <Route path='/first' component={First}></Route>
    </div>
  </Router>
 
 )
ReactDOM.render(<App></App>,document.getElementById('root'))

2.常用组件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-brZAp5k5-1624269396812)(https://github.com/Lichee-cpu/images/raw/master/images/images20210621171350.png)]

3.编程式导航

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-guE1Ta9W-1624269396814)(https://github.com/Lichee-cpu/images/raw/master/images/images20210621173704.png)]

import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter as Router,Route,Link} from 'react-router-dom'

class Login extends React.Component{
  handleLogin = () =>{
    this.props.history.push('/home')
  }

  render(){
    return (
      <div>
        <p>登录页面:</p>
        <button onClick={this.handleLogin}>登录</button>
      </div>
    )
  }
}

const Home =(props)=>{
  const handleBack=()=>{
    props.history.go(-1)
  }

  return (
    <div>
      <h2>这是后台主页</h2>
      <button onClick={handleBack}> 返回登录页面</button>
    </div>
  )
}
const App  = () =>(
  <Router>
    <div>
      <h1>编程式导航:</h1>
      <Link to='/login'>去登录</Link>

      <Route path="/login" component={Login}></Route>
      <Route path="/home" component={Home}></Route>
    </div>

  </Router>
  
)

ReactDOM.render(<App></App>,document.getElementById('root'))
4.默认路由

默认路由path为:/

<Route path="/" component={Home} />
5.匹配模式
模糊匹配

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0oDcMlG1-1624269396818)(https://github.com/Lichee-cpu/images/raw/master/images/images20210621174628.png)]

精确匹配

给Route组件添加exact属性,让其变为精确匹配模式
精确匹配:只有当path和pathname完全匹配时才会展示该路由

//此时,该组件只能匹配pathname="/"这一种情况
<Route exact path='/' component={Home}></Route>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sea_lichee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值