上次更新博客是在5/24了。公司的工作也比较多所以就没有更新。
今天看了一篇文章,讲的是React和Vue的区别。所以今天主要讲下这个。
文章传送门:React和Vue的书写特性差异
渲染过程
React
React的生命周期有以下几个方法:
1. componentWillMount: 这个方法会在组件的第一次渲染前调用。一个组件渲染只会调用一次该方法,除非重新生成组件。
2. componentDidMount: 这个方法同componentWillMount会在第一次渲染后调用,也是一次生成只调用一次。
3. componentWillReceiveProps(nextProps): 组件在接收到新的props会调用,其参数nextProps表示改变后的props,可用this.props访问改变前的props。
4. shouldComponentUpdate(nextProps, nextState): React会根据State和Props的变化判断组件是否需要重新渲染,若返回true则表示重新渲染。
5. componentWillUpdate: 在组件将要更新前的时候调用,此时还没有触发render()
6. componentDidUpdate: 在组件更新后调用。
7. componentWillUnmount: 在组件被移除前被调用。
这几个方法在使用react的时候很常用,因此清楚了解它们的调用顺序和原因很重要。
下面这张图片描述得很清楚:
可以看到,当props改变的时候,首先会调用componentWillReceiveProps。但是则state的改变是直接调用shouldComponentUpdate。
还有,重新渲染 不等于 重新生成。 图片中看到,render后会直接回到运行中的状态而非componentWillMount。
shouldComponentUpdate用于告诉组件是否应该重新渲染,因此我们可以在该方法中判断是否应该重新渲染。
这里要注意的是,shouldComoponentUpdate不能让他永远返回true,否则会导致每一次的无关紧要的改动都会重新渲染,这样的性能会下降。
比如使用React的PureComponent时,react对state的改变的比较是浅比较的,比如
this.state = {
data: {
lh: {
name: 'lihui',
age: 18,
}
}
}
此时你使用this.setState({ data.lh.name: 'csy' });
,其实你改变了state但你会发现组件并没有重新渲染。
这就是浅比较的原因,浅比较会简单比较值而非具体的改变。此时你改变的只是lh
中的一个属性值name
,lh
的引用依旧没变,因此会被认为state没有改变。
解决的方法是使用immutable
对象,每次改动时会返回一个新的对象,这个对象就是新的引用,所以改变会被探测到。这里具体的方法就省略了。
Attention: 在ComponentWillMount
或者ComponentWillReceiveProps
中调用setState
是无法立即得到新的state的,这是因为这两个方法会在执行后再对state进行合并。
shouldUpdateConponent
和ComponentWillUpdate
是不可以在里面调用setState的,否则会循环调用导致崩溃。
Vue
相较于React,Vue的生命周期则更好理解了。
Vue没有什么接受新改变的props和state,而是监听data的改变,data改变后触发beforeUpdate函数并重新渲染。
其实我对vue的了解还不算太深入,希望有人可以解答下这个部分。
入口
React
React.render(
<App />,
document.getElementById('app')
);
<App />
表示一个组件,上面语句表示的是将该组件在app这个元素内进行渲染。
Vue
const app = new Vue({
render: (h) => h(App) // App为根组件
}).$mount('#app')
同一种结果,React和Vue在入口方面的不同。
组件定义
React定义组件
// 组件定义
export default Component extends React.Component{
// ...
}
// 引入组件
import Component from './component';
export default About extends React.Component{
render() {
return (
<div>
<Component></Component>
</div>
);
}
}
Vue
// 组件定义
<template>
div
p
</template>
<script>
export default {
// ...
}
</script>
// 引入组件
<template>
div
my-component
</template>
<script>
import myComponent from './myComponent';
export default {
components: {
myComponent,
}
}
</script>
组件状态修改
组件状态在React中是state,在Vue中是data
React
React修改state需要通过this.setState({ test: 1 });
Vue
Vue修改data只需要this.age = 18;
即可。
JSX / template
React用的是JSX语法,而Vue用的是Template语法。
条件渲染和列表渲染
React
条件渲染
// ...
render() {
return (
<div>
{
this.getChild();
}
</div>
)
}
getChild = () => {
switch(condition) {
case 'xx':
return (
<div></div>
)
}
}
列表渲染
// ...
render() {
return (
<div>
{
this.state.actions.map((action) => {
return (
<p>{action.name}</p>
)
})
}
</div>
)
}
Vue
条件渲染
<div v-if="this.isShow"></div>
<div v-else></div>
列表渲染
<div v-for="item in this.notes">
<p>
{{item.name}}
</p>
</div>
双向数据绑定
React
这个地方我真的有感触颇深,比如当前需要渲染一个input元素。如下
<input defalutValue='default'></input>
此时可能改变了一个state要对input进行重新渲染,前提是你之前在这个input里有输入。
你会发现重新渲染后的input还是保留着你刚刚的值。
这个怎么解决?
这就是因为React中没有实现双向数据绑定的问题了。如何自己实现呢?
<input defalutValue='default' value={this.state.someVlaue}></input>
使用value={this.state.someValue}
使value的值绑定在someValue之上。
但是绑定了之后你会发现,没有办法输入了?!
因此此时需要我们定义一个onChange事件,这个事件会传入一个e对象,使用这个对象的e.target.value
将用户输入的值再保存到someValue上。
<input defalutValue='default' value={this.state.someVlaue} onChange={(e) => this.onInputChange(e)}></input>
onInputChange = (e) => {
this.setState({ someValue: e.target.value });
}
Vue
没有对比就没有伤害,Vue中的双向数据绑定简单多了。如下
<input v-model="someValue"></input>
待更~