react 入门

294 阅读4分钟

react 入门学习笔记

安装react

npm install create-react-app 安装react脚手架
create-react-app my-app 创建项目
cd my-app
npm start

jsx jsavscript的语法扩展 就相当于javascript + html 可以在js里写html代码 具有很强的灵活性

function helloworld(){
  return '<h1 class="greeting">helloworld<h1/>'
}

这就是jsx 可以在函数里生成html代码 jsx会把html代码 通过babel 转成一个dom对象。就类似于下面这样

 const element = {
    type: 'h1',
    props: {
      className: 'greeting',
      children: "hello world"
    }
 }

这些对象被称为 react 元素 -- js对象

元素渲染

react 将一个元素渲染进dom中 会调用reactDom.render() 当元素改变时会从新调用 reactDom.render() 并只会更新改变部分

组件

react编写组件有两种方式 函数和class(类组件)

函数组件

 function myComp(props) {
     return <h1>hello world {props.name}<h1/>
 }

class组件

class myComp extends React.Component {
    constructor(props){
        super(props)
    }
    render() {
        return <h1>hello { this.props.name }</h1>
    }
}

如何使用(使用组件)

 function App () {
    return <div>
         <MyComp name="我的名字" ></MyComp>
     </div>
 }

使用组件是传入name到子组件,而子组件使用props.name 接受他 而props 属性只具有可读性, 不可修改

校验props 的数据类型 (propTypes) 需要引入 prop-types

import PropTypes form 'prop-type'

PropTypes.propTypes = { name: PropTypes.string , age: PropTypes.number }

 function myComp(props){
    return <h1>hello, {props.name}</h1>
 }
 myComp.defaultProps = {
     name: 'World'
 }

生命周期

只有类组件才具有生命周期 函数组件没有生命周期

  • 挂载阶段 constructor class的构造方法

  • componentWillMount 组件挂载前调用

  • render() 组件中定义的方法, 返回一个react元素, 并不负责实际渲染工作

  • componentDidMount() 组件被挂载到dom后调用, 可以在这时向后端请求数据

  • 更新阶段componentWillReceiveProps(nextProps) props变化时候调用,nextProps是更新后的参数

  • shouldComponentUpdate(nextProps, nextState) // 是否继续执行更新过程

  • 通过对比新值和旧值是否相同 返回false后续更新过程不在继续

  • componentWillUpdate(nextProps, nextState) 更新之前

  • render()

  • componentDidUpdate(prevProps, prevState) 组件更新之后调用

  • 卸载阶段

  • componentWillUnmount() 组件被删除前调用 执行一些清理工作

state 组件可以设置自己的数据(是组件私有数据)

class myComp extends React.component {
    constructor(props){
        super(props)
        this.state = {
            time: new Date()
         }
     }
    render(h) {
         return <h1>{this.state.time}</h1>
     }

}

修改state 使用setState() react自动更新子组件 setState()

事件处理

<button onClick="handelr()"></button> react采用驼峰形式命名

this 指向问题, 在组件里使用箭头函数


class myComp extends react.Component {
   constructor(props){
      super(props)
      this.state = {
        name: 'name'
      }
   }

   handelClick(){
    console.log(this.state.name)
   }

   render(h) {
     return <button onClick="() => this.handelClick()"></button>
   }
}

这里的this 指向组件实例 这种写法每次render的时候都会创建一个新的处理函数, 如果想避免从新创建 采用下面写法


class myComp extends react.component {
    constructor(props){
        super(props)
        this.state = {
            name: "jeck"
        },

        this.handelClick = this.handelClick.bind(this)
    }

    handelClick(){
        console.log(this.state.name)
    }
    render(h) {
      return <button onClick="this.handerClick"></button>\
    }
}

这样写法render 不会每次创建的时候都创建一个新的事件处理, 还可以这样

return <button onClick="this.handelClick.bind(this)"></button>

条件渲染 列表

function greet(props){
    const isShow = props.isShow
    if(isShow){
        return <span>我是组件一</span>
    }

    return <span>我是组件二</span>
}

这就是react的条件渲染

列表渲染

const numbers = \[1,2,3,4,5,6]

const dataList = numbers.map((num) => <li>{num}</li>)

状态提升 就是将需要共同维护的数据提升到父组件里去

