小火柴的博客笔记 小火柴的博客笔记
首页
学过的习
踩过的坑
想过的事
首页
学过的习
踩过的坑
想过的事
  • 学过的习

    • CSS的样式优先级权重
    • 事件冒泡和事件捕获
    • js模块可以通过两种方式对外暴露函数
    • js中的内存泄漏和内存溢出
    • js作用域链
    • 控制台暴露vue
    • es5常用知识总结
    • es6常用知识总结
    • es7常用知识总结
    • js模块化
    • nodeJs学习
    • node搭建服务器
    • webPack学习
    • js原型对象和原型链的理解
    • css阻塞与js阻塞
    • ajax的学习
    • 浏览器的重绘与重排
    • 函数防抖与函数节流学习记录
    • 浏览器储存学习
    • React起步
    • React的基本使用
      • React的组件定义方式
      • React的state属性:
      • React的props属性
      • React的refs属性
      • React的生命周期(V16.4^)
    • React项目搭建
    • vue中attrs和listeners的使用
    • js的精度问题
    • React的状态管理
    • yarn和npm的对比
    • websocket的使用
  • 想过的事

  • 踩过的坑

  • 前端
  • 学过的习
小火柴
目录

React的基本使用

# React的组件定义方式

1.函数式组件

定义函数(名字大写,后续组件名字大写才会查询自定义组件,否则是当标签查询)
function MyComponent1(){
    console.log(this); //此处的this是undefined,因为经过babel的编译后,开启了严格模式。
    return <h2>函数式组件</h2>
}

渲染组件到页面
ReactDOM.render(<MyComponent1/>,document.getElementById('xxx'))

执行了ReactDOM.render后:
    1.React获取<MyComponent1/>标签,判断出MyComponent是用函数定义的。
    2.React调用MyComponent1并获取函数的返回的虚拟DOM,随后转为真实DOM,随后渲染到页面。
    
注:由于处于React+babel环境,开启的严格模式。函数中无法使用this

2.类式组件

1、定义组件
class MyComponent extends React.Component{

    //render是MyComponent的原型对象上,给MyComponent的实例对象用的。
    render(){
        console.log(this); //MyComponent的实例对象
        return <h2>类式组件</h2>
    }
}

2、渲染组件到页面
ReactDOM.render(<MyComponent/>,document.getElementById('test'))

执行了ReactDOM.render后:
    1.React获取<MyComponent/>标签,判断MyComponent是用类定义的。
    2.React new了一个MyComponent实例对象
    3.通过实例调用MyComponent原型上的render方法,并获取到了返回的虚拟DOM,转为真实DOM,渲染页面。
    
注:render中是可以获取到实例的this的



# React的state属性:

1、简单写法(this指向问题需要手动解决)

class MyComponent extends React.Component{
    //组件被实例化几次,就调用几次构造器
    constructor(props){
        super(props)
        this.state = {showTest:'显示',other:'测试'} //初始化状态
        //构造器中的this指向实例化对象,将changeTest的this绑定实例化对象并将函数赋值给实例化的对象的changeTest属性,
          所以后面调用的changeTest并不是原型上的,是实例化对象上面的属性。
        this.changeTest = this.changeTest.bind(this) //解决this指向问题
    }
    
    changeTest(){
        //若构造器中不做处理,那么下面的this是undefined,因为changeTest不是通过实例调用的,
          而是作为点击的回调去使用,且类中的方法自动开启了严格模式。
        //更新状态,不能直接获取状态并赋值,不然不会去触发render调用的!!!
        this.setState({showTest:'更改了'}) //此处更新状态是一个合并的动作,不是替换
    }
    
    //render调用次数是1+n次(n是更新状态的次数,每次状态的更改都要重新更改虚拟DOM)
    render(){
        //这里将函数给onClick回调事件,并没有在这里调用函数,所以changeTest中的this不是实例化对象。
        return <h1 onClick={this.changeTest}>
                  this is test state,{this.state.showTest},{this.state.other}
               </h1>
    }
}



