Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

New features of Vue3.0 and sample analysis of its use

2025-03-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article is to share with you about the new features of Vue3.0 and the sample analysis used. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

Why upgrade Vue3

Partners who use Vue2.x are familiar with that all data in Vue2.x is defined in data, methods are defined in methods, and this is used to invoke the corresponding data and methods. Then Vue3.x can not play like this, specific how to play we will talk about later, first talk about what defects in the Vue2.x version so written, all will be upgraded and changed.

Review the addition and subtraction of Vue2.x implementation

Count: {{count}}

Multiple: {{multiple}}

Plus one minus one export default {data () {return {count: 0};}, computed: {multiple () {return 2 * this.count;},}, methods: {increase () {this.count++;}, decrease () {this.count-- },},}

The above code only implements the addition and subtraction of count and the display multiple, which needs to be operated in data, methods and computed respectively. When we add a requirement, the following figure will occur:

A lot of the above happens when our business is complex, and as the complexity increases, there will be a picture where each color square represents a function:

Even one function will rely on other functions, all mixed together.

When the code of this component exceeds a few hundred lines, adding or modifying a requirement requires repeated redirects in data, methods, computed, and mounted, where the pain is well known.

Well, we thought, ah, if we could divide the above picture into the following one logically, would it be much clearer? the code would be more readable and maintainable:

Then the solution given by the vue2.x version is Mixin, but there are also troubling problems when using Mixin:

Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community

Naming conflict problem

It is not clear the role of exposed variables

Logic reuse to other component often encounters problems

With regard to the problems that often occur above, I will not give examples one by one, and the little friends who have used them will encounter them more or less. The focus of the article is not Mixin, if you really want to know, leave a message.

Therefore, we Vue3.x launched Composition API is mainly to solve the above problems, the scattered logic is combined to maintain, and can also split the individual functional logic into separate files. Next, let's focus on Composition API.

Composition API

Setup

Setup is a new option for Vue3.x, which is the entry point for using Composition API within the component.

Timing of setup execution

In the course of my study, I read many articles saying that setup is between beforeCreate and created. This conclusion is wrong. Practice is the only criterion for testing truth, so I went to test it myself:

Export default defineComponent ({beforeCreate () {console.log ("- beforeCreate----");}, created () {console.log ("- created----");}, setup () {console.log ("- setup----");},})

The timing of setup execution is before beforeCreate, which can be explained later in the lifecycle.

Setup parameter

When using setup, it accepts two parameters:

Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community

Props: the attribute passed in by the component

Context

The props accepted in setup is responsive and will be updated in time when a new props is passed in. Because it is responsive, you cannot use ES6 deconstruction, which eliminates its responsiveness. Error code example, which causes props to no longer support responsiveness:

/ / demo.vue export default defineComponent ({setup (props, context) {const {name} = props console.log (name)},})

So in the development, we want to use deconstruction, but also to maintain the responsiveness of props, is there any way to solve it? You can think about it and answer it for you in the place where you learn from toRefs. Let's talk about the second parameter context accepted by setup. We said earlier that setup cannot access the most commonly used this object in Vue2, so context provides the three most commonly used properties in this: attrs, slot, and emit, corresponding to the $attr property in Vue2.x, the slot slot, and the $emit emission event, respectively. And these properties are automatically synchronized with the latest values, so we get the latest values every time we use them.

Reactive, ref and toRefs

In vue2.x, the definition data is all in data, but Vue3.x can use reactive and ref for data definition. So what's the difference between ref and reactive? When should I use it respectively? At this point, I have to mention that I have read a lot of articles on the Internet (reactive is used to deal with two-way binding of objects, while ref deals with two-way binding of js basic types). In fact, I don't quite agree with this view. It's easy for beginners to think that ref can handle js basic types. For example, ref can also define two-way binding of objects. The code above:

Setup () {const obj = ref ({count:1, name: "Zhang San"}) setTimeout () = > {objobj.value.count = obj.value.count + 1 obj.value.name = "Li Si"}, 1000) return {obj}}

It's OK to bind obj.count and obj.name to the page; but the reactive function does proxy an object, but not the basic types, such as strings, numbers, boolean, and so on. Next, use the code to show the use of ref and reactive:

Running effect:

