Front-end/react/3.react组件.md

344 lines
8.6 KiB
Markdown
Raw Normal View History

2023-10-19 02:19:45 -04:00
# 组件介绍
组件表示页面中的部分功能
组合多个组件实现完整的页面功能
可复用,独立(相互之间互不影响),可组合
# 组件的创建方式
## 使用函数创建组件
函数名称必须以大写字母开头
必须有返回值,返回组件结构
如果返回null表示不渲染任何内容
渲染组件:使用函数名作为组件标签名
```html
// function Hello(){
// return (<div>展示的返回函数组件</div>)
// }
const Hello =()=><div>展示的返回函数组件</div>
ReactDOM.render(<Hello />,document.getElementById('root'))
```
## 使用类创建组件
类名称必须以大写字母开头
类组件必须继承React.Component父类
必须提供render方法
render方法必须有返回值.
```html
class HelloClass extends React.Component{
render(){
return (<div>leizujian</div>)
}
}
ReactDOM.render(<HelloClass />,document.getElementById('root'))
```
## 抽离到独立的js文件
1. 创建HelloRender.js文件
2. 在HelloRender.js文件中导入React
3. 创建组件
4. 在HelloRender.js中导出该组件
5. 在index.js中导入HelloRender组件
6. 渲染组件
```html
import HelloRender from './learn/HelloRender'
ReactDOM.render(<HelloRender />,document.getElementById('root'))
```
```
import React from "react"
class HelloRender extends React.Component{
render(){
return (
<div>抽离到js文件中的组件</div>
)
}
}
export default HelloRender
```
# 事件处理
驼峰命名
on+事件名称={事件处理程序}
## 类
```html
class AppOnClick extends React.Component{
handleClick(){
console.log('单机')
}
render(){
return (
<button onClick={this.handleClick}>点击</button>
)
}
}
ReactDOM.render(<AppOnClick />,document.getElementById('root'))
```
## 函数
```html
function AppOnClickFun(){
function handleClick(){
console.log('单机function')
}
return (
<button onClick={handleClick}>点击</button>
)
}
ReactDOM.render(<AppOnClickFun />,document.getElementById('root'))
```
## 事件对象
```html
class AppOnClickUrl extends React.Component{
handleClick(e){
// 阻止浏览器默认跳转行为
e.preventDefault()
console.log('单机,阻止浏览器默认跳转行为')
}
render(){
return (
<a href="http://www.baidu.com" onClick={this.handleClick}>点击</a>
)
}
}
ReactDOM.render(<AppOnClickUrl />,document.getElementById('root'))
```
## 有状态组件和无状态组件
状态(state)即数据
函数组件又叫无状态组件,只负责数据展示(静)
类组件又叫有状态组件,负责更新UI,让页面动起来
## 组件中的state和setState
```html
class AppState extends React.Component{
constructor(){
super()
this.state= {
count:0
}
}
// state= {
// count:0
// }
render(){
return (
<div>有状态组件,{this.state.count}</div>
)
}
}
ReactDOM.render(<AppState />,document.getElementById('root'))
```
修改状态
```html
class AppState extends React.Component{
constructor(){
super()
this.state= {
count:0,
test:'a'
}
}
// state= {
// count:0
// }
render(){
return (
<div>有状态组件,{this.state.count},{this.state.test}
<button onClick={()=>{
this.setState({
count:this.state.count+1
})
}}>+1</button>
</div>
)
}
}
ReactDOM.render(<AppState />,document.getElementById('root'))
```
事件处理程序中this的值为undefined,希望this指向组件实例
事件绑定this指向
1. 箭头函数,利用箭头函数自身不绑定this的特点.
```html
class AppStateJTThis extends React.Component{
constructor(){
super()
this.state= {
count:0
}
}
onIncrement(){
console.info('事件处理this'+this)
this.setState({
count:this.state.count+1
})
}
render(){
return (
<div>有状态组件,{this.state.count}
<button onClick={()=>this.onIncrement()}>+1</button>
</div>
)
}
}
ReactDOM.render(<AppStateJTThis />,document.getElementById('root'))
```
2. Function.prototype.bind()利用ESS中bind方法,将时间处理程序中的this与组件实例绑定到一起
```html
class AppStateJTThis extends React.Component{
constructor(){
super()
this.onIncrement= this.onIncrement.bind(this)
this.state= {
count:0
}
}
onIncrement(){
console.info('事件处理this'+this)
this.setState({
count:this.state.count+1
})
}
render(){
return (
<div>有状态组件,{this.state.count}
<button onClick={this.onIncrement}>+1</button>
</div>
)
}
}
ReactDOM.render(<AppStateJTThis />,document.getElementById('root'))
```
3. class实例方法
```html
class AppStateJTThis extends React.Component{
constructor(){
super()
this.state= {
count:0
}
}
onIncrement=()=>{
console.info('事件处理this'+this)
this.setState({
count:this.state.count+1
})
}
render(){
return (
<div>有状态组件,{this.state.count}
<button onClick={this.onIncrement}>+1</button>
</div>
)
}
}
ReactDOM.render(<AppStateJTThis />,document.getElementById('root'))
```
方法是一个特殊的属性.
类中的方法默认开启了局部严格模式,所以changeWeather中的this为undefined,
use strict 使用严格模式
实例调用,直接调用(严格模式下,this为undefined)
组件内的标签可以定义ref属性来标识自己
箭头函数中的this找外层的this.
## 事件处理
1. 通过onXxx属性指定事件处理函数,必须驼峰
1. React使用的是自定义合成事件,而不是使用原生DOM事件,为了更好兼容性
2. React中的事件是通过事件委托方式处理的(委托给组件最外层的元素),为了更高效
2. 可以通过event.target得到发生事件的DOM元素对象,避免过度使用ref
# 表单处理
## 受控组件,其值受到React控制的表单元素
1. html中表单元素是可输入的,也就是有自己的可变状态
2. react中可变状态通常通过state处理,并且只能通过setState()来处理
3. react将state与表单元素值value绑定到一起,由state的值来控制表单元素的值
4. 类似vue中双向绑定
### 使用步骤
1. 在state中添加一个状态,作为表单元素的value值(控制表单元素的来源)
2. 给表单元素绑定change事件,将表单元素的值设置为state值(控制表单元素值的变化)
### 使用一个事件处理程序同时处理多个表单元素
1. 给表单添加一个name属性,名称与state相同
2. 根据表单元素类型获取对应值
3. 在change事件处理程序中通过name来修改对应的state
```html
class AppInput extends React.Component{
constructor(){
super()
this.state= {
txt:'请输入值',
context:'',
city:'bj',
isChecked:false
}
}
handleClick=e=>{
console.info('事件处理this'+this)
const target = e.target;
const value = target.type === 'checkbox'?target.checked:target.value
const name = target.name
this.setState({
[name]: value
})
console.info('name:'+name+',value:'+value)
}
render(){
return (
<div><input type='text' name='txt' value = {this.state.txt} onChange={this.handleClick}/>
<br/>
<textarea value={this.state.context} name= 'context' onChange={this.handleClick}/>
<br/>
<select value={this.state.city} onChange={this.handleClick} name = 'city'>
<option value="bj">北京</option>
<option value="sh">上海</option>
<option value="gz">广州</option>
</select>
<input type='checkbox' name='isChecked' checked = {this.state.isChecked} onChange={this.handleClick}/>
</div>
)
}
}
ReactDOM.render(<AppInput />,document.getElementById('root'))
```
### 高阶函数
如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数.
1. 若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数
2. 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数
函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式.
## 非受控组件
借助于ref,使用原生DOM方式来获取表单元素值
ref作用:获取DOM或组件
```html
class APPRef 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}>获取文本信息</button>
</div>
)
}
}
ReactDOM.render(<APPRef />,document.getElementById('root'))
```