React组件基础

2 篇文章 0 订阅

一、组件的创建方式

类组件

可以通过ES6中的类来创建组件,该类继承React.Component,并且拥有一个render()函数,该函数的作用于函数组件的那个函数一样,用于返回一个JSX

class Clock extends React.Component {
	// render函数表示渲染,每次重新渲染都要调用该函数
	render(){
		return ( <div>
					<h2>Clock, {this.props.name}</h2>
				</div> 
		); 
	} 
}

二、组件的内部状态

1.state

state是组件内部维护的一组用于反映组件UI变化的状态集合state需要在构造函数中进行初始化,如果要在组件类中重写构造函数,那么需要在构造函数的第一行显式调用super(props)

class Clock extends React.Component { 
	constructor(props){ 
		super(props); 
		this.state = { 
		now:new Date().toLocaleString() 
		};
	}
}
2.state特点

不能直接修改state,需要调用this.setState()方法进行修改。

修改的时候要注意:

  • 状态的类型是不可变类型:直接赋新值
  • 状态的类型是数组:通过concat方法或者ES6数组拓展语法,不能使用在原数组的基础上修改
    的方法,例如push之类
  • 状态的类型是普通对象:通过Object.assgin或者对象拓展语法
  • state的更新是异步的调用setState,组件的state并不会立即改变
  • state的更新是一个浅合并的过程
3.示例
class Mystates extends React.Component{
    constructor(props) {
        super(props);
        this.state = {arr:[1,2,3],obj:{name:'tom',age:28}};
    }
    //在组件将要被挂载前调用
    componentWillMount() {
        //在原先的数组之上追加数据
        this.setState({arr:this.state.arr.concat(4),obj:Object.assign({},this.state.obj,{name:'yoo',age:27,gender:'man'})});
    }
    render(){
        return (
            <div>
                <h3>{this.state.arr.toString()}---{JSON.stringify(this.state.obj)}</h3>
            </div>
        );
    }
}

三、组件的生命周期

1.生命周期图

在这里插入图片描述

2.生命周期
  • componentWillMount
    在组件将要被挂载前调用
  • componentDidMount
    在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。如果调用setState,然后可以再次渲染,但是这次渲染会发生在浏览器更新屏幕之前,用户不会发现中间状态。
  • shouldComponentUpdate
    组件是否被更新,如果返回true则更新(默认),否则不更新。
  • componentWillUpdate
    组件将要被更新
  • componentDidUpdate
    组件被更新。会在更新后会被立即调用。首次渲染不会执行此方法。如果你对更新前后的 props 进行了比较,也可以选择在此处进行网络请求。
  • componentWillUnmount
    会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作。componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。
    在这里插入图片描述
3.示例
class Live extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            msg: 'hello world',
        };
    }
    //在组件将要被挂载前
    componentWillMount() {
       console.log(this.state);
    }
    //组件挂载完毕
    componentDidMount() {
        //修改数据
        setTimeout(() => {
            this.setState({
                msg: 'wonderful world'
            });
        }, 2000);
        console.log(this.state,'+++');
    }
    //是否可以更新
    shouldComponentUpdate() {
        //返回true更新(默认值),返回false不更新也不会再渲染在页面上
        return true;
    }
    //将要更新
    componentWillUpdate(){
        alert(1);
    }
    componentDidUpdate() {
        alert(2);
    }
    componentWillUnmount() {
        console.log('将要被卸载');
    }
    
    render(){
        console.log('render----');
        return (
            <h3>{this.state.msg}</h3>
        );
    }
}

四、事件机制

1.事件绑定

vue绑定方式类似,比如绑定点击事件需要在组件上通过onClick来实现,事件处理函数必须在大括号内通过this来指定。事件处理函数应该定义在类中,与render()函数在同一级别。

class MyComponent extends React.Component{ 
	handleClick(){ 
		alert('handleClick...'); 
	} 
	render(){ 
		return ( 
			<div onClick={this.handleClick}>hello MyComponent</div> 
		);
	} 
}
2.事件对象

DOM中的事件类似,通过事件对象获取目标元素,默认情况下,可以通过在事件处理函数上声明形式参数来获取event。你可以在调用event.preventDefault()来阻止默认行为,调用event.target获取目标元素,调用event.cancelable阻止事件冒泡。

class MyComponent extends React.Component{ 
	handleClick(event){ 
		alert('handleClick...'); 
	} 
	render(){ 
		return ( 
			<div onClick={this.handleClick}>hello MyComponent</div> 
		); 
	} 
}
3.this指针