In the above code, we bind to the page through user.name,user.age; so it feels very tedious to write, can we directly deconstruct the properties in user and use it? The answer is that you can't structure user directly, which eliminates its responsiveness, which echoes the above statement that props cannot be deconstructed directly using ES6. What do we want to do with the deconstructed data? the solution is to use toRefs. ToRefs is used to convert a reactive object into a normal object whose properties are all ref objects. The specific usage is as follows:

Year {{year}}

Name: {{nickname}}

Age: {{age}}

Import {defineComponent, reactive, ref, toRefs} from "vue"; export default defineComponent ({setup () {const year = ref (0); const user = reactive ({nickname: "xiaofan", age: 26, gender: "female"}); setInterval () = > {year.value++; user.age++;}, 1000) Return {year, / / use reRefs... toRefs (user),};},},}); Lifecycle hooks

We can directly look at the life cycle diagram to see which life cycle hooks are available (the picture is based on the translation of the official website):

From the figure, we can see that Vue3.0 has added setup, which we discussed in detail earlier, and then it is more unmounted to change the beforeDestroy name in Vue2.x to beforeUnmount; destroyed table. The author says that this change is purely for more semantic purposes, because a component is a process of mount and unmount. Lifecycles in other Vue2 are still preserved. The above lifecycle diagram does not contain all lifecycle hooks, but there are several others, all of which are shown in the figure:

We can see that beforeCreate and created have been replaced by setup (but you can still use it in Vue3 because Vue3 is backward compatible, that is, you are actually using vue2). Secondly, hook naming has added on; Vue3.x and new hook functions onRenderTriggered and onRenderTricked for debugging. Below we simply use a few hooks to make it easier for you to learn how to use them. Hooks in Vue3.x need to be imported from vue:

Import {defineComponent, onBeforeMount, onMounted, onBeforeUpdate,onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured, onRenderTracked, onRenderTriggered} from "vue"; export default defineComponent ({/ / beforeCreate and created are beforeCreate () {console.log ("- beforeCreate-") of vue2;}, created () {console.log ("- created-");}, setup () {console.log ("- setup-") / / vue3.x life cycle is written in setup onBeforeMount (() = > {console.log ("- onBeforeMount-");}); onMounted (() = > {console.log ("- onMounted-");}); / / debug which data has changed onRenderTriggered ((event) = > {console.log ("- onRenderTriggered-", event);}),},})

So much for lifecycle-related content, and let's take a look at how watch is different in Vue3.x.

The usage of watch and watchEffect

The watch function is used to listen for specific data sources and to perform side effects in callback functions. The default is lazy, that is, callbacks are performed only when the listening source data changes.

Watch (source, callback, [options])

Parameter description:

Source: can support string,Object,Function,Array; to specify responsive variables to listen for

Callback: callback function executed

Options: deep, immediate, and flush options are supported.

Next, I'll show you how to use these three parameters. If you don't understand the use of watch, please read on:

Listen for data defined by reactive

Import {defineComponent, ref, reactive, toRefs, watch} from "vue"; export default defineComponent ({setup () {const state = reactive ({nickname: "xiaofan", age: 20}); setTimeout (() = > {state.age++;}, 1000) / / the watch callback watch (() = > state.age, (curAge, preAge) = > {console.log ("new value:", curAge, "old value:", preAge);}); return {... toRefs (state),};},}) is triggered when the age value is modified.

Listen for data defined by ref

Const year = ref (0); setTimeout (() = > {year.value++;}, 1000); watch (year, (newVal, oldVal) = > {console.log ("New value:", newVal, "Old value:", oldVal);})

Listen for multiple data

In the above two examples, we use two watch respectively. When we need to listen to multiple data sources, we can merge and listen for multiple data at the same time:

Watch ([() = > state.age, year], ([curAge, newVal], [preAge, oldVal]) = > {console.log ("New value:", curAge, "Old value:", preAge); console.log ("New value:", newVal, "Old value:", oldVal);})

Listen for complex nested objects

In our actual development, complex data can be seen everywhere, such as:

