This Vue3 note is based on the jspang.com video tutorial and written by TS

Front knowledge

  • Vue2.x
  • TypeScript
  • npm

Vue3 project construction

Vue-cli is used here to set up the project

First, install vuE-CLI globally. The version must be later than 4.5

npm install -g @vue/cli
Copy the code

Find an empty directory, open the terminal, and run the vue create vue3-1 command

The following dialog appears, where we choose to customize the template manually because we are using TypeScript

After selecting the manual custom template, the following dialog appears, where we select TypeScript, press space to select, and press Enter to proceed to the next step

The following dialog appears, and we choose3.xAnd thenenterGo to the next step

If the following dialog is displayed, choose to compile toJSXSyntax, here we chooseNo

Select No or the first option if the following options are displayed

Here we have the option to write the file separately or to write package.json. Here we choose the first option to write the file separately

The following dialog appears asking if you want to save the Settings. Here we select No

If the following information appears, the project is completed

Execute the prompt command to start the project, so vUE/CLI vuE3 project is completed

cd vue3-1
npm run serve
Copy the code

For details about using vuE3 automatic templates, please see “Front-end Beauty”.

Initial directory structure

node_modules

All projects depend on packages

public

Public folder

  1. favicon.ico
  2. Index.html entrancehtmlfile

src

All the code that was written

  1. Assets static file
  2. Components User-defined components
  3. App. Vue with components
  4. Main.ts entry file
  5. The shims-vue.d.ts class file/definition file defines a file for TS to recognize VUE

.browserslistrc

Compatibility between different front-end tools function browsers to configure node versions

.eslintrc.js

Configuration file for ESLint

.gitignore

The file uploaded to Git was not configured

package.json

"{" name" : "vue3-1, / / project name" version ":" 0.1.0 from ", / / project version "private" : true, "scripts" : {" serve ": "Vue-cli-service serve",// start locally "build": "vue-cli-service build",// pack "lint": "Vue-cli-service lint",// code check}, "dependencies": {// production "vue": "^3.0.0-0"}, "devDependencies": {// Development environment "@typescript-eslint/eslint-plugin": "^2.33.0", "@typescript-eslint/parser": "^ 2.33.0 @", "vue/cli - plugin - eslint" : "~ 4.5.0", "@ vue/cli - plugin - typescript" : "~ 4.5.0", "@ vue/cli - service" : "~ 4.5.0 @", "vue/compiler - the SFC" : "^ 3.0.0-0", "@ vue/eslint - config - typescript" : "^ 5.0.2", "eslint" : "^ 6.7.2 eslint", "- the plugin - vue" : "^ 7.0.0-0" and "typescript" : "~ 3.9.3}}"Copy the code

tsconfig.json

Ts configuration file

SRC/main. Ts, rounding

App import App from './ app.vue '// Root component createApp(App).mount('# App ') // Create an App component to mount to the root nodeCopy the code

Setup and ref functions

First open app.vue and remove all the extra code

<template></template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
  name: 'App'
});
</script>
Copy the code

Change the template to the following

< the template > < div > < h2 > welcome to XX class < / h2 > < p > please select a language learning < / p > < div > < button > < / button > < / div > <! </div> </template>Copy the code

Modify the script as follows

<script lang="ts"> import { defineComponent,ref } from 'vue'; // Export default defineComponent({name: 'App', // data(){return{}} methods:{}... Setup (){const languages = ref([' HTML ',' CSS ','javascript']); Return {languages // and return data}}}); </script>Copy the code

Then modify the template to loop out the data from the script return

<button v-for="(item,index) in languages" :key="index">{{index}}:{{item}}</button>
Copy the code

This is a good time to preview the content of the page

We then need to first add a line to the Template to display the selection

<div> You chose the {{selectLan}} language </div> <! -- Note: there is a selectLan here.Copy the code

Then add the method and the value after the selection to the script setup function

