您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

Vue 转 React 指南,看这篇文章就够了

时间:2021-04-13 10:04:01  来源:今日头条  作者:Python小叮当

为什么要从 Vue 转到 React,这篇文章为什么我们放弃了 Vue?不过对于大多数人来说,用 Vue 还是 React 不是自己说了算,多学一门技术不是坏处,而且 React 被大厂大量使用,要进入大厂也是必备的技能,笔者原先使用 Vue,由于 React 相关概念更加简单,只要会 js 就行,转到 React 只花了几天时间(已经回不去了~)。本文写给想从 Vue 转到 React 的同学,假设读者有一定的 Vue 基础。

JSX

先介绍 React 唯一的一个语法糖:JSX。

<div class='box' id='content'>
  <div class='title'>Hello</div>
  <button>Click</button>
</div>

上面的 DOM 结构可以看出,要每个标签只有 3 个信息:标签名、属性、子元素,所以上面等同于下面的 JSON 结构:

{
  tag: 'div',
  attrs: { className: 'box', id: 'content'},
  children: [
    {
      tag: 'div',
      arrts: { className: 'title' },
      children: ['Hello']
    },
    {
      tag: 'button',
      attrs: null,
      children: ['Click']
    }
  ]
}

当你写下这个 React 组件是:

import React from 'react';

function MyComponent(props) {
    return <div>{props.hello}</div>
}

最终会被自动工具翻译成:

import React from 'react';

function MyComponent(props) {
    return React.createElement('div', null, props.hello);
}

理解 JSX 语法并不困难,简单记住一句话,遇到 {} 符号内部解析为 JS 代码,遇到成对的 <> 符号内部解析为 html 代码。React 就是通过这个小小语法糖,实现在 JS 里面写 HTML,可能有小伙伴会说 HTML 与 JS 分离不是更好吗?责职分明,混合只会更乱。但当你体验到代码自动提示,自动检查,以及调试时精确定位到一行代码的好处时,就清楚 React 和 Vue 的差距了。

语法糖转换

习惯 Vue 的同学都知道很多语法糖,比如 v-if、v-for、v-bind、v-on 等,相比 Vue,React 只有一个语法糖,那就是 jsx/tsx。v-if 这些功能在 React 上都是通过原生 JAVAscript 实现的,慢慢你会发现,其实你学的不是 React,而是 Javascipt,React 赋予你通过 js 完整控制组件的能力,这部分明显比 Vue 的语法糖更加灵活,糖太多容易引来虫子(Bug)。

 

v-if 条件渲染

vue 中写法是这样:

<template>
  <div>
    <h1 v-if="awesome1">Vue is awesome!</h1>
    <h1 v-else>else</h1>
    <h1 v-if="awesome2">Oh no</h1>
  </div>
</template>

<script>
module.exports = {
  data: function() {
    return {
      awesome1: true,
      awesome2: false,
    }
  }
}
</script>

在 React 函数组件中只需这样:

import React, { useState } from 'react';

function Index() {
  const [awesome1, setAwesome1] = useState(true);
  const [awesome2, setAwesome2] = useState(false);

  return (
    <div>
      {awesome1 ? <h1>React is awesome!</h1> : <h1>Oh no</h1>}
      {awesome2 && <h1>React is awesome!</h1>}
    </div>
  );
}

export default Index;

只需使用 js 三目运算符语法即可完成条件渲染的功能。或者使用 && 逻辑,记住下面一句话就能过理解了:

遇到 {} 符号内部解析为 JS 代码,遇到成对的 <> 符号内部解析为 HTML 代码

v-for 列表渲染

Vue 中写法:

<template>
  <ul id="array-rendering">
    <li v-for="item in items">
      {{ item.message }}
    </li>
  </ul>
</template>

<script>
module.exports = {
  data() {
    return {
      items: [{ message: 'Foo' }, { message: 'Bar' }]
    }
  }
}
</script>

React 写法:

import React, { useState } from 'react';

function Index() {
  const [items, setItems] = useState([{ message: 'Foo' }, { message: 'Bar' }]);

  return (
    <ul id="array-rendering">
      {items.map((item, id) => <li key={id}>{item.message}</li>)}
    </ul>
  );
}

export default Index;

React 通过 js 的数组语法 map,将数据对象映射为 DOM 对象。只需学会 js,无需记住各种指令,如果要做列表过滤,直接使用 items.filter(...).map(...) 链式调用即可,语法上更加灵活,如果为了提高渲染性能,使用 useMemo 进行优化即可,类似 Vue 的 computed。

v-model

Vue 中 v-model 是一个数据绑定语法糖,本质上还是单向数据流,下面的子组件通过 update:title 同步 title 参数。

App.component('my-component', {
  props: {
    title: String
  },
  emits: ['update:title'],
  template: `
    <input
      type="text"
      :value="title"
      @input="$emit('update:title', $event.target.value)">
  `
})

React 写法较为简单,不需要像 Vue 一样填鸭代码,记住各种规则,所有数据和事件通过 props 传递就行了:

import React from 'react';

interface Props {
  title: string;
  onUpdateTitle: (title: string) => void;
}

