React 02 - 理解组件 和 三大护法(state, props, ref)

114 阅读4分钟

理解组件

在React中主要就是围绕着组件进行开发的,理解组件和组件化开发;

  • 组件 -- 局部功能效果的资源和代码的集合;
  • 组件化开发

(笔者理解)
组件,可以看作一块拼图,而页面也可看作由一块一块拼图拼成的,一块拼图是可大可小,可包含大块部分,也只包含一个按钮;
组件化开发,是万物皆是组件,有小组件拼建成大组件,大组件拼建成整个项目;

组件的分类

根据不同的分类标准进行分类:

  • 代码书写方式:类式组件,函数式组件;
  • 是否有state:简单组件,复杂组件;
  • 表单是否维护到state:受控组件,非受控组件;

三大护法: state, props, ref

类式组件需要理解的三大概念: state, props, ref。

注意:官方推荐使用函数式组件,现还支持类式组件,但是学习也可从类式组件开始学习; 类式组件修改成函数式组件 推荐参考

理解state

state 又被称为状态机,可以用来更新页面的显示,调用setState()会重新渲染组件;

  • 使用 键值对(key: value) 方式赋值;
  • 调用setState()更新 state;

理解props

组件属性之间传递数据;

  • 数据是只读,可使用{表达式},但无法重新赋值;
  • 批量传输props, {...p}

理解ref

组件属性之间传递数据;

  • 数据是只读,可使用{表达式},但无法重新赋值;
  • 类型: ①字符串式;②回调式;③CreateRef()式

官方建议:

  • 不推荐使用字符串型ref;
  • 推荐使用后两种ref: 回调型ref, createRef, 其中各有各的优势,具体情况具体使用;
  • 请勿过度使用ref

其他

其他概念的理解

  • jsx(JavaScript XML)
  • 虚拟DOM
  • 高阶函数
  • 函数的柯里化

jsx, JavaScript XML

【理解】jsxreact 使用的语法,与 js 有区别,可理解为语法糖,计算机实际使用会翻译成 js

【优点】相对 js,jsx 会①更简单,更易创建虚拟DOM;-- 简单,简单,还是简单;

【劣势】另外的学习成本, jsx的语法规则。

虚拟DOM

【理解】本质是 object 对象,最终会被转化成 真实DOM;

【优点】相对 真实DOM, ①更轻,没有杂乱的属性;

高阶函数

【理解】

  • 两个条件满足任意一个,就是高阶函数:
    1. 若A函数,接收的参数是一个函数,那么A函数就是高阶函数;
    2. 若A函数,返回值是一个函数,那么A函数就是高阶函数;

【优点】通过复用来优化代码; 【常见高阶函数】 Promise, setTimeout, arr.map(), arr.filter()等

函数的柯里化

【理解】通过函数调用继续返回函数的方式,实现多次接收参数,最后统一处理的函数编码形式;


类式组件 -- 最简单版本

class myClassComponent extends React.Component {
    render() {
        return <h2>我是类式组件<h2/>
    }
}
ReactDOM.render(<myClassComponent />, document.getElementById('root'))

函数式组件

function myFunctionComponent() {
    return <h2>我是函数式组件<h2/>
}
ReactDOM.render(<myFunctionComponent/>, document.getElementById('root'))

复杂组件,动态修改天气 (标准形式 和 简写形式)

// 一个动态修改天气的组件 标准形式 = constructor + 其他
class Weather React.Component {
    constructor(props) {
        super(props)
        this.state = {isHot: true}
        this.changeHot = this.changeHot.bind(this)  // 为函数bind this
    }

    changeHot() {
        const isHot = this.state.isHot
        this.setState({isHot:!isHot}) // 修改状态,调用setState修改
    }

    render() {
        const {isHot} = this.state
        return <h2 onClick={ this.changeHot }>今天很{ isHot ? '炎热': '凉爽' }<h2/>
    }
}
ReactDOM.render(<Weather />, document.getElementById('root'))jsx
// 一个动态修改天气的组件, state 简写方式 使用箭头函数 =>{}
class Weather React.Component {
    // 初始化状态
    state = {isHot: true}

