React学习笔记(二)

组件实例的三大属性

1.属性一

state
【概念】React 把组件看成是一个状态机。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
【注意】

  1. 组件中render方法中的this为组件实例对象
  2. 组件自定义的方法中this为undefined,如何解决?
    a. 强制绑定this:通过函数对象的bind()
    b. 箭头函数
  3. 状态数据,不能直接修改或更新
  4. 不要直接修改State,而是使用setState()

2.属性二

props
子组件只能通过 props 来传递数据

	<script type="text/babel">
        //1.创建组件
        class Person extends React.Component {
            render() {
                const {name,age} = this.props;
                return (
                    <div>
                        <ul>
                            <li>姓名:{name}</li>
                            <li>年龄:{age}</li>
                        </ul>
                    </div>
                )
            }
        }
        
        //对标签属性进行类型|必要性的限制(这里需要引入PropTypes的React库文件)
        Person.propTypes = {
            name: PropTypes.string.isRequired,
            sex: PropTypes.string,
            age: PropTypes.number,
            speak: PropTypes.func
        }
        //对标签属性进行类型、必要性的限制
        Person.defultProps = {
            sex:'女',
            age:18
        }

        //2.渲染组件到页面
        ReactDOM.render(<Person name="张三" age="14"/>, document.getElementById('test1'));
        ReactDOM.render(<Person name="老王" age="18"/>, document.getElementById('test2'));
    
        function speak(){
            console.log('我说话了');
        }
    </script>

props简写方式(把所有的限制放在类的里边)

	<script type="text/babel">
	    //1.创建组件
	    class Person extends React.Component {
	        //对标签属性进行类型|必要性的限制
	       static propTypes = {
	            name: PropTypes.string.isRequired,
	            sex: PropTypes.string,
	            age: PropTypes.number,
	            speak: PropTypes.func
	        }
	        //对标签属性进行类型、必要性的限制
	        static defultProps = {
	            sex:'女',
	            age:18
	        }
	        render() {
	            const {name,age} = this.props;
	            return (
	                <div>
	                    <ul>
	                        <li>姓名:{name}</li>
	                        <li>年龄:{age}</li>
	                    </ul>
	                </div>
	            )
	        }
	    }
	
	    //2.渲染组件到页面
	    ReactDOM.render(<Person name="张三" age="14"/>, document.getElementById('test'));
	    
	    function speak(){
	        console.log('我说话了');
	    }
	</script>

3.属性三

ref
ref是React提供的用来操纵React组件实例或者DOM元素的接口。

ref的三种方式

  1. 字符串形式的ref
	 <script type="text/babel">
        //1.创建组件
        class Demo extends React.Component {
            showIputDate = () => {
                const {input2} = this.refs;
                alert(input2.value);
            }
            render() {
                return (    
                    <div>
                        <input onBlur={this.showIputDate} ref="input2" type="text" placeholder="失去焦点获取内容" />&nbsp;&nbsp;
                    </div>
                )
            }
        }

        //2.渲染组件到页面
        ReactDOM.render(<Demo/>, document.getElementById('test'));
    </script>
  1. 回调形式的ref
	 <script type="text/babel">
        //1.创建组件
        class Demo extends React.Component {
            showDate = () => {
                const {input} = this;
                alert(input.value);
            }

            showIputDate2 = () => {
                const {input3} = this;
                alert(input3.value);
            }

            render() {
                return (    
                    <div>
                        <input type="text" ref={(e)=>{this.input=e;console.log("@",e)}} placeholder="点击按钮获取内容" /> &nbsp;&nbsp;
                        <button onClick={this.showDate}>按钮</button>&nbsp;&nbsp;
                        <input onBlur={this.showIputDate2} ref={(c) => {this.input3 = c}} type="text" placeholder="失去焦点获取内容" />
                    </div>
                )
            }
        }

        //2.渲染组件到页面
        ReactDOM.render(<Demo/>, document.getElementById('test'));
    </script>
  1. ceateRef的使用
	<script type="text/babel">
	  //1.创建组件
        class Demo extends React.Component {
            /*
                React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点
            */
            myRef = React.createRef();
            myRef2 = React.createRef();
            showDate = () =>{
                alert(this.myRef.current.value);
            }
             
            showIputDate2 = () =>{
                alert(this.myRef2.current.value);
            }
            render() {
                return (    
                    <div>   
                        <input type="text" ref={this.myRef} placeholder="点击按钮提示数据" />&nbsp;&nbsp;
                        <button onClick={this.showDate}>按钮</button>&nbsp;&nbsp;
                        <input onBlur={this.showIputDate2} ref={this.myRef2} type="text" placeholder="失去焦点获取内容" />&nbsp;&nbsp;
                    </div>
                )
            }
        }

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