function MyComponent(props: Props) {
  return <input
    type='text'
    value={props.title}
    onInput={e => props.onUpdateTitle(e.target.value)}
  />
}

更加容易整合 typescript 实现类型推断,需要的逻辑都由 JS 完成,无需记住各种指令、使用方法,参数命名规则。

事件处理

Vue 中写法

<template>
  <div id="inline-handler">
    <button @click="say('hi')">Say hi</button>
    <button @click="say('what')">Say what</button>
  </div>
</template>

<script>
module.exports = {
  methods: {
    say(message) {
      alert(message)
    }
  }
}
</script>

React 写法:

import React, { useState } from 'react';

function Index() {
  const onClick = (message) => () => alert(message);

  return (
    <div id="inline-handler">
      <button onClick={onClick('hi')}>Say hi</button>
      <button onClick={onClick('what')}>Say what</button>
    </div>
  );
}

export default Index;

这里用了函数柯里化,一般事件处理这样就行了:

import React from 'react';

function Index() {
  const onClick = () => alert('hi');

  return (
    <div id="inline-handler">
      <button onClick={onClick}>Say hi</button>
    </div>
  );
}

export default Index;

如果需要优化缓存事件处理函数,使用 useCallback 即可。可以看到 Vue 中的事件触发 this.$emit('click') 或者父组件中的代码 v-on="say('hi')" 都使用了字符串的写法,这样非常不利于类型推断,不利于代码重构。React 的函数写法或者 class 写法都直接使用 js 语法,没有额外的东西,相比 Vue 更容易通过 IDE 进行重构优化。React 中无论方法还是变量,都是采用驼峰命名法,也可以自由定制,Vue 中必须混合小写中隔线、驼峰、字符串组合,不利于统一代码规范。

插槽

Vue 中写法:

<template>
  <button class="btn-primary">
    <slot></slot>
  </button>
</template>

<script>
module.exports = {
  methods: {}
}
</script>

React 写法:

import React from 'react';

function Index() {
  return (
    <button classNames="btn-primary">
      {props.children}
    </button>
  );
}

export default Index;

React 的插槽写法没有 Vue 那么复杂,也没有“备用内容”、“具名插槽”、“渲染作用域”、“作用域插槽”、“动态插槽名”,这些概念和特殊情况的处理,一切通过 JS 逻辑搞定就行了,怎么方便怎么来,比如备用内容的实现:

import React from 'react';

function Index() {
  // 默认情况下使用 Summit 作为按钮文字
  return (
    <button classNames="btn-primary">
      {props.children === null ? 'Summit' : props.children}
    </button>
  );
}

export default Index;

样式 & 属性

这部分 Vue 的写法实在是太麻烦了。。。每次我都要查查文档具体怎么用,对象语法、数组语法、内联样式,要记住的有点多,Vue 动态修改样式的写法:

<template>
  <div
    class="static"
    :class="{ active: isActive, 'text-danger': hasError }"
  ></div>
</template>

<script>
module.exports = {
  data() {
    return {
      isActive: true,
      hasError: false
    }
  }
}
</script>

React 写法:

import React, { useState } from 'react';

function Index() {
  const [isActive, setIsActive] = useState(true);
  const [hasError, setHasError] = useState(false);

  return (
    <div
      classNames={`static ${isActive ? 'active':'} ${hasError? 'text-danger':''}`}
    ></div>
  );
}

export default Index;

React 里面直接采用 JS 的模板字符串语法,如果样式太多,可以使用 classnames 这个 npm 包,优雅传递各种状态,使用非常简单:

classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'

状态管理

Vue 的状态管理官方推荐使用 Vuex 也可采用 Redux。

Vue 转 React 指南,看这篇文章就够了

 

引用官方文档一段话:

如果你是来自 React 的开发者,可能会对 Vuex 和 Redux 间的差异表示关注,Redux 是 React 生态环境中最流行的 Flux 实现。Redux 事实上无法感知视图层,所以它能够轻松地通过一些简单绑定和 Vue 一起使用。Vuex 区别在于它是一个专门为 Vue 应用所设计。这使得它能够更好地和 Vue 进行整合,同时提供简洁的 API 和更好的开发体验。

这段话其实暴露了 Vuex 的一个缺陷,它和 Vue 强绑定,无法独立存在,这种一些项目升级和迁移时会有很大的麻烦。Redux 作为 React 的状态管理方案之一其实不依赖于 React。

React 周边的状态管理方案特别多,如 Redux、Mobx、Recoil 等,各有各的亮点,其中使用最多的应该是 Redux。

Vue 转 React 指南,看这篇文章就够了

 

Redux 周边生态也很丰富,可以更加下图选择不同的方案:

Vue 转 React 指南,看这篇文章就够了

 

  • redux-thunk
  • redux-promise
  • redux-saga
  • redux-observable

由于这部分代码较多,不详细写,不过如果你熟悉 Vuex 的概念,转到 Redux 应该不难。Vuex + axIOS 的做法和 Redux + redux-thunk 的写法类似,不过现在 redux-saga 的方案被更多复杂项目采用,其中很重要的原因是 saga 的概念编写异步代码非常优雅,且能够很好地解决静态问题(如果采用 Vuex + axios 的写法会异常复杂、冗长),高度定制。

