344 lines
8.6 KiB
Markdown
344 lines
8.6 KiB
Markdown
# 组件介绍
|
|
组件表示页面中的部分功能
|
|
组合多个组件实现完整的页面功能
|
|
可复用,独立(相互之间互不影响),可组合
|
|
# 组件的创建方式
|
|
|
|
## 使用函数创建组件
|
|
函数名称必须以大写字母开头
|
|
必须有返回值,返回组件结构
|
|
如果返回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'))
|
|
```
|