本文将会以与Vue的差别来进行React的学习,所以在阅读本文之前我希望你能具备以下技能
- 前端三剑客HTML+CSS+JavaScript
- 了解Vue的使用
书写形式
React在采用自创jsx语法,即HTML in JavaScript,将UI与逻辑耦合在一起
import React from 'react';
class item extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return <div>
{/*要显示的内容*/}
</div>
}
}
Vue常规采用模板语法,将HTML文档与JavaScript逻辑分离开,Vue也可以设置使用jsx
<template>
<!--页面内容-->
</template>
<script>
// 逻辑部分
</script>
<style>
/*css样式*/
</style>
组件及传递数据
二者都通过导入外部文件然后使用HTML标签的形式在引用组件,不同点在于二者的组件接收形式
React中通过构造函数来接收props,
constructor(props) {
super(props);
this.state = {}
}
// 通过构造函数接收props之后就可以直接通过this.props来获得参数
vue通过options来接收参数,可以规定props的类型及默认值
<script>
props: {
message: {
type: String,
default: 'from father'
}
}
</script>
在react中也可以规定类型及默认值,但是需要引入第三方的包,这里官网文档已经说得很清楚了
从子组件向父组件传递数据时都是通过触发父组件传递过来的回调函数来实现
// Vue
this.$emit('eventName', data)
// React
this.props.eventName(data)
修改数据
在React中数据存储在state中,不可以直接修改,直接修改不会触发render,而Vue中则可以直接修改data中的数据,因为Vue对每一个数据都进行了数据劫持,当数值发生改变时都会触发渲染
在React中想要修改数据需要使用API——setState
constructor(props) {
super(props);
this.state = {
value: 12
}
}
changeValue() {
this.setState({
value: 13
})
}
事件
Vue中通过v-on来绑定事件,可以简写为@
<button @click="eventHandler">
点击
</button>
React中跟传统HTML相似但又略微不同
<button onClick={this.eventHandler.bind(this)}>
点击
</button>
在React中声明方法this指向并不是组件的this,需要改变其this指向,可以使用的方法有:
- 在构造函数中绑定:this.eventHandler = this.eventHandler.bind(this)
- 在声明方法时使用eventHandler = () => {}的形式
- 在调用方法时绑定:onClick={this.eventHandler.bind(this)}或者onClick={() => this.eventHandler()}
条件渲染
Vue中的条件渲染使用v-if
、v-else-if
、v-else
、v-show
来进行条件渲染,区别在于v-if不会渲染到文档中,v-show会渲染到文档中,只是display变为none
<div v-if="value">
{{value}}
</div>
<div v-else>
暂无数据
</div>
React中的条件渲染是通过js的if语句控制变量或者运算符来控制的
// 变量控制
let data;
if(this.state.value) {
data = <div>{this.state.value}</div>
} else {
data = <div>暂无数据</div>
}
return(
{data}
)
// _______________________
// &&运算符
// 因为在 JavaScript 中,true && expression 总是会返回 expression
// 而 false && expression 总是会返回 false
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
// ________________________
// 三目运算符
return (
<div>
The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
</div>
);
列表
在Vue中通过v-for属性来生成列表
<ul>
<li v-for="(item, index) in list" :key="index">{{item}}</li>
</ul>
在React中使用js的遍历来生成列表
<ul>
list.map((item, index) => {
return <li key={index}>{item}</li>
})
</ul>
实际上并不建议使用index作为key值,每个key应该是独一无二的
“双向绑定”
在Vue中使用v-model属性来绑定data,这是真正的双向绑定,绑定之后我们不再需要关心值的改变,而在React中,重新赋值就需要我们来手动操作,如果不手动修改,页面不会重新渲染,比如输入框中使用键盘输入一串字符,其实他已经有值了,但是页面上的输入框还是会显示空白
inputHandler = (e) => {
this.setState({
inputValue: e.target.value
})
}
render(
return <div>
<input value={this.state.inputValue} onChange={this.inputHandler}/>
</div>
)
生命周期
关于生命周期已经有很多讲的不错的文章了,可以去看一下
重点两个比较难搞得就是shouldComponentUpdate
和componentWillReceiveProps
shouldComponentUpdate(nextProps, nextState)通过返回值是true和false来控制组件是否重新渲染(react父组件发生改变时所有的子组件都会重新render),可以通过对比前后的props来决定是否进行重新渲染,这是一种优化手段;只在props或者state发生改变时执行
shouldComponentUpdate(nextProps, nextState, nextContext) {
if(this.props.person === nextProps.person) {
return false
} else {
return true
}
}
componentWillReceiveProps只在props发生改变时执行,可以在这里面使用setState,不会引起额外的render
获取DOM元素
Vue中获取DOM的方式是通过给元素添加ref属性,然后通过$refs来获取DOM
<template>
<input ref="inputRef" type="text" />
</template>
<script>
mounted() {
console.log(this.$refs['inputRef'])
}
</script>
在React中有很多种方式,其中一种就跟Vue这种形式一样,但是已经废弃了,我们再来看一下其他方法
React.createRef()
在构造函数中声明一个变量并赋值React.createRef(),然后在元素上挂载ref,就可以通过这个变量来访问DOM
constructor() {
this.inputRef = React.createRef()
}
componentDidMount() {
console.log(this.inputRef.current)
// 这里注意使用createRef的方式需要通过current来获取
}
render(
return <div>
<input ref={this.inputRef} />
</div>
)
回调函数
直接在回调函数中向组件传递DOM
componentDidMount() {
console.log(this.inputRef)
// 回调函数的方式直接获取
}
render(
return <div>
<input ref={(ul) => {this.inputRef = ul}} />
</div>
)
子组件ref
通过React.forward()来创建子组件,接收两个参数props、ref,将元素绑定接收来的ref就可以在父组件中获取子组件的DOM了
// 子组件
const InputComponent = React.forwardRef((props,ref)=>(
<input type="text" ref={ref} />
));
// 父组件,使用createRef声明this.InputRef变量
<InputComponent ref={this.InputRef} />