Hello React day2


学习React基础的第一天

Day two

1.组件实例的三大核心属性 1:State

  • state(做状态管理的)
 class Weather extends React.Component {
            constructor(props) {
                super(props)    //不一定要写
                this.state = { isHot: true }   //当state里面的数据更新时,会重新调用render方法
            }
            render() {
                const { isHot } = this.state
                return <h2>今天天气真{isHot ? '炎热' : '凉快'}</h2>
            }
        }
ReactDOM.render(<Weather />, document.querySelector('#test'))

2.React中的事件绑定

        class Weather extends React.Component {
            constructor(props) {
                super(props)
                this.state = { isHot: true }
            }
            //react解析到组件的时候发现是class组件,就会去new这个class,让这个实例去调用render方法 所以render this指向这个类
            render() {
                const { isHot } = this.state
                //推荐行内的事件绑定,但是注意写法格式 含义为将demo这个函数作为onClick事件的回调,当你点击的时候,React会帮你执行   onClick={demo()}这种形式的话,React解析到这里的时候会直接会调用这个函数拿到这个函数的返回值给onClick
                return <h2 id="title" onClick={demo}>今天天气真{isHot ? '炎热' : '凉快'}</h2>
            }
        }
        ReactDOM.render(<Weather />, document.querySelector('#test'))
        function demo() {
            console.log(111111);
        }

3.类里面的注意点

  • 类里面的方法会默认在局部开启严格模式!!!
  • 类里面是可以直接写类似 a = 1, fn = () => {} 这样的赋值语句的,他们会作为实例自身的方法或属性存在,不在构造函数的原型对象上

4.类中方法的this

       class Weather extends React.Component {
            constructor(props) {
                super(props)
                this.state = { isHot: true }
            }
            render() {    //
                const { isHot } = this.state
                return <h2 id="title" onClick={this.demo}>今天天气真{isHot ? '炎热' : '凉快'}</h2>
            }
            demo() {
                //dmeo是放在Demo类的原型上的
                //由于demo是作为onClick的回调,所以不是通过实例调用的,是直接调用
                //类中·方法默认开启了局部的严格的模式,所以demo中的this为undefined
                console.log(this); //undefined
            }
        }
        ReactDOM.render(<Weather />, document.querySelector('#test'))

5.使用bind方法实现state状态更新步骤

   //定义一个展示天气情况的组件
        class Weather extends React.Component {
            //constructor只调用一次
            constructor(props) {
                super(props)
                this.state = { isHot: true }
                //解决demo中的this指向问题
                this.demo = this.demo.bind(this)
            }
            // 调用 1+n次
            render() {    //
                const { isHot } = this.state
                //调用的时候是普通调用  但是这个时候调用的函数是绑定在实例身上的方法,不是原型上的方法,而且已经用bind改变了this的指向了,
                //换句话说就是这个实力上的方法始终指向的是这个实例
                return <h2 id="title" onClick={this.demo}>今天天气真{isHot ? '炎热' : '凉快'}</h2>
            }
            //点几次就调用几次
            //这个方法在构造函数的原型对象上
            demo() {
                //开启了严格模式
                const ishot = this.state.isHot
                //严重注意状态(state)不可以直接更改,必须要通过settate方法修改
                //这个setState方法是来自React.Component这个类上的 是一种合并,不是替换!!!!
                this.setState({ isHot: !ishot })
            }
        }
        ReactDOM.render(<Weather />, document.querySelector('#test'))

6.精简版实现state状态更新

        class Weather extends React.Component {
            state = { isHot: true }  //直接以赋值的形式写在class中是作为实例的一个属性的
            render() {    
                //this指向的也是实例化对象
                const { isHot } = this.state
                return <h2 id="title" onClick={this.demo}>今天天气真{isHot ? '炎热' : '凉快'}</h2>
            }
//以赋值的方式去写,是作为实例的一个方法,不是在对象原型上,而且因为是箭头函数,中的this指向的是自己的上下文(父级),也就是实例化对象,所以就不需要bind在demo方法中可以直接使用this就是实例化对象
            demo = () => {
                const ishot = this.state.isHot
                this.setState({ isHot: !ishot })
            }
        }
        ReactDOM.render(<Weather />, document.querySelector('#test'))

7.组件实例三大核心组件 2:props

  class List extends React.Component {
        render() {
            const { name, sex, age } = this.props
                return (
                    <ul>
                        <li>姓名: {name}</li>
                        <li>性别: {sex}</li>
                        <li>年龄: {age}</li>
                    </ul>
                )
            }
        }
        // ReactDOM.render(<List name="Tom" sex="女" age="18" />, document.querySelector('#test1'))
        const obj = { name: "jerry", sex: "男", age: "20" }
        //注意这里的{...obj} 外层的{}表示里面是一个js表达式,里面的...不是拓展运算符!!!
        //是react加上babel才可可以使用的语法糖 
        //批量传递标签属性
        ReactDOM.render(<List {...obj} />, document.querySelector('#test2'))

