SoFunction
Updated on 2025-04-05

Detailed explanation of incompatible changes to components in vue3

Functional Components

functional attribute in single file component (SFC) <template> has been removed
{ functional: true } option has been removed when creating component through function

// Using the <dynamic-heading> component, responsible for providing the appropriate title (i.e.: h1, h2, h3, etc.), in which this may be written as a single file component:// Vue 2 Functional Component Exampleexport default {
 functional: true,
 props: ['level'],
 render(h, { props, data, children }) {
 return h(`h${}`, data, children)
 }
}

// Vue 2 functional component example uses <template>&lt;template functional&gt;
 &lt;component
 :is="`h${}`"
 v-bind="attrs"
 v-on="listeners"
 /&gt;
&lt;/template&gt;

&lt;script&gt;
export default {
 props: ['level']
}
&lt;/script&gt;

Now in Vue 3, all functional components are created with normal functions, in other words, there is no need to define the { functional: true } component option.
They will receive two parameters: props and context. The context parameter is an object containing the attrs, slots, and emit property of the component.
Furthermore, now instead of providing h implicitly in the render function, h is imported globally.
Using the aforementioned example of the <dynamic-heading> component, here is what it looks like now.

// vue3.0
import { h } from 'vue'
const DynamicHeading = (props, context) =&gt; {
 return h(`h${}`, , )
}
 = ['level']
export default DynamicHeading
// vue3.0 single file writing method&lt;template&gt;
 &lt;component
 v-bind:is="`h${$}`"
 v-bind="$attrs"
 /&gt;
&lt;/template&gt;

&lt;script&gt;
export default {
 props: ['level']
}
&lt;/script&gt;

The main difference is

functional attribute exist &lt;template&gt; Removed in
listeners 现exist作为 $attrs Part of the delivery,It can be deleted

Writing asynchronous components and defineAsyncComponent method

Now use the defineAsyncComponent helper method, for displaying the definition asynchronous component
Rename the component option to loader
The Loader function itself no longer accepts resolve and rejuct parameters, and must return a promise

// 
// Previously, asynchronous components were created by defining the component as a function that returns a Promiseconst asyncPage = () =&gt; import('./')
// Or create as an optionconst asyncPage = {
 component: () =&gt; import('./'),
 delay: 200,
 timeout: 3000,
 error: ErrorComponent,
 loading: LoadingComponent
}

// 
In,Need to usedefineAsyncComponentTo define
import{ defineAsyncComponent } from 'vue'
import ErrorComponent from './components/'
import LoadingComponent from './components/'

// Definition method without optionsconst asyncPage = defineAsyncComponent(() =&gt; import('./'))

// Asynchronous component with optionsconstasyncPageWithOptions = defineAsyncCopmonent({
 loader: () =&gt; import('./'),
 delay: 200,
 timeout: 3000,
 errorComponent: ErrorComponent,
 LoadingComponent: LoadingComponent
})

The loader function no longer receives resolve and reject parameters and must always return Promise.

// 
const oldAsyncComponent = (resolve, reject) => {}
// 
const asyncComponent = defineAsyncComponent(() => new Promise((resolve, reject) => {}))

Component events need to be declared in emits option

A emits option is now available in vue3, similar to props option
This option can be used to define events emitted by a component to its parent object

&lt;!--  --&gt;
&lt;template&gt;
 &lt;div&gt;
 &lt;p&gt;{{ text }}&lt;/p&gt;
 &lt;button v-on:click="$emit('accepted')"&gt;OK&lt;/button&gt;
 &lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
 export default {
 props: ['text']
 }
&lt;/script&gt;

&lt;!--  --&gt;
&lt;!-- Now andpropsimilar,Can be usedemitsTo define the events emitted by the component --&gt;
&lt;!-- This option also receives the object,Used topropsVerify the passed parameters as well --&gt;
&lt;!-- It is strongly recommended to record all issued by each componentemits,Because it's removed.nativeModifier,All listeners for undeclared events will be included in the$attrmiddle,By default,This listener will be bound to the component's root node --&gt;
&lt;template&gt;
 &lt;div&gt;
 &lt;p&gt;{{ text }}&lt;/p&gt;
 &lt;button v-on:click="$emit('accepted')"&gt;OK&lt;/button&gt;
 &lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
 export default {
 props: ['text'],
 emits: ['accepted']
 }
&lt;/script&gt;

The above is a detailed explanation of the incompatible changes of components in vue3. For more information about incompatible changes of components in vue3, please pay attention to my other related articles!