1. The introduction

The Vue 3.0 release caused quite a stir, so let’s take a look at the Function API RFC to see what the Vue team was thinking.

First, the official answers to a few of the most popular questions:

Does Vue 3.0 have break change, just like Python 3 / Angular 2?

No, it is 100% Vue 2.0 compliant and has no plans to scrap any apis at this time (or in the future). An earlier draft attempted to do so, but was withdrawn due to overwhelming user feedback.

Is the final word on Vue 3.0?

No ah, this intensive reading of the draft is RFC (Request For Comments), translated into Chinese is “opinion soliciting draft”, is still asking For everyone’s opinions in oh.

Why is this RFC so complicated?

RFC is written for contributors/maintainers and has a lot of boundary cases and details to consider, so of course it’s a lot more complicated. Of course, Vue itself is very simple to use.

Vue itself is Mutable + Template, which is bound to be a framework that is both simple to use (convention + nature) and complex to implement (parsing + double binding).

This change is a lot like imitating React, why not just use React?

First of all, the Template mechanism is still the same, and second of all, it’s modeled after Hooks instead of React. If you don’t like this change, then you won’t like React.

PS: The person asking this question must not understand React and Vue at the same time. In fact, the two frameworks are quite different now, and will be explained in detail after intensive reading.

The Vue 3.0 Function API is introduced.

Summary of 2.

Basic Demo of Vue function:

<template>
  <div>
    <span>count is {{ count }}</span>
    <span>plusOne is {{ plusOne }}</span>
    <button @click="increment">count++</button>
  </div>
</template>

<script>
import { value, computed, watch, onMounted } from 'vue'

export default {
  setup() {
    // reactive state
    const count = value(0)
    // computed state
    const plusOne = computed(() => count.value + 1)
    // method
    const increment = () => { count.value++ }
    // watch
    watch(() => count.value * 2, val => {
      console.log(`count * 2 is ${val}`)
    })
    // lifecycle
    onMounted(() => {
      console.log(`mounted`)
    })
    // expose bindings on render context
    return {
      count,
      plusOne,
      increment
    }
  }
}
</script>
Copy the code

The entry point for the functional style is the setup function, which offers the following benefits: automatic type derivation and reduced packaging volume.

The return value of the setup function is the variable injected into the page template. We can also return a function that generates properties and modifies them by using the value API:

import { value } from 'vue'

const MyComponent = {
  setup(props) {
    const msg = value('hello')
    const appendName = (a)= > {
      msg.value = `hello ${props.name}`
    }
    return {
      msg,
      appendName
    }
  },
  template: `<div @click="appendName">{{ msg }}</div>`
}
Copy the code

Note that value() returns an object whose true value is accessible through.value.

Why does value() return Wrappers instead of specific values? The reason for this is that Vue uses bidirectional binding, which ensures that the final value is accessed only when the value is accessed as an object. This is similar to the.current rule in the React useRef() API.

Since all values returned by value() are Wrapper values, should we call.value directly to the template? The answer is no, just use it, the template will Unwrapping automatically:

const MyComponent = {
  setup() {
    return {
      count: value(0)}},template: `<button @click="count++">{{ count }}</button>`
}
Copy the code

Next are Hooks. Here is an example of using Hooks to get the real-time position of the mouse:

function useMouse() {
  const x = value(0)
  const y = value(0)
  const update = e= > {
    x.value = e.pageX
    y.value = e.pageY
  }
  onMounted((a)= > {
    window.addEventListener('mousemove', update)
  })
  onUnmounted((a)= > {
    window.removeEventListener('mousemove', update)
  })
  return { x, y }
}

// in consuming component
const Component = {
  setup() {
    const { x, y } = useMouse()
    const { z } = useOtherLogic()
    return { x, y, z }
  },
  template: `<div>{{ x }} {{ y }} {{ z }}</div>`
}
Copy the code

As you can see, useMouse encapsulates all the logic associated with “handle mouse position”, which at first glance looks similar to that of React Hooks, but there are two differences:

  1. useMouseChange in functionx,yAfter, it will not be retriggeredsetupThe execution.
  2. x yThe Wrapper instead of the raw values is given, and the values change dynamically.

Another important API is watch, which acts like the useEffect of the React Hooks, but is implemented in a completely different way than when they are called.

The purpose of watch is to listen for changes in certain variables and execute logic. For example, when the ID changes, resend the number:

const MyComponent = {
  props: {
    id: Number
  },
  setup(props) {
    const data = value(null)
    watch((a)= > props.id, async (id) => {
      data.value = await fetchData(id)
    })
  }
}
Copy the code

The reason to watch is because in Vue, the setup Function is executed only once, so unlike React Function Component, the Function is executed again every time the props change. So if you want to do something with the props, They need to be wrapped in the watch.

There are also unwatching, life cycle functions, dependency injection, are some grammar definitions, interested can continue to read the original text, the author will not repeat.

3. The intensive reading

For Vue 3.0 Function API + Hooks and React Function Component + Hooks, the author makes some comparison.

Vue and React logic structure

React Function Component and Hooks are different from Vue3.0 Immutable and Mutable, JSX and Template, but they have the same logic.

const MyComponent = {
  setup(props) {
    const x = value(0)

    const setXRandom = (a)= > {
      x.value = Math.random()
    }

    return { x, setXRandom }
  },
  template: ` {{x}} `
}
Copy the code

Although the setup function is executed only once in Vue and looks completely different from the React function (React is executed every time), Vue separates the render layer (Template) from the data layer (setup), while React is combined.

We can completely isolate the data layer from the rendering layer using React Hooks:

// Setup function similar to vue
function useMyComponentSetup(props) {
  const [x, setX] = useState(0)

  const setXRandom = useCallback((a)= > {
    setX(Math.random())
  }, [setX])

  return { x, setXRandom }
}

// Template function similar to vue
function MyComponent(props: { name: String }) {
  const { x, setXRandom } = useMyComponentSetup(props)

  return (
    <button onClick={setXRandom}>{x}</button>)}Copy the code

This stems from a fundamental difference between JSX and Template. JSX allows templates and JS to be written together, so the data layer and the rendering layer can be written together (or split), but Vue’s Template approach forces the data layer to be separated, which makes the code layer clearer.

React setup is a Mutable function that is optional when used in Vue3.0. When combined with TSX support, React is only Mutable:

// This is a Vue component
const MyComponent = createComponent((props: { msg: string }) = > {
  return (a)= > h('div', props.msg)
})
Copy the code

It is difficult for us to evaluate the good or bad of Template and JSX, but in order to understand Vue and React more thoroughly, we need to look beyond JSX&Template, Mutable&Immutable. In fact, we need to remove the technical selection independent of these two frameworks. React@16 and Vue@3 are already very much alike.

The essence of Vue3.0 is that you learned the React Hooks concept, so you can use them to simulate Vue setup functions in React.

JSX is a Mutable Mutable Mutable Mutable Mutable Mutable Mutable Mutable Mutable Mutable Mutable Mutable Mutable Mutable Mutable

  • Vue: Mutable + Template
  • React: Immutable + JSX

The real influence of coding habits is Mutable and Immutable, use Vue firmly use Mutable, use React firmly use Immutable, so as to maximize the value of the two sets of frameworks.

Differences between Vue Hooks and React Hooks

Start with the React Hooks simple syntax:

const [ count, setCount ] = useState(0)

const setToOne = (a)= > setCount(1)
Copy the code

Simple syntax for Vue Hooks:

const count = value(0)

const setToOne = (a)= > count.value = 1
Copy the code

Vue returns count as an object that is Immutable. Vue returns count as an object that is Mutable. Vue returns count as a number. This makes all variables defined by Vue similar to useRef variables defined in React, so there is no React Capture value feature.

For more information about Capture Value, read the Description of Capute Value in Function VS Class Components

In addition, for Hooks, the mechanism for changing values is different. Let’s look at Vue code:

const Component = {
  setup() {
    const { x, y } = useMouse()
    const { z } = useOtherLogic()
    return { x, y, z }
  },
  template: `<div>{{ x }} {{ y }} {{ z }}</div>`
}
Copy the code

Since the setup function is executed only once, how can you get the latest values in the setup when the values of x and y change due to useMouse?

In React, useMouse reexecutes functions that are mutable if they change x. In Vue, Hooks are deeply combined with Immutable. Such that when x changes, the reference remains the same and only the value changes. Therefore, with the use of Proxy listening mechanism, Vue can achieve the effect that the setup function is not re-executed, but the Template is re-rendered.

