举起Vue2大刀转战React16(一)
大家好,我是猿小蚁(简称"小蚁"),因为我个人在整个我们这个社会生态中是个很微小的存在,我难以想象一个"离群索居"的人会是什么样子的,就像是蚂蚁和蚁群的关系一样,但蚂蚁个体的力量却是很强大的,它能举起超越自己体中几十倍以上的重物,而我却无法在前端领域中表现的那么强悍的力量,所以我想成为一只小蚂蚁,在强大的合作/协作关系网中变得very strong.
vue2的使用已经两年多了,但react的内容还是一片空白,这片空白同时影响到了自己的职业发展,所以想要扩展一下,从vue2的角度来边学习边对比react。
1. 入门解析
对比项 | Vue2.x | React16.x |
---|---|---|
定位 | 一套用于构建用户界面的**渐进式框架,**这是构建web开发的一整套解决方案的集合。特点: 简单、易用、需要额外学习写法 | 用于构建用户界面的 JavaScript 库,这是构建web页面的专用库,可以通过一系列不同的组合搭建web开发的解决方案特点:灵活、js的使用方法 |
渲染方式 | template模板+vue实例 [详见2.渲染方式] | jsx语法 [详见2.渲染方式] |
深入渲染模式 | 深入渲染模式 | 深入渲染模式 |
使用变量和表达式 | {{变量名/表达式}} -->双大括号 | {变量名/表达式} --> 单大括号 |
属性使用 | 动态::propName="propValue" 静态:propName="xxxx" | 动态: propName={propValue} 静态:propName="xxx"类名: className=.... |
事件 | @eventName="handler" | onEventName={handler}传参更麻烦: e=> handler(xxx)绑定this也麻烦: handler.bind(this); |
条件渲染 | v-if/v-else-if/v-else指令 | js的判断方法,例如 {boolean ? <div>hello</div>: null } |
列表渲染 | v-for指令 | jsx自动展开数组 js的循环方法,返回对应的jsx |
使用dom | ref="refName" <--> $refs.refName | 声明ref: ref={this.testRef} 定义ref: this.testRef = React.createRef() 使用ref: this.testRef |
2. 渲染方式
2.1 模板和实例
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
</head>
<body>
<div id="app">{{name}}</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
name: "vue页面渲染",
};
},
});
</script>
</body>
</html>
2.2 jsx语法
尴尬了, jsx的使用必须借助babel进行转义,这一点上没有vue方便呀!(第一次想要放弃,直接使用vue,何必要使用react呢)
2.2.1 react环境搭建
- 初始化前端项目:
npm init -y
- 安装babel环境及其他依赖:
npm i @babel/core @babel/preset-env @babel/preset-react babel-loader clean-webpack-plugin html-webpack-plugin webpack webpack-cli webpack-dev-server -D
- 配置webpack:详情见git仓库
- 配置babel:详情见git仓库
- 在index.html中引入react、reactDOM两个CDN链接, 注意是两个!两个!!两个!!!
<!-- index.html -->
<script crossorig src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
2.2.2 使用jsx语法
// index.js
let name = "react页面渲染";
let element = <div id="app">{name}</div>;
ReactDOM.render(element, document.getElementById("root"));
2.3 总结
- react的使用是基于两个库和工程化环境,一个库是react.js,一个库是react-dom.js,工程化环境是babel
- react.js --> react的核心逻辑库
- react-dom.js --> react渲染逻辑库
- babel --> 将jsx语法转为浏览器可用语法, 实际上jsx仅仅是React.createElement的语法糖,用来生成虚拟DOM,详细见官网
- 对于一直使用vue的我们来说, react使用的缺点有:
- 使用很不爽,需要配置一大堆的环境配置才可以使用
- 没有唯一的引用源,太麻烦了
- 但是react优点也很明显:
- 使用react时,就能明显感受到react的核心逻辑
- 体现了react的分工明确、自由组合的特点
- 对于js的深度用户,使用很符合口味
3. 深入渲染模式
以 "todolist" 为目标,以vue和react两种技术同时实现,效果图如下(突出一个简陋,不喜勿喷):
3.1 vue版本思路
- 响应式数据
- currentTask:绑定在输入框上,表示输入的任务数据
- tasks:存储所有的任务数据
- 计算属性:
- taskings:待完成的任务数据
- taskeds:已完成的任务数据
- 方法:
- getPageHeight():获取待完成列表的高度
- addTask():新增任务进入待完成列表
- doComplete(id):将待完成状态的任务改为已完成状态
- doRedo(id):将已完成状态的任务改为待完成状态
- doDelete(id):删除指定的任务
3.2 react实现过程
3.2.1 定义数据
let tasks = [
{
id: "2",
text: "待完成示例",
done: false,
},
{
id: "1",
text: "已完成示例",
done: true,
},
];
let currentTask = "";
let doingRef = React.createRef(); // 显式声明元素引用
**总结:**其中注意关于元素引用,vue中不需要额外声明变量,而react需要显式声明变量,即let doingRef = React.createRef()
。
3.2.2 定义方法
let getPageHeight = () => { // 计算元素的高度
alert(window.getComputedStyle(doingRef.current).height);
};
let addTask = () => { // 新增任务
if (!currentTask) return;
tasks.unshift({
id: Date.now(),
text: currentTask,
done: false,
});
currentTask = "";
render(tasks);
};
let doComplete = (id) => { // 设置任务已完成状态
tasks.forEach((task) => {
if (task.id == id) task.done = true;
});
render(tasks);
};
let doRedo = (id) => { // 设置任务待完成状态
tasks.forEach((task) => {
if (task.id == id) task.done = false;
});
render(tasks);
};
let doDelete = (id) => { // 删除任务
tasks.forEach((task, index) => {
if (task.id == id) tasks.splice(index, 1);
});
render(tasks);
};
总结:
- 每一个任务完成后都要手动调用一下render函数,即进行都会渲染页面;而vue是不需要管调用时机的
- 通过ref调用元素时,需要主要使用其中的 current属性;而vue中是直接调用的
3.2.3 定义表单行为
let handleChange = (e) => {
currentTask = e.target.value;
render(tasks);
};
总结:
- 每次表单输入时,都要手动显式调用事件函数进行数据状态改变,并重新渲染页面;而vue中不需要,通过v-model实现了数据绑定以及数据响应式。
3.2.4 定义页面内容
function render(tasks) {
let rootElement = (
<>
<div className="add">
<input
type="text"
value={currentTask}
onChange={(e) => handleChange(e)}
></input>
<button onClick={addTask}>新增</button>
<button onClick={getPageHeight}>获取页面高度</button>
</div>
<div className="list-show" ref={doingRef}>
<h2>待完成</h2>
<ul>
{tasks
.filter((task) => !task.done)
.map((task) => (
<li key={task.id}>
<span>{task.text}</span>
<div className="operation">
<button onClick={(e) => doDelete(task.id)}>删除</button>
<button onClick={(e) => doComplete(task.id)}>done</button>
</div>
</li>
))}
</ul>
</div>
<div className="list-show">
<h2>已完成</h2>
<ul>
{tasks
.filter((task) => task.done)
.map((task) => (
<li key={task.id}>
<span>{task.text}</span>
<div className="operation">
<button onClick={(e) => doDelete(task.id)}>删除</button>
<button onClick={(e) => doRedo(task.id)}>undone</button>
</div>
</li>
))}
</ul>
</div>
</>
);
ReactDOM.render(rootElement, document.getElementById("root"));
}
总结:
- 每次数据变化后,都要手动重新执行下页面渲染;而vue中只需要负责数据变化即可,这一点喜欢vue的实现逻辑
- 类名定义:react中使用className,和html中不一致;而vue中就直接是class
- 使用变量和表达式: react使用单大括号; 而vue中使用双大括号
- 事件定义:react中使用"on+事件名"(事件名首字母大写)的方式来声明;而vue通过
v-on:事件名
或者@事件名
的方式,两者有区别,但使用上差不多;但是react中的this需要手动绑定 - 条件渲染:react可以通过js三元表达式的写法;而vue使用的是v-if/v-else-if/v-else的指令实现;用起来js的写法更贴近使用习惯;
- 列表渲染:react可以通过js数组方法的写法;而vue使用的是v-for指令实现;两者都需要使用key来指定唯一标识,估计react也是用来做元素diff操作的;
4. 总结
这是第一次全方面对比学习react,主要从基础和组件两方面出发学习react的使用,但发现基础方面就有很大的差别,即渲染方面,因此打算分两篇来整理学习,react学习这就结束第一过程——dom渲染的对比分析,从中学习到了几点:
- 在使用时就感受到组件是函数或者对象的存在,感觉更接近JavaScript,而vue更像是一门新的语言;
- react由于jsx语法的存在必须基于babel来解析,所以需要很多前期准备,当然官方提供了脚手架,还没学习——
create-react-app
- react的渲染需要每次手动调用函数, 有点烦;而vue可以自动实现,这一点很爽的。
- 最后一点:果然是各有各的好,看自己的使用习惯了!!!
后续将继续学习组件部分,敬请期待哟~~~
转载自:https://juejin.cn/post/7138990970317570055