day02—React组件化

1、模块&组件

模块是指:
组件是指:结构样式交互全拆
比如某一个网页中的头部Header,可以将所有css、images、video等等文件一起复用。

2、类式组件初体验

无论是函数式组件还是类式组件,组件名的首字母都是大写
【注】:后期中函数式组件会使用更多

//类式组件只要调用一次,就相当于new 类名,创建了一个类组件实例化对象
//组件调用一次,相当于new一次,就会产生一个实例化对象
//调用:<组件名/>或者是<组件名><组件名/>

class MyComponent extends React.Component {
//类式组件中,render方法是必须要存在的,且返回一个虚拟DOM元素结构
//而其中的构造器函数,非必须要写,实在需要处理其类的实例化对象时才要加
	constructor(){
		//调用父类的constructor
		super();
		//this指向子类组件App的实例化对象
	}
	//render方法放在哪里? —— MyComponent的原型对象上,供实例化对象使用
	//render中的this指向? —— MyComponent的实例化对象,即MyComponent组件的实例对象
	render(){
		return <p></p>
	}
	//1、React解析组件标签,找到了MyComponent组件;
	//2、发现组件是使用类定义的,随后new出来该类的实例化对象,并通过实例对象调用原型身上的render方法;
	//3、将render返回的虚拟DOM转换为真实DOM,随后呈现在页面上;
}

3、组件实例的三大核心属性

1》state属性

React 把组件看成是一个状态机(State Machines)。

如果在类中,想要将一些可以变化状态的数据存储到类的实例化对象之中,则需要将数据放在state。

React 里,通过更新组件的state来更新对应的页面显示,

只需更新组件的 state,然后根据新的 state 重新渲染用户界面。

State值是一个对象(可以包含多个key-value)

初始化state数据:类构造器中:this.state = {…} 类结构中: state={…}(更推荐!)
读取state数据: this.state.xxx
更新state数据: this.setState({…})

<div id="root"></div>
<script type="text/babel">
    const root = ReactDOM.createRoot(document.querySelector('#root'));
    let { Component, Fragment } = React;
    class ChangeSun extends Component {
    	//constructor调用1次
    	//constructor中的this是组件实例化对象
    	constructor() {
                super();
                //this.state = { }
                //方式三
                //严格模式下,普通函数中的this指向undefined,修改this指向
                this.changeSun2 = this.changeSun2.bind(this);
            }
            
        //设置状态值
        //在实例化对象身上添加属性
        state = {
            isSunny: true;
        }
        
        //方式一
        changeSun = () => {
            let { isSunny } = this.state;
            this.setState({
                isSunny: !isSunny
            })
        }
        //方式二
        changeSun1() {
                let { isSunny } = this.state;
                this.setState({
                    isSunny: !isSunny
                })
            }
        //方式三
        //changeSun是作为onClick的回调,所以不是通过实例调用的,是直接调用的
        //类中的方法,默认开启了严格模式,所以普通函数changeSun中的this指向undefined
        //全局严格模式下的this丢失指向,不允许随意操作window对象,this为undefined。禁止自定义函数的this指向window
        changeSun2() {
            let { isSunny } = this.state;
            this.setState({
                isSunny: !isSunny
            })
        }
		
		//render函数会调用几次?n+1次  第一次是初始化的那次,n表示的是状态更新的次数
		//render中的this是组件实例化对象
        render() {
            let { isSunny } = this.state;
            return (
                <Fragment>
                    <h1>今天天气很{isSunny ? '晴朗' : '凉爽'}</h1>
                    <button onClick={this.changeSun}>切换天气—方式一</button>
                    <button onClick={() => { this.changeSun1() }}>切换天气—方式二</button><br />
                    <button onClick={this.changeSun2}>切换天气—方式三</button><br />
                </Fragment>
            )
        }
    }
    root.render(<ChangeSun />)
</script>

state属性注意

2》Props属性:

每个组件对象都有Props属性,类式组件、函数组件都有Props属性,
Props是properties的缩写,如果想要在组件的外部向组件的内部传数据,那么就可以利用props

【知识点回顾——展开/扩展运算符】
…arr:可以展开一个数组
…obj:不能展开一个对象,语法错误
但如果使用babel语法转化为了JSX,就可以允许扩展运算符展开一个对象,但不允许随意使用,仅仅适用于标签中批量传递Props,也即批量传递标签属性。

(1)传递Props&批量传递Props

以key-value的形式传递,key={…}

//父组件
class Person extends Component {
   render() {
        let obj = {
            uname: 'Evelyn',
            uage: 22,
            usex: '女'
        }
        return (
            // <Student uname={obj.uname} uage={obj.uage} usex={obj.usex} />
            //批量传递Props
            //展开运算符本来是不能展开对象的
            //由于babel转化文件,允许在Props传递数据时,展开对象
            //通过...运算符来将对象的多个属性分别传入子组件
            <Student {...obj} />
        )
    }
}

