文章系列(React框架基础)
1-1、React环境搭建,以及初识jsx语法。
1-2、React熟悉,jsx语法以及变量绑定和三种渲染语句
1-3、React绑定属性和事件,以及事件的响应。
1-4、React中form表单下的input框初使用以及列表渲染
1-5、React初探组件化开发,高内聚低耦合
1-6、React组件中传值、添加事件和this丢失问题(本文)
大家好,我是Counterrr
不忘初心,砥砺前行
本文目录
一、组件中传值;
二、添加事件和this丢失问题;
(tips:本文为我们React框架基础系列最后一篇,下个系列将开启React组件化开发和项目实战)
1、组件中传值:
好的在上节5、React初探组件化开发,高内聚低耦合中我们用react组件化开发的思想将之前的小项目重构了,最后的效果如下:
我们知道组件化开发最大的好处就是组件的复用,但是在我们这个小项目中Option
组件即如下图:
当我们去复用的话还是react,写死的状态,将Options
组件写成如下代码:
class Options extends React.Component {
render () {
return (<ul>
<Option/>
<Option/>
<Option/>
</ul>)
}
}
我们看到这显然不是我们想要的结果,我们要的复用是,可以去暴露接口让我们去定制想要的内容。那么在没有组件化重构之前我们是怎么去做这件事情的,我们是将对象定义在全局上,对象上有数组,去渲染这个数组,那么在我们组件化开发中直接在类render( )
方法上去定义我们的数组,从而传值给我们的子组件,代码如下:
class MySelectLanApp extends React.Component {
render () {
let obj = {
"title": "今天学习什么语言?",
"des": "大家好,我是Counterrr",
"tips": "不忘初心,砥砺前行",
"languages": ['React', 'Vue', 'php']
}
return (<div>
<Header obj={obj}></Header>
<main>
<ButtonActive languages={obj.languages}></ButtonActive>
<AddLang languages={obj.languages}></AddLang>
<Options languages={obj.languages}></Options>
</main>
</div>)
}
}
可以看到我们直接在每个组件上直接写上属性,然后将值传入。接着我们在Options
组件上这样去渲染:
class Options extends React.Component {
render () {
return (<ul>
<Option languages={this.props.languages}/>
</ul>)
}
}
我们可以看到这边采用this.props.languages
去获取这个数组。render
函数定义在类的原型上我们去调用render
里的this
可以打印出组件实例对象,从而去获取绑定在实例对象上的props
字段下的languages
数组,紧接着我们又将这个数组以languages属性传递给了Option
组件,Option
组件写成如下:
class Option extends React.Component {
render () {
return (
this.props.languages.map((item, index) => {
return <li key={`option${index}`}>{item}</li>
})
)
}
}
我们在Option
组件里再用我们map
方法去真实的渲染,页面如下:
Header
组件代码如下:
class Header extends React.Component {
render () {
console.log(this)
return (<header>
<div>{this.props.obj.title}</div>
<div>{this.props.obj.des}</div>
<div>{this.props.obj.tips}</div>
</header>)
}
}
组件之间传值还是比较简单的,我们在组件标签上去绑定属性,然后在组件render
方法上去使用this.props
去获取我们自定义的属性。
2、添加事件和this丢失问题:
添加事件,在没有重构之前,我们也是将事件函数定义在全局上,通过onClick
去绑定这个事件函数,那我们重构后,也是将事件函数定义这个组件的类里,我们拿AddLang
这个组件来写一下,这个组件也是传入languages
属性并且将对象上的languages
数组传入,AddLang
组件代码如下:
class AddLang extends React.Component {
submitFunc (e) {
e.preventDefault();
if (e.target.elements.languages.value == '') {
alert('请输入!');
}
else {
console.log(this.props.languages)
}
}
render () {
return (<form onSubmit={this.submitFunc}>
<div>
<input type="text" name="languages"></input>
<button>添加语言</button>
</div>
</form>)
}
}
我们可以看到我们还是在form上去监听原生的submit
事件,并且这个函数写在了AddLang
这个类里,那就相当于在创建这个对象实例的时候,submitFunc
绑定在了这个原型上,那么在这个函数执行的时候this
就指向这个类的实例对象。我们来点击下添加语言这个按钮看看,效果如下:
没问题,显示让我们输入,那我们就输入再试试:
我们发现报错了,Cannot read property 'props' of undefined
这段代码我们熟悉的不能再属性,那这个是什么意思呢,读取不到undefined
上的props
属性,那为什么会这样呢,这个this
不是指向这个AddLang
创建出来的实例对象吗,并且在组件传值那已经把languages
给传入,那这个就是this
丢失的问题了,当我们点击这个按钮,说明这个函数自执行而不是给到我们对象去调用,那么这个this
指向非严格模式下就指向window
,严格模式下就指向undefined
,那这边走的是严格模式,那这个this
就是undefined
。
那我们怎么去解决这个问题呢?我们可以这样写:
class AddLang extends React.Component {
constructor(props) {
super(props)
this.submitFunc = this.submitFunc.bind(this)
}
submitFunc (e) {
e.preventDefault();
if (e.target.elements.languages.value == '') {
alert('请输入!');
}
else {
console.log(this.props.languages)
}
}
render () {
return (<form onSubmit={this.submitFunc}>
<div>
<input type="text" name="languages"></input>
<button>添加语言</button>
</div>
</form>)
}
}
我们用到这个类里constructor
构造函数,在这个类实例化的时候就是去执行这段代码,我们将submitFunc
函数的指向用bind
函数给改变了,对于bind
这块可以查看浅谈JavaScript的函数的call( ) apply( ) bind( )我的这篇博客。这样的话我们输入再去点击:
就会把this.props.languages
给打印出来。