preface

As for VUe3, it has been more than a year since its birth. Although the usage rate is still low, the popularity and users of the community and Github are rising steadily. Therefore, learning vue3 well will be very helpful for us now and in the future. Here to write a blog, record, convenient for their future study and access

My name is Yuko, a small programmer

Introduction to Vue3

The ecology of VuE3

  • Community ecology – gradually improved
  • Overall optimization – Performance optimization /TS support optimization/combined API support
  • Market use – VuE3 is already being used in production environments by some companies with aggressive technology selection

Community ecology

Component (plug-in) name The official address Introduction to the
ant-design-vue Antdv.com/docs/vue/in… Ant-design-vue is a VUE implementation of Ant Design, and the style of the components keeps pace with Ant Design
element-plus element-plus.gitee.io/#/zh-CN Element Plus, a Vue 3.0-based desktop component library for developers, designers and product managers
vant Vant – contrib. Gitee. IO/vant/v3 / # / z… The open source mobile component library of the Awesome front End team was opened in 2016 and has been maintained for 4 years
Naive UI www.naiveui.com/zh-CN/ A Vue 3 component library is complete, theme tunable, uses TypeScript, not too slow, but interesting
VueUse vueuse.org/ A common collection based on the Composition API
## Vue3 development environment construction

Next we will learn some new syntax of VUe3. First we will build a basic environment, or use the familiar VUE-CLI to quickly build an integrated vue3 environment

Task of this section: Master how to use VUE-CLI to build a development environment based on Vue3.0

1) Select custom configuration

2) Select the custom installation version

3) Select version 3.x

After the above step, vuE-CLI will help us run a vUE project with vuE3 built in

Json file, as shown in the Dependencies configuration item. The version we currently use is 3.2.0

"Dependencies ": {"vue":" 3.2.0"}Copy the code

. Then open the main entrance js file, found that some changes have taken place in the instantiation of the Vue, by previous instantiate new keywords, into createApp method call form (for more details: www.bilibili.com/read/cv1013.)

vue2.x

new Vue({
  el: '#app',
  render: h => h(App)
})
Copy the code

vue3.x

import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
Copy the code

Finally, we opened a single file component and found that the single file component of Vue3.0 no longer requires a unique root element

<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
</template>
Copy the code

That’s all we need to focus on at this stage, so we can learn vue3’s new Composition API based on our current environment

Two apis in Vue3

The Composition API is a very valuable update to vue3 for us as developers. We don’t care about the syntax, but we have a general sense of it

Objective of this section: Get a general sense of composition apis

Style contrast

Case comparison

In this section, we will take a closer look at the comparison of development modes between the two apis through a specific case study. We will ignore the syntax details for the moment and focus only on the code writing form

Objective: To understand the benefits of the Compition Api by implementing the same requirement in both Api forms

Understanding the requirements

Optional Api version implementation

