react学习记录

74 阅读5分钟

react定义

  • react用于构建用户界面的js库
  • 特点
    • 组件化模式, 声明式编码提高开发效率和组件复用率
    • react native:可以做安卓或ios开发
    • 使用了虚拟dom+diffing算法, 尽量避免和真实dom交互,提高了加载效率
  • 虚拟dom和真实dom
    • 虚拟dom本质上是object类型对象
    • 虚拟dom比较轻 . 上面属性比真实dom少, 因为虚拟dom在react内部使用, 用不上那么多的属性
    • 虚拟dom最终被转化成真实dom显示在页面上

jsx语法规则

  1. 定义虚拟dom不加引号
  2. 标签中混入js表达式要用花括号, {}
  3. 样式标签名不用class 要用className
  4. 内联样式: 要用style= {{key: v}} 的形式去写
  5. 只有一个根标签
  6. 标签必须闭合
  7. 标签首字母 (1) 标签首字母小写, 会在html中寻找同名标签, 如果没有则报错 (2) 标签首字大写,react会渲染对应的组件,如果组件未定义则报错

组件

  • 函数式组件
    • 函数式组件(用于定义简单组件),函数名就是组件名
    • 函数组件内的this为undefined, 因为babel转换开启了严格模式
    • 执行过程
      • react解析组件标签找到组件
      • 发现是函数定义的, 调用函数, 将虚拟dom转成真实dom并显示到页面中
  • 类组件
    • 条件
      • react中使用类组件时需要继承react中的Component类
      • 必须有render 且返回
    • rander放在组件的原型对象中, 给组件的实例使用
    • rander的this指向的是组件的实例对象
    • 执行过程
      • react解析组件名, 找到组件
      • 发现是类定义的, new该类的实例, 并通过该实例调用原型的rander方法
      • 将rander返回的虚拟dom转成真实dom随后呈现到页面
<div id="lenxi"></div>
<div id="test"></div>
// 函数组件
  function MyComponent() {
      console.log(this); // undefined    因为babel编译后开启了严格模式
      retur    (<h2>函数组件,适用于简单组件定义</h2>)
      // 渲染函数组件到页面
        ReactDOM.render(<MyComponent/>, document.getElementById('lenxi'))
  }
// 类组件
 class MyComponent extends React.Component {
      render() {
          // render的this是 组件的实例对象
          console.log(this)  //MyComponent {props: {…}  context: {…}, refs: {…}, updater  {…}, _reactInternalFiber  FiberNode, …}
          return <h2>类定义组件  适用于复杂组件的定义</h2>
      }
  }
  // 渲染类组件到页面
  ReactDOM.render(<MyComponent />  document.getElementById('test'))
  • 复杂组件和简单组件
    • 复杂组件: 有状态(state)
    • 简单组件: 没有状态(state)
  • 组件实例的三大属性
  1. state
    1. state的值为对象,
    2. 通过更新组件state来更新页面显示(重新渲染组件)
    3. 组件render方法的this为组件实例对象
    4. 组件自定义方法的this为undefined
      1. 强制绑定this通过bind方法
      2. 赋值语句+箭头函数
    5. 状态数据不能直接修改
    <div id="test"></div>
    <script type="text/babel">
        // 创建组件
        class Wather extends React.Component {
            render() {
                const { isHout, wind } = this.state
                return <span onClick={this.clickTitle}>今天天气很{isHout ? '炎热' : '凉快'},{wind}</span>
            }
            // 类中可以直接写赋值语句
            state = {
                isHout: true,
                wind: '刮台风'
            }
            // 利用箭头函数没有this指向, 他的this会向外寻找,找到类的实例对象
            // 自定义方法 --- 赋值语句的形式+箭头函数
            clickTitle =  ()=> {
                let isHout = this.state.isHout
                this.setState({
                    isHout: !isHout
                })
            }
        }
        ReactDOM.render(<Wather />, document.getElementById('test'))
    </script>
  1. props
  • 类中构造器可写可不写, 一旦写了就要用super接收props否则this.props会为undefined
  • 每个组件都有props属性,组件标签的属性保存在props中
  • 作用: 通过标签属性向组件内传递变化数据,注意,组件内部不要修改props的数据
    <div id="test"></div>
    <script type="text/babel">
        // 创建组件
        class Person extends React.Component {
            render() {
                // 传递标签属性 
                const {name, age, sex} = this.props
                return (
                    <ul>
                        <li>姓名: {name}</li>
                        <li>性别: {sex}</li>
                        <li>年龄: {age + 1}</li>
                    </ul>
                )
            }
        }
        // 渲染
        let p = {name: 'haruki', age: 26, sex: '男'}
        ReactDOM.render(<Person {...p}/>, document.getElementById('test'))
    </script>
