组件
一、React 组件介绍
- 使用 React 就是在用组件
- 组件表示页面中的部分功能
- 组合多个组件实现完整的页面功能
- 特点:可复用、独立、可组合
二、 React 组件的两种创建方式
1、使用函数创建组件
函数组件:使用 JS 的函数(或箭头函数)创建的组件
如下所示即为一个组件:
function Hello(){
return (
<div>这是一个函数组件</div>
)
}
- 约定1:函数名称必须以大写字母开头
- 约定2:函数组件必须有返回值,表示该组件的结构
- 如果返回值为 null,表示不渲染任何内容
渲染函数组件:用函数名作为组件标签名
如下:
let root = document.getElementById('root')
ReactDom.render(< Hello />,root)
打印结果为:
注意:组件标签可以是单标签也可以是双标签
2、 使用类创建组件
类组件:使用 ES6 的 class
创建的组件
如下所示:
class Hello extends React.Component{
render(){
return (
<div>这是一个类组件</div>
)
let root = document.getElementById('root')
ReactDOM.render(<Hello />,root)
打印结果为:
- 约定1:类名称也必须以大写字母开头
- 约定2:类组件应该继承
React.Componen
t 父类,从而可以使用父类中提供的方法或属性 - 约定3:类组件必须提供
render()
方法 - 约定4:
render()
方法必须有返回值,表示该组件的结构
三、React 事件处理
1、事件绑定
React 事件绑定语法与 DOM 事件语法相似
语法:on+事件名称={事件处理程序}
比如:
onClick={() => {}}
注意:React 事件采用驼峰命名法,比如:onMouseEnter
、onFocus
1、在函数组件中绑定事件
如下所示:
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
function App(){
function handleClick(){
console.log('单击触发了函数事件处理')
}
return (
<button onClick={handleClick}>单击</button>
)
}
//元素渲染
ReactDOM.render(<App />,root)
</script>
</body>
打印结果为:
2、在类组件中绑定事件
如下所示:
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
class App extends React.Component{
handClick(){
console.log('单击触发了类事件处理')
}
render(){
return (
<button onClick={this.handClick}>点击</button>
)
}
}
//元素渲染
ReactDOM.render(<App />,root)
</script>
</body>
打印结果为:
2、事件对象
可以通过事件处理程序的参数获取到事件对象,React 中的事件对象叫做:合成事件(对象)。
合成事件:兼容所有浏览器,无需担心跨浏览器兼容性问题
例如:我们想要通过一个a
标签,不发生事件的跳转,而实现其点击事件。示例如下:
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
class App extends React.Component{
handleClick(e){
e.preventDefault()
console.log('a标签的单击事件触发了')
}
render(){
return (
<a href="https://blog.csdn.net/m0_48375854?type=blog" onClick={this.handleClick>bear*6</a>
)
}
}
//元素渲染
ReactDOM.render(<App />,root)
</script>
</body>
结果为:
四、有状态组件和无状态组件
函数组件又叫做无状态组件,类组件又叫做有状态组件。
- 状态(state)即数据
- 函数组件没有自己的状态,只负责数据展示
- 类组件有自己的状态,负责更新 UI,让页面“动” 起来
比如计数器案例中,点击按钮让数值加 1 。0 和 1 就是不同时刻的状态,而由 0 变为 1 就表示状态发生了变化。状态变化后,UI 也要相应的更新。React 中想要实现该功能,就要使用有状态组件来完成。
五、组件中的 state 和 setState()
1、 state的基本使用状态即数据
- 状态是私有的,只能在组件内部使用
- 通过
this.state
来获取状态
如下例所示,初始化count
的值为0:
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
class App extends React.Component{
//法一:
// constructor(){
// super()
// //初始化state
// this.state = {
// count:0
// }
// }
//法二:
state = {
count:0
}
render(){
return (
<h1>计数器:{this.state.count}</h1>
)
}
}
//元素渲染
ReactDOM.render(<App />,root)
</script>
</body>
最终输出的结果为:
2、 setState()修改状态
我们想要将计数器的值从0变化到1,这个时候,我们就需要让状态发生变化,该如何修改值呢?
语法:this.setState({ 要修改的数据 })
setState()
作用:修改 state
和更新UI
代码如下:
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
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
})
}}>点击+1</button>
</div>
)
}
}
//元素渲染
ReactDOM.render(<App />,root)
</script>
</body>
实现效果为:
注意:不能直接修改 state 中的值
如果不用箭头函数写呢?如下所示:
class App extends React.Component{
state={
count:0
}
add(){
this.setState({
count:this.state.count+1
})}
render(){
return (
<div>
<div>修改状态的值为:{this.state.count}</div>
<button onClick={this.add}>+1</button>
</div>
)
}
}
打印的结果为:
可知:发生错误,这是因为事件处理程序中的this
指向是undefine
,而箭头函数没有this指向的问题。
六、事件绑定 this 指向
要处理事件绑定中的this指向问题,有三种方法。
1、箭头函数
利用箭头函数自身不绑定this的特点,以 render()
方法中的 this 为组件实例,可以获取到 setState()
,如下所示:
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
class Hello extends React.Component{
state = {
count:0
}
add(){
this.setState({count:this.state.count+1})
}
render(){
return (
<div>
<h3>计数器{this.state.count}</h3>
<button onClick={()=>{this.add()}}>加1</button>
</div>
)
}
}
//元素渲染
ReactDOM.render(<Hello />,root)
</script>
</body>
实现效果为:
2、Function.prototype.bind()
利用ES5中的bind
方法,将事件处理程序中的this
与组件实例绑定到一起
代码如下:
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
class Hello 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>
<h3>计数器{this.state.count}</h3>
<button onClick={this.add}>加1</button>
</div>
)
}
}
//元素渲染
ReactDOM.render(<Hello />,root)
</script>
</body>
实现效果为:
3、class 的实例方法
利用箭头函数形式的class实例方法
代码如下:
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
class Hello 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>
<h3>计数器{this.state.count}</h3>
<button onClick={this.add}>加1</button>
</div>
)
}
}
//元素渲染
ReactDOM.render(<Hello />,root)
</script>
</body>
实现效果同上,不在附图。
七、表单处理
1、受控组件
我们知道,HTML 中的表单元素是可输入的,也就是有自己的可变状态,而React 中可变状态通常保存在 state
中,并且只能通过 setState()
方法来修改,那么,React将 state
与表单元素值value
绑定到一起,最终由 state
的值来控制表单元素的值,这样就实现了变化的状态都保存在state
中,并将其值受到 React 控制的表单元素称为受控组件。
1、受控组件的使用步骤
(1) 在 state
中添加一个状态,作为表单元素的value
值(控制表单元素值的来源)
state = { txt: '' }
<input type="text" value={this.state.txt} />
(2)给表单元素绑定 change
事件,将 表单元素的值 设置为 state
的值(控制表单元素值的变化)
<input type="text" value={this.state.txt}
onChange={e => this.setState({ txt: e.target.value })}
/>
2、操作表单元素
例如操作文本框、富文本框、下拉菜单、复选框的值,示例如下:
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
class App extends React.Component{
constructor(){
super()
this.state = {
txt:'',
text:'',
sele:'xl',
isCheck:true
}
}
handleChange = e=>{//文本框
this.setState({
txt:e.target.value
})
}
handleText = e=>{//富文本框
this.setState({
text:e.target.value
})
}
handleSele = e=>{//下拉菜单
this.setState({
sele:e.target.value
})
}
handleCheck = e=>{//复选框
this.setState({
isCheck:e.target.checked
})
}
render(){
return (
<div>
<input type="text" value={this.state.txt} onChange = {this.handleChange}/>
<br />
<textarea name="" id="" cols="30" rows="10" value={this.state.text} onChange={this.handleText}></textarea>
<br />
<select value={this.state.sele} onChange={this.handleSele}>
<option value="wh">小欢</option>
<option value="xl">小熊</option>
<option value="rc">小冉</option>
<option value="lj">小刘</option>
</select>
<br />
<input type="checkbox" value={this.state.isCheck} onChange={this.handleCheck}/>
</div>
)
}
}
//元素渲染
ReactDOM.render(<App />,root)
</script>
</body>
显示结果为:
3、多表单元素优化
通过上例,我们可以看到每个表单元素都有一个单独的事件处理程序处理,使得我们的代码很太繁琐,我们可以对其进行优化,具体的实现方法是:使用一个事件处理程序同时处理多个表单元素
操作步骤为:
(1)给表单元素添加name属性,名称与 state 相同
<input type="text" name="txt" value={this.state.txt} onChange={this.handleForm}/>
(2)根据表单元素类型获取对应值
const value = target.type === 'checkbox' ? target.checked: target.value
(3)在 change 事件处理程序中通过 [name] 来修改对应的state
this.setState({[name]: value})
对上例进行优化,代码如下:
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
class App extends React.Component{
constructor(){
super()
this.state = {
txt:'',
text:'',
sele:'xl',
isCheck:true
}
}
handleForm = e=>{//文本框
//获取当前DOM对象
const target = e.target
//进行类型获取值
const value = target.type==='checkbox'? target.checked:target.value
//获取name
const name = target.name
this.setState({
[name]:value
})
}
render(){
return (
<div>
<input type="text" name='txt' value={this.state.txt} onChange = {this.handleForm}/>
<br />
<textarea name="text" id="" cols="30" rows="10" value={this.state.text} onChange={this.handleForm}></textarea>
<br />
<select name = 'sele' value={this.state.sele} onChange={this.handleForm}>
<option value="wh">小欢</option>
<option value="xl">小熊</option>
<option value="rc">小冉</option>
<option value="lj">小刘</option>
</select>
<br />
<input type="checkbox" name='isCheck' value={this.state.isCheck} onChange={this.handleForm}/>
</div>
)
}
}
//元素渲染
ReactDOM.render(<App />,root)
</script>
</body>
最终实现效果同上。
2、非受控组件
使用步骤:
(1) 调用 React.createRef() 方法创建一个 ref 对象
constructor() {
super()
this.txtRef = React.createRef()
}
(2) 将创建好的 ref 对象添加到文本框中
<input type="text" ref={this.txtRef} />
(3)通过 ref 对象获取到文本框的值
console.log(this.txtRef.current.value)
示例代码如下:
在这里插入代码片<body>
<div id="root"></div>
<script type="text/babel">
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}>获取文本框的值 </button>
</div>
)
}
}
//元素渲染
ReactDOM.render(<App />,root)
</script>
</body>
实现效果为: