Although some of my articles are related to vUE, they are all summarized in my student days. The funny thing is that I’ve been on the React stack since I started working. However, I have to review VUE recently due to work requirements. It’s just tools, but after all, it’s hard to get out of your comfort zone and accept something unfamiliar. Finally, I will combine vUE and React diff to review the key knowledge of VUE.

Start with the entry functions and app components for both

react

import React from "react";
import ReactDOM from "react-dom";

const App = () = > {
  return <div>App component</div>;
};

ReactDOM.render(<App />.document.getElementById("root"));
Copy the code

vue

import Vue from "vue";
import App from "./App.vue";


new Vue({
  render: (h) = > h(App),
}).$mount("#app");
Copy the code

App Component (.vue file type)

<template> <div id="app">app component </div> </template> <script> export default {name: "app",}; </script>Copy the code

Just to be familiar with the contrast, how much difference can you see?

  • 【 Difference 1】 React components are written in JSX mode, while VUE components are written in template mode

    Let’s just say it in a little bit more detail

    • In the React component,<app/>This is either a function or a class (think of app as a variable). Because there are two types in the React component, either class or function. Therefore, these two data structures are imported through import
    • Vue components,<app/>Inside this horn is an object. Because what we usually export in a component is an option object, but. The option object that we pass out is going to be a little bit more than what we export ourselves. Print it out and have a look at it [more hooks, render functions and other properties]
  • The React component is essentially a function, whereas the VUE component is essentially a vue instance

    To be even more specific, the intended product of a component is a VNode.

    React:

    The first thing to remember is that JSX is handled by Babel during the packaging process as a call to the createElement function (before React V17). JSX in React is equivalent to a Vnode.

    The react component types are both easy to access from JSX.

    1. Function, which itself returns a JSX
    2. Class, and the return value of the render method on the instantiated object is also a JSX

    The function type

    const App = () = > {
      return <div>App component</div>;
    };
    Copy the code

    The class type

    class App extends React.Component {
      render() {
        return <div>app</div>; }}Copy the code

    Take a look at the React VNode

    import React from "react";
    import ReactDOM from "react-dom";
    
    const Test01 = () = > {
      return <div>test01</div>;
    };
    
    const Test02 = () = > {
      return <div>test02</div>;
    };
    
    const App = () = > {
      return (
        <>
          <Test01 />
          <Test02 />
        </>
      );
    };
    
    console.log(App());
    ReactDOM.render(<App />.document.getElementById("root"));
    
    Copy the code

But what does it look like in VUE?

Start by reading the documentation, which explains that each VUE component is essentially a VUE instance. Let’s verify this first, print out the root instance, and see what the data structure looks like.

import Vue from "vue";
import App from "./App.vue";

console.log(
  new Vue({
    render: (h) = > h(App),
  }).$mount("#app"));Copy the code

The output

You can see that the child component is indeed a Vue instance (or VueComponent instance, to be exact)

So I have some questions?

  1. How does a child component in a VUE become a VUE instance?
  2. How do Vue instances produce VNodes?

I think it’s similar to the react idea. React wants to get a VNode. If it’s a functional component, it executes function (class components instantiate first and then call the render method on the instance). The vue should also be instantiated at some point in time by passing in a subcomponent option object.

As to how it generates a VNode, first take a look at the child component instance output above. It has a VNode property. How did that happen?

The first thing to know is that in the.vue component the template will eventually compile into a render function. This render function is injected into the option object exported from script (see the vUE exported component option object I printed above).

Take a look at a simple render function provided by the official documentation:

render: function (createElement) {
  return createElement('h1'.this.blogTitle)
}
Copy the code

Look at this createElement and you’ll be familiar with it. It’s similar to JSX. React provides a createElement function that produces a Vnode. How about vue?

Document Introduction:

Here’s the answer: The createElement function in Vue is also a vNode, so there’s no question here. React is similar to react

Let’s look at the differences in daily development

Develop core – component communications

Component communication is the most basic and important part of daily development. What are the differences between vUE and React communication?

The first is father-son correspondence

There is no difference between father and son. All in the form of props to pass data to the underlying components

react

  1. If it is a functional component, the parent component properties are passed to the child component as function parameters when the child component VNode is acquired. Therefore, it can be directly obtained from the props of the sub-component
  2. If it is a class component, the parent component property is passed to the child component as the constructor parameter type when the child component vNode is obtained, so that the data is put into the props property of the child component instance and can be passed directlyThis component instance.propsTo obtain
const Test01 = (props) = > {
  return <div>{props.name}</div>;
};

const App = () = > {
  return (
    <>
      <Test01 name="zs" />
    </>
  );
};
Copy the code

Vue (here I mixed JSX and template syntax, temporarily only write use level [shame 💧])

// Parent <template> <div id="app"> App <Test01 :name="name" /> </div> </template> <script> import Test01 from "./components/Test01"; export default { name: "App", data: function () { return { name: "zs", }; }, components: { Test01, }, }; </script>Copy the code

Child components

/* eslint-disable no-unused-vars */
export default {
  name: "test01".props: {
    name: {
      type: String,}},render: function (h) {
    return <div>{test01 component enclosing the name}</div>; }};Copy the code

The second is parent-child communication

There's a difference between react and Vue

A common scenario for child and parent communication is that a child component wants to modify the state that the parent component sends to it. However, the react and Vue data flow ideas are one-way to ensure the clarity of the data flow. This means that a subcomponent cannot modify props data within it

So what to do?

In fact, it is also very simple, mainly who is the state who will have access to management

  • React: When you pass a state to a child component, you also need to pass the method to change the state to the child component

  • For VUE: Publish subscribe, take the idea of a custom event. The child component fires a custom event, and the parent component listens and performs state change logic

code demo

react

/ / child component
const Test01 = ({ name, updataName }) = > {
  return (
    <>
      <div>
        {name}
        <button
          onClick={()= >{updataName(" child component "); }} > Modify name</button>
      </div>
    </>
  );
};

/ / the parent component
const App = () = > {
  const [name, updataName] = useState("Parent component initial State");
  return (
    <>
      <Test01 name={name} updataName={updataName} />
    </>
  );
};
Copy the code

vue

Child components

/* eslint-disable no-unused-vars */
export default {
  name: "test01".props: {
    name: {
      type: String,}},render: function (h) {
    return (
      <div>{test01 component enclosing the name}<button onClick={()= >This.$emit("updataData", "child component controlled ")}> Modify the parent component state</button>
      </div>); }};Copy the code

The parent component

<template> <div id="app"> App component <Test01 :name="name" @updatadata ="updataName" /> </div> </template> <script> import Test01 from "./components/Test01"; export default { name: "App", data: function () { return { name: "zs", }; }, methods: { updataName: function (value) { this.name = value; }, }, components: { Test01, }, }; </script>Copy the code

Cross level communication

For cross – level communication

React’s solution is to use Context. The idea, then, is to create and maintain a context in which all components have access to the data in the current context. It can be understood by scope. No matter how deep the nested subscope is, it can find the variables declared at the top of the scope chain

The vUE option object also provides the option properties provide and Inject with similar functionality

vuex vs redux

The idea is the same, both are publish-subscribe based

redux

Redux is relatively simple on its own, but it needs to be used around it in real projects. Such as the react – story, story – saga, etc

Take a look at the basic principles of Redux, diagram

The main code for createStore in Redux

function createStore(reducer,preloadedState){
    let state=preloadedState;
    let listeners = [];

  
    function getState(){
        return state;
    }

    function subscribe(listener){
        listeners.push(listener);
        return () = >{
            let index = listeners.indexOf(listener);
            listeners.splice(index,1); }}function dispatch(action){
        state=reducer(state,action);
        listeners.forEach(l= >l());
        return action;
    }
    dispatch({type:'@@REDUX/INIT'});
    const store = {
        getState,
        subscribe,
        dispatch
    }
    return store;
}
export default createStore;
Copy the code

The React stack is not viable with just one Redux, but with some middleware for peripheral plugins & Redux

The basic idea of redux middleware

First, every piece of middleware is a function. They always revolve around dispatch

A simple middleware script: again based on the Onion model, takes the previous dispatch and returns a new modified dispatch

const middlewareDemo=next= >action= >{
  // Logical processing
}
Copy the code

React-redux implements the main idea

React-redux is a must if you want to use Redux in react projects

The main idea: Use context. By using the repository as a data source for the react application context, its subcomponents can easily consume (mainly getting the dispatch or getState provided by the repository).

Basic idea of Redux-Saga

If you want to use Redux if you want to do asynchronous operations, you will probably use the middleware redux-Saga. I have sorted out the basic idea of its implementation before.

vuex

Vuex feels relatively simple

other

React and Vue are basically the same. I’m not going to do the code demo

  1. For example, using the event bus, simply a publish subscription

  2. Another example is by taking an instance object of the communication target and using it to modify its state

Core modules – Components and their code reuse methods

What are the differences between the methods or ideas provided within the framework for code reuse

react

From mixins to higher-order components, and now functional components

For now, it seems that most of the business is still class components. So the main way to reuse code for class components at this stage is to use higher-order components.

A higher-order component is essentially a function that takes the old component as a parameter and returns the new component as a value. The main thing I feel is similar to the idea of middleware

vue

The way to reuse code in VUE is to use mixins, which extract common logic from two or more components. It is then mixed into related components. Extraction is similar to util method but with many differences.

Take an example: let’s say multiple components need a countdown logic

The specific operation of simple implementation is: first define a number state. The number– operation is then performed in the component mount hook

If reuse is not considered, multiple components need to write a set of such logic code is not only bloated and disgusting to write.

code demo

Before mixins:
/ / test02 components
export default {
  data: () = > {
    return {
      count: 10}; },mounted: function () {
    setInterval(() = > {
      if (this.count > 0) {
        this.count--; }},1000);
  },
  render: function (h) {
    return <div>{this.count}</div>; }};Copy the code

If there is another component that needs the same countdown function, then there is no question. You have to copy it again

After extracting using mixins

The countdown function is removed

/ / the countdown
/* eslint-disable no-unused-vars */
export default {
  data: () = > {
    return {
      count: 10}; },mounted: function () {
    setInterval(() = > {
      if (this.count > 0) {
        this.count--; }},1000); }};Copy the code

The original component

// Component: test02
/* eslint-disable no-unused-vars */
import timer from ".. /common/timer";
export default {
  mixins: [timer],
  data: function () {
    return {
      count: 10}; },render: function (h) {
    return <div>test02:---{this.count}</div>; }};Copy the code

If component test03 also needs this function

/* eslint-disable no-unused-vars */
import timer from ".. /common/timer";
export default {
  mixins: [timer],
  data: function () {
    return {
      count: 20}; },render: function (h) {
    return <div>test03:---{this.count}</div>; }};Copy the code

And because of the merge rule, the initial value of the countdown can also be customized within the component

This is obviously much better

Mixins merge rules

Data: contains data with the same name, mainly component data

Hook: There is a hook function with the same name, both of which are called in a slightly different order, mixed in with the > component

The value is the selection of the reference type (eg: Method) : the property key is the same, and the component data is dominant

Let’s briefly talk about the advantages of VUE compared with React on the design level

Let’s start with the react design shortcomings

When components in react are updated, the application does not know which component needs to diff again to obtain the latest VNode. So you have to start with the whole app, diff from the beginning. This leads to an increase in diFF computations, which may take longer than a single browser frame to complete as the project complexity increases. The page is stuck

Although the architecture was upgraded after React, fiber was released. The large diff task was split and prioritized. Although in effect, it can solve the problem

But on closer inspection, the underlying problem is still there (unnecessary diff computation), but it’s no longer prone to page stutter.

The reason vue doesn’t react is because vue does some optimizations at compile time.

The first thing to know is when a component needs to recalculate a VNode, or as React speak, what causes the component to re-render, or to change its state (props). The same is true in VUE.

First, each state in the component corresponds to a DEP. Dep and Watcher can first be understood as a publish subscription. When data’s attribute triggers set, its corresponding DEP will let its associated Watcher perform update work

That is to say, the graph. When the state of a component changes in the component tree, only the old and new components are diff again, rather than diff all of them like react.