Vue Hooks, Vue Hooks, Vue Hooks, Vue Hooks, Vue Hooks, Vue Hooks, Vue Hooks React Immutable performance can be achieved after the optimized effect, this is the charm of Mutable.

Advantages of Vue Hooks

The author makes an extended explanation of the comparison between Vue and React Hooks in THE RFC:

First, the biggest difference: Setup only executes once, whereas React Function Component executes each rendering.

The use of Vue code is more intuitive with JS.

JS is not designed for Immutable language, so it is very natural to write Immutable, while Immutable writing is more awkward.

When Hooks want to update, Vue is assigned with an equal sign. React Hooks need to call an assignment function. When objects of complex types, third-party libraries are required to ensure correct Immutable updates.

There is no requirement on the order in which you use Hooks, and they can be placed in conditional statements.

In the case of React Hooks, calls must come first and cannot be included in conditional statements. This is because React Hooks subscript their status, and if they are not in the right position or if they are placed in a condition, they will not find the correct value.

Hooks in the Vue Function API can be placed anywhere, named anywhere, and wrapped around conditional statements, since they do not trigger setup updates, they only update their own references when needed. The Template rerender inherits Vue 2.0’s dependency collection mechanism completely. It can be rerendered regardless of where the value comes from, as long as the value used changes.

No more repeated calls for each rendering, reducing GC pressure.

This is indeed a problem with React Hooks, all of which are executed in render closures, so there is some performance pressure on each rerender, and frequent renderings cause a lot of closures, which can rely on GC to collect, but can put a lot of pressure on GC.

Vue Hooks, on the other hand, have only one reference, so they are stored very thin, which means they have a small memory footprint, and they do not retrigger setup execution when the values change, so they do not cause GC stress.

It has to be a total packageuseCallbackFunction ensures that child elements are not frequently rerendered.

One problem with React Hooks is that they rely entirely on Immutable properties. When a Function is created inside a Function Component, a new object is created each time. If this object is passed to a child Component, the child Component cannot be optimized. So React adopted useCallback as an optimization:

const fn = useCallback((a)= > / *.. * /[]),Copy the code

The new reference is returned only if the second dependency parameter changes. But the second dependency argument requires the Lint tool to make sure that the dependency is always correct. (For more on why you should be honest about dependencies, read The Introduction to Function Component – Always be honest about dependencies.)

Back in Vue 3.0, since the setup is executed only once, the function itself is created only once, there is no multi-instance problem, no need to use the concept of useCallback, and no need to use a Lint plugin to make sure the dependencies are written correctly, which is truly developer friendly.

You don’t need to useuseEffect useMemoAll performance optimizations are automatic.

This is also true. After all, Mutable + relies on automatic collection to make fine-grained updates that do not trigger Rerender unnecessarily, thus eliminating the need for useMemo.

You don’t need to pass dependencies in Vue at all, so you don’t need to pass them by accident. You don’t need to write a Plugin like React to make sure the dependencies are correct. (This is where I’m making fun of the React Hooks. How does the React team ensure that everyone has Lint installed? Even with Lint installed, if there are bugs in the IDE that make it ineffective, it can write “dangerous code” with incorrect dependencies, causing serious consequences such as infinite loops.)

4. To summarize

By comparing Vue Hooks with React Hooks, we can find that Vue 3.0 perfectly combines the Mutable feature with Vue Hooks, which avoid some of the disadvantages of React Hooks. So we could say that Vue borrowed from React Hooks, but what he created was a much finer work of art.

But React Hooks follow Immutable, which is also a good side, is that each time the state is stabilized in the render, do not worry about the impact of sudden changes in the state (in fact, should pay attention to the impact of the state is not changed), for data records, program running stability is highly predictable.

Finally, for developers who prefer to be Mutable, Vue 3.0 is your best bet. React + Mutable is the only way to do it. For React developers, stick to your Immutable belief. Vue 3.0 has already maximized Immutable. Only by maximizing the React Immutable feature can React make the most of its value.

Discussion address: Intensive reading of Vue3.0 Function API · Issue #173 · DT-FE/Weekly

If you’d like to participate in the discussion, pleaseClick here to, each week has a new theme, released on the weekend or Monday. Front end intensive reading – to help you filter the right content.

Pay attention to the front end of the intensive reading wechat public account

Copyright Notice: Free Reprint – Non-Commercial – Non-Derivative – Keep Your Name (Creative Sharing 3.0 License)