This paper mainly includes the following contents:
- Changes in V-Model usage
- Render function API changes
- Functional component usage changes
- Asynchronous component usage changes
The model option and the V-bind. sync modifier are removed to unify as a V-model parameter
V – model change
-
In vue2.0, using v-models on components is equivalent to binding value prop and input events:
<ChildComponent v-model="pageTitle" /> <! -- equivalent to: --> <ChildComponent :value="pageTitle" @input="pageTitle = $event" /> Copy the code
-
In Vue2.2, add the Model component option. If you change the property or event name to something else, add the Model option to the ChildComponent component:
<! -- ParentComponent.vue --> <ChildComponent v-model="pageTitle" /> <! -- equivalent to: --> <ChildComponent :title="pageTitle" @change="pageTitle = $event" /> Copy the code
// ChildComponent.vue export default { model: { prop: 'title'.event: 'change' }, props: { // This will allow the 'value' attribute to be used for other purposes value: String.// Use 'title' instead of 'value' as model prop title: { type: String.default: 'Default title'}}}Copy the code
Another option is to use v-bind.sync
Bidirectional data binding for a prop, the child component can pass the new value to the parent using the Update :myPropName emit event:
this.$emit('update:title', newValue) Copy the code
<ChildComponent :title.sync="pageTitle" /> <! -- equivalent to: --> <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" /> Copy the code
-
In VUe2, sync and v-model functions overlap, but vue3 is unified: The model option and the v-bind. Sync modifier are removed, and the v-model parameter is unified
A V-Model on a custom component is equivalent to passing a modelValue prop and receiving an Update :modelValue event thrown
<comp v-model="data"></comp> <! -- equivalent to: --> <comp :modelValue="data" @update:modelValue="data=$event"></comp> Copy the code
app.component('comp', { template: ` <div @click="$emit('update:modelValue', 'new value')"> {{modelValue}} </div> `, props: ['modelValue'], }) Copy the code
If you want to bind a prop of another name, you can pass an argument to the model:
<comp v-model:title="data"></comp> <! -- equivalent to: --> <comp :title="data" @update:title="data=$event"></comp> Copy the code
Render function API changes
It mainly includes the following contents:
- What is the
h()
3.x
In contrast to2.x
What are the changes to the render function?
h
function
The h() function is a utility used to create a VNode. It is more accurately named createVNode(), but is shortened to H () due to its frequent use and brevity. The function takes three arguments:
// @returns {VNode}
h(
// {String | Object | Function | null} tag
// An HTML tag name, a component, an asynchronous component, or null.
// Using null will render a comment.
//
// Necessary.
'div'.// {Object} props
// Objects corresponding to attributes, prop, and events.
// We will use it in the template.
//
// Optional.
{},
// {String | Array | Object} children
// Subvnodes, built using 'h()',
// Get "text Vnode" with string or
// Objects with slots.
//
// Optional.
[
'Some text comes first.',
h('h1'.'A headline'),
h(MyComponent, {
someProp: 'foobar'})])Copy the code
Rendering functions have become simpler and easier to use. The main changes are as follows:
-
The Render function no longer takes the H argument, but imports it manually
In 2.x, the render function automatically takes an h function as an argument:
export default { render(h) { return h('div'); }}Copy the code
In 3.x, h requires manual import rather than automatic parameter passing, and the render function is often used inside the setup function, which makes it easier to access reactive states defined in scope, functions, and parameters passed in setup()
import { h, reactive } from 'vue' export default { props: { counter: { type: Number.default: 0}},setup(props, {emit}) { const state = reactive({ count: props.counter }) function increment() { state.count++; emit('update:counter', state.count); } // Render function return () = > h( 'div', { onClick: increment }, state.count ) } } Copy the code
-
Flattened props parameter structure
In 2.x, domProps contains a nested list of VNode attributes:
{ class: ['color-tips'].style: { color: '#34495E' }, attrs: { title: 'text'.target: '_blank'.href: `www.baid.com`,},domProps: { innerText: 'content',},on: { click: () = > { console.log('Click event')}},key: 'xx' } Copy the code
3. In x, the overall VNode attribute structure is flattened. The above example is rewritten as follows:
{class: ['color: #34495E'], style: {color: '#34495E'}, href: 'www.baid.com ', innerText: 'content' onClick: () = > {the console. The log (' click event ')}, key: 'xx'}Copy the code
-
ScopedSlots has been deleted. It’s consolidated into slots
2. X uses scopedSlots to obtain the slot content
render() { // `<div><slot></slot></div>` return h('div', {}, this.$scopedSlots.default()) } Copy the code
3. X uses slots to access static slots, each of which is a VNode:
render() { // `<div><slot></slot></div>` return h('div', {}, this.$slots.default()) } Copy the code
Vue3 Disruptive Changes — Changes to functional components
Functional components vary greatly, mainly in the following aspects:
- Performance improvement in
vue3
Can be ignored, so using the state component is officially recommended - Functional components can only be declared and received in purely functional form
props
和context
(Object containsslots
,attrs
,emit
) two parameters Incompatible change
: in the SFC<template> cannot be added
The functional ‘feature declares functional componentsIncompatible change
:{functional: true}
Component option Removal
2. Functional components in x
In 2.x, functional components have the following main advantages:
1. As a performance optimization, functional components initialize much faster than stateful components. Return multiple root nodes. 3. Create simple componentsCopy the code
Example: Creating a dynamic title component
// Function component Fuctional. Js
export default {
functional: true.props: ['level'].render(h, ctx) {
console.log('ctx', ctx);
return h(`h${ctx.props.level}`, ctx.data, ctx.children); }};// The functional component example uses
fuction.vue
<template functional>
<component :is="`h${props.level}`" v-bind="attrs" v-on="listeners">
<div v-if="slots()">
<slot></slot>
</div>
</component>
</template>
<script>
export default { props: ['level']};</script>
/ / the parent component
<template>
<div>
<Functional :level="1">This is a dynamic title element</Functional>
</div>
</template>
<script>
import Functional from '@/components/Functional';
export default { components: { Functional } };
</script>
Copy the code
The console sees CTX as a FunctionalRenderContext object in the child component
3. functional components in x
In VUe3, the performance of stateful components is negligible, and stateful components can return multiple root nodes, so the advantages of functional components mentioned in VUE2 are eliminated, leaving scenarios created by simple components.
All functional components in VUe3 are created using normal functions, so there is no need to define {functional: true} component options. This function takes two arguments, props and context.
Additionally, H is not supplied implicitly in the render function, but is imported manually.
For migrations using functional on SFCs, simply remove the fucntional attribute and change propos to props, ‘attrs’ to props,’ attrs’ to props, ‘attrs’ to attrs, Listeners transmitted as part of attr may be deleted
The above example is written in VUe3:
// Function component Fuctional. Js
import {h} from 'vue';
const Heading = (props, context) = > {
return h(`h${props.level}`, context.attrs, context.slots)
}
Heading.props = ['level'];
export default Heading;
// Single file component
<template>
<component
v-bind:is="`h${$props.level}`"
v-bind="$attrs"
/>
</template>
<script>
export default {
props: ['level']}</script>
Copy the code
Print the context on the console for a clearer structure, including attrs Emit slots
The original functional component was born for performance improvement, but the performance of VUe3 state component has been improved, the significance of functional component is not much, VUe3 destructive changes to functional components, subsequent development, it is suggested to write with state component
Asynchronous components are requireddefineAsyncComponent
Method to create
Since functional components in VUe3 must be defined as pure functions, asynchronous components are defined with the following changes:
- Must be explicitly used
defineAsyncComponent
Wrap, distinguished from functional components component
Let’s rename the choicesloader
loader
Function not acceptedresolve
和reject
, and must return a Promise
2.x
In writing:
// No configuration
const asyncPage = () = > import('./NextPage.vue')
/ / configuration
const asyncPage = {
component: () = > import('./NextPage.vue'),
delay: 200.timeout: 3000.error: ErrorComponent,
loading: LoadingComponent
}
Copy the code
3.x
Asynchronous component writing:
Define an asynchronous component: the defineAsyncComponent package
import { definedAsyncCompnent} from 'vue';
// No configuration
const asyncPage = definedAsyncCompnent(() = > import('./NextPage.vue'))
Copy the code
Asynchronous component with configuration. Loader option is the previous Component option
import { defineAsyncComponent } from 'vue'
import ErrorComponent from './components/ErrorComponent.vue'
import LoadingComponent from './components/LoadingComponent.vue'
const asyncPageWithOptions = defineAsyncComponent({
loader: () = > import('./NextPage.vue'),
delay: 200.timeout: 3000.errorComponent: ErrorComponent,
loadingComponent: LoadingComponent
})
Copy the code
The loader function no longer accepts resolve and reject, and must always return a Promise
/ / 2. X version
const oldAsyncComponent = (resolve, reject) = > {
/ *... * /
}
/ / 3. X version
const asyncComponent = defineAsyncComponent(
() = >
new Promise((resolve, reject) = > {
/ *... * /}))Copy the code