2、常用方法,利用箭头函数解决this的指向问题

class MyComponent extends React.Component{

    constructor(props){
        super(props)
        this.state = {showTest:'显示',other:'测试'} //初始化状态
    }
    
    //使用箭头函数解决this指向问题,箭头函数的this在定义的时候由同外部环境
    changeTest = ()=>{
         this.setState({showTest:'更改了'})
    }
    
    render(){
        //这里将函数给onClick回调事件,并没有在这里调用函数,所以changeTest中的this不是实例化对象。
        return <h1 onClick={this.changeTest}>this is test state,{this.state.showTest},{this.state.other}</h1>
    }
}


注: 原生JS中绑定函数,是将函数绑定,react的绑定的函数,是将函数的返回值提交绑定

jsx:
<h1 onClick={this.changeTest}>this is test state,{this.state.showTest},{this.state.other}</h1>

js:事件名大小写不同,并且绑定的方式不同,
   原生中不会执行changeTest()这个函数,但是jsx中加括号会执行函数,绑定返回值。
<h1 onclick='this.changeTest()'>this is test state</h1>



# React的props属性

class Person extends React.Component{

    //对传给Person组件的props进行类型的限制
    static propTypes = {
        name:PropTypes.string, //限制name必须为字符串类型
     ** sex:PropTypes.string.isRequired,//限制sex必须为字符串类型,且是必要属性
        age:PropTypes.number,//限制age必须为数值类型
        address:PropTypes.string, //限制address必须为字符串类型
    }
    
    //对传给Person组件的props进行默认值的设置
    static defaultProps = {
        address:'中国'
    }
    
    render(){
        const {name,age,sex,address} = this.props
        return (
            <ul>
                <li>姓名:{name}</li>
                <li>性别:{sex}</li>
                <li>年龄:{age+1}</li>
                <li>地址:{address}</li>
            </ul>
        )
    }
}

//渲染组件
ReactDOM.render(<Person name="tom" sex="女" age="18"/>,document.getElementById('XXX'))

const p1 = {
    name:'程老师',
    sex:'男',
    age:19,
    address:"北七家镇"
}

//下面的...p1,并不是原生js里的{...p1},{}是jsx的写法要求
//babel+react环境就可以让展开运算符展开一个对象,但是仅仅适用于传递标签属性!!
ReactDOM.render(<Person {...p1}/>,document.getElementById('XXX'))


//高级用法,利用prop传递一个箭头函数(用于子组件传递参数给父组件)
updateAppState = (stateObj)=>{
    this.setState(stateObj)
}

render() {
    return (
        <div className="container">
            //将更新的函数通过prop传递给子组件
            <Search updateAppState={this.updateAppState}/>
        </div>
    )
}

//子组件中通过调用prop的函数进行传参
this.props.updateAppState({...})



# React的refs属性

1、字符串类型的Refs,标记了ref的节点可以直接通过refs属性获取。(官方不建议继续使用,论坛显示有效率问题)

class Test extends React.Component{

    //箭头函数解决this指向问题
    showData = ()=>{
        //获取用户的输入,inputRef是真实DOM节点!!
        const {inputRef} = this.refs
        //提示数据
        alert(inputRef.value)
    }
    
    render(){
        return (
            <div>
                <input ref="inputRef" type="text" placeholder="点击按钮提示输入"/>&nbsp;
                <button onClick={this.showData}>点我提示数据</button>
            </div>
        )
    }
}

2、回调形式的ref,在ref中传入回调函数,函数的形参默认就是当前节点ref,直接绑定ref(形参)到实例的属性上。

class Demo extends React.Component{
    
    showData = ()=>{
        //获取用户的输入,input1是真实DOM节点!!
        const {inputRef} = this
        //提示数据
        alert(inputRef.value)
    }
    
    render(){
        return (
            <div>
                <input ref={c => this.inputRef = c} type="text" placeholder="点击按钮提示输入"/>&nbsp;
                <button onClick={this.showData}>点我提示数据</button>
            </div>
        )
    }
    }

