Getting Started Guide to Converting Vue to React

Getting Started Guide to Converting Vue to React

Because the new company uses the react technology stack, including a series of solutions such as Umi, Dva, and Ant-design. After getting a little familiar with it, I realized that although there are some differences, they are still very different. Below I will make a simple comparison between two popular frameworks, react16 & vue2 (actively learning vue3), in terms of design, writing method, API, life cycle and popular ecology:

design

react vue illustrate
position js library for building user interfaces Progressive Framework React focuses on library, while Vue focuses on framework
Rendering setState updates the state value to re-render the view Responsive data rendering, the view corresponding to the modified responsive data is also rendered React needs to consider when to setState and when to render; Vue only needs to consider modifying data
Writing method jsx template React is functional, all in js; Vue distinguishes between template, script, style, provides syntax sugar, and is compiled using vue-loader

Component Communication

react: Strictly one-way data flow

  • Downward props
  • Up props func
  • Multi-level context transfer

Follow the principle that everything can be props, onChange/setState()

Vue: One-way data flow

  • props down
  • events up (subscribe to publish)
  • Multi-level passing of $attrs and $listeners

There are also various ways to get component instances (VueComponent), such as: $refs, $parent, $children; get parent or child components recursively, such as: findComponentUpward, findComponentsUpward; high-level components: provide/reject, dispatch/broadcast

react vue illustrate
Subcomponent data transfer props props All are declarative
Component state machine state data To manage the status of components, react uses setState to change, vue directly assigns values, and uses $set for new properties; vue uses the function closure feature to ensure the independence of component data, and react is a function.

life cycle

react vue illustrate
Data initialization constructor created
Mount componentDidMount mounted DOM node has been generated
renew componentDidUpdate updated react: After the component is updated, react will only enter componentDidmount after the first successful initialization, and will enter this life cycle after each re-rendering. Here you can get prevProps and prevState, that is, props and state before the update. vue: Called after the virtual DOM is re-rendered and updated due to data changes
uninstall componentWillUnmount destroyed Destroy Event

Event Handling

react

  • React events are named in camelCase instead of lowercase.
  • When using JSX syntax, you need to pass a function as the event handler, not a string.
  • The default behavior cannot be prevented by returning false. You must explicitly use preventDefault
  • Cannot be uninstalled on non-Element tags, otherwise it will be passed down as props
function Form() {
  function handleSubmit(e) {
    e.preventDefault();
    console.log('You clicked submit.');
  }
  return (
    <form onSubmit={handleSubmit}>
      <button type="submit">Submit</button>
    </form>
  );
}

vue

When used on normal elements, only native DOM events can be listened. When used on a custom element component, you can also listen to custom events triggered by child components

//Native event <form v-on:submit.prevent="onSubmit"></form>
//Custom event <my-component @my-event="handleThis(123, $event)"></my-component>

Vue event modifiers:

  • .stop - Calls event.stopPropagation().
  • .prevent - calls event.preventDefault().
  • .capture - Use capture mode when adding event listeners.
  • .self - The callback will only fire if the event was fired from the element the listener is bound to.
  • .native - listens to native events on the component's root element.
  • .once - triggers the callback only once.
  • .left - (2.2.0) Fires only when the left mouse button is clicked.
  • .right - (2.2.0) Fires only when the right mouse button is clicked.
  • .middle - (2.2.0) Fires only when the middle mouse button is clicked.
  • .passive - (2.3.0) Adds a listener in { passive: true } mode

class and style

class

react

render() {
  let className = 'menu';
  if (this.props.isActive) {
    className += 'menu-active';
  }
  return <span className={className}>Menu</span>
}

vue

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

 
<div :class="[{ active: isActive }, errorClass]"></div>

style

react

<div style={{color: 'red', fontWeight: 'bold'}} />

vue

<div :style="[baseStyles, overridingStyles]"></div>