如果你要迁移 Vue 到 React,建议采用的方案是 Redux + saga,saga 的概念不是那么容易懂,学习需要一些时间,但当你学会的时候就会明白这种写法比直接用 Promise 好太多了。

生命周期

Vue 的生命周期这里不再重复,查询官方文档即可,React 生命周期如图:

Vue 转 React 指南,看这篇文章就够了

 

图片可以在这里找到。一般情况下 class 写法主要用到 componentDidMount 和 componentWillUnmount 钩子,React 的函数写法下可以用 useEffect 的执行函数和清理函数去模拟 mount 和 unmount 过程:

import React, { useRef, useEffect } from 'react';

function Index() {
  const ref = useRef(null);
  
  useEffect(() => {
    console.log('mounted');

    return () => {
      console.log('will unmount');
    };
  }, []);

  return <input ref={ref}/>
}

export default Index;

useEffect 的原理这里不多说,可以看看相关文章:轻松学会 React 钩子:以 useEffect() 为例。其实从 React hook 中可以看到,React 在慢慢淡化生命周期的概念,减少自己对用户代码的侵入,将更多控制权交给用户。

原生 DOM 操作

这部分 Vue 和 React 都是采用 ref 写法,Vue:

<template>
  <input ref="input" />
</template>

<script>
module.exports = {
  methods: {
    focusInput() {
      this.$refs.input.focus()
    }
  },
  mounted() {
    this.focusInput()
  }
}
</script>

React 写法:

import React, { useRef, useEffect } from 'react';

function Index() {
  const ref = useRef(null);
  
  useEffect(() => {
    ref.current?.focuse();
  }, []);

  return <input ref={ref}/>
}

export default Index;

useEffect 是 React hook,在依赖数组为空的时候效果类似 componentDidMount 的生命周期函数(类似 Vue 的 mounted)。此外 useRef 不止用在这里,也可以挂载一些其他的东东,实现一些复杂操作,比如 previousValue 和对象属性等。



Tags:React   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
React 简介 React 基本使用<div id="test"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js...【详细内容】
2021-11-30  Tags: React  点击:(19)  评论:(0)  加入收藏
什么是vuevue是尤雨溪在2014年发布的一个渐进式的js框架,它有着双向绑定的特性,同时它的虚拟dom技术让性能得到大大提升。最重要的就是它是渐进式的应用,你可以在你的项目中逐...【详细内容】
2021-09-22  Tags: React  点击:(77)  评论:(0)  加入收藏
每个前端开发人员都听说过三个用于构建 Web 应用程序的框架:React、Vue.js和Angular。React 是一个 UI 库,Angular 是一个成熟的前端框架,而 Vue.js 是一个渐进式框架。它们几...【详细内容】
2021-08-25  Tags: React  点击:(96)  评论:(0)  加入收藏
领域驱动,各自只管各自的模块,顶层再来进行组装和分配...【详细内容】
2021-06-25  Tags: React  点击:(92)  评论:(0)  加入收藏
public class SReactorSThread { private Selector selector; private ServerSocketChannel serverSocketChannel; private int PORT = 6666; public SReactorS...【详细内容】
2021-05-25  Tags: React  点击:(779)  评论:(0)  加入收藏
为什么要从 Vue 转到 React,这篇文章为什么我们放弃了 Vue?不过对于大多数人来说,用 Vue 还是 React 不是自己说了算,多学一门技术不是坏处,而且 React 被大厂大量使用,要进入大厂...【详细内容】
2021-04-13  Tags: React  点击:(264)  评论:(0)  加入收藏
前言 同步I/O模型通常用于实现Reactor模式 异步I/O模型则用于实现Proactor模式 最后我们会使用同步I/O方式模拟出Proactor模式一、Reactor模式 Reactor 释义“反应堆”,是一...【详细内容】
2020-12-24  Tags: React  点击:(205)  评论:(0)  加入收藏
在我回答之前,如果你读这篇文章是为了选择一个“要学习”的框架,不要这样做。还是读读这篇文章吧。如果你想选择一个框架来使用(在一个实际的项目中),你可以继续:)“更好”是...【详细内容】
2020-11-03  Tags: React  点击:(88)  评论:(0)  加入收藏
在这篇文章中,我将分享我对React Hooks的观点,正如这篇文章的标题所暗示的那样,我不是一个忠实的粉丝。让我们来分析一下React官方的文档中描述的放弃类而使用钩子的动机。动...【详细内容】
2020-11-03  Tags: React  点击:(80)  评论:(0)  加入收藏
Netty 怎么切换三种 I/O 模式什么是经典的三种 I/O 模式?生活场景:当我们去饭店吃饭时:&bull; 食堂排队打饭模式:排队在窗口,打好才走;&bull; 点单、等待被叫模式:等待被叫,好了自己...【详细内容】
2020-10-13  Tags: React  点击:(101)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的&emsp;&emsp;程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条