如果通过es6的函数声明方式来定义事件处理函数,那么在事件处理函数中的thisundefined。我们可以用箭头函数来定义事件处理函数,这时候箭头函数中的this指向组件对象

class MyComponent extends React.Component{ 
	handleClick = (event)=>{ 
		alert('handleClick...'); 
		console.log(this);
	} 
	render(){ 
		return ( 
			<div onClick={this.handleClick}>hello MyComponent</div> 
		); 
	} 
}
4.参数传递方式1

如果想要传递参数给事件处理函数,需要在事件绑定的时候调用bind()方法,然后将this作为第一个实参,其他的参数可以自定义。但是要注意,在事件处理函数中,第一个参数为你绑定的第二个形参,… ,最后一个参数为event对象。

class MyComponent extends React.Component{ 
	handleClick = (param,event)=>{ 
		alert('handleClick...'); 
		console.log(this);
	} 
	render(){ 
		return ( 
			<div onClick={this.handleClick.bind(this,1)}>hello MyComponent</div> 
		); 
	} 
}
5.参数传递方式2

也可以使用箭头函数传参。

class MyComponent extends React.Component{ 
	handleClick = (p1,p2,event)=>{ 
		alert('handleClick...'); 
		console.log(event);
	} 
	render(){ 
		return ( 
			<div onClick={(e)=>this.handleClick(1,2,e)}>hello MyComponent</div>
		); 
	} 
}
6.示例
//事件绑定
class MyEvent extends React.Component{
    constructor(props) {
        super(props);
        this.state = {
            msg: 'hello',
        };
    }
    //箭头函数
	handle1 = (event)=>{
    	console.log(event);
        console.log(this);
        this.setState({
            msg:'msg'
        });
    } 
    //函数声明
    handle2(event){
    	console.log(event);
        console.log(this);
        this.setState({
            msg: 'msg'
        });
    }
    //上面两种事件处理函数功能一样
    render(){
        return (
            <div>
            	{/*方法一:使用箭头函数声明事件处理程序可以解决内部this指向的问题*/}
                <button onClick={this.handle1}>点击{this.state.msg}</button> 
                
                {/*方法二:使用bind()方法*/}
                <button onClick={this.handle1.bind(this)}>点击{this.state.msg}</button>
                <button onClick={this.handle2.bind(this)}>点击{this.state.msg}</button>
                
                {/*方法三:使用箭头函数*/}
                <button onClick={(event)=>{this.handle1(event)}}>点击{this.state.msg}</button>
                <button onClick={(event)=>{this.handle2(event)}}>点击{this.state.msg}</button>
            </div>
        );
    }
}
//事件传参
class MyTest extends React.Component{ 
	//箭头函数方式
    handle1 = (a,b,event) => {
    	console.log(event.target.getAttribute('data-id'));
       	console.log(a,b,event);
    }
    //函数声明方式
    handle2(a,b,event){
    	console.log(event.target.getAttribute('data-id'));
    	console.log(a,b,event);
    }
    //上面两种事件处理函数功能一样
	render(){ 
		return ( 
			<div>
				{/*用bind()方法绑定事件传参*/}
				<button data-id='1001' onClick={this.handle1.bind(this,1002,1003)}>点击</button>
				<button data-id='1001' onClick={this.handle2.bind(this,1002,1003)}>点击</button>
				
				{/*用箭头函数传参*/}
				<button data-id='1001' onClick={(e)=>{this.handle1(1002,1003,e)}}>点击</button>
				<button data-id='1001' onClick={(e)=>{this.handle2(1002,1003,e)}}>点击</button>
			</div>
		); 
	} 
}

五、Ref

1.介绍

React提供的这个ref属性,表示为对组件真正实例的引用,其实就是ReactDOM.render()返回的组件实例。ref属性可以挂载到组件上也可以是dom元素上。Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。

ref 属性接受一个回调函数,它在组件被加载或卸载时会立即执行,回调函数的参数为该组件的真正实例的引用;ref属性接受一个字符串,例如foo,通过this.refs.foo来访问该组件真正实例。

