Vue开发者如何上手React(hooks)
Vue和React是什么?
引用官方文档Vue.js的介绍:
引用React官方博客 《我们为什么要构建 React?》
从上面知道他们两者实际上都是在处理视图层的问题。
我们思考一下,如果没有React和Vue,那么在一个传统的 JavaScript 应用中,我们需要观察数据发生了什么变化, 并且为了让 DOM 保持最新的状态还必须对它进行更改。 比如:通过JQuery来获取到对应的DOM然后修改该节点的值等。
Vue和React给出的解决方式:胶水层 + 响应式更新
明确两者实际都是处理同一中问题,并选择了是同一个方向的解决方式,那么所谓的差异就可以局限到两者是如何实现所谓的胶水层+响应式更新了。
Vue的胶水层与响应式更新
举个官网的Demo的例子。
new Vue({
el: '#app-5',
template:`
<div id="app-5">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">反转消息</button>
</div>
`
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
那上面的template
就是本文特指的胶水层的具体体现,data
就是相应式更新的具体体现。
在实际开发中我们不再直接接触所谓的HTML+CSS了,即真实DOM,都是在tempalte里面书写UI逻辑。
通过这个胶水层,即teample
的内容,Vue就能感知数据的变化,即tempalte
里依赖的data
数据,就会自动进行真实的DOM操作,从而达到视图更新。
当一个对象是Vue.data
这种方式来定义的时候,它就应该不再普通的对象,而是上图里面的data,即响应式数据,所以我们对他的操作,已经不再是简单的“JS操作”,即getter/setter,而是经过来Vue这个代理商,那Vue所做的事就是:某个数据变化了,依赖与这个数据的tempalte
应该更新了。
具体下来就是,当我们在Vue.data
里面定义数据时,Vue2通过Object.defineProperty
获取setter/getter
操作,从而实现data
与template
的绑定及监听数据的变化。
实际开发过程中,我们是不会看到代理的存在的,即
所以,开发起来,一起都那么简单,并符合直觉。
React的胶水层与响应式更新
React的团队可能是觉得探索一种成熟的简单的方式,没那么好玩,所以他们选择了另一个探索性(坑多)的思路。
举个和上面一样的例子
import { useState } from "react";
import ReactDOM from "react-dom";
function App() {
const [message, setMessage] = useState("Hello React.js!");
const reverseMessage = () => {
setMessage(message.split("").reverse().join(""));
};
return (
<div className="App">
<p>{message}</p>
<button onClick={reverseMessage}>反转消息</button>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
我们可以把React中return
出的JSX
等同于Vue中的tempalte
,setState
所做的事就是Vue中在data
里定义一个响应式变量。
Vue的响应式数据只需要在Vue.data中定义,对开发者而言,这个对象已经是响应式数据了,所以我修改他,他就应该自己更新到视图中。
而React就比较麻烦了,==React中并没有响应式数据==,就算是通过useState
获取的message
变量,它还是一个普普通通的变量,所以被修改了,就是简单的被修改,并不会反映到视图中,达到响应式更新。
React的思路是:如果你要让一个变量的变化同步到视图中,你可以使用useState
方法来定义一个变量,但它并不监听这个变量的变化过程,当用户想要去更新到视图中时,请调用该变量的setter
函数(即例子中的setMessage
),并传递这个变量具体的值(即:message.split("").reverse().json("")
),那React就拿到这个数据重新绘制(重新执行函数组件)一遍。
这是什么感觉呢?拿房子的设计稿和房子举例
房子已经根据设计稿已经造好了,但是我觉得不满意,我想改一下房间的形状。
当这个工人是Vue的时候,==他是一个把顾客当上帝的好工人==,他发现顾客把设计图中的房间改了,作为一个好工人,不需要顾客来告知,他就立马!主动!快速!地去==把这个房间拆了==,然后造个圆形的房间出来。
当这个工人是React的时候,他是有自己生活的人,所以工作只是他生活的一部分。顾客怎么改设计图,他都不关心,当用户改好了,定稿了,顾客来找他的时候,他才开始去看设计稿。而且他不想和顾客多说一句话,并告诉顾客:你图怎么样,我就造得怎么样,如果不确定的话,你就回去确定好了再来。如果用户确定了设计稿,那他转身就把==房子全拆了==,根据最新的设计稿来重新建一个房子。那么房间的修改一定是符合用户的预期的。
对应到代码中就是:
- 设计稿就是:胶水层(tempalte、JSX)
- 房子就是:真实DOM
- 房间就是:data
在Vue里面我们修改data
,temaplte
就感知到了,Vue就会主动去修改真实的DOM
在React中我们要修改state
时,需要显示地调用setState
来告知React去更新视图,并且需要传递一个具体的值。
所谓的==房子全拆==了,是表示React把Function Component
重新执行一遍。我们可以简单的实现一个useState来模拟这个过程,以便更好的理解
import ReactDOM from "react-dom";
let memoizedState;
function useState(initialState) {
memoizedState = memoizedState || initialState;
function setState(newState) {
memoizedState = newState;
render(); // 告诉React工人去改房子
}
return [memoizedState, setState];
}
// 设计稿
function App() {
const [message, setMessage] = useState("Hello React.js!");
const reverseMessage = () => {
setMessage(message.split("").reverse().join(""));
};
return (
<div className="App">
<p>{message}</p>
<button onClick={reverseMessage}>反转消息</button>
</div>
);
}
function render() {
// 根据设计稿 从零开始造房子
ReactDOM.render(<App />, document.getElementById("root"));
}
render();
当用户在JSX中使用函数组件时,即<App/>
,React会去执行这个函数组件,即function APP(){...}
以获得return
返回的值。
所以,每次render
的时候,function App
都会去执行,这就像原本建好的房子,全部不好,从零开始造的感觉。
至此,我们可以把React的响应式思路理解成:通过重新执行函数获取最新的结果,拿到结果后的React再去更新到真实DOM中,即视图更新。
有了这个思维后,我们再去看平时为什么
- 写出无限渲染的组件时,就知道一定是多个
setXXX
造成了问题了。 - 为啥那么卡,是因为每次函数都重新执行了,我们在这个函数里面定义了过多的操作,需要去优化,这就是useEffect或者useCallback去告诉React,这个地方你重新执行函数的时候,请不要重复操作。
具体如何使用useEffect
和useCallback
之类的,请阅读React Hooks最好的资料:Hook 概览
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!