Previous Article:Time to migrate from VUe2 to VUe3 (Series 1)
16. Inline template AttributeNot compatible with
Change overview:
- Support for inline features has been removed.
2. X syntax
In 2.x, Vue provides inline-template attributes for child components to use their internal content as a template rather than as distribution content.
<my-component inline-template>
<div>
<p>They are compiled into the component's own template</p>
<p>It's not what the parent contains.</p>
</div>
</my-component>
Copy the code
3. X syntax
This feature is no longer supported.
Migration strategy
Most use cases for inline-template assume that there are no build tool Settings and that all templates are written directly to the HTML page.
Option 1: Use the <script> tag
In this case, the simplest solution is to
<script type="text/html" id="my-comp-template">
<div>{{ hello }}</div>
</script>
Copy the code
In the component, use a selector to point to the target template:
const MyComp = {
template: '#my-comp-template'
// ...
}
Copy the code
It doesn’t require any build Settings, works in all browsers, isn’t constrained by any internal DOM HTML parsing warnings (you can use camelCase Prop names, for example), and provides proper syntax highlighting in most ides. In a traditional server-side framework, you can split these templates into server template parts (included in the main HTML template) for better maintainability.
Option 2: Default slot
Components that previously used inline-template can also use the default slot — for refactoring, which makes the data range more explicit while preserving the convenience of inlining subcontent:
<! --2.X syntax - ><my-comp inline-template :msg="parentMsg">
{{ msg }} {{ childState }}
</my-comp><! -- Default Slot version --><my-comp v-slot="{ childState }">
{{ parentMsg }} {{ childState }}
</my-comp>
Copy the code
The child should now render the default slot* instead of the supplied empty template:
<! In the child template, render the default slot in the necessary private state on pass. --><template>
<slot :childState="childState" />
</template>
Copy the code
17.key attribute Not compatible with
Change overview:
- New: Branch keys for V-if/V-else/V-else -if are no longer required, as Vue now automatically generates unique keys.
- Incompatibility: If you supply keys manually, each branch must use a unique key. You cannot force reuse of branches by deliberately using the same key.
- Incompatible: The key of
should be set on the
tag (not on its children).
background
Special key attributes are used to prompt Vue’s virtual DOM algorithm to keep track of node identity. This allows Vue to know when existing nodes can be reused and patched, and when they need to be reordered or recreated.
In the condition branch
Vue 2.x recommends using keys in branches of V-if/V-else/V-else -if.
<! -- Vue2.x -->
<div v-if="condition" key="yes">Yes</div>
<div v-else key="no">No</div>
Copy the code
This example still works in Vue 3.x. However, we no longer recommend continuing to use key attributes in v-if/ V-else/V-else if branches, because a unique key is automatically generated when no key is provided for the conditional branch.
<! -- Vue 3.x --> <div v-if="condition">Yes</div> <div v-else>No</div>Copy the code
Incompatible changes occur when each branch must use a unique key if you manually provide a key. Therefore, in most cases, you don’t need to set these keys.
<! -- Vue2.x -->
<div v-if="condition" key="a">Yes</div>
<div v-else key="a">No</div><! -- Vue3.x (recommended solution: remove keys) -->
<div v-if="condition">Yes</div>
<div v-else>No</div><! -- Vue3.x (alternate solution: make sure the keys are always unique) -->
<div v-if="condition" key="a">Yes</div>
<div v-else key="b">No</div>
Copy the code
Combining with the < the template for > with a v –
In Vue 2.x, the <template> tag cannot have a key. However, you can set a key for each of its children.
<! -- Vue 2.x --> <template v-for="item in list"> <div :key="item.id">... </div> <span :key="item.id">... </span> </template>Copy the code
In Vue 3.x, the key should be set on the <template> tag.
<! -- Vue3.x -->
<template v-for="item in list" :key="item.id">
<div>.</div>
<span>.</span>
</template>
Copy the code
Similarly, when using <template v-for> there are children that use V-if, the key should be set on the <template> tag instead.
<! -- Vue2.x -->
<template v-for="item in list">
<div v-if="item.isVisible" :key="item.id">.</div>
<span v-else :key="item.id">.</span>
</template><! -- Vue3.x -->
<template v-for="item in list" :key="item.id">
<div v-if="item.isVisible">.</div>
<span v-else>.</span>
</template>
Copy the code
18. Key modifierNot compatible with
Change overview:
- Incompatible: The use of numbers (i.e. key codes) as V-ON modifiers is no longer supported
- Incompatible: Config.keycodes are no longer supported
2. X syntax
In Vue 2, keyCodes are supported as a way to modify V-on methods.
<! -- Keycode version --><input v-on:keyup.13="submit" /><! -- Alias version --><input v-on:keyup.enter="submit" />
Copy the code
In addition, you can also use the global config.keyCodes option.
Vue.config.keyCodes = {
f1: 112
}
Copy the code
<! -- Keycode version --><input v-on:keyup.112="showHelpText" /><! -- Custom alias version --><input v-on:keyup.f1="showHelpText" />
Copy the code
3. X syntax
Since KeyboardEvent. KeyCode has been deprecated, it no longer makes sense for Vue 3 to continue to support this. Therefore, it is now recommended to use the kebab-cased (dash) case name for any key to be used as a modifier.
<! -- Vue3Use keystroke modifier on V-ON --><input v-on:keyup.delete="confirmDelete" />
Copy the code
Therefore, this means that config.keycodes are now deprecated and no longer supported.
19. Remove $listenersNot compatible with
Change overview:
- The $Listeners object has been removed from Vue 3. Now the event listener is part of $attrs:
{
text: 'this is an attribute'.onClose: () = > console.log('close Event triggered')}Copy the code
2. X syntax
In Vue 2, you can use this.$attrs and this.$Listeners to access the attributes and event listeners passed to the component, respectively. With inheritAttrs: false, developers can apply these attributes and listeners to other elements other than the root element:
<template>
<label>
<input type="text" v-bind="$attrs" v-on="$listeners" />
</label>
</template>
<script>
export default {
inheritAttrs: false
}
</script>
Copy the code
3. X syntax
In the virtual DOM of Vue 3, event listeners are now just attributes prefixed with on, which makes them part of the $attrs object, so $Listeners have been removed.
<template>
<label>
<input type="text" v-bind="$attrs" />
</label>
</template>
<script>
export default {
inheritAttrs: false
}
</script>
Copy the code
If this component received an ID attribute and a V-ON :close listener, the $attrs object would now look like this:
{
id: 'my-input'.onClose: () = > console.log('close Event triggered')}Copy the code
20. Access this in prop’s default functionNot compatible with
Factory functions that generate prop defaults can no longer access this.
Alternatives:
-
Pass the original prop received by the component as an argument to the default function;
-
Inject API is available in default functions.
import { inject } from 'vue'
export default {
props: {
theme: {
default (props) {
// 'props' is the raw value passed to the component.
// Before any type/default cast
// The injected property can also be accessed using 'inject'
return inject('theme'.'default-theme')}}}}Copy the code
21. Render function APINot compatible with
Change overview:
-
This change does not affect <template> users.
-
Here is a brief summary of the changes:
- H is now imported globally instead of being passed as an argument to the render function
- Render function parameters changed to be more consistent between stateful components and function components
- VNode now has a flat prop structure
Render function parameters
2. X syntax
In 2.x, the render function automatically accepts h (the traditional alias for createElement) as an argument:
// Vue 2 render function example
export default {
render(h) {
return h('div')}}Copy the code
3. X syntax
In 3.x, h is now imported globally instead of being passed automatically as a parameter.
// Vue 3 render function example
import { h } from 'vue'
export default {
render() {
return h('div')}}Copy the code
Render function signature changed
2. X syntax
In 2.x, the render function automatically accepts arguments such as h.
// Vue 2 render function example
export default {
render(h) {
return h('div')}}Copy the code
3. X syntax
In 3.x, since the render function no longer takes any arguments, it will be used primarily inside the setup() function. This has another benefit: you can access reactive states and functions declared in scope, as well as parameters passed to setup().
import { h, reactive } from 'vue'
export default {
setup(props, { slots, attrs, emit }) {
const state = reactive({
count: 0
})
function increment() {
state.count++
}
// returns the render function
return () = >
h(
'div',
{
onClick: increment
},
state.count
)
}
}
Copy the code
Format VNode Prop
2. X syntax
In 2.x, domProps contains a nested list in VNode Prop:
// 2.x
{
staticClass: 'button'.class: { 'is-outlined': isOutlined },
staticStyle: { color: '#34495E' },
style: { backgroundColor: buttonColor },
attrs: { id: 'submit' },
domProps: { innerHTML: ' ' },
on: { click: submitForm },
key: 'submit-button'
}
Copy the code
3. X syntax
In 3.x, the entire VNode prop structure is flat. Use the example above to see what it looks like today.
/ / 3. X syntax
{
class: ['button', { 'is-outlined': isOutlined }],
style: [{ color: '#34495E' }, { backgroundColor: buttonColor }],
id: 'submit'.innerHTML: ' '.onClick: submitForm,
key: 'submit-button'
}
Copy the code
Certified components
2. X syntax
In 2.x, after registering a component and passing the component name as the first argument to the render function as a string, the render function works fine:
// 2.x
Vue.component('button-counter', {
data() {
return {
count: 0}}template: ` `
})
export default {
render(h) {
return h('button-counter')}}Copy the code
3. X syntax
In 3.x, because VNode is context-free, you can no longer use string IDS to implicitly look up registered components. Instead, you need to use an imported resolveComponent method:
// 3.x
import { h, resolveComponent } from 'vue'
export default {
setup() {
const ButtonCounter = resolveComponent('button-counter')
return () = > h(ButtonCounter)
}
}
Copy the code
22. Unify slotsNot compatible with
Change overview:
- This change unifies normal and scoped slots in 3.x.
- This.$slots now exposes slots as functions
- Incompatible: Remove this.$scopedSlots
2. X syntax
When using render functions, h, 2.x is used to define slot data properties on content nodes.
/ / 2 x syntax
h(LayoutComponent, [
h('div', { slot: 'header' }, this.header),
h('div', { slot: 'content' }, this.content)
])
Copy the code
In addition, when referencing scoped slots, you can refer to them using the following method:
/ / 2 x syntax
this.$scopedSlots.header
Copy the code
3. X syntax
In 3.x, the slot is defined as a child object of the current node:
// 3.x Syntax
h(LayoutComponent, {}, {
header: () = > h('div'.this.header),
content: () = > h('div'.this.content)
})
Copy the code
When you need to programmatically refer to scoped slots, they are now consolidated into the $slots option.
/ / 2 x syntax
this.$scopedSlots.header
/ / 3. X syntax
this.$slots.header()
Copy the code
Migration strategy
Most of the changes have been released in 2.6. Therefore, migration can be done in one step:
- In 3.x, replace all this.$scopedSlots with this.$slots.
- Replace all this.$slots.myslot with this.$slots.myslot ().
23. Transition class name changeNot compatible with
Changes in the overview
- The name of the transition class v-enter was changed to v-enter-from, and the name of the transition class v-leave was changed to v-leave-from.
2. X syntax
Prior to v2.1.8, two transition class names were provided for transition directives corresponding to the initial and active states.
In v2.1.8, v-enter was introduced to define the transition animation frame between the Enter or leave transform. For downward compatibility, the v-Enter class name was not changed:
.v-enter,
.v-leave-to {
opacity: 0;
}
.v-leave,
.v-enter-to {
opacity: 1;
}
Copy the code
3. X syntax
For clarity and legibility, we now rename these initial states to:
.v-enter-from,
.v-leave-to {
opacity: 0;
}
.v-leave-from,
.v-enter-to {
opacity: 1;
}
Copy the code
Now, the distinction between these states is much clearer.
<transition> Component property names have also changed:
- Leave-class has been renamed leave-from-class (in rendering functions or JSX you can write leaveFromClass)
- Enter-class has been renamed to enter-from-class (in render functions or JSX it could be: enterFromClass)
24.Transition Group root elementNot compatible with
Change overview:
-
no longer renders the root element by default, but it can still be created with tag Prop.
2. X syntax
In Vue 2, <transition-group>, like other custom components, requires a root element. The default root element is a <span>, but can be customized with Tag Prop.
<transition-group tag="ul">
<li v-for="item in items" :key="item">
{{ item }}
</li>
</transition-group>
Copy the code
3. X syntax
In Vue 3, we have fragment support, so components no longer need a root node. So, <transition-group> does not render the root node by default.
- If, as in the example above, tag Prop has been defined in Vue 2 code, everything will be just as before
- If no tag prop is defined, and the style or other behavior depends on the presence of the root element to work properly, then simply add tag=”span” to
:
<transition-group tag="span"> <! -- --> </transition-group>Copy the code
25. Remove the V-on. native modifierNot compatible with
Change overview:
- The.native modifier for v-ON has been removed.
2. X syntax
By default, event listeners passed to components with V-ON can only be emitted via this.$emit. To add a native DOM listener to the root element of a child component, use the.native modifier:
<my-component
v-on:close="handleComponentEvent"
v-on:click.native="handleNativeClickEvent"
/>
Copy the code
3. X syntax
The.native modifier for v-ON has been removed. Also, the new emits option allows child components to define events that will actually be fired.
As a result, Vue will now add all event listeners in the child component that are not defined to be triggered by the component as native event listeners to the root element of the child component (unless inheritAttrs: False is set in the child component’s options).
<my-component
v-on:close="handleComponentEvent"
v-on:click="handleNativeClickEvent"
/>
Copy the code
MyComponent.vue
<script>
export default {
emits: ['close']
}
</script>
Copy the code
26.v-model Not compatible with
Change overview:
- Incompatible: V-Model Prop and event default names have been changed when used for custom components:
- Prop: value -> modelValue;
- Event: input -> update:modelValue;
- Incompatible: v-bind’s.sync modifier and component’s model option have been removed and v-model can be used instead;
- New: Bidirectional binding with multiple V-Models on the same component is now possible;
- New: V-Model modifiers can now be customized.
introduce
After Vue 2.0 was released, developers using v-model directives had to use prop as Value. If a developer needs to use another prop for a different purpose, they have to use V-bind.sync. In addition, this hard-coded relationship between the V-Model and value raises the question of how to handle native and custom elements.
In Vue 2.2, we introduced the Model component option, which allows components to customize prop and events for v-Models. However, this still allows only one Model to be used on the component.
In Vue 3, the API for two-way data binding has been standardized, reducing developer confusion when using V-Model directives and allowing more flexibility when using V-Model directives.
2. X syntax
In 2.x, using v-Models on components is equivalent to binding value prop and input events:
<ChildComponent v-model="pageTitle"/ > <! -- is short for: --><ChildComponent :value="pageTitle" @input="pageTitle = $event" />
Copy the code
To change the property or event name to something else, add the Model option to the ChildComponent component:
<! -- ParentComponent.vue --><ChildComponent v-model="pageTitle" />
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
So, in this case v-model is shorthand for:
<ChildComponent :title="pageTitle" @change="pageTitle = $event" />
Copy the code
Use the v – bind. The sync
In some cases, we may need to “bidirectional bind” a prop (except for the previous v-model binding of the prop). To do this, we recommend throwing events using Update :myPropName. For example, for the ChildComponent with a title prop in the previous example, we could communicate the intent to assign a new value to the parent as follows:
this.$emit('update:title', newValue)
Copy the code
The parent can listen for this event and update the local data property if needed. Such as:
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
Copy the code
For convenience, we can use the.sync modifier to abbreviate, as follows:
<ChildComponent :title.sync="pageTitle" />
Copy the code
3. X syntax
In 3.x, a V-Model on a custom component is equivalent to passing a modelValue prop and receiving an Update :modelValue event thrown:
<ChildComponent v-model="pageTitle"/ > <! -- is short for: --><ChildComponent
:modelValue="pageTitle"
@update:modelValue="pageTitle = $event"
/>
Copy the code
V – model parameters
If we need to change the Model name instead of changing the Model option within the component, we can now pass an argument to Model:
<ChildComponent v-model:title="pageTitle"/ > <! -- is short for: --><ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
Copy the code
This can also be used as an alternative to the.sync modifier and allows us to use multiple V-Models on custom components.
<ChildComponent v-model:title="pageTitle" v-model:content="pageContent"/ > <! -- is short for: --><ChildComponent
:title="pageTitle"
@update:title="pageTitle = $event"
:content="pageContent"
@update:content="pageContent = $event"
/>
Copy the code
V – model modifier
In addition to hard-coded 2.x V-model modifiers like.trim, 3.x now supports custom modifiers:
<ChildComponent v-model.capitalize="pageTitle" />
Copy the code
27. Priority comparison between V-IF and V-forNot compatible with
Changes in the overview
- Incompatible: V-if has a higher priority than V-for when both work on the same element.
introduce
The two most used directives in vue.js are V-if and V-for, so developers may want to use both. While this is not recommended, it is sometimes necessary, so we want to provide guidance on how it works.
2. X syntax
2. In the x version, when v-if and V-for are used on the same element, v-for takes precedence.
3. X syntax
3. In the X version, V-if always takes effect before V-for.
28. V-bind merge behaviorNot compatible with
Change overview:
- Incompatible: The binding order of V-bind affects the rendering result
introduce
When attributes are dynamically bound to elements, a common scenario is to use both the V-bind =”object” syntax and a separate property in one element. However, this raises questions about the priority of the merger.
2. X syntax
In 2.x, if an element defines both v-bind=”object” and an identical separate property, that separate property will always override the binding in object.
<! -- template --><div id="red" v-bind="{ id: 'blue' }"></div><! -- result --><div id="red"></div>
Copy the code
3. X syntax
In 3.x, if an element defines both V-bind =”object” and the same individual property, the order in which the bindings are declared determines how they are combined. In other words, developers now have much better control over what they want to merge, rather than assuming that they always want separate properties to override what is defined in object.
<! -- template --><div id="red" v-bind="{ id: 'blue' }"></div><! -- result --><div id="blue"></div><! -- template --><div v-bind="{ id: 'blue' }" id="red"></div><! -- result --><div id="red"></div>
Copy the code
29.Watch on Arrays Not compatible with
Change overview:
- Incompatible: When listening on an array, the callback is triggered only when the array is replaced. If you need to trigger a callback when an array changes, you must specify the deep option.
3. X syntax
When you listen on an array with the Watch option, the callback is triggered only if the array is replaced. In other words, the Watch callback will no longer be fired when the array changes. To trigger the Watch callback when the array changes, you must specify the deep option.
watch: {
bookList: {
handler(val, oldVal) {
console.log('book list changed')},deep: true}},Copy the code
Finally:
This note is based on the official document migration policy. If there is any discrepancy, please refer to the official document. You are advised to use the official documents as a supplement. This way you can examine the reading “for yourself” and not be swayed by my opinions
Share the links of some knowledge points and articles arranged by yourself
-
Record front-end development engineer interviews from the end of March to April
-
Interview high frequency handwritten JS code
-
A big factory
-
Webpack explains everything from shallow to deep, so as to achieve the so-called “familiar” on the resume (Series 1)
-
Webpack explains everything from shallow to deep, so as to be truly “familiar” on the resume (Series 2)
-
Webpack explains everything from shallow to deep, so as to be truly “familiar” on the resume (Series 3)
-
Webpack explains everything from shallow to deep, so as to be truly “familiar” on the resume (Series 4)
-
Webpack explains everything from shallow to deep, so as to be truly “familiar” on the resume (Series 5)