组件声明
React
中声明组件有两种方式,一是函数式组件,就是把一个函数作为组件的构造器;二是class
组件,即用ES6
的class
语法声明一个类作为组件的构造器。在16.8版本以前函数式组件不能使用组件的state
,refs
属性等诸多特性,这使得函数式组件只能用来定义一些简单组件,对于复杂一些的组件只能使用class
组件。而此版本以后React
加入了Hook
,使得函数式组件也能够使用组件的其它特性。官方文档
函数式组件
函数式组件中我们只能用props
属性,定义一个函数式组件只需要创建一个开头为大写字母的函数,然后再将函数最后return
回一个jsx
标签即可。代码如下:
function Person(props) {
return (
<div>
<h2>{props.name}</h2>
</div>
)
}
ReactDOM.render(<Person name="Asuhe" />,document.querySelector('#root'))
class组件
class
组件要比函数式组件强大的多,它可以完全使用组件三大属性:state
、props
、refs
。它还有生命周期函数可供使用,在生命周期函数中我们可以进行许多操作。但创建一个class
组件需要从React对象
中继承一个类React.Component
。代码如下:
class MyComponent extends React.Component {
// render函数必须要有
render(){
return (
<div>
<h2>Asuhe</h2>
</div>
)
}
}
ReactDOM.render(<MyComponent />,document.querySelector('#root'))
当我们需要在class
组件上挂载事件处理函数时有两种方式,一是在constructor
中重写该事件处理函数,二是利用箭头函数和class语法声明函数。
class Weather extends React.Component {
/* 第一种方法 在jsx中调用的this调用weather和设置state
constructor(props) {
super(props)
this.state = { isHot: true, breeze: '微风' }
// 关键步骤:将原型上的changeWeather挂载载到组件实例对象的changeWeather里并更改this
this.changeWeather = this.changeWeather.bind(this)
}
changeWeather() {
let {isHot} = this.state
this.setState({
isHot: !isHot
})
}
// 未重写changeWeather前,onClick绑定的this.changeWeather相当于
// let a = new Weather()
// let x = a.changeWeather
// x()
*/
// 第二种方法 不在原型上挂载changeWeather
state = { isHot: true, breeze: '微风' }
changeWeather = () => {
let { isHot } = this.state
this.setState({
isHot: !isHot
})
}
render() {
return (
<h2 onClick={this.changeWeather}>
今天天气很{this.state.isHot ? '炎热' : '凉爽'},{this.state.breeze}
</h2>
)
}
}
ReactDOM.render(<Weather />, el)
组件的三大属性
组件实例中有很多属性,但比较常用的就三个分别是:state、props、refs。
state
state
属性是用来存储该组件实例的状态的。当我们使用this.setState
函数去修改state
时,页面会因为组件状态改变而同步改变。以上面的MyComponent
组件为例,我们可以给组件定义一个初始状态:
class MyComponent extends React.Component {
/* 第一种方式在构造器里初始化状态
constructor(props){
// 使用了构造器就一定要调用super 否则React报错
super(props)
this.state = {name:'Asuhe'}
// 若不给super传props,则在constructor中使用this.props可能会出错
}
*/
// 第二种方式
state = {name:'Asuhe'}
// render函数必须要有
render(){
return (
<div>
<h2>{this.state.name}</h2>
</div>
)
}
}
props
props
属性是用来接收外部传给组件的数据的,如果我们直接在标签上写数据,props
会自动接收该数据。
ReactDOM.render(<MyComponent age={18} />,document.querySelector('#root'))
限制props的数据类型
有时候我们希望限制传入数据的类型,此时我们需要额外加载一个prop-types.js
包,里面有PropTyps
对象以供我们使用。示例代码如下:
// 需求:
// 1.name属性必须为string,age属性必须为number,sex属性必须为string
// 2.sex属性必须传入
// 3.sex若未传入则默认值为male
class Person extends React.Component {
static propTypes = {
name: PropTypes.string,
age: PropTypes.number,
// sex为必须
sex: PropTypes.string.isRequired
}
// 设置默认props值
static defaultProps = {
sex: 'male'
}
render() {
return (
<ul>
<li>name:{this.props.name}</li>
<li>age:{this.props.age}</li>
<li>sex:{this.props.sex}</li>
</ul>
)
}
}
let data = {
name: 'asuhe',
age: 22,
// sex: 'male'
}
ReactDOM.render(<Person {...data} />, el)
refs
当我们需要获取标签or组件实例时,可以使用ref
标记。然后就可以在函数中利用this.refs
找到该组件or标签。ref
有三种形式分别是:字符串类型、回调函数类型和refs
对象类型。
字符串类型的ref
字符串形式的ref 已经不推荐使用, ref会被自动收录进组件的refs里,如同props。
class Person extends React.Component {
showData = (event) => {
event.preventDefault()
let { input2: { value } } = this.refs
console.log(value)
}
render() {
return (
<form>
<input ref="input1" type="text" placehoder="username" />
<button onClick={this.showData}>提交</button>
<input ref="input2" type="password" placehoder="password" />
</form>
)
}
}
ReactDOM.render(<Person />, el)
回调函数类型的ref
回调函数形式的ref 会将该标签DOM传给回调函数的形参,用this接住挂载在组件实例上。
class Person extends React.Component {
showData = (event) => {
event.preventDefault()
let { input2: { value } } = this
console.log(value)
}
render() {
return (
<form>
<input ref={a => this.input1 = a} type="text" placehoder="username" />
<button onClick={this.showData}>提交</button>
<input ref={b => this.input2 = b} type="password" placehoder="password" />
</form>
)
}
}
ReactDOM.render(<Person />, el)
refs对象类型的ref
使用自定义ref对象 ref对象内含{ current:被ref标记的标签实例 } 当多个标签使用同一个ref对象标记时,仅保留最后一个。
class Person extends React.Component {
// 若要ref标记多个标签实例,则需要声明多个属性创建多个React.createRef
myRefs = React.createRef()
showData = (event) => {
event.preventDefault()
let { current: { value } } = this.myRefs
console.log(value)
}
render() {
return (
<form>
<input ref={this.myRefs} type="text" placehoder="username" />
<button onClick={this.showData}>提交</button>
<input ref={this.myRefs} type="password" placehoder="password" />
</form>
)
}
}
ReactDOM.render(<Person />, el)