The highly anticipated version of Vue3 was released on September 18, codenamed One Piece. As anyone who has seen Pirates knows, One Piece is the ultimate secret, which means there are plenty of highlights and surprises waiting to be discovered in the 2.x to 3.x upgrade. Examples include the new Proxy architecture, Composition API, and TypeScript support. It also learns from the hooks feature that is currently popular with React, making it much easier for users to choose frameworks. Let’s use a TodoList component example to see how React Hooks compare to the Composition API.

Hooks and the Composition API. If you haven’t seen it yet, check it out:

The react entrance

Vue3 entrance

Development experience

To start, let’s try out one of the tools mentioned earlier, Vite. Vite is a native ESM-driven Web development build tool developed in a development environment based on the browser’s Native ES Imports, and the build environment is Rollup packaged.

vite: github.com/vitejs/vite

It has the following characteristics:

  • Lightweight quick cold start
  • Module hot update
  • True load on demand

I have to say, the features of this tool are reallyvue, lightweight, fast to read, easy to use.

As for React, we chose UmiJS, a plug-in front-end application framework provided by Ant Financial.

UmiJs: umijs.org/zh-CN/docs/…

Umi has a series of built-in development and production modules such as routing, construction, deployment and testing, which can be developed with only one dependency. It is also quite elegant to use with ANTD, which can be said to be a one-stop React application framework.

In order to compare the actual development experience, we made two sets of projects (Vue and React) for the same business scenario (TodoList) and used them respectivelyComposition API 和 React Hooks 。

In terms of UI, there is no difference. After all, they use the same CSS. Vue uses Template and React uses JSX to introduce CSS. Personally, I would prefer to use the additional introduction of CSS, which is clearer to manage and supported in VUE.

Function code

Hooks style

function TodoList({ dataSource, onChange }: TProps) {
  const [itemName, setItemName] = useState(' ')

  const handleChangeItemName = (e: any) = > {
    setItemName(e.target.value);
  }

  const handleAddItem = () = > {
    const newList = [
      ...dataSource,
      {
        name: itemName,
        hasDo: false
      }
    ]
    setItemName(' ')
    onChange(newList)
  }

  const handleItemStatus = (value: boolean, index: number) = > {
    const newList = dataSource.map((item, tIndex) = > {
      if (tIndex === index) {
        return {
          ...item,
          hasDo: value
        }
      }
      return item
    })
    onChange(newList)
  }

  const handleRemove = (index: number) = > {
    const newList = dataSource.filter((item, tIndex) = >tIndex ! == index) onChange(newList) }return (
    <div>
      <div className="input-line">. Content of the input</div>
      <div className="todo-list">. The list of rendering</div>
    </div>)}Copy the code

The React component updates the virtual DOM every time the state changes and re-renders it. The React component cannot manage the state because this points to a problem. This time hooks add useState for state management, essentially taking advantage of JS closures to persist state. In addition, the state cannot be changed using the previous this.setState, but can only be updated using the second parameter deconstructed in the useState result.

Hooks is also a direction for the future development of the react, component as pure functions as far as possible, if you need the external function and side effects, with the hook to external code to “hook”. There are many hooks in the community. For example, Ahooks provides a high quality library of hooks that are commonly used. React-table7.x fully embraces hooks.

Custom Hooks: reactjs.org/docs/hooks-…

Composition API style

export default {
  name: 'TodoList'.props: {
    dataSource: Array.// onChange: Function
  },
  setup() {
    const itemName = ref(' ')

    const handleAddItem = (dataSource) = > {
      dataSource.push({
        name: itemName.value,
        hasDo: false
      })
      itemName.value = ' '
    }

    const handleItemStatus = (index, dataSource) = >{ dataSource[index].hasDo = ! dataSource[index].hasDo }const handleRemove = (index, dataSource) = > {
      dataSource.splice(index, 1)}return {
      itemName,
      handleAddItem,
      handleItemStatus,
      handleRemove
    }
  }
}
Copy the code

Vue3.0 provides the Composition API, which defines a setup function that corresponds to both beforeCreated and created life cycles, and then assigns some properties to responsive listening capabilities. The output is returned to the view layer so that the data can be bidirectionally bound. React vue looks convenient in the following ways:

  1. usev-modelAfter bidirectional binding, you don’t need to care about InputonChangeThe event processing
  2. React is setState when changing the state and then rerender, which is a lot of performanceuseMemoVue can directly modify attribute values:ref.value = ''And does not trigger re-rendering.
  3. React To make surediffAlgorithm comparison, it’s a little bit cumbersome to modify some arrays, use rest style, even use someimmutable , immerLibrary to assist, vue becauseproxyCan be directly modified.

The Composition API borrowed a lot from Hooks in the style of the previous Option API. That is, business-driven code, centralized management of small business modules, and reuse of business logic using custom Hooks.

The life cycle

function Todo () {
  const [todo, setTodo] = useState<Todo[]>([])

  useEffect(() = > {
    async function fetchData() {
      const info = await request('/api/todolist')
      setTodo(info)
    }
    fetchData()
    return () = >{...// Do some cleanup}}, [])return (
    <TodoList
      dataSource={todo}
      onChange={(val: Todo[]) = > {
        setTodo(val)
      }}
    />)}Copy the code

We added a logic to the React parent component to initialize the data, using the useEffect method. Passing the second argument [] is equivalent to the class component’s componentDidMount life cycle. This function is executed when the component is destroyed. One thing to note though: hooks cannot be loaded in if judgments, which would result in a mess every time the component renders.

export default {
  name: 'App'.components: {
    TodoList
  },
  setup() {
    const dataSource = ref([])

    onMounted(() = > {
      async function fetchData() {
        const info = await request('/api/todolist')
        dataSource.value = info
      }
      fetchData()
    })

    return {
      dataSource
    }
  }
}
Copy the code

In the same way, we can see that the Composition API is to pass in a function containing processing logic to the onMounted function to mount the life cycle. Migrating from the Options API to the Composition API is also smoother, with hooks and Composition API similar in style.

Vue2 Vue3
beforeCreated setup
created setup
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestroy onBeforeUnmount
destroyed onUnmounted
errorCaptured onErrorCaptured

Here we also list the life cycle function comparison of Vue2 and Vue3.

Performance comparison

So how does Vue3 perform? I did a little experiment here, creating a list data of 10000 length to initialize, and then adding new data.

const list = []

for(let i = 0; i < 10000; i++) {
  list.push({
    name: `${i}--test plan`.hasDo: false})}Copy the code

The one on the left is thetaVue Composition APIOn the right isReact hooksAs a result, the code on both sides is actually not optimized. In terms of indicators,VueIt takes up less memory and CPU executionReactLower, indicating Vue brand newProxyThe underlying performance gains are significant, of coursereactThere are also means (Immutable) to optimize.

The last

React hooks and Composition apis are both good front-end solutions with their own features, and point to a more standardized and universal front-end in the future. (Any errors in the article are welcome to correct)