// 函数使用props
    <div id="test"></div>
    <script type="text/babel">
        function Person(props) {
            const { name, age, sex } = props
            return (
                <ul>
                    <li>姓名: {props.name}</li>
                    <li>性别: {props.sex}</li>
                    <li>年龄: {props.age + 1}</li>
                </ul>
            )
        }
        // 限制组件类型规则
        Person.propTypes = {
            name: PropTypes.string.isRequired, // 定义name为string类型, 必传
            age: PropTypes.number,
            speak: PropTypes.func // 限制为函数类型
        }
        // 默认值限制
        Person.defaultProps = {
            sex: 'nan',
            age: 13
        }
        let p = { name: 'haruki', age: 26, sex: '男' }
        ReactDOM.render(<Person {...p} />, document.getElementById('test'))
    </script>
  1. refs
  • 标签可以定义ref来标识自己, 收集其真实dom到refs中.
// 回调函数ref
<div id="test1"></div>
    <script type="text/babel">
        // 创建组件 字符串类型的ref
        class Demo extends React.Component {
            render() {
                // 内联里写ref在更新时会调用两次, 通过将ref回调函数定义为class的绑定函数方式可以避免
                return (
                    <div>
                        {/*<input type="text" ref={(c) => { this.input1 = c }} placeholder="点击按钮提示" />*/}
                        <input type="text" ref={this.saveInput} placeholder="类绑定方式" />
                        <button onClick={this.showData}>提示左侧数据</button>
                        <input ref={c => this.input2 = c} type="text" onBlur={this.showData2} placeholder="失去焦点提示" />
                    </div>
                )
            }
            saveInput=(c)=> {
                console.log(c, 'ppppppp');
                this.input1 = c
            }
            // static input1
            // static input2
            // 点击按钮提示方法
            showData = () => {
                // 获取input内的内容
                console.log(this.input1, '点击按钮提示方法1', this.input1.value);
            }
            // 展示右侧输入框数据
            showData2 = () => {
                console.log(this.input2, '点击按钮提示方法2', this.input2.value);
            }
        }
        ReactDOM.render(<Demo />, document.getElementById('test1'))
    </script>
// create ref
    <div id="test1"></div>
    <script type="text/babel">
        // 创建组件 字符串类型的ref
        class Demo extends React.Component {
            // 调用后, 返回一个容器, 该容器可以存储ref标识节点, 该容器专人专用,只能存一个
            myRef = React.createRef()
            myref2 = React.createRef()
            render() {
                return (
                    <div>
                        <input type="text" ref={this.myRef} placeholder="点击按钮提示" />
                        <button onClick={this.showData}>提示左侧数据</button>
                        <input ref={this.myref2} type="text" onBlur={this.showData2} placeholder="失去焦点提示" />
                    </div>
                )
            }
            // 点击按钮提示方法
            showData = () => {
                // 获取input内的内容
                console.log(this.myRef.current, this.myRef.current.value);
            }
            // 展示右侧输入框数据
            showData2 = () => {
                console.log(this.myref2.current, this.myref2.current.value);
            }
        }
        ReactDOM.render(<Demo />, document.getElementById('test1'))
    </script>

事件处理

  • 高阶函数: 如果一个函数符合下面两个的一个,就是高阶函数
    1. 若A函数, 接收的参数是一个函数,A就可以称之为高阶函数
    2. 若A函数, 调用的返回值是一个函数, A也可以称之为高阶函数
    3. 常见的高阶函数: Promise, setTimeout, 数组场景方法 map...
  • 函数柯里化: 通过函数调用继续返回函数的方式, 实现多次接收参数最后统一处理的函数编码形式
    <div id="test1"></div>
    <script type="text/babel">
        // 受控组件, 页面中输入类dom输入时会将数据放到状态里, 使用时取出
        class Login extends React.Component {
            render() {
                return (
                    <form action="http://www.atguigu.com/" onSubmit={this.getInfor}>
                        用户名: <input onChange={this.saveForeDate('userName')} ref={c => this.userName = c} type="text" name='userName' />
                        密码: <input onChange={this.saveForeDate('passWord')}  ref= {c => this.passWord = c} type="password" name="password" id="" />
                        <button>登录</button>
                    </form>
                )
            }
            // 初始化状态,
            state = {
                userName: '',
                passWord: '',
            }
            // saveForeDate: 高阶函数, 柯里化
            saveForeDate = (dataType) => {
                //  柯里化
                return (e) => {
                    console.log(dataType, e.target.value);
                    // dataType: 对象属性,[]获取
                    this.setState({[dataType]: e.target.value})
                }
            }
            // 提交事件
            getInfor = (event) => {
                event.preventDefault() // 阻止表单提交
                console.log(this.state );
            }
        }
        ReactDOM.render(<Login/>, document.getElementById('test1'))
    </script>