    // 自定义方法,=()=>{}
    changeHot = ()=>{
        const isHot = this.state.isHot
        this.setState({isHot:!isHot}) // 修改状态,调用setState修改
    }

    render() {
        const {isHot} = this.state
        return <h2 onClick={ this.changeHot }>今天很{ isHot ? '炎热': '凉爽' }<h2/>
    }
}
ReactDOM.render(<Weather />, document.getElementById('root'))

非受控组件

// 一个登录的非受控组件, 现用现取
class Login React.Component {

    handleSubmit = (event)=>{
        event.preventDefault() //阻止表达提交
        const {username, password} = this
        alter(`用户名:${username.value}, 密码: ${password.value}`)
        
    }

    render() {
        const {isHot} = this.state
        return (
            <from onSubmit={this.handleSumit}>
            用户名:<input ref={c=>this.username=c} type="text" name="username"/>
            密码:<input ref={c=>this.password=c} type="password" name="password"/>
            <from/>
    }
}
ReactDOM.render(<Login />, document.getElementById('root'))

受控组件

// 一个登录的受控组件, 推荐(不使用ref), 维护到了state, 受到了state控制
class Login React.Component {
    state = {
        username: '',
        password: ''
    }
    
    saveUsername = (event)=>{
        this.setState({username: event.target.value})
    }
    
    savePassword = (event)=>{
        this.setState({username: event.target.value})
    }
    
    handleSubmit = (event)=>{
        event.preventDefault() //阻止表达提交
        const {username, password} = this.state
        alter(`用户名:${username}, 密码: ${password}`)
    }

    render() {
        const {isHot} = this.state
        return (
            <from onSubmit={this.handleSumit}>
            用户名:<input  onChange={this.saveUsername} type="text" name="username"/>
            密码:<input onChange={this.savePassword} type="password" name="password"/>
            <from/>
    }
}
ReactDOM.render(<Login />, document.getElementById('root'))

props

class Person extends Component {
  // 对属性进行限制
  static propTypes = {
    name: PropTypes.string.isrequred,
    age: PropTypes.number
  }
  // 属性赋予默认值
  static defaultProps = {
    age: 18
  }

  render() {
    const {name, age} = this.props
    return (
      <ul>
        <li>姓名: {name} </li>
        <li>年龄: {age+1} </li>
      </ul>
    )
  }
}

ReactDOM.render(<Person name="jack" age={19}/>, document.getElementById('root'));
// 批量传递
const p = {name:"jack", age:18}
ReactDOM.render(<Person {...p}/>, document.getElementById('root'));

Ref

class Demo extends Component {
  input3 = React.CreateRef()
  showDate = ()=>{
    const {input1} = this.refs
    alter(input1.value)
    }

  render() {
    const {name, age} = this.props
    return (
      <div>
        <input ref="input1" type="text" placeholder="字符串Ref"/>
        <button onclick={this.showData}></button>
        <input ref={c=>this.input2=c} type="text" placeholder="回调Ref"/>
        <input ref={this.input3=c} type="text" placeholder="createRef"/>
        
      </div>
    )
  }
}

ReactDOM.render(<Demo />, document.getElementById('root'));

高阶函数

class Login extends Component {
  state = {
    'username':'',
    'password':'',
   }

  // 高阶函数, 返回值是一个函数,可以保存用户名和密码等表单数据
  // 应用了函数的柯里化技术
  saveForm = (dataType) =>{
    return (event)=>{
      this.setsState({[dataType: event.target.value]})
    }
  }
    
  handleSubmit = (event)=>{
  	event.preventDefault()
  }
  

  render() {
    const {name, age} = this.props
    return (
      <form onSubmit={this.handleSubmit}>
        用户名:<input onchange={this.saveForm('username')} type="text" name="username"/>
        密码:<input  onchange={this.saveForm('password')}  type="password" name="password" />
        
        <button}>登录</button>
      </div>
    )
  }
}

ReactDOM.render(<Demo />, document.getElementById('root'));