When styling a component, you can declare a scoped tag on the style tag as a component style isolation annotation, such as: <style lang="sass" scoped></style>. When packaging, the styles are actually added with a unique hash value to avoid CSS pollution between components

Conditional Rendering

  • react: jsx expression, && or ternary expression; return false means no rendering
  • vue: The expression returns true to be rendered, multiple v-else-if and v-else can be nested

List Rendering

react: Using .map, the key of an element is preferably a unique string that the element has in the list

<ul>
  {props.posts.map((post) =>
    <li key={post.id}>
      {post.title}
    </li>
  )}
</ul>

vue: To give Vue a hint so that it can keep track of the identity of each node and thus reuse and reorder existing elements, you need to provide a unique key attribute for each item.

<li v-for="item in items" :key="item.message">
  {{ item.message }}
</li>

Component Nesting

react

Default Slots

<div className={'FancyBorder FancyBorder-' + props.color}>
  {props.children}
</div>

Named Slots

<div className="SplitPane">
  <div className="SplitPane-left">
    {props.left}
  </div>
  <div className="SplitPane-right">
    {props.right}
  </div>
</div>

<SplitPane left={<Contacts />} right={<Chat />} />

vue

Default Slots

<main>
  <slot></slot>
</main>

Named Slots

<header>
  <slot name="header"></slot>
</header>

Get the DOM

react: Manage focus, text selection, or media playback. Triggers a forced animation. Integrate third-party DOM libraries

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

vue: used to register reference information for elements or subcomponents

<div ref="div">hello</div>

this.$refs.p.offsetHeight

Document structure

Umi

├── config # umi configuration, including routing, building and other configurations│ ├── config.ts # Project configuration.umirc.ts has a higher priority, and this method requires deleting .umirc.ts
│ ├── routes.ts # Routing configuration│ ├── defaultSettings.ts # System configuration│ └── proxy.ts # Proxy configuration├── mock # All js and ts files in this directory will be parsed as mock files├── public # All files in this directory will be copied to the output path. Even if hash is configured, it will not be added├── src
│ ├── assets # Local static resources│ ├── components # Business common components│ ├── e2e # Integration test cases│ ├── layouts # Global layout file for conventional routing│ ├── models # Global dva model
│ ├── pages # All routing components are stored here│ │ └── document.ejs # It is agreed that if this file exists, it will be used as the default template│ ├── services # Backend interface services│ ├── utils # Tool library│ ├── locales # International resources│ ├── global.less # Global style│ ├── global.ts # Global JS
│ └── app.ts # Runtime configuration file, such as modifying routes, modifying render methods, etc. ├── README.md
└── package.json

vue_cli

├── mock # Project mock simulation data├── public # Static resources│ └── index.html # HTML template├── src # Source code│ ├── api # All requests│ ├── assets # Theme fonts and other static resources│ ├── components # Global public components│ ├── directive # Global directive│ ├── filters # Global filter
│ ├── layout # Global layout
│ ├── router # Routing│ ├── store # Global store management│ ├── utils # Global public methods│ ├── views # views of all pages│ ├── App.vue # Entry page│ └── main.js # Entry file loading component initialization, etc.├── tests # Tests├── vue.config.js # vue-cli configuration such as proxy, compressed images└── package.json # package.json

routing

Dynamic Routing & Routing Parameters

react-router

  • history.push(/list?id=${id})
  • history.push({pathname: '/list', query: {id}})
  • history.push(/list/id=${id})
  • history.push({pathname: '/list', params: {id}})

Get props.match.query / props.match.params

vue-router

  • this.$router.push({path: '/list', query: {id}})
  • this.$router.push({path: '/list', params: {id}})

Get this.$router.query / this.$router.params

Nested Routes

-react

{
  path: '/',
  component: '@/layouts/index',
  routes: [
    { path: '/list', component: 'list' },
    { path: '/admin', component: 'admin' },
  ],
}

<div style={{ padding: 20 }}>{ props.children }</div>

