初识react

目录

react官网

一、新建react项目命令

二、初始化react项目

三、事件的简单处理

四、页面数据的更新

 五、ref的使用

六、列表的渲染、超出隐藏、添加、删除

七、组件传参

八、子传父

九、试用ref获取子组件

十、简单介绍下兄弟传参

十一、插槽的使用

十二、生命周期

十二、hooks的使用


react官网

React 官方中文文档

React 英文官网

一、新建react项目命令

安装脚手架

npm install -g create-react-app 

创建项目

create-react-app my-react

二、初始化react项目

        1.创建的时候会把依赖一块创建出来所以就可以直接运行

        运行命令

        npm run start

        2.删除src下面的文件(注意文件夹留下不要删除),新建index.js作为入库js文件(必须叫index.js)

        3.初始化index.js(组件首字母要大写)注意:组件的封装与调用不过多讲解


import React from "react";

import ReactDOM from "react-dom";

import './index.css'

import App from "./app";

import { createRoot } from 'react-dom/client';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App />);

三、事件的简单处理

        1.三种事件的处理方式和this指向问题

import React, { Component } from 'react'



export default class clickEvent extends Component {

  render() {

    return (

      <div>

        <button onClick={() =>{

            console.log('标签内部处理点击事件');

        }}> 点击事件1</button>

        <button onClick={this.handleClick2}> 点击事件2</button>

        <button onClick={() =>{

            this.handleClick3(2)

        }}> 点击事件3</button>

      </div>

    )

  }

  handleClick2(){

    console.log('外部处理一');

  }

  handleClick3(e){

    console.log('外部处理2,接收参数',e);

  }

}

四、页面数据的更新

        1.状态管理(及响应式)简单的选项卡切换

SwitchTabs.css代码



.tabs{

    display: flex;

    margin-top: 10px;

}

.tab{

    background-color: #f1f1f1;

    padding: 5px 10px;

    color: #000;

}

.active{

    background-color: skyBlue;

    color: #fff;

}



SwitchTabs代码



import React, { Component } from 'react'

import './SwitchTabs.css'

export default  class SwitchTabs extends Component {

  state ={

    currentShow :'选项一'

  }

  render() {

    return (

      <div className='tabs'>

        <div className={"tab "+(this.state.currentShow === '选项一' ?'active':'')} onClick={()=>{

          this.handleTabClick('选项一')

        }}>选项一</div>

        <div className={"tab "+(this.state.currentShow === '选项二' ?'active':'') } onClick={()=>{

          this.handleTabClick('选项二')

        }} >选项二</div>

        <div className={"tab "+(this.state.currentShow === '选项三' ?'active':'')}  onClick={()=>{

          this.handleTabClick('选项三')

        }}>选项三</div>

      </div>

    )

  }

  handleTabClick(e){

    this.setState({

      currentShow:e

    })

  }

}

 五、ref的使用

        

import React, { Component } from 'react'

export default class ref extends Component {
    myInput = React.createRef()
  render() {
    return (
      <div>
        <input ref={this.myInput} />
        <button onClick={() =>{
            this.getDom()
        }
        }>获取dom</button>
      </div>
    )
  }
  getDom(){
    console.log('获取到的元素',this.myInput);
  }
}

六、列表的渲染、超出隐藏、添加、删除

安装better-scroll插件使用超出隐藏滚动

npm i better-scroll

import React, { Component } from 'react'
import BetterScroll from 'better-scroll'
import './index.css'
export default class index extends Component {
    state = {
        list:[]
    }
  render() {
    return (
      <div>
        <button onClick={() =>{
            this.addList()
        }}>添加列表元素</button>
          <div className='box'>
             <ul>
                 {
                    this.state.list.map((item,index) =>
                        <li key={index}>{item}
                        <button onClick={() =>{
                            this.del(index)
                        }}>删除单个元素</button>
                        </li>)
                 }
            </ul>
          </div>
      </div>
    )
  }
  del(i){
    var arr = this.state.list.slice()
    arr.splice(i,1)
    this.setState({
        list:arr
    })
  }
  addList(){
    var arr = [1,2,3,4,5,6,7,8,9,0]
    this.setState({
        list:arr
    },() =>{
        new BetterScroll('.box')
    })
  }
}

七、组件传参

        1.父传子,可以传多个,如非字符串使用{},传参限制类似使用   类名.propTypes默认值 类名.defaultProps 

父组件在标签内部使用参数名加参数进行传参

<TransferData title="父传子" show={false}/>
<TransferData title="父传子" show={true}/>

子组件使用this.props进行接收

import React, { Component } from 'react'
import kerwinPropType from 'prop-types'
export default class index extends Component {
    static propTypes = {
        show:kerwinPropType.bool()
    }
    
  render() {
    return (
      <div style={{display:'flex',width:'100px',justifyContent:'flex-end',alignItems:'center'}}>
        {this.props.show && <h3>显示</h3>}
        <h2>{this.props.title}</h2>
      </div>
    )
  }
}

index.defaultProps = {
    show :true
}

函数组件,无法限制类性,无法添加默认值,以形参的方式进行传参

import React from 'react'

