SoFunction
Updated on 2025-04-06

Master the vue-next functional API in 15 minutes (summary)

Write in front

Before sharing the implementation of various submodules of vue-next, I feel it is necessary to organize the functional APIs proposed in vue-next in a more comprehensive way. If you understand these, it should play a certain auxiliary role whether it is reading the source code or starting to learn when the official version is released.

There are many similar things on the Internet, but they are fragmented, and some are relatively outdated. Of course, the current sorting may also be outdated. After all, the code is still in the pre-alpha stage, but the design ideas in it should not be changed.

Past articles

Master the principle of vue-next responsiveness in 15 minutes
vue-next/runtime-core source code reading guide

setup

setup will serve as the main battlefield for writing component business logic. Various hook-type methods need to be called under the scope of setup. Let’s take a look at the examples in RFC:

<template>
 <button @click="increment">
  Count is: {{  }}, double is: {{  }}
 </button>
</template>

<script>
import { reactive, computed } from 'vue'

export default {
 setup() {
  const state = reactive({
   count: 0,
   double: computed(() =>  \* 2)
  })

  function increment() {
   ++
  }

  return {
   state,
   increment
  }
 }
}
</script>

The code structure looks basically the same as vue2, but there are some points to note:

  • The call time of setup itself, from the current source code, is between the two life cycles of beforeCreate and created, the implication is that you cannot use this to point to the current component instance here.
  • For the declaration of state, we use the reactive API to construct it. For the declaration of computed state, we use computered. Both are essentially Proxy objects.
  • For the declaration of component methods, we can declare it directly by declaring ordinary functions. For changes to state, we can use the Proxy object returned by reactive through the closure.
  • The return value of setup is called render context. As the name suggests, it is a context object of various data and methods that can be accessed in the template. I mentioned in previous articles that when analyzing data, the template will give priority to taking values ​​from the data object. Then this render context will be
  • In addition to returning the render context, you can also return the template rendering function. Yes, that is, that h(...). This form corresponds to the case when we do not declare the template attribute.

In vue-next, we can import reactive, computed and other APIs directly from vue. If it is on vue2, we can also use itcomposition-api This plugin uses these APIs.

state

Statement state mainly has the following forms.

Basic Type

The basic type can be declared through the ref API, as follows:

import { ref } from "vue";

export default {
setup() {
 const count = ref(0);
 
 function inc() {
  ++;
 }
 
 return { count, inc };
}
};

The reason for passing ref is that the value passed in the basic type in js is not a reference value passed, so vue-next will automatically encapsulate it as a ref object with its value pointing to the original value. Of course, there is no problem with ref pointing to a reference type, and its value points to a reference to a reference type variable.

Reference Type

In addition to using ref to declare reference types, they can also use reactive directly, as follows:

import { reactive } from "vue";

export default {
 setup() {
  const state = reactive({
    count: 0
  });
  
  function inc() {
   ++;
  }
  
  return { state, inc };
  // Or through the toRefs method  // return { ...toRefs(state), inc };
 }
};

The main reason for using toRefs here is that if it is an object generated by reactive, since we want to just save a reference to the Proxy object, we cannot flatten it using deconstruction, and toRefs will wrap each property internally into a ref object.

props

For prop, you can declare and use it through the following code:

export default {
 props: {
  count: Number
 },
 setup(props) {
  watch(() => {
   (\`count is: \` + )
  })
 }
}

Here we can find that the declaration method is basically the same as in vue2, but it is worth noting that in vue-next, the type declaration of props is not necessary. If you use typescript, you can completely rewritten it into the following version:

interface PropTypesI {
  count: number
}

export default {
 setup(props: PropTypesI) {
  watch(() => {
   (\`count is: \` + )
  })
 }
}

In addition, you can also directly observe the changes in a prop through the watch method. Why is this? The answer is very simple, that is, props itself is also an object wrapped in reactive in the source code, so it is responsive, so the callback function in the watch method will automatically collect dependencies, and then when count changes, these callback logic will be automatically called.

context

In that section of setup, we know that when the setup is called, the component instance has not been created, which means we cannot use this to access the current instance. Then I want to access some built-in properties in vue2 through this, what should I do? For example attrs or emit. We can use the second parameter of setup:

setup(props, context) {
 do anything...
}

This context object is also a Proxy object. When we access its properties through , the proxy object will essentially access the internal instance of the component (i.e. componentInternalInstance mentioned in the article between).

life cycle

Each component lifecycle function in vue2 currently corresponds to a lifecycle hook, such as:

import { onMounted, onUpdated, onUnmounted } from "vue";

setup() {
 onMounted(() => { ... });
 onUpdated(() => { ... });
 onUnmounted(() => { ... });
}

One thing worth noting here is that although there are responsive hooks for beforeCreate and created life cycles, I don’t think it is necessary to use them separately, because most of these logical codes are initialized logic codes, and can be written directly in the setup method.

How to reuse code

On this basis, the method of multiplexing code is no longer achieved through mixin or HOC like in vue2. Let me briefly talk about it. The more significant disadvantages of these multiplexing code methods are:

  • Hidden data sources, mainly reflected in mixin
  • Some performance will be sacrificed, mainly reflected in the HOC
  • You may encounter naming conflict issues, mainly reflected in mixin

In vue-next, the logic of the reuse code is essentially using these hooks to split business logic and state. If you are more familiar with react hooks, you should quickly understand what I mean. If we write all the logic in the setup method, the code will soon become difficult to maintain. In this regard, we can extract some coupled codes, name them with the use prefix, and declare a custom hook, as follows:

export default {
 setup() {
  const data = useSearch()
  const { sortedData, sort } = useSorting(data)
  return { data, sortedData, sort }
 }
}

function useSearch() { 
  ...fetch data
}

function useSort(data) { 
  ...sort data
}

In addition to declarations in the form of inline, you can also declare these custom hooks in a separate file and directly import them through import, for example:

import useSearch from '@hooks/search'
import useSort from '@hooks/sort'

Compare with react hooks

vue-next draws on the design idea of ​​react hooks in this regard, but from the perspective of implementation level, they are different, mainly as follows:

  • vue-next does not depend on its call order, while react depends on
  • vue-next provides a life cycle method, while react deliberately blurs the concept of life cycle
  • vue-next is based on a responsive system implementation, meaning that its dependencies do not need to display declarations (and are automatic), while react requires manual declaration of dependency arrays

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.