class MyRefs extends React.Component{
    constructor(props) {
        super(props);
        this.state = {
            msg:'123'
        };
    }
    componentDidMount() {
        //this.refs保存该组件内有ref属性并且属性值为字符串的元素
        console.log(this.refs);
        console.log(this.refs.hello);
        console.log(this.refs.world);
    }
    courseFormRefs(n){
    	console.log("ref参数",n);
    }
    render(){
        return (
            <div>
                <h3 ref="hello">{this.state.msg}</h3>
                <h3 ref="world">hello</h3>
                <h3 ref={(node)=>{console.log(node);}}>ref值为回调函数</h3>
                <h3 ref={this.courseFormRefs}>hello</h3>
            </div>
        );
    }
}
2.何时使用 Refs
  • 管理焦点,文本选择或媒体播放
  • 触发强制动画
  • 集成第三方 DOM 库
3.创建 Refs

Refs 是使用 React.createRef() 创建的,并通过 ref 属性附加到 React 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。

class MyComponent extends React.Component {
	constructor(props) {
    	super(props);
    	this.myRef = React.createRef();
  	}
  	render() {
    	return <div ref={this.myRef} />;
  	}
}
4.访问 Refs

当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。

const node = this.myRef.current;

ref 的值根据节点的类型而有所不同:

  • 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性
  • 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性。
  • 不能在函数组件上使用 ref 属性,因为他们没有实例
5.父组件改子组件state数据

在父组件获取子组件实例 refs,再调用 setState() 更改子组件state数据。

父组件

import React,{Component} from 'react';
import ChildrenComponent from './ChildrenComponent';
class ParentComponent extends Component{
    changeChildState = ()=>{
        const child = this.refs.child;
        console.log(child.state.childrenMsg);
        child.setState({
            childrenMsg:'childrenHello'
        });
    }
    render(){
        return (
            <div>
                <button onClick={this.changeChildState}>点击更改子组件中state中childrenMsg</button>
                <ChildrenComponent ref="child" />
            </div>
        );
    }
}
export default ParentComponent;

子组件

import React,{Component} from 'react';
class ChildrenComponent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            childrenMsg: 'childrenMsg'
        };
    }
    render() {
        return (
            <div>
                <h3>子组件state中的数据:{this.state.childrenMsg}</h3>
            </div>
        );
    }
}
export default ChildrenComponent;
6.子组件改父组件state数据

需要父组件传递修改自己state的函数给子组件调用。

父组件

import React,{Component} from 'react';
import ChildrenComponent from './ChildrenComponent';
class ParentComponent extends Component{
    constructor(props) {
        super(props);
        this.state = {
            parentMsg: 'parentMsg'
        };
    }
  	changeParentState = ()=>{
       this.setState({
           parentMsg:'parentHello'
       });
    }
    render(){
        return (
            <div>
                <ChildrenComponent ref="child" parentMsg={this.state.parentMsg} changeParentState={this.changeParentState}/>
            </div>
        );
    }
}
export default ParentComponent;

子组件

import React,{Component} from 'react';
class ChildrenComponent extends Component {
    render() {
        return (
            <div>
                <h3>接受父组件state中的数据:{this.props.parentMsg}</h3>
                <button onClick={this.props.changeParentState}>更改父组件中的数据</button>
            </div>
        );
    }
}
export default ChildrenComponent;
7.在jsx中添加样式
1.添加行内样式

注意:

  • 应使用 className 属性来引用外部 CSS 样式表中定义的 class
  • style 接受一个采用小驼峰命名属性的 JavaScript 对象,而不是 CSS 字符串
  • 样式不会自动补齐前缀。如需支持旧版浏览器,请手动补充对应的样式属性
import React,{Component} from 'react';
class Style extends Component{
    render(){
        const btnStyle = {background:'teal',width:100,border:'none',fontSize:30,color:'white',borderRadius:5};
        return (
            <div className="Style">
                <span style={{color:'red',fontSize:40}}>hello</span>
                <button style={btnStyle}>按钮</button>
            </div>
        );
    }
}
export default Style;

React 会自动添加 ”px” 后缀到内联样式为数字的属性后。如需使用 ”px” 以外的单位,请将此值设为数字与所需单位组成的字符串。但并非所有样式属性都转换为像素字符串。有些样式属性是没有单位的(例如 zoom,order,flex)。无单位属性的完整列表在此处。

// Result style: '10px'
<div style={{ height: 10 }}>
	Hello World!
</div>

// Result style: '10%'
<div style={{ height: '10%' }}>
  	Hello World!
</div>
2.引入外部样式
import React,{Component} from 'react';
//引入外部样式
import './3-Style.css';
class Style extends Component{
    render(){
        return (
            <div className="Style">
                <h3>world</h3>
            </div>
        );
    }
}
export default Style;

css

.Style h3{
    color: cornflowerblue;
    font-size: 40px;
    margin: 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值