<template> <div> <! <button @click="show"> </button> <button @click="hide"> </button> <div v-if="showDiv"> </div> <div> <! <button @click="changeRed"> red </button> <button @click="changeYellow"> blue </button> <div :style=" color:${fontColor} '"> </div> </div> </template> <script> export default {name: 'App', data() {return {showDiv: true, // fontColor: "// function 2 data}}, methods: Show () {this.showdiv = true}, hide() {this.showdiv = false}, ChangeRed () {this.fontColor = 'red'}, changeYellow() {this.fontColor = 'blue'}}} </script>Copy the code

Combined API version

<template> <div> <! <button @click="show"> display </button> </button @click="hide"> hide </button> <div V-if ="showDivFlag"> a div</div> </div> <div> <! <button @click="changeRed"> red </button> <button @click="changeBlue"> blue </button> <div :style=" color:${fontColor} '"> a div</div> </template> <script> import {ref} from 'vue' export default { name: 'App', Setup () {const showDivFlag = ref(true) function show() {showdivflag. value = true} function hide() { // Const fontColor = ref('') function changeRed() {fontcolor. value = 'red'} function changeBlue() { fontColor.value = 'blue' } return { showDivFlag, show, hide, fontColor, changeRed, changeBlue } } } </script>Copy the code

Combined API optimized version

You might wonder, well, now that we’re keeping all the data and behavior related to the functionality together, doesn’t the setup function get really big if you’re using a lot of functionality? It will become more difficult to maintain, so let’s take apart the huge setup function

<script> import {ref} from 'vue' // function A function useShow() {const showDivFlag = ref(true) function show() { showDivFlag.value = true } function hide() { showDivFlag.value = false } return { showDivFlag, show, Function useColor() {const fontColor = ref('') function changeRed() {fontcolor. value = 'red'} function changeBlue() { fontColor.value = 'blue' } return { fontColor, changeRed, changeBlue } } export default { name: Setup () {const {showDivFlag, show, hide} = useShow() const {fontColor, changeRed, changeBlue } = useColor() return { showDivFlag, show, hide, fontColor, changeRed, changeBlue } } } </script>Copy the code

Above, we define the function function, separate the two function related code into a separate small function, and then combine the two small function functions in the setup function, so that we can not only clean up the setup function, but also easy to maintain and quickly locate the function location

The relationship between optional and composite apis

Goal: Be able to understand the relationship between two apis

  1. Composite apis are intended to enhance, not replace, alternative apis, and Vue3. X supports both
  2. Simple scenarios are easier and more convenient to use with optional apis
  3. Preferred composite apis for projects that require strong TS support
  4. Composite apis are preferred for scenarios that require a lot of logical reuse

Nice ~ so far we have not focused on the details of the API, just to appreciate the benefits of the composite API. Now we will dive into the details of the API and see how the new API is used

Modular API

Setup entry function

Objective: To understand what the setup function does and when to call it

The main content

  1. The setup function is a new component option that serves as a starting point (entry) for the composite API in the component
  2. The setup function is executed only once when the component is initialized
  3. The setup function is executed before the beforeCreate lifecycle hook is executed, the instance has not been generated, and there is no this

Code demo

Export default {setup () {console.log('setup performed ') console.log(this)}, BeforeCreate () {console.log('beforeCreate performed ') console.log(this)}}Copy the code

Reactive API-Reactive

Objective of this section: Learn the functions and procedures of reactive functions

role

Reactive is a function that receives an ordinary object, converts the object data into a reactive object and returns it

Using the step

  1. Import from the VUE frameworkreactivefunction
  2. Call reactive in the setup function and pass in the object data that you want to make responsive as arguments
  3. The setup function returns the value of a call to reactive as an object

Code demo

< the template > < div > {{state. The name}} < / div > < div > {{state. The age}} < / div > < button @ click = "state. The name = 'pink'" > change value < / button > </template> <script> import { reactive } from 'vue' export default { setup () { const state = reactive({ name: 'zs', age: 18 }) return { state } } } </script>Copy the code

Reactive API-ref

Objective of this section: to understand the functions and procedures of ref function

role

Ref is a function that takes an incoming simple type or complex type and returns a responsive, mutable ref object

Using the step

  1. Export from the VUE frameworkreffunction
  2. Called in the setup functionrefFunction and pass in data (simple or complex type)
  3. The setup function returns the value of the ref call as an object
  4. Note:To use the ref result in the setup function, pass.valueValue is not required for use in templates

Code demo

<template> <div>{{money}}</div> < button@click ="changeMondy"> </button> </template> <script> import {ref} from 'vue' export default { setup() { let money = ref(100) console.log(money.value) return { money } } } </script>Copy the code

Reactive contrast ref

Objective of this section: Know the specific nature of the two apis and how to choose between them in the project

  1. A ref function can take a value of a simple type and return a ref-responsive object that can be changed to compensate for the lack of simple type support in reactive functions
  2. Reactive and REF functions both provide reactive data conversion. There are no community best practices on which API to use and when, so you can use your own API for conversion
  3. Reactive is used only if we know exactly what field names are inside the object to be transformed, otherwise ref is used to reduce the mental burden of choosing a syntax

Responsive API – Computed

Objective of this section: To learn how to use computed in computing the attribute function

role

According to the existing responsive data, the new data is obtained through certain calculation

Using the step

  1. Import from the VUE frameworkcomputedfunction
  2. Perform a computed function in the setup function and pass in a function that defines the calculation formula
  3. Put the value returned after a computed function call into an object that the setup function returns

Code demo

<template> {{ list }} {{ filterList }} <button @click="changeList">change list</button> </template> <script> import { computed, ref } from 'vue' export default { setup() { const list = ref([1, 2, 3, 4, 5, 6]) // Enter a number greater than 2 const filterList = computed(() => {return list.value.filter(item => item > 2)}) // Modify the list function changeList() { list.value.push(6, 7, 8) } return { list, filterList, changeList } } } </script>Copy the code

Responsive API-Watch

Objective of this section: to understand what the watch function does and how to use it

role

Callback logic based on changes in reactive data is the same as watch in VUe2

  1. Ordinary listening
  2. Executed immediately
  3. The depth of the listening

Using the step

  1. Import the Watch function from the VUE framework

  2. Enable listening for reactive data by executing the watch function in the setup function

  3. The watch function takes three general arguments

    1. The first argument is a function that returns the responsive data you want to listen for changes
    2. The second parameter is the callback function to execute after a reactive data change
    3. The third parameter is an object in which to enable immediate execution or deep listening

Code demo

1) General monitoring

<template> {{ age }} <button @click="age++">change age</button> </template> <script> import { ref, watch } from 'vue' export default { setup() { const age = ref(18) watch(() => { return age.value }, () => console.log('age has changed ')}) return {age}} </script>Copy the code

2) Enable immediate execution

By default, the watch callback is executed only when the monitored data changes. If you want to execute the callback immediately, you need to configure the immediate attribute

<template> {{ age }} <button @click="age++">change age</button> </template> <script> import { ref, Watch} from 'vue' export default {setup() {const age = ref(18) watch(() => {// Return the response attribute you want to listen on. Return age.value}, () => console.log('age changed ')},{immediate: true}) return {age}} </script>Copy the code

3) Enable deep listening

By default, when the data we are listening to is an object, the callback function will not be executed if the properties inside the object are changed. If you want all properties of the object to be listened on, you need to enable the deep configuration

<template> {{ state.name }} {{ state.info.age }} <button @click="name = 'pink'">change name</button> <button @click="info.age++">change age</button> </template> <script> import { reactive, toRefs, watch } from 'vue' export default { setup() { const state = reactive({ name: 'zs', info: { age: 18}}) watch(() => {return state}, () => {console.log('age changed ')}, {deep: true }) return { state } } } </script>Copy the code

4) A better way

When using Watch, be as specific as possible about which properties you want to listen for to avoid the performance problems associated with using deep. For example, I only want to perform a callback when the age property of the state object changes

<template> {{ state.name }} {{ state.info.age }} <button @click="state.name = 'pink'">change name</button> <button @click="state.info.age++">change age</button> </template> <script> import { reactive, toRefs, watch } from 'vue' export default { setup() { const state = reactive({ name: 'zs', info: { age: 18}}) watch(() => {return state.info.age}, () => console.log('age changed ')}) return {state}}} </script>Copy the code

Life cycle function

Review the life cycle

Objective of this section: review the lifecycle and understand the role of the lifecycle

Use the lifecycle hook function in the setup function

Goal of this section: Learn how to use life cycle functions in setup functions

Using the step

  1. Import from vUE firstOn headingThe lifecycle hook function of
  2. Call the lifecycle function in the setup function and pass in the callback function
  3. Lifecycle hook functions can be called multiple times

Code demo

<template> <div> Life cycle function </div> </template> <script> import {onMounted} from 'vue' export default {setup() {// The time is ripe OnMounted (() => {console.log('mouted lifecycle ')}) onMounted(() => {console.log('mouted lifecycle ')})}} </script>Copy the code
Life cycle functions under the optional API Use of life cycle functions under the composite API
beforeCreate No need (directly to the setup function)
created No need (directly to the setup function)
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestroy Vue 3: beforeUnmount onBeforeUnmount
destroyed Vue 3: unmounted onUnmounted

Lifecycle hook function usage scenarios

Lifecycle hook functions Application scenarios
created Send ajax requests/mount shared properties
mounted Send Ajax requests/DOM-dependent businesses such as maps, charts
destroyed -> unmounted Destroy operations, such as timers

Parent-child communication

Objective of this section: Master parent-child communication under the combined API

In vue3 combined API, the basic routine of parent to child is exactly the same, the basic idea is still: parent to child is passed in through prop, and child to parent is completed by calling custom events

Implementation steps

  1. The setup function takes two arguments, the first parameter being props and the second parameter being an object context
  2. Props is an object that contains all prop data passed by the parent component. The context object contains the attrs, slots, emit properties, of which the props is an objectemitYou can trigger the execution of a custom event to complete child to parent transmission

Code demo

app.vue

<template>
  <son :msg="msg" @get-msg="getMsg"></son>
</template>
​
<script>
import { ref } from 'vue'
import Son from './components/son'
export default {
  components: {
    Son
  },
  setup() {
    const msg = ref('this is msg')
    function getMsg(msg) {
      console.log(msg)
    }
    return {
      msg,
      getMsg
    }
  }
}
</script>
Copy the code

components/Son.vue

<template> <div> {{msg}} <button @click="setMsgFromSon">set</button> </div> </template> <script> export default { props:  { msg: { type: String } }, emits: ['get-msg'], Setup (props,{emit}) {function setMsgFromSon(){emit('get-msg',' this is a new MSG message from a child component ')} return {// Declare a custom event triggered by the current component setup(props,{emit}) {function setMsgFromSon(){emit('get-msg',' this is a new MSG message from a child component ')} return { setMsgToSon } } } </script>Copy the code

Dojo.provide and inject

1. Application scenarios

Objective of this section: to be able to clarify the usage scenarios of this API, and what problems are solved

Usually, we use props to transfer data between parent and child. However, if components are nested at a deeper level, layer by layer transmission becomes very complicated. Is there a way to simplify this process? Together, they make it easy to transfer data from a top-level component to any underlying component

2. Basic use

Objective of this section: To learn the basics of using provide and Inject in setup functions

Requirement: the parent component has a copy of data passed to the grandson component for direct use

Implementation steps

  1. The top-level component provides data in the setup method using the provide function

    Provide ('key', data)

  2. Any underlying component retrieves data using the Inject function in the setup method

    const data = inject('key')

The code to the ground

Grandpa component - app.vue

<template> <father></father> </template> <script> import Father from '@/components/Father' import { provide } from 'vue'  export default { components: {Father}, setup() {let name = 'Father' // provide key-value provide('name', name)}} </script>Copy the code

Suncomponent-components/son.vue

<template> I am a child component {{name}} </template> <script> import {inject} from 'vue' export default {setup() {const name = inject('name') return { name } } } </script>Copy the code

In fact, any descendant component can easily access the data provided by the top-level component

Pass reactive data

By default, the data transferred by provide is not reactive, that is, if the data provided by provide is modified, it cannot affect the use of data by underlying components in a reactive manner. If you want to transfer the response data, you only need to use REF or Reactive to generate the passed data

Objective of this section: How to provide/inject responsive data

app.vue

<template> <father></father> <button @click="changeName">change name</button> </template> <script> import Father from '@/components/Father' import { provide, ref } from 'vue' export default { components: { Father }, Function changeName(){name.value = 'pink'} provide('name', name) return { changeName } } } </script>Copy the code

TemplateRef

The goal of this section is to learn how to get a DOM node or component instance object using ref in the Setup function

Background knowledge

When we use ref in templates, we all know that there are three common scenarios for using it

  1. Ref + Plain DOM tag gets the real DOM object

    this.$refs.box

  2. This.$refs.form.validate()
  3. Ref + V-for gets an array of DOM objects (instance objects) (not often used)

Implementation steps

  1. Create a ref object with null =>const hRef = ref(null)
  2. Create a template association by defining the name of the ref object created in the ref attribute =><h1 ref="hRef"></h1>
  3. thehRefReturn to go out
  4. Using = >hRef.value

The code to the ground

components/RefComponent.vue

<template> I am a normal component </template>Copy the code

app.vue

<template> <h1 ref="h1Ref"> I am a normal DOM tag </h1> <ref-component ref="comRef"></ref-component> </template> <script> import { onMounted, ref } from 'vue' import RefComponent from '@/components/RefComponent' export default { components: { RefComponent }, setup() { const h1Ref = ref(null) const comRef = ref(null) onMounted(() => { console.log(h1Ref.value) Console. log(comref.value)}) // Must return return {h1Ref, comRef}} </script>Copy the code

Incompatible syntax

Vue3.0 is compatible with most of the syntax of version 2.0, but there are some damaging syntax updates, which should be paid attention to

  1. Instance method $ON removed (Existing implementation mode of eventBus no longer supports tripartite plug-in instead)

    event Bus 1. Vue.prototype.$eventBus = new Vue() 2. Receiving data of the components in this. $eventBus. $on (' get - MSG '(MSG) = > {}) 3. $emit('get-msg',' sent data ') in vue3, eventBus mode is not supported by default using third-party plugins insteadCopy the code
  2. Filter removed (interpolation can no longer use filters, can use methods instead)

    The filter filter string formatting method receives the original string Returns the formatted string {{MSG | formatMsg}} vue3 directly removed the grammar can directly use the methods to replace {{formatMsg (' this is the MSG ') }} // What is the result of rendering? {formatMsg(MSG){return MSG + 'zs'}}Copy the code
  3. .sync syntax removed (merged with V-model syntax)

    ElementUI -> Dialog visible. Sync ="showFlag"Copy the code

Read more: v3.cn.vuejs.org/guide/migra…