//子组件
class Student extends Component {
    render() {
    	//解构
        let { uname, uage, usex } = this.props;
        return (
            <ul>
                <li>姓名:{uname}</li>
                <li>年龄:{uage}</li>
                <li>性别:{usex}</li>
            </ul>
        )
    }
}
root.render(< Person />)

(2)限制Props类型 & 指定默认值

Props是只读属性,不允许改
Props在三大属性中,唯一一个,既可以在类中使用(this),又可以在函数中使用 (传参)!

3》refs属性

refs是虚拟DOM元素身上的属性名,可以用来标识将要获取的真实DOM。
refs是类式组件实例化对象身上的属性,用来获取真实的DOM元素对象。
函数式组件没有refs属性,但可以使用Hooks的useRef方法。

(1)Refs属性——字符串写法 (ref=" ")(官方最不推荐)

render() {
  return <div>
       用户名:<input type="text" ref="unameIpt" />
       密  码:<input type="password" ref="upassIpt" />
       <button onClick={() => { this.getFormValue() }}>获取表单元素值</button>
   </div>
};
getFormValue() {
   // console.log(this);
   // 只有这种字符串方法,才会使用到this.refs的写法
   // console.log(this.refs);
   let uname_v = this.refs.unameIpt.value;
   let upass_v = this.refs.upassIpt.value;
   
   console.log(uname_v);
   console.log(upass_v);

   this.refs.unameIpt.value = '';
   this.refs.upassIpt.value = '';
}

(2)Refs属性——回调函数写法

ref属性是虚拟DOM元素身上的一个属性名,目的是为了获取的真实DOM。

render() {
   return <div>
       用户名:<input type="text" ref={el => this.uname_ipt = el} />
       密  码:<input type="password" ref={el => this.upass_ipt = el} />
       <button onClick={this.getFormValue}>获取表单元素的值</button>
       <div className={'box'} ref={el => this.box = el}></div>
   </div>
}
getFormValue = () => {
   let uname_v = this.uname_ipt.value;
   let upass_v = this.upass_ipt.value;

   let str = `用户名是:${uname_v}</br>密码是:${upass_v}`
   this.box.innerHTML = str;
}

(3)Refs属性——React.createRef()写法

class GetFormValue extends React.Component {
   //在类式组件实例化对象身上添加属性
   unameIpt = React.createRef();//{current:null}
   upassIpt = React.createRef();
   box = React.createRef();

   render() {
       return <React.Fragment>
           用户名:<input type="text" ref={this.unameIpt} /><br />
           密  码:<input type="password" ref={this.upassIpt} /><br />
           <button onClick={this.getFormValue}>获取表单元素值</button>
           <div className={'box'} ref={this.box}></div>
       </React.Fragment>
   }

   getFormValue = () => {
       console.log(this);
       let uname_v = this.unameIpt.current.value;
       let upass_v = this.upassIpt.current.value;
       let str = `用户名是${uname_v}</br>密码是${upass_v}`;

       this.box.current.innerHTML = str;
   }
}

4、非受控组件&受控组件

受控组件和非受控组件唯一的区别是,是否和状态值有关!

class Login extends Component {
   unameIpt = React.createRef();
   upassIpt = React.createRef();

   //将表单元素中的值和状态值state绑定
   state = {
       uname: '',
       upass: ''
   }
   changeName = () => {
       this.setState({
           uname: this.unameIpt.current.value
       })
   }

   changePass = () => {
       this.setState({
           upass: this.upassIpt.current.value
       })
   }
   show = () => {
       console.log('用户名:', this.state.uname);
       console.log('密码:', this.state.upass);
   }

   render() {
       let { uname, upass } = this.state;
       //双向绑定,通过属性值
       return (
           <Fragment>
               <p>用户名:<input type="text" value={uname} onChange={this.changeName} ref={this.unameIpt} /></p>
               <p>密  码:<input type="password" value={upass} onChange={this.changePass} ref={this.upassIpt} /></p>
               <button onClick={this.show}>点击获取表单元素的值</button>
           </Fragment>
       )
   }
}

5、案例优化——高阶函数

一个函数的实际参数 或 返回值是一个函数,则这样的函数就称为是一个高阶函数。

class Login extends Component {
   unameIpt = React.createRef();
   upassIpt = React.createRef();

   //将表单元素中的值和状态值state绑定
   state = {
       uname: '',
       upass: ''
   }
   //高阶函数,通过传参的方式
   changeValue = (type) => {
   	   //高阶函数的返回值是一个函数
       return (ev) => {
           this.setState({
               [type]: ev.target.value
           })
       }
   }
   show = () => {
       console.log('用户名:', this.state.uname);
       console.log('密码:', this.state.upass);
   }

   render() {
       let { uname, upass } = this.state;
       //双向绑定,通过属性值
       return (
           <Fragment>
               <p>用户名:<input type="text" value={uname} onChange={this.changeValue('uname')} ref={this.unameIpt} /></p>
               <p>密  码:<input type="password" value={upass} onChange={this.changeValue('upass')} ref={this.upassIpt} /></p>
               <button onClick={this.show}>点击获取表单元素的值</button>
           </Fragment>
       )
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值