Const state = reactive ({room: {id: 100, attrs: {size: 140m2, type: "three rooms and two rooms",}); watch (() = > state.room, (newType, oldType) = > {console.log ("New value:", newType, "Old value:", oldType);}, {deep: true})

If you don't use the third parameter, deep:true, you can't listen for data changes. As we mentioned earlier, by default, watch is lazy, so when is it not lazy and the callback function can be executed immediately? In fact, it is also very easy to use, just set immediate: true in the third parameter. Flush configuration is still being learned and will be supplemented later.

Stop stops snooping

The watch snooping we created in the component automatically stops when the component is destroyed. If we want to stop a listening before the component is destroyed, we can call the return value of the watch () function as follows:

Const stopWatchRoom = watch (() = > state.room, (newType, oldType) = > {console.log ("New value:", newType, "Old value:", oldType);}, {deep:true}); setTimeout () = > {/ / stop listening stopWatchRoom ()}, 3000)

There is also a listening function watchEffect, in my opinion, watch has been able to meet the monitoring needs, why there is watchEffect? Although I don't have the need to get into it, I'd like to introduce watchEffect and first see how its use is different from that of watch.

Import {defineComponent, ref, reactive, toRefs, watchEffect} from "vue"; export default defineComponent ({setup () {const state = reactive ({nickname: "xiaofan", age: 20}); let year = ref (0) setInterval (() = > {state.age++ year.value++}, 1000) watchEffect (() = > {console.log (state); console.log (year)) }); return {... toRefs (state)}},})

The execution result first prints the state and yearvalue, and then prints the state and yearvalue every other second. As you can see from the above code, you don't need to pass in dependencies first like watch. WatchEffect automatically collects dependencies, as long as you specify a callback function. When the component is initialized, it is executed once to collect dependencies, and then when the data in the collected dependencies changes, the callback function is executed again. So the summary and comparison are as follows:

Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community

WatchEffect does not need to manually pass in dependencies

WatchEffect will first execute once to automatically collect dependencies

WatchEffect cannot get the value before the change, only the value after the change

Some of the contents of Vue3 Composition API are introduced above, and there are many very useful API. It is recommended to check the official website composition-api directly. In fact, we can also do custom encapsulation.

Custom Hooks

At the beginning, we wrote an example of implementation addition and subtraction using Vue2.x, which can be encapsulated into a hook, and we agree that these "custom Hook" are prefixed with use and distinguished from ordinary functions. UseCount.ts implementation:

Import {ref, Ref, computed} from "vue"; type CountResultProps = {count: Ref; multiple: Ref; increase: (delta?: number) = > void; decrease: (delta?: number) = > void;}; export default function useCount (initValue = 1): CountResultProps {const count = ref (initValue); const increase = (delta?: number): void = > {if (typeof delta! = "undefined") {count.value + = delta } else {count.value + = 1;}}; const multiple = computed (() = > count.value * 2); const decrease = (delta?: number): void = > {if (typeof delta! = = "undefined") {count.value-= delta;} else {count.value-= 1;}} Return {count, multiple, increase, decrease,};}

Next, take a look at using the hook of useCount in the component:

Count: {{count}}

Multiple: {{multiple}}

Plus one minus one import useCount from ".. / hooks/useCount"; setup () {const {count, multiple, increase, decrease} = useCount (10); return {count, multiple, increase, decrease,};}

At the beginning of the Vue2.x implementation, scattered in data,method,computed, etc., if you have just taken over the project, it is really impossible to quickly associate the data field with method, and the way of Vue3 can clearly see that aggregating count-related logic together looks much more comfortable, and useCount can expand more functions. After the development of the project, we will write an article summarizing the "custom Hooks" used in the project to help you develop more efficiently. This is the end of the introduction on Composition API and custom Hooks, and then a brief introduction to the responsive comparison of vue2.x and vue3.

A simple comparison between vue2.x and vue3.x response

In fact, before Vue3.x released bate, a hot topic was that Vue3.x would use Proxy instead of Vue2.x 's version of Object.defineProperty. There is no love for no reason, no hate for no reason. Why replace the Object.defineProperty? we can have a brief chat. When I first started Vue2.x, I often encountered a problem, the data has been updated, ah, why the page is not updated? When to update with $set and when to force updates with $forceUpdate, have you ever been in trouble? Later in the learning process began to contact the source code, only to know that the root of everything is Object.defineProperty. For those of you who want to learn more about this area, you can read this article. Why doesn't Vue3.0 use defineProperty for data monitoring? To explain in detail is another article, here is a brief comparison between Object.defineProperty and Proxy

1. Object.defineProperty can only hijack the properties of an object, while Proxy is a direct proxy object.