handelClick(e){
     this.props.onTempPeratureChange(e.target.value)
} 
//和vue this.\$emit 类似

react 16新特性 16之前 render方法必须返回单个元素 现在支持返回数组 和 字符串

class example extends React.Component {
    constructor(props){
       super(props)
    }

    render(h) {
      return 'sssss'
    }

}

react 16 增加了错误边界处理,如果一个组件内部发生错误 可以捕获错误 优雅的处理

class errorExtents extends react.Component {
    constructor(props){
        super(props)
        this.state = {
           isError: false
        }
    }
    componentDidCatch(error, info){
        this.setState({
            isError : true
        })
    }
    render(){
         if(this.state.isError){
            return <p>出错啦</p>
         }
         return this.props.children
    }
}

使用 errorExtents

<errorExtents>
     <helloworld></helloworld>
</errorExtents>

深入组件

  • 直接修改state, 这样不会触发render()
  • state的更新是异步的 react可能会将多次修改合并为一次更新 当调用steState()
  • 的时候 React会将其标记为dirty 并将添加到事件处理队列里 然后通过合并处理来
  • 更新优化, 应为是异步的当更改完就去访问值的时候可能会没有变化

组件与服务器通信,官方推荐 componentDidMount 钩子

componentDidMount(){
    let that = this
    fetch('/api/xxx').then( function(response){
        that.setState({
            data.response.data
        })
    })
}

组件之前的通信 (父传子) props属性 (子传父) 回调
this.props.handelClick(xxx)

子传父 通过props调用父组件方法
<child handelClick={this.handelClick}></chlid>

Context 组件层级太深 props 会很繁琐 可以使用Content

 getChildContent(){
     return { handleClick: this.handleClick}
 }
 Father.childContextTypes = {
     handleClick: propTypes.func
 }

子组件通过context访问

 this.context.handleClick()
 Child.contextTypes = {
     handleClick: Propstypes.func
 }

使用ref 获取dom

<input type="text" ref = { (input) => { this.textInput = input}}></input>

this.textInput.focus()

在组件上使用 只能是类组件

高阶组件 HOC

高阶组件是以函数为参数, 返回值也是函数的函数 高阶组件只需关注抽象的逻辑, 无需关注页面ui/dom, 可以使用高阶组件 数据校验 请求 当多个组件有相同的逻辑的时

function HocComp(comp){
    return class extends React.Component {
        componentWillMount(){
            let data = localStorage.getItem('data')
            this.setState({data})
        }

        render (){
            return \<comp data={this.state.data} {...this.props}><comp/>
        }
    }
}

class myComp extends React.Component{
    render(){
        return <duv>{this.props.data}</duv>
    }
}

const myCompWith = HocComp(myComp)

上面可以看出高阶组件可以 封装并分离组件通用逻辑, 让逻辑在组件中更好的被复用

使用场景 操作props

function HocRef(warpComp){
    return class extends React.Component {
        constructor(props){
            super(props)
            this.someMenten = this.someMenten.bind(this)
        }
        someMenten(){
            this.instance.menthofWarpper()
        }
        render(){
            return <warpComp ref={ (instance) => this.instance = instance } ></warpComp>
        }
    }
}

react Router

react router 包含了3个库 react-router, react-router-dom react-router-natiive react router 通过router 和 route 两个组件完成路由功能 import { Route } from 'react-router'

<Route path="/"></Route>
<Route path="/" component = {Home}></Route>
<Route path="/" render = {
(props) => {
<Home { ... props }></Home>
}
}></Route>

如果想匹配到一个路由可以

import { Router, Switch, Route , Link } from 'react-router-dom'
 <Router> 
    <Switch>
        <Route path="/" component= { Home }></Route>
        <Route path="/about" component= { About }></Route>
        <Route path="/user" component= { User }></Route> 
    </Switch>
</Router> 

重定向 <Redirect to = { xxx }

link 定义了如何路由

<link to="/login"><link/>


<Link to = {{
    pathname:"/login",
    stateL {isLogin: false}
}} 

withRouter
import react from 'react'
import { withRouter } from 'react-router-dom'

function backBtn(props){
    let { history } = props
    return <button onClick= { () =>{
        history.gobac
        k()
    }}></button>
}
backBtn = withRouter(backBtn)
export default backBtn