The usage and understanding of React components

React components

functional components

<div id="test"></div>

<script type="text/babel">
	//1.创建函数式组件(必须大写,函数必须有返回值)
	function MyComponent(){
    
    
		console.log(this); //此处的this是undefined,因为babel编译后开启了严格模式
		return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
	}
	//2.渲染组件到页面
	ReactDOM.render(<MyComponent/>,document.getElementById('test'))
	/* 
		执行了ReactDOM.render(<MyComponent/>.......之后,发生了什么?
			1.React解析组件标签,找到了MyComponent组件。
			2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。
	*/
</script>

class component

<div id="test"></div>

<script type="text/babel">
	//1.创建类式组件
	class MyComponent extends React.Component {
    
    
		render(){
    
    
			//render是放在哪里的?—— MyComponent的原型对象上,供实例使用。
			//render中的this是谁?—— MyComponent的实例对象 <=> MyComponent组件实例对象。
			console.log('render中的this:',this);
			return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
		}
	}
	//2.渲染组件到页面
	ReactDOM.render(<MyComponent/>,document.getElementById('test'))
	/* 
		执行了ReactDOM.render(<MyComponent/>.......之后,发生了什么?
			1.React解析组件标签,找到了MyComponent组件。
			2.发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
			3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。
	*/
</script>

Three properties of component instance

state

State is the most important attribute of the component object, and the value is an object (which can contain multiple key-value combinations); the component is called a "state machine", which updates the corresponding page display (re-renders the component) by updating the state of the component.

class Person extends React.Component{
    
    
   state = {
    
    isHot:false,wind:'weifeng'}
    render(){
    
    
        const {
    
    isHot, wind} = this.state
        return (
            <h1>今天天气很{
    
    isHot ? '炎热' : '凉爽'}{
    
    wind}</h1>
        )
    }
}

insert image description here

  1. The this in the render method of the component is the component instance object
  2. This is undefined in the component custom method, how to solve it?
    a) Mandatory binding of this: through bind() of the function object
    b) Arrow function
  3. State data, which cannot be directly modified or updated
<div id="test"></div>