Rendering child routes using props.children

vue-router

{
  path: '/user/:id',
  component: User,
  children: [
    {
      path: 'profile',
      component: UserProfile
    },
    {
      path: 'posts',
      component: UserPosts
    }
  ]
}

<div id="app">
  <router-view></router-view>
</div>

Use vue native components/<router-view/> components to render sub-routes

Route Jump

umi

<NavLink exact to="/profile" activeClassName="selected">Profile</NavLink>
history.push(`/list?id=${id}`)

vue

<router-link to="/about">About</router-link>
this.$router.push({path: '/list', query: {id}})

Routing guard (login verification, special routing processing)

  • Umi
  • vue-router

Global routing guard

Global pre-guard: router.beforeEach

 const router = new VueRouter({ ... })
 router.beforeEach((to, from, next) => {
   // ...
 })

Global post-guard: router.beforeEach

 router.afterEach((to, from) => {
   // ...
 })

State Management

A state manager is needed when multiple views depend on the same state or when behaviors from different views need to change the same state.

dva vuex illustrate
Modules namespace modules All states of the application will be concentrated into a relatively large object, and the store object may become quite bloated
Single State Tree state state The only data source
Submit state machine reducer mutations Used to handle synchronous operations, the only place where state can be modified
Handling asynchronous operations effects action Call the submit state machine to change the state tree

use

dva: model connect UI

// new model: models/products.js
export default {
  namespace: 'products',
  state: [],
  reducers: {
    'delete'(state, { payload: id }) {
      return state.filter(item => item.id !== id);
    },
  },
};
//connect model
export default connect(({ products }) => ({
  products,
}))(Products);

//dispatch model reduce
dispatch model reduce({
  type: 'products/delete',
  payload: id,
})

If there are asynchronous operations, such as ajax requests, dispath model effects, and then effects call model reduce
vuex

// new module
const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations:
    increment(state) {
      state.count++
    }
  },
  actions: {
    increment(context) {
      context.commit('increment')
    }
  }
})
//bind UI
<input v-model="$store.state[modelesName].name"/>
//commit module mutation 
store.commit('increment')

If there are asynchronous operations, such as ajax requests, dispath module actions, and then actions call module mutations

store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

This is the end of this article about the Getting Started Guide to Converting Vue to React. For more relevant content about Converting Vue to React, please search for previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed explanation of project preparation for switching from react to vue development
  • How to write commands to convert React components to Vue components

<<:  Example code for implementing equal width layout in multiple ways using CSS

>>:  Docker deploys mysql remote connection to solve 2003 problems

Recommend

Installation process of CentOS8 Linux 8.0.1905 (illustration)

As of now, the latest version of CentOS is CentOS...

Table paging function implemented by Vue2.0+ElementUI+PageHelper

Preface I have been working on some front-end pro...

Analysis of MySQL cumulative aggregation principle and usage examples

This article uses examples to illustrate the prin...

Simple principles for web page layout design

This article summarizes some simple principles of...

CSS perfectly solves the problem of front-end image deformation

I saw an article in Toutiao IT School that CSS pe...

How to block IP and IP range in Nginx

Written in front Nginx is not just a reverse prox...

Vue sample code for easily implementing virtual scrolling

Table of contents Preface Rolling principle accom...

Solution to 2059 error when connecting Navicat to MySQL

Recently, when I was learning Django, I needed to...

Vue implements a simple shopping cart example

This article shares the specific code of Vue to i...

JavaScript pie chart example

Drawing EffectsImplementation Code JavaScript var...

Design theory: people-oriented design concept

<br />When thoughts were divided into East a...

How to Install Oracle Java 14 on Ubuntu Linux

Recently, Oracle announced the public availabilit...

A comprehensive analysis of what Nginx can do

Preface This article only focuses on what Nginx c...

Steps to create a Vite project

Table of contents Preface What does yarn create d...