Because Object.defineProperty can only hijack object properties, you need to traverse every property of the object, and if the attribute value is also an object, you need to do depth traversal recursively. But Proxy directly proxies objects and does not need to traverse

2. Object.defineProperty needs to manually Observe the new attributes.

Because Object.defineProperty hijacks the properties of an object, when you add new properties, you need to traverse the object again and hijack its new properties using Object.defineProperty. That is, when adding properties to arrays and objects in Vue2.x, you need to use $set to ensure that the new properties are responsive, and $set is also handled internally by calling Object.defineProperty.

Teleport

Teleport is a new feature of Vue3.x, which may be unfamiliar to friends who have not heard of the word; it translates to the meaning of transmission, but they may still feel confused, so I will give you a visual description below.

What is Teleport?

Teleport is like an "arbitrary door" in a doa dream. The function of an arbitrary door is to instantly transfer a person to another place. With this understanding, let's take a look at why we need to use the features of Teleport. Let's take a look at a small example: when we use Dialog components in the sub-component Header, we often use Dialog in similar situations in our actual development. At this time, Dialog is rendered into a layer of sub-components, and it becomes difficult to deal with the positioning, z-index and style of nested components. From a user-perceived level, Dialog should be a separate component, and the DOM; mounted by the Vue top-level component should be completely stripped from the dom structure while the value of the state (data or props) within the Vue component can also be used. To put it simply, you want to continue to use Dialog within the component, and you want the rendered DOM structure not to be nested in the component's DOM. At this point, we need Teleport to play, we can wrap Dialog, and we have set up a portal that can send the content rendered by Dialog to any specified place. Let's give a small example to see how Teleport is used.

The use of Teleport

We want the dom and top-level components of Dialog rendering to be sibling nodes, and define an element for mounting in the index.html file:

Define a Dialog component Dialog.vue, and notice the to property, which is consistent with the id selector above:

{{title}}

Finally, the Dialog component is used in a subcomponent Header.vue, which mainly demonstrates the use of Teleport, and irrelevant code is omitted. Header component

......

The Dom rendering is as follows:

As you can see in image .png, we use the teleport component to specify the rendering location and sibling of the component through the to attribute, that is, under body, but the state of the Dialog dialogVisible is completely controlled by the internal Vue component.

Suspense

Suspense is a new feature in Vue3.x, so what's its use? Don't worry, let's see how it works through some scenarios in Vue2.x. You should often encounter scenarios like this in Vue2.x:

... Loading.

When the front and rear end interacts to obtain data, it is an asynchronous process. Generally speaking, we will provide a loaded animation. When the data is returned, we cooperate with v-if to control the data display. If you have used the vue-async-manager plug-in to accomplish the above requirements, you may be familiar with Suspense, and Vue3.x feels like referring to vue-async-manager. Vue3.x 's new built-in component Suspense, which provides two template slot, initially renders the content in the fallback state, and does not render the official content in the default state until a certain condition is reached. It is easier to display asynchronous rendering using the Suspense component. : warning if you use Suspense, return the use of a promise: Suspense component:

Loading...

AsyncComponent.vue:

{.})

Vue.nextTick () is a global API exposed directly from the Vue object. In fact, $nextTick () is just a simple wrapper for Vue.nextTick (), binding the this of the latter's callback function to the current instance for convenience. Although we use webpack's tree-shaking, whether we actually use Vue.nextTick () or not, we end up in our production code, because the Vue instance is exported as a single object, and the Packer cannot insist on which properties of the object are always used by the code. Rewrite it in Vue3.x like this:

Import {nextTick} from "vue" nextTick (() = > {...}) affected API

This is a big change because the previous global API can now only be imported by name, and this change affects the following API:

Vue.nextTick

Vue.observable (replaced with Vue.reactive)

Vue.version

Vue.compile (available in full version only)

Vue.set (available only in 2.x compatible versions)

Vue.delete (same as above)

Built-in tool

In addition to the API above, there are many built-in components that apply only to ES Modules builds, and are used to support tree-shaking binders-- the UMD build still includes all the features and exposes everything on the Vue global variable (the compiler will generate the appropriate output to use the global external api instead of the import). : the front are some new features of Vue3.0, and then I will focus on what has changed compared to Vue2.x.

Change the syntax of slot named slots

In Vue2.x, the writing of a named slot:

Use in the parent component:

Song: Chengdu

If we want to bind data on the slot, we can use the scope slot as follows:

/ / Sub-component export default {data () {return {data: ["people come and go", "appreciate it even if you don't like it", "companionship is the most lasting confession"]}} {{item}}

Named slots and scope slots are implemented by slot and slot-scope respectively in Vue2.x, and slot and slot-scope are combined and agreed to use in Vue3.0. V-slot in Vue3.0:

{{item}} {{item}} Custom instruction

First, review the implementation of a custom directive in Vue 2:

/ / register a global custom directive `v-focus` Vue.directive ('focus', {/ / when the bound element is inserted into the DOM. Inserted: function (el) {/ / focus element el.focus ()})

In Vue 2, custom instructions are created with the following optional hooks:

Bind: called only once, the first time an instruction is bound to an element. One-time initialization settings can be made here.

Inserted: called when the bound element is inserted into the parent node (only the parent node is guaranteed to exist, but not necessarily inserted into the document).

Update: called when the VNode of the component in which it is located is updated, but may occur before its child VNode update. The value of the instruction may or may not have changed. However, you can ignore unnecessary template updates by comparing the values before and after the update (see below for detailed hook function parameters).

ComponentUpdated: called after the VNode and its child VNode of the component to which the instruction belongs are all updated.

Unbind: called only once, when the instruction is unbound from the element.

More semantic changes have been made to the API of custom instructions in Vue 3, just like component lifecycle changes, for better semantics, as follows:

So in Vue3, you can customize instructions like this:

Const {createApp} from "vue" const app = createApp ({}) app.directive ('focus', {mounted (el) {el.focus ()}})

You can then use the new v-focus directive on any element in the template, as follows:

V-model upgrade

We learned that great changes have taken place in v-model before using Vue 3, and only after using get can we really realize these changes. Let's take a look at what changes have taken place, and then talk about how to use them:

Change: when using v-model on custom components, the default names of properties and events change

Change: the .sync modifier of v-bind was removed in Vue 3 and merged into v-model

Added: multiple v-model can be set for the same component at the same time

Added: developers can customize the v-model modifier

A little confused? Don't worry, in Vue2, using v-model on a component actually passes the value property and triggers the input event:

At this point, v-model can only be bound to the value property of the component, so we are unhappy. It's like giving our component a different property, and we don't want to update the value by triggering input, as we did in Vue 2 before .async came out:

/ / Sub-component: searchInput.vue export default {model: {prop: 'search', event:'change'}}

After modification, the use of v-model for searchInput components is equivalent to this:

However, in actual development, we may need to "two-way bind" a prop in some scenarios. Here is the most common example of modal: modal is suitable for two-way binding of attributes, the external can control the visible display or hiding of the component, the internal closure of the component can control the hiding of visible attributes, and the visible attributes can be transferred to the external synchronously. Within the component, when we close modal, we trigger the event in update:PropName mode in the subcomponent:

This.$emit ('update:visible', false)

You can then listen to this event for data updates in the parent component:

At this point we can also use v-bind.async to simplify the implementation:

The above reviews the v-model implementation in Vue2 and the two-way binding of component properties, so how should it be implemented in Vue 3? In Vue3, using v-model on a custom component is equivalent to passing a modelValue property and triggering a update:modelValue event:

If you want to bind property names, you only need to pass a parameter to v-model, and you can bind multiple v-model at the same time:

I don't know if you have noticed that there is nothing wrong with async at all, so, Vue 3 abandons the .async method and uses v-model.

Asynchronous component

DefineAsyncComponent is used in Vue3 to define asynchronous components, and the configuration option component is replaced with loader. The Loader function itself no longer receives resolve and reject parameters, and must return a Promise. The usage is as follows:

Import {defineAsyncComponent} from "vue" Export default {components: {/ / Asynchronous component AsyncPage: defineAsyncComponent (() = > import (". / NextPage.vue")), / / Asynchronous component with configuration item AsyncPageWithOptions: defineAsyncComponent ({loader: () = > import (".NextPage.vue"), delay: 200, timeout: 3000, errorComponent: () = > import (". / ErrorComponent.vue") LoadingComponent: () = > import (". / LoadingComponent.vue"),})}, thank you for reading! This is the end of this article on "Vue3.0 new features and sample analysis". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report