<script type="text/babel">
	//1.创建类式组件
	class Weather extends React.Component {
    
    
		constructor(props){
    
    
			super(props)
			//初始化状态
			this.state = {
    
    isHot:false}
		}

		//render调用几次? ———— 1+n次 1是初始化的那次 n是状态更新的次数
		render(){
    
    
			//读取状态
			const {
    
    isHot} = this.state//解构赋值,不这样的话也可以this.state.isHot?'炎热' : '凉爽'
			return <h1>今天天气比较{
    
    isHot?'炎热' : '凉爽'}</h1>
		}
	//2.渲染组件到页面
	ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>
<div id="test"></div>

<script type="text/babel">
	//1.创建组件
	class Weather extends React.Component{
    
    
		//构造器调用几次? ———— 1次
		constructor(props){
    
    
			console.log('constructor');
			super(props)
			//初始化状态
			this.state = {
    
    isHot:false,wind:'微风'}
			//解决changeWeather中this指向问题
			this.changeWeather = this.changeWeather.bind(this)
		}

		//render调用几次? ———— 1+n次 1是初始化的那次 n是状态更新的次数
		render(){
    
    
			console.log('render');
			//读取状态
			const {
    
    isHot,wind} = this.state//解构赋值
			return <h1 onClick={
    
    this.changeWeather}>今天天气很{
    
    isHot ? '炎热' : '凉爽'}{
    
    wind}</h1>
		}

		//changeWeather调用几次? ———— 点几次调几次
		changeWeather(){
    
    
			//changeWeather放在哪里? ———— Weather的原型对象上,供实例使用
			//由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
			//类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
			
			console.log('changeWeather');
			//获取原来的isHot值
			const isHot = this.state.isHot
			//严重注意:状态必须通过setState进行更新,且更新是一种合并,不是替换。
			this.setState({
    
    isHot:!isHot})
			console.log("asf",this);

			//严重注意:状态(state)不可直接更改,下面这行就是直接更改!!!
			//this.state.isHot = !isHot //这是错误的写法
		}
	}
	//2.渲染组件到页面
	ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>

The abbreviated form used in practice:

<div id="test"></div>

<script type="text/babel">
	//1.创建组件
	class Weather extends React.Component{
    
    
		//初始化状态
		state = {
    
    isHot:false,wind:'微风'}

		render(){
    
    
			const {
    
    isHot,wind} = this.state
			return <h1 onClick={
    
    this.changeWeather}>今天天气很{
    
    isHot ? '炎热' : '凉爽'}{
    
    wind}</h1>
		}

		//自定义方法————要用赋值语句的形式+箭头函数
		changeWeather = ()=>{
    
    
			const isHot = this.state.isHot
			this.setState({
    
    isHot:!isHot})
		}
	}
	//2.渲染组件到页面
	ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>

props

Each component object will have a props (short for properties) attribute; all properties of the component tag are stored in props.
ReactDOM.render(<Person name='jerry' age={19} sex='男'/>,document.getElementById('test1'))
insert image description here

…this.props

...this.props can receive all parameters.
insert image description here

// MyNavLink/index.jsx
import React, {
    
     Component } from 'react'
import {
    
    NavLink} from 'react-router-dom'

export default class MyNavLink extends Component {
    
    
	render() {
    
    
		console.log(this.props);
		return (
			<NavLink activeClassName="atguigu" className="list-group-item" {
    
    ...this.props}/>
		)
	}
}

The tag body of an unclosed tag can also be displayed with the tag attribute this.props.children.

// App.jsx
<MyNavLink to="/about" a={
    
    1} b={
    
    2} c={
    
    3}>About</MyNavLink>
{
    
    /* 上下两个作用一样 */}
<MyNavLink to="/about" a={
    
    1} b={
    
    2} c={
    
    3} children="About"/>

Pass the changed data from outside the component to inside the component through the label attribute; Note: Do not modify the props data inside the component (read-only).

<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>

<!-- 除了之前的三个外还需引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>

<script type="text/babel">
	//创建组件
	class Person extends React.Component{
    
    
		render(){
    
    
			const {
    
    name,age,sex} = this.props// 不然下面就要用this.props.name
			//props是只读的,this.props.name = 'jack'会报错
			return (
				<ul>
					<li>姓名:{
    
    name}</li>
					<li>性别:{
    
    sex}</li>
					<li>年龄:{
    
    age+1}</li>
				</ul>
			)
		}
	}
	//对标签属性进行类型、必要性的限制
	Person.propTypes = {
    
    // 注意这个和下一行的大小写
		name:PropTypes.string.isRequired, //限制name必传,且为字符串
		sex:PropTypes.string,//限制sex为字符串
		age:PropTypes.number,//限制age为数值
		speak:PropTypes.func,//限制speak为函数
	}
	//指定默认标签属性值
	Person.defaultProps = {
    
    
		sex:'男',//sex默认值为男
		age:18 //age默认值为18
	}
	
	//渲染组件到页面
	ReactDOM.render(<Person name="jerry" age={
    
    19}  sex="男"/>,document.getElementById('test1'))//{19}js
	ReactDOM.render(<Person name="tom" speak={
    
    speak} sex="女"/>,document.getElementById('test2'))
	// 批量传递props(标签属性)
	const p = {
    
    name:'老刘',age:18,sex:'女'}
	// ReactDOM.render(<Person name={p.name} age={p.age} sex={p.sex}/>,document.getElementById('test3'))
	ReactDOM.render(<Person {
    
    ...p}/>,document.getElementById('test3'))// 上面的简写
	function speak(){
    
    
		console.log('我说话了');
	}
</script>

The abbreviated form used in practice:

//创建组件
class Person extends React.Component{
    
    

	constructor(props){
    
    // 一般都省略
		//构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props;想要父类中的方法与属性就要传,也要接。
		// console.log(props);
		super(props)
		console.log('constructor',this.props);
	}

	//对标签属性进行类型、必要性的限制
	static propTypes = {
    
    // 前面加static以把属性写在类内部 
		name:PropTypes.string.isRequired, //限制name必传,且为字符串
		sex:PropTypes.string,//限制sex为字符串
		age:PropTypes.number,//限制age为数值
	}

	//指定默认标签属性值
	static defaultProps = {
    
    
		sex:'男',//sex默认值为男
		age:18 //age默认值为18
	}
	
	render(){
    
    
		// console.log(this);
		const {
    
    name,age,sex} = this.props
		//props是只读的,this.props.name = 'jack'会报错
		return (
			<ul>
				<li>姓名:{
    
    name}</li>
				<li>性别:{
    
    sex}</li>
				<li>年龄:{
    
    age+1}</li>
			</ul>
		)
	}
}

Functional components use props:

<div id="test1"></div>

<script type="text/babel">
	//创建组件
	function Person (props){
    
    
		const {
    
    name,age,sex} = props
		return (
				<ul>
					<li>姓名:{
    
    name}</li>
					<li>性别:{
    
    sex}</li>
					<li>年龄:{
    
    age}</li>
				</ul>
			)
	}
	Person.propTypes = {
    
    
		name:PropTypes.string.isRequired, //限制name必传,且为字符串
		sex:PropTypes.string,//限制sex为字符串
		age:PropTypes.number,//限制age为数值
	}

	//指定默认标签属性值
	Person.defaultProps = {
    
    
		sex:'男',//sex默认值为男
		age:18 //age默认值为18
	}
	//渲染组件到页面
	ReactDOM.render(<Person name="jerry"/>,document.getElementById('test1'))
</script>

refs and event handling

A tag within a component can define a ref attribute to identify itself.
1. ref in the form of a string <input ref="input1"/>(not efficient, not recommended)
2. ref in the form of a callback function <input ref={(c)=>{this.input1 = c}}
3.createRef creates a ref container<input ref={this.myRef}/>

A ref as a string:

<div id="test"></div>

<script type="text/babel">
	//创建组件
	class Demo extends React.Component{
    
    
		showData = ()=>{
    
    // 用refs取代document.getElementById
			const {
    
    input1} = this.refs// 解构赋值this.refs.input1
			console.log(input1)// <input type="text" placeholder="点击按钮提示数据">
			console.log(input1.value)
		}
		showData2 = ()=>{
    
    
			const {
    
    input2} = this.refs
			console.log(input2.value)
		}
		render(){
    
    
			return(
				<div>
					<input ref="input1" type="text" placeholder="点击按钮提示数据"/>&nbsp;
					<button onClick={
    
    this.showData}>点我提示左侧的数据</button>&nbsp;
					<input ref="input2" onBlur={
    
    this.showData2} type="text" placeholder="失去焦点提示数据"/>
				</div>
			)
		}
	}
	//渲染组件到页面
	ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>

A ref in the form of a callback function:

<div id="test"></div>

<script type="text/babel">
	//创建组件
	class Demo extends React.Component{
    
    
		showData = ()=>{
    
    
			console.log(this.input1.value)
		}
		showData2 = ()=>{
    
    
			const {
    
    input2} = this
			console.log(input2.value)
		}
		render(){
    
    
			return(// 回调函数:定义后没有马上调用,最终却又执行了。
				<div>
					<input ref={
    
    c => this.input1 = c } type="text" placeholder="点击按钮提示数据"/>&nbsp;
					<button onClick={
    
    this.showData}>点我提示左侧的数据</button>&nbsp;
					<input onBlur={
    
    this.showData2} ref={
    
    c => this.input2 = c } type="text" placeholder="失去焦点提示数据"/>&nbsp;
				</div>
			)// 打印c是当前所处的节点<input type="text" placeholder="点击按钮提示数据"/>。
			// 箭头函数没有自己的this,往外找render的this是组件实例对象
		}
	}
	//渲染组件到页面
	ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>

createRef creates a ref container:
After React.createRef is called, a container can be returned, which can store the node identified by ref, and this container is "specially assigned"

<div id="test"></div>

<script type="text/babel">
	//创建组件
	class Demo extends React.Component{
    
    
		myRef = React.createRef()// 用几个创建几个
		myRef2 = React.createRef()
		showData = ()=>{
    
    
			alert(this.myRef.current.value);
		}
		showData2 = ()=>{
    
    
			alert(this.myRef2.current.value);
		}
		showData3 = (event)=>{
    
    // 不要过度使用ref,有时直接用js事件源对象也行
			alert(event.target.value);
		}
		render(){
    
    
			return(
				<div>
					<input ref={
    
    this.myRef} type="text" placeholder="点击按钮提示数据"/>&nbsp;
					<button onClick={
    
    this.showData}>点我提示左侧的数据</button>&nbsp;
					<input onBlur={
    
    this.showData2} ref={
    
    this.myRef2} type="text" placeholder="失去焦点提示数据"/>&nbsp;
					<input onBlur={
    
    this.showData3} type="text" placeholder="失去焦点提示数据"/>
				</div>
			)
		}
	}
	//渲染组件到页面
	ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>

Guess you like

Origin blog.csdn.net/zag666/article/details/129000727