export default function fun(data) {
  return (
    <div>
        <h1>{data.title}</h1>
    </div>
  )
}

八、子传父

理解:使用父传子的方案,定义一个方法吧父组件的方法传过去,子组件操作的时候,把父组件的方法执行一下

父组件代码
     <Son event={() =>{
            this.setState({
              val:'子组件传的'
            })
          }}/>

子组件代码

class Son extends Component{
  render(){
    return (
      <div>
        <button onClick={()=>{
          console.log(this.props);
          this.props.event()
        }}>这是子组件</button>
      </div>
    )
  }
}

九、试用ref获取子组件

ref可以获取子组件整个class类属性,包括里面的方法,dom等,试用方案请看代码

父组件
   <FieId ref={this.userName}></FieId>
            <button onClick={() =>{
              console.log(this.userName.current.state.val);
            }}>获取子组件val</button>
            <button  style={{margin:'0 10px'}} onClick={() =>{
              this.userName.current.clear()
            }}>清除</button>
            <button onClick={() =>{
              this.userName.current.serVal()
            }}>set子value</button>

子组件

class FieId extends Component{
  state = {
    val:''
  }
  clear(){
    this.setState({
      val:''
    })
  }
  serVal(){
    this.setState({
      val:'123'
    })
  }
  render(){
    return(
      <div>
        <input onChange={(e)=>{
          this.setState({
            val:e.target.value
          })
        }} value={this.state.val}/>
      </div>
    )

  }
}

十、简单介绍下兄弟传参

①.父传子 -> 子传父 ->父传第二个子

父代码

export default class index extends Component {
  constructor() {
    super()
    this.state = {
      filmsList: [],
      val:'初始值'
    }
    axios.get('http://localhost:3000/test.json').then(res => {
      this.setState({
        filmsList: res.data.data.films
      })
    })
  }
  render() {
    return (
      <div>
        <h1>组件传参</h1>
        {
          this.state.filmsList.map(item =>
            <Son {...item} key={item.filmId} onEvent={(val) =>{
              this.setState({
                val:val
              })
            }
            }/>
          )
        }
        <div className='con'><Son1 val={this.state.val}/></div>
        {/* <div className='footer'><Footer></Footer></div> */}
      </div>
    )
  }
}

第一个子组件

class Son extends Component {

  render() {
    return (
      <div className='son1' onClick={() =>{
        this.props.onEvent(this.props.synopsis)
      }}>
        {/* <h1 onClick={  this.get()}>子组件1</h1> */}
       
        <img src={this.props.poster} />
        {this.props.name}
      </div>
    )
  }
}

第二个子组件

class Son1 extends Component {
  render() {
    return (
      <div className='son2'>
        <h1>{this.props.val}</h1>
      </div>
    )
  }
}