3、createRef创建ref,类中直接使用React.createRef()创建容器,虚拟节点上直接使用ref指向容器即可

class Demo extends React.Component{

    //使用createRef,可以创建一个存储节点的容器,并且每个容器只能存储一个ref节点,多个ref需要多次创建。
    container1 = React.createRef()
    container2 = React.createRef()

    showData = ()=>{
        const {current} = this.container1
        alert(current.value)
    }
    
    showData2 = ()=>{
        const {current} = this.container2
        alert(current.value)
    }
    
    render(){
        return (
            <div>
                <input ref={this.container1} onBlur={this.showData1} type="text"/>
                <input ref={this.container2} onBlur={this.showData2} type="text"/>
            </div>
        )
    }
}



注:
1.类式组件中的构造器,完全可以省略掉
2.若在类式组件中写了构造器,那就必须调用super,调用super时,如果不传props,那么在构造器中,通过this.props是不可以访问props的


# React的生命周期(V16.4^)

//定义组件
class LifeHoook extends React.Component{

    //构造器
    constructor(){
        console.log('---constructor---');
        super()
        this.state = {count:0}
    }

    //更改状态
    add = ()=>{
        const {count} = this.state
        this.setState({count:count+1})
    }

    //卸载的回调
    death = ()=>{
        ReactDOM.unmountComponentAtNode(document.getElementById('test'))
    }

    //强制更新的回调
    force = ()=>{
        this.forceUpdate()
    }
    
    //会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。
    //它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
    static getDerivedStateFromProps(props,state){
        console.log('---getDerivedStateFromProps---',props,state)
        return null
    }
    
    //在最近一次渲染输出(提交到 DOM 节点)之前调用。
    //它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。
    //此生命周期方法的任何返回值将作为参数传递给 componentDidUpdate()。
    getSnapshotBeforeUpdate(prevProps, prevState){
        console.log('---getSnapshotBeforeUpdate---',prevProps, prevState)
        return null
    }
    
    //组件更新完毕----调用n次,n是更新的次数,会在更新后会被立即调用。首次渲染不会执行此方法。
    componentDidUpdate(prevProps, prevState, snapshot){
        console.log('---componentDidUpdate----',prevProps, prevState, snapshot);
    }
    
    //组件将要挂载---调1次
    UNSAFE_componentWillMount(){
        console.log('---componentWillMount---');
    }

    //组件挂载完毕---调1次,会在组件挂载后(插入 DOM 树中)立即调用。
    //依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。
    componentDidMount(){
        console.log('---componentDidMount---');
    }

    //组件将要卸载---调1次,在此方法中执行必要的清理操作。
    //例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。
    componentWillUnmount(){
        console.log('---componentWillUnmount---');
    }
    
    //组件更新的“阀门”
    shouldComponentUpdate(){
        console.log('---shouldComponentUpdate---');
        return true
    }

    //组件将要更新----调用n次,n是更新的次数
    UNSAFE_componentWillUpdate(){
        console.log('---componentWillUpdate---');
    }

    UNSAFE_componentWillReceiveProps(){
        console.log('---componentWillReceiveProps---');
    }
    
    //组件初次渲染+更新---调1+n次
    render(){
        console.log('---render---');
        return(
            <div>
                <h2>当前状态为:{this.state.count}</h2>
                <button onClick={this.add}>更改状态</button>
                <button onClick={this.death}>卸载组件</button>
                <button onClick={this.force}>强制更新</button>
            </div>
        )
    }
}

//渲染组件
ReactDOM.render(<LifeHoook/>,document.getElementById('XXX'))

注: 下述生命周期方法即将过时,在新代码中应该避免使用它们;因为这些生命周期方法经常被误解和滥用,此外,预计在异步渲染中,它们潜在的误用问题可能更大

  • UNSAFE_componentWillMount()
  • UNSAFE_componentWillUpdate()
  • UNSAFE_componentWillReceiveProps()
#React
React起步
React项目搭建

← React起步 React项目搭建→

Theme by Vdoing | Copyright © 2021-2023 X match
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式