setup(){ const languages = ref(['html','css','javascript']); const selectLan = ref(""); Const selectLanFun = (index:) const selectLanFun = (index:) const selectLanFun = (index:) const selectLanFun = (index: Number) => {// Value selectlan. value = languages.value[index]} return {languages,// }}}}}}}}}}}}}}}Copy the code

Then add the click event to the Button in the Template

<button 
    v-for="(item,index) in languages" 
    :key="index" 
    @click="selectLanFun(index)"
>{{index}}:{{item}}</button>
Copy the code

Reactive function

This function mainly optimizes the code from the previous section

  1. The main optimizationsetupIn the functionmethodsvariableIt’s all mixed up
  2. To optimize theSet up theandGet ` ` refValues are requiredvalueIn the form of

Let’s start with a small change

Remove the defineComponent introduced and change the exposure to the following

import { ref } from 'vue'
export default {
    ...
}
Copy the code

The program can run normally without error after detection

Next, let’s tune inside setup

Setup (){const data = reactive({languages:[' HTML ',' CSS ','javascript']); SelectLan: ",// The selected language selectLanFun:(index: Data.selectlan = data.languages[index]; // Select data.languages[index]; // const languages = ref([' HTML ',' CSS ','javascript']); // const selectLan = ref(""); // select language // const selectLanFun = (index: number) => { // selectLan.value = languages.value[index] // } return { data // languages, // selectLan, // selectLanFun } }Copy the code

Modify the data in template by prefacing data.

<div> <button v-for="(item,index) in data.languages" :key="index" @ click = "data. SelectLanFun (index)" > {{index}}, {{item}} < / button > < / div > < div > you have chosen to {{data. SelectLan}} [language] < / div >Copy the code

Because we use TypeScript here, we add ts-specific type annotations to make our code more rigorous

What is a type annotation? It refers to the determination of the data type of a variable or parameter without the use of type inference.

We write a formal interface definition type annotation on export Default

interface DataProps{
  languages:string[];
  selectLan:string;
  selectLanFun:(index:number)=> void;
}
Copy the code

In this case, if we add the type annotation to data inside the setup function, the properties under data will all have the specified data type

const data: DataProps = reactive({
    languages:['html','css','javascript'],
    selectLan:'',
    selectLanFun:(index: number)=>{
      data.selectLan = data.languages[index]
    }
})
Copy the code

Now we don’t want to use data in the template so how do we do that

ToRefs function

First of all, we introduce toRefs when we introduce Reactive

import { reactive,toRefs } from 'vue';
Copy the code

Change the setup function to wrap data in toRefs

const data: DataProps = reactive({
    languages:['html','css','javascript'],
    selectLan:'',
    selectLanFun:(index: number)=>{
      data.selectLan = data.languages[index]
    }
})
const refData = toRefs(data);
Copy the code

In this case, we need to return the wrapped data as refData and use the extension operator to expand it

return{ ... refData }Copy the code

Finally, remove the data in template. After checking, it is found that there is no error and the program can be used normally

The lifecycle of VUE3

  • Setup (): Execute before beforeCreate and Created before starting component creation. Create data and Method

  • OnBeforeMount (): Function executed before the component is mounted to the node.

  • OnMounted (): a function executed after components are mounted.

  • OnBeforeUpdate (): Function executed before component updates.

  • OnUpdated (): Function to execute after the component is updated.

  • OnBeforeUnmount (): Function executed before component unmounts.

  • OnUnmounted (): the function executed after the component is unmounted

  • OnActivated (): The component that is included in this component has two additional lifecycle hook functions. Executed when activated.

  • OnDeactivated (): Switches from component A to component B, for example, when component A disappears.

  • OnErrorCaptured (): Activates the hook function when an exception from a descendant component is captured.

Lifecycle functions must be introduced before using them (except setup)

import { onMounted, onBeforeMount, onBeforeUpdate, onUpdated, } from "vue"; Export default {name: "App", setup() {console.log("1- Start creating component -----setup()"); const data: DataProps = reactive({ language: ["html", "css", "javascript"], selectLan: "", selectLanFun: (index: number) => { data.selectLan = data.languages[index] }, }); OnBeforeMount (() => {console.log("2- execute -----onBeforeMount() before mounting components to the page "); }); OnMounted (() = > {the console. The log (" 3 - the components mounted to the page after execution -- -- -- -- -- onMounted () "); }); OnBeforeUpdate (() => {console.log("4- component before update -----onBeforeUpdate()"); }); OnUpdated (() = > {the console. The log (" 5 - components after the update -- -- -- -- -- onUpdated () "); }); const refData = toRefs(data); return { ... refData, }; }}}Copy the code

You can also write the Vue2 lifecycle function after the setup() function, as follows

BeforeCreate () {console.log("1- before component creation -----beforeCreate()"); }, beforeMount() {console.log("2- perform ----- beforeMount() before mounting components to the page "); {}, mounted () the console. The log (" 3 - the components mounted to the page after execution -- -- -- -- -- mounted () "); }, beforeUpdate() {console.log("4- component beforeUpdate ----- beforeUpdate() "); {}, updated () the console. The log (" 5 - components after the update -- -- -- -- -- the updated () "); },Copy the code

Vue2. X and Vue3. X life cycle comparison

Vue2--------------vue3
beforeCreate  -> setup()
created       -> setup()
beforeMount   -> onBeforeMount
mounted       -> onMounted
beforeUpdate  -> onBeforeUpdate
updated       -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed     -> onUnmounted
activated     -> onActivated
deactivated   -> onDeactivated
errorCaptured -> onErrorCaptured
Copy the code

OnRenderTracked () and onRenderTriggered() hook functions are used

These two hook functions are newly added in Vue3. X version. Officially, they are used for debugging, but there are no specific debugging cases

Principles for using old and new hook functions

Vue official documentation, it is clearly stated. If you are using Vue3, try to use the new lifecycle hook functions, the ones with on in the setup() function in the previous article

OnRenderTracked state tracking

OnRenderTracked literally is state tracking, so it tracks the state of all the responsive variables and methods on the page, the values that we return, it tracks. Whenever there is an update on the page, it tracks it and generates an event object that we use to find problems with the program

Using onRenderTracked is also introduced using import

The reference is then used in the setup() function

import { .... ,onRenderTracked,} from "vue"; OnRenderTracked (= > {(event). The console log (" state tracking component -- -- -- -- -- -- -- -- -- -- - > "); console.log(event); });Copy the code

After that you can go to a terminal and start the test service Yarn Serve and see what happens. OnRenderTracked is not executed if the component is not updated. When the component is updated, it changes every value and method in the group

OnRenderTriggered state triggered

OnRenderTriggered is a state trigger that does not track every value. It gives you information about changing values, and both old and new values are explicitly displayed

To use it again, import is introduced first

import { .... ,onRenderTriggered,} from "vue";
Copy the code

Before using onRenderTriggered, comment the corresponding onRenderTracked code so it looks a lot more intuitive. Write the onRenderTriggered() function inside the setup() function

OnRenderTriggered (= > {(event). The console log (" state trigger components -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- > "); console.log(event); });Copy the code

Details on the Properties of the Event object:

- Key Which variable is changed - newValue Value of the variable after the update - oldValue Value of the variable before the update - target Response variable and function in the current pageCopy the code

Use and precautions of Watch in Vue3

Vue2 also has a watch-listener, which is used to detect changes in responsive data and can get newValue and oldValue, but in Vue3 watch has some slight changes

This article will implement a function to modify the page title

Start by adding the following code to the Template section

</button></div> </div>Copy the code

Make the page look like the image below

Then ref and watch are introduced in the TS section

import { ref,reactive,toRefs,watch  } from 'vue';
Copy the code

Add the following code before return in the setup function

Const overText = ref (" xx classroom ") / / define an attribute is used to display in the template const overAction = () = > {/ / define a method used to click overText value = "order complete | +" overText.value; } watch([overText,()=> data.selectlan],(newValue,oldValue) => {//watch event listener, Console. log(newValue,oldValue) document.title = newValue[0]; // Modify page title})Copy the code

Return the overText and overAction defined in the setup function

return { ... refData, overText, overAction }Copy the code

Then bind the click event to the button in the Template to render the content

</button></div> {{overText}}</div>Copy the code

Here’s the Watch event listener

Watch is a function that is called directly when used, but requires two arguments

  1. The first argument is an Array or String
  2. The second argument is a callback function that also takes two arguments, newValue and oldValue

When the first argument is Array, newValue and oldValue are arrays, respectively

[Note] : If you listen for the parameters below the toRefs wrapped object, you must use the getter, so we use the arrow function to return it, making a fake getter

This section describes modularity in Vue3

This time we are going to create a function that needs to display a time on the page, as shown in the picture below

First open app. vue, first implement the function and delete all useless codes. The deleted codes are shown below

<template>
  <div></div>
</template>

<script lang="ts">
import { ref } from 'vue'
export default {
  name: 'App',
  setup(){
  }
}
</script>
Copy the code

Let’s start implementing the functionality

Add the following to template

The < div > < p > {{nowTime}} < / p > < button @ click = "getNowTime" > show time < / button > < / div >Copy the code

Add the following to the setup function

setup(){ const nowTime = ref('00:00:00'); Const getNowTime = () => {const now = new Date(); const hour = now.getHours() < 10 ? '0'+now.getHours() : now.getHours(); // const minu = now.getminutes () < 10? '0'+now.getMinutes() : now.getMinutes(); Const SEC = now.getseconds () < 10? '0'+now.getSeconds() : now.getSeconds(); Value = hour+":"+minu+":"+ SEC; SetTimeout (getNowTime,1000)} return{nowTime, getNowTime}}Copy the code

The code is basically realized, you can click the show time button, show the time

But, obviously, it’s all implemented in our app.vue, so we’re going to change the time display in a modular way

Start by creating a new hooks directory in the SRC directory and create a new usenowtime. ts file in the hooks directory

Copy everything from the setup function in app. vue to usenowtime. ts except return

We get an error because we don’t have ref, so we need to introduce ref

Since we need to use this module outside, we need to export it. The specific code of usenowtime. ts is as follows

import { ref } from 'vue';
const nowTime = ref('00:00:00');
const getNowTime = () => {
    const now = new Date();
    const hour = now.getHours() < 10 ? '0'+now.getHours() : now.getHours();
    const minu = now.getMinutes() < 10 ? '0'+now.getMinutes() : now.getMinutes();
    const sec = now.getSeconds() < 10 ? '0'+now.getSeconds() : now.getSeconds();
    nowTime.value = hour+":"+minu+":"+sec;
    setTimeout(getNowTime,1000)
}

export {nowTime,getNowTime}
Copy the code

Next we go back to the app.ts file and need to introduce the properties and methods exposed by the usenowtime. ts module

And return to be used in template

The script of app. vue after modification is as follows

<script lang="ts"> import {nowTime,getNowTime} from './hooks/useNowTime'; Export default {name: // import the exposed attributes and methods in the module. 'App', setup(){return{// Expose properties and methods in the module to the current file to use nowTime in the template, getNowTime}}} </script>Copy the code

An exercise in modularity in Vue3

This time implement a function, randomly select a little sister

First we cleaned out the extra code in app.vue, leaving only the following code

<div> <script lang="ts"> export default {name: 'App', setup(){}} </script>Copy the code

NPM install axios -s

After the installation, create a new useurlaxios.ts file in the hooks directory to request data, as shown below

Import {ref} from 'vue' // import axios from 'axios' // import axios from 'axios' // define a method to pass in the argument url function useUrlAxios(url: string){ const result = ref(null); // Define the result, default is null const loading = ref(true); Const loaded = ref(false); // Define whether loading ends, default false const error = ref(null); // Define error feedback axios.get(url). Then ((res) => { loaded.value = true; result.value = res.data; }).catch(err => { error.value = err; Load. value = false}) return {result, loading, loaded, error}} export default useUrlAxios; // Since there is only one method in this module, export default is used hereCopy the code

Then we go back to app.vue

First introduce modules

import useUrlAxios from './hooks/useUrlAxios'
Copy the code

Then return the module return value in the setup function

setup(){
    const url = 'https://apiblog.jspang.com/default/getGirl';
    const { result,loading,loaded } = useUrlAxios(url);
    return{
      result,
      loading,
      loaded
    }
}
Copy the code

Finally, we modify the template

The < div > < h2 > random little sister < / h2 > < div v - if = "loading" > loading... </div> <img v-if="loaded" :src="result.imgUrl"> </div>Copy the code

Then you can refresh the page and randomly appear little sister photos

The API used here is jspang tutorial: 【 apiblog.jspang.com/default/get…

Use of Teleport standalone components

The Teleport component is used to mount a component to any DOM node, which was not possible in previous vue2. X, where all components are directly mounted under #app

First of all, let’s write a popup frame component. Click the button to show and hide for the time being

Create a new Model.vue in the Components directory and write the component

<template> <div id="center">Hello xueshuai.top ! </div> </template> <script lang="ts"></script> <style> #center { width: 200px; height: 200px; border: 2px solid black; background: white; position: fixed; left: 50%; top: 50%; margin-left: -100px; margin-top: -100px; } </style>Copy the code

Then enter app. vue and delete the previous code, leaving only a div in template and only a name in Export default in script

You then import the Modal component and register it in components

import modal from './components/modal.vue';
export default {
  name: 'App',
  components:{
    modal
  }
}
Copy the code

You can then use this component directly in the template using < Modal />

However, we can see that the component is mounted under #app. To allow it to be mounted under any DOM node, we need to open model.vue and add Teleport

<template> <! <teleport to="#modal"> <div ID ="center">Hello xueshuai. Top! </div> </teleport> </template>Copy the code

Then you need to add a Modal DIV node to the index. HTML file in the public directory so that you can mount the popup component to other DOM nodes

<div id="app"></div>
<div id="modal"></div>
Copy the code

You can open the browser console to see the effect

This was not possible in previous vue2. X, but it is easy to do in VUe3

Suspense- Getting to know asynchronous request components

First we will clean up the code we wrote before, and then rewrite the asyncshow. vue custom component

Note: If you are going to useSuspenseReturn a Promise object instead of the original oneJSONObject.

Create a new asyncshow. vue component in the Components directory and write the following code

<template> <h1>{{ result }}</h1> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ setup() { return new Promise((resolve, reject) => { setTimeout(() => { return resolve({ result: "XueShuai" }); }, 2000); }); }}); </script>Copy the code

DefineComponent is designed to address TypeScript situations where traditional ue. Extends does not give components the right argument type inference. That is, use the defineComponent() component to wrap functions in the TypeScript environment if argument type inference is not normal

Then we new a Promise object and use setTimeout to wait two seconds before returning XueShuai text

Next you need to put this component into app.vue

Start by importing and registering components in app.vue

import AsyncShow from './components/AsyncShow.vue'
export default {
  name: 'App',
  components:{
    AsyncShow
  }
}
Copy the code

Then use the component in the template

You wrap it up with the Suspense component, which has two template slots

  1. slotdefaultThe contents of the inner wrapper are what will be displayed when the asynchronous request succeeds
  2. slotfallbackThe content of the inner package is what is displayed when an asynchronous request fails
<div> <suspense> <template #default> <AsyncShow /> </template> <template #fallback> <h1>loading... </h1> </template> </suspense> </div>Copy the code

Suspense- Learn more about real requests

In the last article we actually used setTimoout to simulate requests. In this article we will write a real request

First presents the random of jspang provide little sister API: 【 apiblog.jspang.com/default/get…

Start by creating a new girlshow. vue component in the Components directory and write the following code

The previous article returned the Promise object, and this one uses async and awit, the syntactic sugar of the former

<template>
    <img :src="result && result.imgUrl"  />
</template>
<script lang="ts">
import axios from 'axios'
import { defineComponent } from 'vue'
export default defineComponent({
    async setup() {  //promise 语法糖  返回之后也是promise对象
        const rawData = await axios.get('https://apiblog.jspang.com/default/getGirl')
        return {result:rawData.data}
    }
})
</script>
Copy the code

Next introduce this component in app.vue and use Suspense

import GirlShow from './components/GirlShow.vue'
export default {
  name: 'App',
  components:{
    GirlShow  
  }
}
Copy the code

Use Suspense in template

<div> <suspense> <template #default> <girl-show /> </template> <template #fallback> <h1>loading... </h1> </template> </suspense> </div>Copy the code

At this point, the real requests for Suspense are implemented, and there is an exception catch

In vue3. X, you can use the onErrorCaptured hook function to catch exceptions. Before you can use this hook function, you need to introduce it

import {ref,onErrorCaptured} from 'vue'
Copy the code

Once the hook reference is complete, we can use it in the setup function

The hook function asks us to return a Boolean value indicating whether the error was passed up

setup() {
    onErrorCaptured((error) => {
      console.log(`error====>`,error)
      return true  
    })
    return {};
}
Copy the code

Personal blog: Click to enter

Front-end AC group: 1063233592