②.使用全局订阅、发布的方案进行传参(思路很简单,在第二个子组件定义一个回调函数,通过全局的方法可以调取到第二个组件的方法,使用一个变量,然后在第一个子组件出发的时候调用回调函数即可

全局定义对象

var bus = {
    method: '11233',
    // 订阅
    subscribe(val) {
        this.method = val
    },
    //发布
    publish(v) {
        this.val = v
        this.method(v)
    }
}
//父组件正常渲染数据
export default class 兄弟传参02 extends Component {
    constructor() {
        super()
        this.state = {
            filmsList: []
        }
        axios.get('http://localhost:3000/test.json').then(res => {
            this.setState({
                filmsList: res.data.data.films
            })
        })
    }
    render() {
        return (
            <div>
                {
                    this.state.filmsList.map(item =>
                        <Son {...item} key={item.filmId} />
                    )
                }
                <div className='con'>
                    <Son1 val={this.state.val} />
                </div>
            </div>
        )
    }
}

第一个子组件
class Son extends Component {
    render() {
        return (
            <div className='son1' onClick={() => {
                // this.props.onEvent(this.props.synopsis)
                bus.publish(this.props.synopsis)
            }}>
                <img src={this.props.poster} alt={this.props.name} />
                {this.props.name}
            </div>
        )
    }
}
第二个子组件

class Son1 extends Component {
    state = {
        val: '初始化'
    }
    constructor() {
        super()
        bus.subscribe((v) => {
            this.setState({
                val: v
            })
        })

    }
    render() {
        return (
            <div className='son2'>
                <h1>{this.state.val}</h1>
            </div>
        )
    }
}

③.context状态树传参(没有子、父组件之分,通过回调函数进行传参)

最外层使用GlobalContext.Provider

组件使用GlobalContext.Consumer

const GlobalContext = React.createContext()
//最外层代码
export default class 组件传参 extends Component {
    constructor() {
        super()
        this.state = {
            filmsList: [],
            val: '初始值'
        }
        axios.get('http://localhost:3000/test.json').then(res => {
            this.setState({
                filmsList: res.data.data.films
            })
        })
    }
    render() {
        return (
            <GlobalContext.Provider value={{
                val:this.state.val,
                chanSetSynopsis:(val) =>{
                    this.setState({val:val})
                }
            }}>
                <div>
                    <h1>组件传参</h1>
                    {
                        this.state.filmsList.map(item =>
                            <Son {...item} key={item.filmId} />
                        )
                    }
                    <div className='con'><Son1 /></div>
                    {/* <div className='footer'><Footer></Footer></div> */}
                </div>
            </GlobalContext.Provider>

        )
    }
}

组件1
class Son extends Component {
    render() {
        return (
           <GlobalContext.Consumer>
          {
              (value) =>{
                return(
                    <div className='son1' onClick={() => {
                        value.chanSetSynopsis(this.props.synopsis)
                    }}>
                        <img src={this.props.poster} alt={this.props.name} />
                        {this.props.name}
                    </div>
                )
            }
          }
           </GlobalContext.Consumer>
        )
    }
}
组件2
class Son1 extends Component {
    render() {
        return (
           <GlobalContext.Consumer>
            {
                (value) =>{
                    return(
                        <div className='son2'>
                        <h1>{value.val}</h1>
                    </div>
                    )
                }
            }
           </GlobalContext.Consumer>
        )
    }
}

十一、插槽的使用

export default class index extends Component {
  render() {
    return (
      <div>
        <ChildComponent>
            <div>111111</div> 
            <div>222222</div> 
            <div>333333</div> 
        </ChildComponent>
      </div>
    )
  }
}
const ChildComponent = (props) => {
        return (
            <div>
                {props.children}
            </div>
        )
}

十二、生命周期

import React, { Component } from 'react'

export default class index extends Component {
    state ={
        val : '初始',
        type:true
    }
    static getDerivedStateFromProps(e,v){
        console.log(e,v);
        console.log('运行render之前 修改state的值');
        return {

        }
    }
   
    componentDidMount(){
        console.log('dom挂在后 可以拿到dom元素',document.getElementsByClassName('dom'));
    }
  render() {
    console.log('默认执行');
    return (
      <div className='dom'>
        <button onClick={() =>{
            this.setState({
                val:'123',
                type:!this.state.type
            })
        }}>更换</button>
        {this.state.val}
        {this.state.type && <Son title={this.state.val} />}
      </div>
    )
  }
getSnapshotBeforeUpdate(e,v){
    console.log(e,v);
    console.log('更新后生命周期');
    return{type:111}
}
  shouldComponentUpdate(e,v){
    console.log(e,v);  
    console.log('返回 true 页面进行 返回 false 则不更新');
    return true
  }
  componentDidUpdate(e,v,value){
    console.log(e,v);
    console.log('使用setState修改值以后触发 值是修改后的值','getSnapshotBeforeUpdate返回的数据',value);
    console.log(this.state.val);

  }
}

class Son extends Component{
    UNSAFE_componentWillReceiveProps(e,v){
        console.log(e,v);
        console.log('父组件更新以后会触发子组件的生命周期');
    }
    render(){
        return (
            <div>123</div>
        )
    }
    componentWillUnmount(){
        console.log('销毁生命周期');
    }
}

十二、hooks的使用

(在function组件使用)

useState定义变量,修改变量方法

useEffect初始化运行,[]为空时默认执行一次

useMemo重新渲染页面事触发,[]传入,修改的数据。如:list,val分别是列表、val值

useRef 获取dom元素

useReducer设置全局变量

import React, { useEffect, useState, useMemo, useRef, useReducer } from 'react'

import React, { useEffect, useState, useMemo, useRef, useReducer } from 'react'
import axios from 'axios'

const reducer = (e, type) => {
    const types = type.type
    let newCount = { ...e }
    if (types == '-') {
        newCount.count--
        return newCount
    } else {
        newCount.count++
        return newCount
    }
}
//数据可以有多个  useReducer
const intialState = {
    count: 0,
}
export default function useMemo1() {
    const [val, setval] = useState('')
    const [list, setlist] = useState([])
    const useRefData = useRef()
    const [state, setState] = useReducer(reducer, intialState)
    // useEffect的使用
    useEffect(() => {
        axios({
            url: "/test.json",
            method: "get",
            headers: {
                'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.0.4","e":"16395416565231270166529","bc":"110100"}',
                'X-Host': 'mall.film-ticket.cinema.list'
            }
        }).then(res => {
            setlist(res.data)
        })
    }, [])
    const getList = useMemo(() => list.filter(item => item.name.toUpperCase().includes(val.toUpperCase()) ||
        item.address.toUpperCase().includes(val.toUpperCase())
    ), [list, val])

    const getRef = () => {
        console.log(useRefData.current.value);
    }
    return (
        <div>
            <p> useState, useRef,的使用</p>
            <input value={val} ref={useRefData} onChange={(e) => {
                setval(e.target.value)
            }} /> <button onClick={() => {
                getRef()
            }}>获取ref数据</button>
            <p>useMemo的使用</p>
            {
        getList.map(item =>
            <li key={item.cinemaId}>{item.name}</li>)
      }

            <p>useReducer的使用</p>
            <button onClick={() => {
                setState({
                    type: '-'
                })
            }}>-</button>

            {state.count}
            <button onClick={() => {
                setState({
                    type: '+'
                })
            }
            }>+</button>
        </div>
    )
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值