【强调】勿过度使用refs

非受控组件与受控组件

非受控组件

	<script type="text/babel">
        class Login extends React.Component{
            onLogin = (event) => {
                //阻止表单提交
                event.preventDefault();
                const {username,password} = this;
                alert(`你输入的用户名是${username.value},密码是${password.value}`)
            }
            render() {
                return (
                    <form action="https://baidu.com" onSubmit={this.onLogin}>
                        用户名: <input ref={c => this.username=c} type="text" name="username"/> &nbsp;
                        密码:<input ref={c => this.password=c} type="text" name="password"/>&nbsp;
                        <button>提交</button>
                    </form>
                )
            }
        }

        ReactDOM.render(<Login/>,document.getElementById('test'));
    </script>

受控组件

	<script type="text/babel">
       class Login extends React.Component{
            // 获取用户名到state
            changeUsername = (event) => {
                this.setState({username:event.target.value});
            }
            // 获取密码到state
            changePassword = (event) => {
                this.setState({password:event.target.value});
            }
            onLogin = (event) => {
                //阻止表单提交
                event.preventDefault();
                const {username,password} = this.state;
                alert(`你输入的用户名是${username},密码是${password}`)
            }
            render() {
                return (
                    <form action="https://baidu.com" onSubmit={this.onLogin}>
                        用户名: <input onChange={this.changeUsername} type="text" name="username"/> &nbsp;
                        密码:<input onChange={this.changePassword} type="text" name="password"/>&nbsp;
                        <button>提交</button>
                    </form>
                )
            }
            
        }

        ReactDOM.render(<Login/>,document.getElementById('test'));  
   </script>

概念
高阶函数与函数的柯里化

高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。

  1. 若A函数,接受的参数是一个函数,那么A就是可以称之为高阶函数。
  2. 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
    a.常见的高阶函数有:PromisesetTimeoutarr.map()等等

函数的柯里化:通过函数调用继续返回函数方式,实现多次接受参数最后统一处理的函数编码形式。

例子

		class Login extends React.Component{
            // 初始化状态
            state = {
                username:'', //用户名
                password: '' // 密码
            }
            // 获取表单数据到状态中
            saveFromDate = (typeDate) => {
                return(event)=>{
                    this.setState({[typeDate]:event.target.value});
                }
            }
            onSubmit = (event) => {
                //阻止表单提交
                event.preventDefault();
                const {username,password} = this.state;
                alert(`你输入的用户名是${username},密码是${password}`)
            }
            render() {
                return (
                    <form action="https://baidu.com" onSubmit={this.onSubmit}>
                        用户名: <input onChange={this.saveFromDate('username')} type="text" name="username"/> &nbsp;
                        密码:<input onChange={this.saveFromDate('password')} type="text" name="password"/>&nbsp;
                        <button>提交</button>
                    </form>
                )
            }
        }

        ReactDOM.render(<Login/>,document.getElementById('test'));

不用函数的柯里化实现

	、<script type="text/babel">
        class Login extends React.Component{
            // 初始化状态
            state = {
                username:'', //用户名
                password: '' // 密码
            }
            // 获取表单数据到状态中
            saveFromDate = (typeDate,event) => {
               this.setState({[typeDate]:event.target.value});
            }
            onSubmit = (event) => {
                //阻止表单提交
                event.preventDefault();
                const {username,password} = this.state;
                alert(`你输入的用户名是${username},密码是${password}`)
            }
            render() {
                return (
                    <form action="https://baidu.com" onSubmit={this.onSubmit}>
                        用户名: <input onChange={event => this.saveFromDate('username',event)} type="text" name="username"/> &nbsp;
                        密码:<input onChange={event => this.saveFromDate('password',event)} type="text" name="password"/>&nbsp;
                        <button>提交</button>
                    </form>
                )
            }
            
        }

        ReactDOM.render(<Login/>,document.getElementById('test'));
    </script>