8. … 的注意点

  • 在react的props传参位置使用代表的是这里的语法糖,将这个对象转换为注释那里的样子
  • js原生中的…分为两种,一种为拓展运算符,一种为剩余参数
  • 注意对象{}是不可以使用…展开的,因为他没有部署iterator接口
  • 特殊情况为{…obj},这个表达式的意思为,对象的复制(首层深拷贝),而不是展开!!

9.对props属性做限制

  //要多导入一个类型限制的包
<script src="./prop-types.js"></script>
List.propTypes = {   //大小写区分好
            name: PropTypes.string.isRequired,  //字符且必须
            age: PropTypes.number,   //数字类型
            speak: PropTypes.func    //限定为函数类型
        }
        //默认值设置
        List.defaultProps = {
            sex: '不男不女',
            age: 18
        }
        ReactDOM.render(<List name='nihao' sex="女" age={18} speak={speak} />, document.querySelector('#test1'))
        function speak() {
            console.log('hahaha');
        }

10.constructor的使用注意点

  • 在 React 组件挂载之前,会调用它的构造函数。在为 React.Component 子类实现构造函数时,应在其他语句之前调用 super(props)。否则在constructor中不用直接使用this.props会出现undefined 的情况
  • 通常,在 React 中,构造函数仅用于以下两种情况:
    • 通过给 this.state 赋值对象来初始化内部 state
    • 事件处理函数绑定实例就是 ( this.demo = this.demo.bind(this) ) 就是偏函数的一种体现

11.props的简写和注意事项

  • 因为加限制的propTypes 和 defaultProps 必须加在这个构造函数上
  • 可以使用static关键字把这两个属性直接写在class中,作为这个类的静态属性,即可实现简写
  • 组件标签的所有属性都保存在props中
  • 不要直接修改props的值,会报错,它是一个只读属性

12.函数组件使用props(利用参数)

//函数组件使用不了状态(state) 和refs   但是用hooks的话就可以使用
function Demo(props) {
          //利用了函数可以接收参数的特性接收props
            const { name, age, sex } = props
            return (
                <ul>
                    <li>姓名: {name}</li>
                    <li>性别: {sex}</li>
                    <li>年龄: {age + 1}</li>
                </ul>
            )
        }
        //和类中做限制的普通方法一致
        Demo.propTypes = {
            name: PropTypes.string.isRequired,  //字符且必须
            age: PropTypes.number,   //数字类型
        }
        //默认值设置
        Demo.defaultProps = {
            sex: '不男不女',
            age: 18
        }
        ReactDOM.render(<Demo name='nihao' age='18' sex="男" />, document.querySelector('#test1'))

13.ref的使用方式

  • 字符型 : 不推荐使用,效率很低(后续可能会丢弃)
  • 回调函数型: (推荐使用,官网说了,没啥影响)
  1. 如果 ref 回调函数是以内联函数(ref ={(currentNode) => {this.xxxx = currentNode}})的方式定义的,在更新过程中(state状态改变,render重新渲染后)它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。
  2. 通过将 ref 的回调函数定义成 class的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。
  • React.createRef() 专人专用 React.createRef这个函数被调用之后会返回一个容器,可以存储被ref标识的节点

14.到现在为止用到的几个API

  • React.createElement(tag, props, children) // 可以用来创建虚拟DOM
  • ReactDOM.render(VDOM, ‘dom容器’) // 将虚拟DOM渲染到页面上
  • React.createRef() //返回一个可以用来存储被ref标识的节点的容器
  • 构造函数.propTypes / PropTypes(用来做props类型的限制的js文件) / 构造函数.defaultProps(用来设置默认值的)
  • RactDOM.unmountComponentAtNode(node) //用来销毁一个dom容器中的组件
  • this.setState() //修改状态(状态不能直接修改)
  • this.farceUpdate() //强制更新

15.React中的事件处理

  1. 通过onXxxx属性指定的事件处理函数(注意大小写)
    • React使用的是自定义(合成)事件(不是原生的DOM事件) —— 为了更好的兼容性
    • React中的事件是通过事件委托的方式来处理的(委托给组件最外层的元素)—— 为了更高效
  2. 在事件处理函数中可以接收到事件event,通过event.target可以获取到触发事件的那个DOM元素—— 不要过度的使用ref打标识

16.受控组件于非受控组件

  • 在HTML中,标签


文章作者: 洪大俊
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 洪大俊 !
评论
  目录