React三大核心属性State、Props和Refs的详细介绍以及React组件的详细介绍
一、 基本理解和使用
1. 使用React开发者工具调试
下载链接:React开发者工具
2. React组件的两种形式
-
函数式组件:
// 1.创建函数式组件 function MyComponent() { console.log(this); // 此处的this是undefined,因为babel编译后开启了严格模式禁止普通函数的this指向window return <h2>函数式定义的组件(适用于【简单组件的定义】)</h2>; } // 2.渲染组件到页面 ReactDOM.render(<MyComponent />, document.getElementById("test")); /** * 执行了ReactDOM.render(<MyComponent />,...)之后,发生了什么? * 1.React解析组件标签,找到了Mycomponent组件 * 2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转化为真实DOM,随后呈现在页面中。 */
-
类式组件:
// 1.创建类式组件 class MyComponent extends React.Component { render() { // render是放在哪?——MyComponent类的原型对象上,供实例使用 // render中的this是 MyComponent组件实例对象。 return <h2>类定义的组件(适用于【复杂组件】)</h2>; } } // 2.渲染组件到页面 ReactDOM.render(<MyComponent />, document.getElementById("test")); /** * 执行了ReactDOM.render(<MyComponent />,...)之后,发生了什么? * 1.React解析组件标签,找到了Mycomponent组件 * 2.发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用原型上的render方法 * 3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面上 */
3. 注意
-
组件名必须首字母大写
-
虚拟DOM元素只能有一个根元素
-
虚拟DOM元素必须有结束标签
4. 渲染类组件标签的基本流程
-
React内部会创建组件实例对象
-
调用render()得到虚拟DOM, 并解析为真实DOM
-
插入到指定的页面元素内部
二、 组件三大核心属性1: state
1. 效果
需求:定义一个展示天气信息的组件
-
默认展示天气炎热 或 凉爽
-
点击文字切换天气
2. 理解
-
state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
-
组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
-
代码如下
// 1.创建类式组件 class Weather extends React.Component { // 构造器调用几次?—— 1 次 constructor(props) { super(props); // 初始化状态 this.state = { isHot: true, wind: "微风", }; // 解决changeWeather中的this指向问题 this.changeWeather = this.changeWeather.bind(this); } // render调用几次?—— 1+n 次 :1是初始化那次 n是setState的调用的次数(即状态更新的次数) render() { // 读取状态 return ( <h1 onClick={this.changeWeather}> 今天天气很{this.state.isHot ? "炎热" : "凉爽"},{this.state.wind} </h1> ); } // changeWeather调用几次?—— 点几次调用几次 changeWeather() { // changeWeather方法放在了哪?——Weather原型对象上,供实例使用 // 通过Weather实例调用changeWeather时,changeWeather中的this就是Weather实例对象 // 由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用的 // 类中的方法默认开启了严格模式,所以changeWeather中的this为undefined // 严重注意:状态(state)不可以直接更改,下面这行就是直接更改!!! // this.state.isHot = !this.state.isHot //react不认可 // 严重注意:状态(state)必须通过setState进行更改,且更新是合并 this.setState({ isHot: !this.state.isHot, }); // console.log(this); } } // 2.渲染组件到页面 ReactDOM.render(<Weather />, document.getElementById("test"));
-
简写方式
// 1.创建类式组件 class Weather extends React.Component { // 初始化状态 state = { isHot: true, wind: "微风", }; render() { return ( <h1 onClick={this.changeWeather}> 今天天气很{this.state.isHot ? "炎热" : "凉爽"},{this.state.wind} </h1> ); } // 自定义方法 —— 要用赋值语句 + 箭头函数 // 其实就是给实例对象身上添加changeWeather方法 // 箭头函数为了能够使这个函数访问到的this是该实例对象 changeWeather = () => { this.setState({ isHot: !this.state.isHot, }); // console.log(this); }; } // 2.渲染组件到页面 ReactDOM.render(<Weather />, document.getElementById("test"));
3. 强烈注意
-
组件中render方法中的this为组件实例对象
-
组件自定义的方法中this为undefined,如何解决?
- 强制绑定this: 通过函数对象的bind()
- 箭头函数(赋值语句形式)
-
状态数据,不能直接修改或更新,需使用serState方法
三、组件三大核心属性2: props
1. props的含义
- 每个组件对象都会有props(properties的简写)属性
- 组件标签的所有属性都保存在props中
2. props作用
- 通过标签属性从组件外向组件内传递变化的数据
- 注意: 组件内部不要修改props数据,因为它是只读的
3. 使用方式
-
传递的方式
<!-- 方式一 --> <Person name="tom" gender="男" age={23} /> <!-- 方式二:将对象的所有属性通过props传递(扩展属性) person = {name:'xzq',age:20} --> <Person {...person}/>
-
props的读取
this.props.name
4. 对props中的属性值进行类型限制和必要性限制
-
第一种方式(React v15.5 开始已弃用):
Person.propTypes = { name: React.PropTypes.string.isRequired, age: React.PropTypes.number }
-
第二种方式(新):使用prop-types库进限制(需要引入prop-types库)
Person.propTypes = { name: PropTypes.string.isRequired, age: PropTypes.number. }
5. props的默认值
-
使用defaultProps
Person.defaultProps = { age: 18, sex:'男' }
6. 组件类的构造函数里的props小细节
若构造器中没有传递props,或传递了props,但是super调用未传递props,则通过this使用props可能会出现this.props为undefined的情况
7. 类式组件的props
-
对props的属性限制的方式一
// 1.创建组件 class Person extends React.Component { render() { // console.log(this); const { name, gender, age } = this.props; // props是只读的 // this.props.name = 'jack' // 报错,因为props是只读的 return ( <ul> <li>姓名:{name}</li> <li>性别:{gender}</li> <li>年龄:{age + 1}</li> </ul> ); } } // 对标签属性进行类型、必要性的限制 Person.propTypes = { name: PropTypes.string.isRequired, // 限制name必传,且为字符串 gender: PropTypes.string, // 限制gender为字符串 age: PropTypes.number, // 限制age为数字 speak: PropTypes.func, // 限制sprak为函数 }; // 指定props属性默认值 Person.defaultProps = { gender: "男", // gender默认值为男 age: 18, // age默认值为18 };
-
对props的属性限制的方式二(简写方式)
// 1.创建组件 class Person extends React.Component { // 对标签属性进行类型、必要性的限制 // static修饰的属性表示给Person添加属性 static propTypes = { name: PropTypes.string.isRequired, // 限制name必传,且为字符串 gender: PropTypes.string, // 限制gender为字符串 age: PropTypes.number, // 限制age为数字 speak: PropTypes.func, // 限制sprak为函数 }; // 指定props属性默认值 static defaultProps = { gender: "男", // gender默认值为男 age: 18, // age默认值为18 }; render() { const { name, gender, age } = this.props; return ( <ul> <li>姓名:{name}</li> <li>性别:{gender}</li> <li>年龄:{age + 1}</li> </ul> ); } }
8. 函数组件的props
// 1.创建组件
function Person(props) {
// console.log(props);
const { name, sex, age } = props;
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
);
}
// 对标签属性进行类型、必要性的限制
Person.propTypes = {
name: PropTypes.string.isRequired, // 限制name必传,且为字符串
sex: PropTypes.string, // 限制gender为字符串
age: PropTypes.number, // 限制age为数字
};
// 指定props属性默认值
Person.defaultProps = {
sex: "男", // gender默认值为男
age: 18, // age默认值为18
};
四、组件三大核心属性3:refs
组件内的标签可以定义ref属性来标识自己
1. 字符串形式的ref
React官方不推荐使用的一种方式,因为存在一些效率上的问题,应避免使用
-
使用方式:
-
标识:
<input ref="input1"/>
-
获取:
this.refs.input1
-
-
代码如下
class Demo extends React.Component { // 展示左侧输入框数据 showData = () => { const { input1 } = this.refs; alert(input1.value); }; // 展示右侧输入框数据 blurHandler = () => { const { input2 } = this.refs; alert(input2.value); }; render() { return ( <div> <input ref="input1" type="text" placeholder="点击按钮提示数据" /> <button onClick={this.showData}>点我提示左侧的数据</button> <input ref="input2" onBlur={this.blurHandler} type="text" placeholder="失去焦点提示数据" /> </div> ); } }
2. 回调形式的ref
-
内联函数方式的回调使用方式
// 内联函数方式定义回调函数,初始时执行一次,在更新过程(再次执行render时)中会被执行两次,第一次为null表示清空旧的ref,第二次传入的才是DOM元素 // 参数c表示当前DOM元素 <input ref={(c)=>{this.input1 = c}}
-
类实例方法形式的回调函数
class Demo extends React.Component { state = { isHot: true }; showInfo = () => { alert(this.input1.value); }; changeWeather = () => { this.setState({ isHot: !this.state.isHot, }); }; saveInput = (c) => { this.input1 = c; console.log(c); }; render() { return ( <div> <div>今天天气很{this.state.isHot ? "炎热" : "凉爽"}</div> <hr /> { // 内联函数方式定义回调函数,初始时执行一次,在更新过程(再次执行render时)中会被执行两次, // 第一次为null表示清空旧的ref,第二次传入的才是DOM元素 /*<input ref={c => { this.input1 = c; console.log(c); }} type="text" placeholder="" /> <br /><br />*/ } { // 定义成类实例方法形式的回调函数,同样会收到一个参数c表是当前DOM元素,只有在初始时调用一次,后面的更新不会再调用 // 关于React官网说明:两种方式选择哪种都是无关紧要的 } <input ref={this.saveInput} type="text" /> <br /> <br /> <button onClick={this.showInfo}>点我提示输入的数据</button> <button onClick={this.changeWeather}>点我切换天气</button> </div> ); } }
3. createRef形式的ref
-
使用createRef创建ref容器
- React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点
- 该容器是"专人专用"的,一一对应,即不能使用同一个容器标识多个DOM元素
// this.myRef.current为当前的DOM元素 myRef = React.createRef() <input ref={this.myRef} />
4. 事件处理
-
通过onXxx属性指定事件处理函数(注意大小写与原生不同,原生是onxxx)
- React使用的是自定义(合成)事件, 而不是使用的原生DOM事件 —— 为了更好的兼容性
- React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)——为了高效
- 事件绑定一定是本着一个原则:必须把一个函数交给事件
-
通过event.target得到发生事件的DOM元素对象
本文来自博客园,作者:你就是星光,转载请注明原文链接:https://www.cnblogs.com/xzqyl/p/17045396.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~