[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5zo7zriO-1668351209724)(images/组件.png)]
函数组件:使用JS的函数或者箭头函数创建的组件
大写字母开头
必须有返回值
,表示该组件的结构使用函数创建组件
function Hello () {
return (
<div>这是我的函数组件</div>
)
}
使用箭头函数创建组件
const Hello = () => <div>这是一个函数组件</div>
使用组件
ReactDOM.render(<Hello />, document.getElementById('root'))
class 类名{}
constructor
的用法,创建对象类组件:使用ES6的class语法创建组件
约定1:类组件的名称必须是大写字母开头
约定2:类组件应该继承React.Component
父类,从而可以使用父类中提供的方法或者属性
约定3:类组件必须提供render
方法
约定4:render方法必须有返回值
,表示该组件的结构
定义组件
class Hello extends React.Component {
render() {
return <div>这是一个类组件</div>
}
}
使用组件
ReactDOM.render(<Hello />, document.getElementById('root'))
思考:项目中的组件多了之后,该如何组织这些组件呢?
实现方式
比如计数器案例,点击按钮让数值+1, 0和1就是不同时刻的状态,当状态从0变成1之后,UI也要跟着发生变化。React想要实现这种功能,就需要使用有状态组件来完成。
state
即数据,是组件内部的私有数据
,只有在组件内部可以使用state的值是一个对象
,表示一个组件中可以有多个数据class Hello extends React.Component {
constructor() {
super()
// 组件通过state提供数据
this.state = {
msg: 'hello react'
}
}
render() {
return <div>state中的数据--{this.state.msg}</div>
}
}
class Hello extends React.Component {
state = {
msg: 'hello react'
}
render() {
return <div>state中的数据--{this.state.msg}</div>
}
}
安装谷歌插件react-devtools
React注册事件与DOM的事件语法非常像
语法on+事件名={事件处理程序}
比如onClick={this.handleClick}
注意:React事件采用驼峰命名法,比如onMouseEnter
, onClick
class App extends React.Component {
render() {
return (
<div>
<button onClick={this.handleClick}>点我</button>
</div>
)
}
handleClick() {
console.log('点击事件触发了')
}
}
function handleClick(e) {
e.preventDefault()
console.log('事件对象', e)
}
<a onClick={this.handleClick}>点我,不会跳转页面</a>
事件处理程序中的this指向的是undefined render方法中的this指向的而是当前react组件。只有事件处理程序中的this有问题
class App extends React.Component {
state = {
msg: 'hello react'
}
handleClick() {
console.log(this.state.msg)
}
render() {
return (
<div>
<button onClick={this.handleClick}>点我</button>
</div>
)
}
}
方案1:箭头函数
方案2:bind修改this指向
方案3:类实例方法
箭头函数的特点:自身没有this,访问的是外部的this
方式1:
class App extends React.Component {
state = {
msg: 'hello react'
}
render() {
return (
<div>
<button onClick={() => { console.log(this.state.msg) }>点我</button>
</div>
)
}
}
缺点:会把大量的js处理逻辑放到JSX中,将来不容易维护
方式2
class App extends React.Component {
state = {
msg: 'hello react'
}
handleClick() {
console.log(this.state.msg)
}
render() {
return (
<div>
<button onClick={() => {this.handleClick()}}>点我</button>
</div>
)
}
}
缺点:把大量的js逻辑写在了JSX结构中,不好维护
class App extends React.Component {
state = {
msg: 'hello react'
}
handleClick() {
console.log(this.state.msg)
}
render() {
return (
<div>
<button onClick={this.handleClick.bind(this)}>点我</button>
</div>
)
}
}
或者
class App extends React.Component {
constructor() {
super()
this.handleClick = this.handleClick.bind(this)
}
state = {
msg: 'hello react'
}
handleClick() {
console.log(this.state.msg)
}
render() {
return (
<div>
<button onClick={this.handleClick}>点我</button>
</div>
)
}
}
class App extends React.Component {
state = {
msg: 'hello react'
}
handleClick = () => {
console.log(this.state.msg)
}
render() {
return (
<div>
<button onClick={this.handleClick}>点我</button>
</div>
)
}
}
注意:这个语法是试验性的语法,但是有babel的转义,所以没有任何问题
this.setState({要修改的数据})
this.setState()
方法进行修改
setState
的作用
class App extends React.Component {
state = {
count: 1
}
handleClick() {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<div>
<p>次数: {this.state.count}</p>
<button onClick={this.handleClick.bind(this)}>点我+1</button>
</div>
)
}
}
我们在开发过程中,经常需要操作表单元素,比如获取表单的值或者是设置表单的值。
react中处理表单元素有两种方式:
setState
进行修改。
由state的值来控制表单元素的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4kQhEXEx-1668351209725)(images/受控组件.png)]
class App extends React.Component {
state = {
msg: 'hello react'
}
handleChange = (e) => {
this.setState({
msg: e.target.value
})
}
render() {
return (
<div>
<input type="text" value={this.state.msg} onChange={this.handleChange}/>
</div>
)
}
}
class App extends React.Component {
state = {
usernmae: '',
desc: '',
city: "2",
isSingle: true
}
handleName = e => {
this.setState({
name: e.target.value
})
}
handleDesc = e => {
this.setState({
desc: e.target.value
})
}
handleCity = e => {
this.setState({
city: e.target.value
})
}
handleSingle = e => {
this.setState({
isSingle: e.target.checked
})
}
render() {
return (
<div>
姓名:<input type="text" value={this.state.username} onChange={this.handleName}/>
<br/>
描述:<textarea value={this.state.desc} onChange={this.handleDesc}></textarea>
<br/>
城市:<select value={this.state.city} onChange={this.handleCity}>
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
<option value="4">深圳</option>
</select>
<br/>
是否单身:<input type="checkbox" checked={this.state.isSingle} onChange={this.handleSingle}/>
</div>
)
}
}
问题:每个表单元素都需要一个单独的事件处理程序,处理太繁琐
优化:使用一个事件处理程序处理多个表单元素
步骤
[name]
修改对应的stateclass App extends React.Component {
state = {
username: '',
desc: '',
city: "2",
isSingle: true
}
handleChange = e => {
let {name, type, value, checked} = e.target
console.log(name, type, value, checked)
value = type === 'checkbox' ? checked : value
console.log(name, value)
this.setState({
[name]: value
})
}
render() {
return (
<div>
姓名:<input type="text" name="username" value={this.state.username} onChange={this.handleChange}/>
<br/>
描述:<textarea name="desc" value={this.state.desc} onChange={this.handleChange}></textarea>
<br/>
城市:<select name="city" value={this.state.city} onChange={this.handleChange}>
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
<option value="4">深圳</option>
</select>
<br/>
是否单身:<input type="checkbox" name="isSingle" checked={this.state.isSingle} onChange={this.handleChange}/>
</div>
)
}
}
非受控组件借助于ref,使用原生DOM的方式来获取表单元素的值
使用步骤
React.createRef()
方法创建一个refconstructor() {
super()
this.txtRef = React.createRef()
}
<input type="text" ref={this.txtRef}/>
handleClick = () => {
console.log(this.txtRef.current.value)
}
非受控组件用的不多,推荐使用受控组件
评论列表案例
渲染评论列表(列表渲染)
获取评论信息,评论人和评论内容(受控组件)
发表评论,更新评论列表(更新状态)
边界处理
使用步骤
React.createRef()
方法创建一个refconstructor() {
super()
this.txtRef = React.createRef()
}
<input type="text" ref={this.txtRef}/>
handleClick = () => {
console.log(this.txtRef.current.value)
}
非受控组件用的不多,推荐使用受控组件