react生命周期(旧与新)

  1. 组件从创建到死亡它会经历一些特定的阶段
  2. React组件中包含一系列钩子函数的生命周期,会在特定的时刻调用
  3. 我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作

生命周期(旧)
React学习笔记(二)

  1. 初始化阶段:由ReactDOM.render()触发—初次渲染
    1)constructor()
    2) componentWillMount()
    3) render()
    4) componentDidMount() ====> 常用
    一般在这个钩子中做一些初始化的事,例如:开启定时器、 送网络请求、订阅消息
  2. 更新阶段:由组件内部this.setSate()或父组件render触发
    1) shouldComponentUpdate()
    2) componentWillUddate()
    3) render() ====> 必须使用的一个
    4)componentDidUpdate()
  3. 卸载组件:由ReactDOM.unmountComponentAtNode()触发
    1) componentWillUnmount() ====> 常用
    一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

例子

	<script type="text/babel">
        //创建组件
        class Sum extends React.Component{
            //构造器
            constructor(props){
                console.log('count---constructor');
                super(props)
                // 初始化状态
                this.state = {count:0};
            }

            //加1按钮的回调
            add = ()=>{
                //获取原状态
                let {count} = this.state;
                //更新状态
                this.setState({count:count+1})
            }

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

            //强制更新按钮的回调
            force = ()=>{
                this.forceUpdate();
            }

            //组件将要挂载的钩子
            componentWillMount(){
                console.log('count---componentWillMount');
            }

            //组件将要挂载完毕的钩子
            componentDidMount(){
                console.log('count---componentDidMount');
            }

            //组件将要卸载的钩子
            componentWillUnmount(){
                console.log('count---componentWillUnmount');
            }

            //控制组件更新的“阀门”
            shouldComponentUpdate(){
                console.log('count---shouldComponentUpdate');
                return true;
            }

            //组件将要更新的钩子
            componentWillUpdate(){
                console.log('count---componentWillUpdate');
            }

            //组件更新完毕的钩子
            componentDidUpdate(){
                console.log('count---componentDidUpdate');
            }

            render() {
                console.log('count---render');
                return (
                    <div>
                        <h2>当前求和为{this.state.count}</h2>
                        <button onClick={this.add}>点我+1</button>&nbsp;
                        <button onClick={this.death}>卸载</button>&nbsp;
                        <button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
                    </div>
                )
            }
            
        }

        //父组件A
        class A extends React.Component{
            //初始化状态
            state = {carName:'奔弛'}

            changeCar = ()=>{
                this.setState({carName:'奥拓'})
            }
            render(){
                return(
                    <div>
                        <div>我是A组件</div>
                        <button onClick={this.changeCar}>换车</button>
                        <B carName={this.state.carName}/>
                    </div>
                )
            }
        }
        
        //子组件B
        class B extends React.Component{
            //组件将要接受新的props的钩子
            componentWillReceiveProps(props){
                console.log('B---componentWillReceiveProps',props);
            }

            //控制组件更新的“阀门”
            shouldComponentUpdate(){
                console.log('B---shouldComponentUpdate');
                return true;
            }

            //组件将要更新的钩子
            componentWillUpdate(){
                console.log('B---componentWillUpdate');
            }

            //组件更新完毕的钩子
            componentDidUpdate(){
                console.log('B---componentDidUpdate');
            }

            render(){
                console.log('B---render');
                return(
                    <div>我是B组件,接受到的车:{this.props.carName}</div>
                )
            }
        }

        //渲染组件
        ReactDOM.render(<A/>,document.getElementById('test'));
        // ReactDOM.render(<Sum/>,document.getElementById('test'));
    </script>

生命周期(新)
React学习笔记(二)

生命周期新与旧版本的区别:

  1. 新版本即将废弃三个生命钩子:componentWillUnmount、componentWillUpdate和componentWillReceiveProps
  2. 提出2个新的生命钩子:getDerivedStateFromProps和getSnapshotBeforeUpdate
上一篇:自顶而下学习react源码 (1) 理念篇


下一篇:表单无刷新上传图片