React组件介绍
组件是Reat的一等公民,使用 React就是在用组件组件表示页面中的部分功能,组合多个组件实现完整的页面功能。
特点:可复用、独立、可组合
React创建组件的两种方式
使用函数创建组件
函数组件:使用JS的函数(或箭头函数)创建的组件
- 约定一:函数名称必须以大写字母开头
- 约定二:函数组件必须有返回值,表示该组件的结构
- 如果返回null,表示不渲染任何内容
// 函数组件
function Hello() {
return (
<div>这是一个组件</div>
)
}
渲染函数组件:使用函数名作为组件的标签名
ReactDOM.render(<Hello/>, document.getElementById('root'))
使用类创建组件
使用ES6的 class
关键字创建组件:
- 约定一:类名称也必须以大写字母开头
- 约定二:类组件应该继承
React.Component
父类,从而可以使用父类中提供的方法或属性。 - 约定三:类组件必须提供
render()
方法 - 约定四:
render()
方法必须有返回值,表示为该组件的结构
class Hello extends React.Component{
render() {
return <h1>hello</h1>
}
}
ReactDOM.render(<Hello/>, document.getElementById('root'))
抽离为单独的JS文件
新建一个js文件,然后再该文件中导入React,接着创建组件(函数或者类),最后导出组件即可。
输入rcc
敲下回车,可以快速创建 react class component。
// Hello.js
import React from 'react';
// 创建组件
class Hello extends React.Component{
render() {
return (
<div>
hi,我是一个组件
</div>
)
}
}
// 导出组件
export default Hello;
// 导入组件
import Hello from './Hello';
ReactDOM.render(<Hello/>, document.getElementById('root'))
React 事件处理
React事件绑定语法与DOM事件语法相似。
- 语法:
on+事件名称={事件处理程序}
,比如:onClick={()=>{}} - 注意:React事件采用驼峰命名法,比如:onMouseEnter、 onFocus
// 类组件
class App extends React.Component{
// 事件处理程序
handleClick() {
console.log('单击事件触发了');
}
render() {
return <button onClick={this.handleClick}>点我点我</button>
}
}
//函数组件绑定事件
function App2() {
function click() {
console.log('I got clicked');
}
return <button onClick={click}>Click ME</button>
}
事件对象
- 可以通过事件处理程序的参数获取到事件对象
- React中的事件对象叫做:合成事件(对象)
- 合成事件:兼容所有浏览器,无需担心跨浏览器兼容性问题
// React事件对象
class App extends React.Component{
handleClick(e) {
e.preventDefault();
}
render() {
return (<a href='https://jiaqicoder.com' onClick={this.handleClick}>click me</a>);
}
}
有状态组件和无状态组件
函数组件又叫做无状态组件,类组件又叫做有状态组件。
- 状态(state)即数据。
- 函数组件没有自己的状态,只负责数据的展示(静态)
- 类组件有自己的状态,负责更新UI,让页面动起来
比如计数器案例中,点击按钮让数值加1。0和1就是不同时刻的状态,而由0变为1就表示状态发生了变化。状态变化后,UI也要相应的更新。 React中想要实现该功能,就要使用有状态组件来完成。
state和setSate
a. state
状态( state)即数据,是组件内部的私有数据,只能在组件内部使用。state的值是对象,表示一个组件中可以有多个数据。
// state的基本使用
class App extends React.Component{
// 方式一:
// constructor() {
// super();
// // 初始化state
// this.state = {
// count:0,
// };
// }
// 方式二:
state = {
count:0,
}
render() {
return <div><h1>计数器:{ this.state.count}</h1></div>
}
}
- 状态即数据
- 状态是私有的,只能在组件内部使用
- 通过this.state来获取状态
b. setState()修改状态
- 状态是可变的
- 语法:this.setState({要修改的数据})
- 注意:不要直接修改state中的数据,这是错误的。
- setState()的作用:1. 修改state 2.更新UI
- 思想:数据驱动视图
class App extends React.Component {
state = {
count: 0,
}
render() {
return (
<div>
<h1>计数器:{this.state.count}</h1>
<button onClick={() => { this.setState({ count: this.state.count + 1 }) }}> 加一</button>
</div>)
}
}
从JSX中抽离事件处理程序
- JSX中掺杂过多JS逻辑代码,会显得非常混乱
- 推荐:将逻辑抽离到单独的方法中,保证JSX结构清晰
class App extends React.Component {
state = {
count: 0,
}
// 事件处理程序
add() {
console.log(this);
}
render() {
return (
<div>
<h1>计数器:{this.state.count}</h1>
<button onClick={this.add}> 加一</button>
</div>)
}
}
但是事件处理程序中this的值为 undefined,但是我们希望this指向组件实例( render方法中的ths即为组件实例)。
解决办法:
-
箭头函数
使用箭头函数让
this.add
指向上一级作用域,也就是指向render函数。class App extends React.Component { state = { count: 0, } // 事件处理程序 add() { console.log(this); } render() { //箭头函数中的this指向外部环境,此处为render()方法 return ( <div> <h1>计数器:{this.state.count}</h1> <button onClick={()=>this.add()}> 加一</button> </div>) } }
-
Function.prototype.bind()
- 利用ES5中的bind方法,将事件处理程序中的this与组件实例绑定到起
class App extends React.Component { constructor() { super(); this.state = {count: 0}; this.add = this.add.bind(this); } // 事件处理程序 add() { this.setState({ count: this.state.count + 1 }) } render() { return ( <div> <h1>计数器:{this.state.count}</h1> <button onClick={this.add}> 加一</button> </div>) } }
-
class的实例方法
- 利用箭头函数形式的class实例方法
- 注意:该语法是实验性语法,但是,由于 babel的存在可以直接使用
class App extends React.Component { state = { count: 0, } // 事件处理程序 add=()=> { this.setState({ count: this.state.count + 1 }) } render() { return ( <div> <h1>计数器:{this.state.count}</h1> <button onClick={this.add}> 加一</button> </div>) } }
表单处理
受控组件
-
HTML中的表单元素是可输入的,也就是有自己的可变状态。
-
而React中可变状态通常保存在
state
中,并且只能通过setstate()
方法来修改。 -
React将 state与表单元素值 value 绑定到一起,由 state 的值来控制表单元素的值。
步骤
-
在 state中添加一个状态,作为表单元素的
value
值(控制表单元素值的来源)state = {txt:''}
<input type='text' value = {this.state.txt} />
-
给表单元素绑定
change
事件,将表单元素的值设置为state
的值(控制表单元素值的变化)<input type='text' value = {this.state.txt} onChange = { e => this.setState({txt: e.target.value}) }/>
文本框,多行文本,下拉框,复选框
文本框,多行文本,下拉框操作的是 value
属性,而复选框操作的是 checked
属性。
class App extends React.Component {
state = {
txt: '',
content: '',
city: 'bj',
isChecked: true,
}
handleChange = (e) => {
this.setState({
txt: e.target.value,
})
}
// 处理富文本框的变化
handleContent = (e) => {
this.setState({
content: e.target.value,
})
}
// 处理下拉框的变化
handleCity = (e) => {
this.setState({
city: e.target.value,
})
}
// 处理复选框的变化
handleCheck = (e) => {
this.setState({
isChecked: e.target.checked
})
}
render() {
return (
<div>
{/* 文本框 */}
<input type="text" value={this.state.txt} onChange={this.handleChange} />
<br />
{/* 富文本框 */}
<textarea value={this.state.content} onChange={this.handleContent}></textarea>
<br />
{/* 下拉框 */}
<select value={this.state.city} onChange={this.handleCity}>
<option value="sh">上海</option>
<option value="bj">北京</option>
<option value="gz">广州</option>
</select>
{/* 复选框 */}
<input type="checkbox" checked={this.state.isChecked} onChange={this.handleCheck} />
</div>
)
}
}
多表单元素优化
-
问题:每个表单元素都有一个单独的事件处理程序处理太繁琐
-
优化:使用一个事件处理程序同时处理多个表单元素
方法:
-
给表单元素添加name属性,名称与state相同
<input type='text' name='txt' value = {this.state.txt} onChange = {this.handleForm}/>
-
根据表单元素类型获取相对应的值
const target = e.target; //根据表单元素获取相对应的值 const value = target.type ==='checkbox' ? target.checked: target.value //根据名称name设置对应的state this.setState({ [target.name]: value })
// 多表单组件的优化 class App extends React.Component { state = { txt: '', content: '', city: 'bj', isChecked: true, } handleChange = (e) => { const target = e.target; const value = target.type === 'checkbox' ? target.checked : target.value; this.setState({ [target.name]: value }) } render() { return ( <div> {/* 文本框 */} <input type="text" name='txt' value={this.state.txt} onChange={this.handleChange} /> <br /> {/* 富文本框 */} <textarea name='content' value={this.state.content} onChange={this.handleChange} ></textarea> <br /> {/* 下拉框 */} <select name='city' value={this.state.city} onChange={this.handleChange} > <option value="sh">上海</option> <option value="bj">北京</option> <option value="gz">广州</option> </select> {/* 复选框 */} <input type="checkbox" name='isChecked' checked={this.state.isChecked} onChange={this.handleChange} /> </div> ) } }
非受控组件
- 借助于ref,使用原生DOM方式来获取表单元素值
- ref的作用:获取DOM或者组件
使用步骤
-
调用
React.createRef()
方法创建一个ref对象。constructor(){ super(); this.txtRef = React.createRef(); }
-
将创建好的 ref 对象添加到文本框中。
<input type='text' ref={this.txtRef}/>
-
通过 ref 对象获取到文本框的值。
console.log(this.txtRef.current.value)
// 非受控组件 class App extends React.Component { constructor() { super(); // 创建ref this.txtRef = React.createRef(); } // 获取文本框的值 getTxt = () => { console.log(this.txtRef.current.value); } render() { return ( <div> <input type="text" ref={this.txtRef} /> <button onClick={this.getTxt}>click me</button> </div> ) } }
笔记基于:React视频