preface

Vue3 has been released almost a year from now 2021-11-28, and VUE2 is still mainly used in the market. Are your partners still hesitating to learn Vue3? This article does not tell you the answer, the author is also at a stage of studying Vue3, will only list what changes Vue3 has taken place in the end, and whether it brings surprises to us…… You can judge for yourself after reading this article

The more you know, the more you don’t know

I’m very happy with this picture

I. Ecology and advantages 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

Whole optimization

  1. Performance improvement

    • Faster first render
    • The Diff algorithm is faster
    • Less memory footprint
    • Packing volume is smaller
  2. Better Typescript support

  3. Composition API (Emphasis)

Related reading:

  1. Vue3 Chinese document vue3js.cn/docs/zh/
  2. Vue3 design concept vue3js.cn/vue-composi…

Market using

It’s got a lot of potential, but it hasn’t really caught on yet

Ii. Vue3 development environment construction

  1. Global installation vUE – CLI
npm i -g @vue/cli
Copy the code
  1. Create scaffolding
Vue create VUE3 - Demo (custom name)Copy the code

I chose the default vuE3 version, which can be customized

  1. Vue3 debugging tools need to download additional plug-ins, vue2 debugging tools to disable before you can use, both hands have been used by the author of the plug-in

Plug-in address

  1. 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

Add #app to template with appendChild (#app); insert #app with appendChild (#app); insert #app (#app)

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

However, eslint will report an error, so you need to find the vuter pinion in vscode – “extension Settings -“

Just uncheck this box and you’ll get away with it

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

1. Optional API in vue2

<template>
  <p>
    <button @click="show">According to</button>
    <button @click="hide">hidden</button>
  </p>
  <div class="id" v-if="isShow">I'm a div that shows hidden</div>
  <p>
    <button @click="changeWhite">white</button>
    <button @click="changeBlue">blue</button>
  </p>
  <div class="id" :style="{color}">I'm a div that changes the color of the text</div>
</template>

<script>
export default {
  name: "".data() {
    return {
      isShow: true.color:' '
    };
  },
  methods: {
    show() {
      this.isShow = true;
    },
    hide() {
      this.isShow = false;
    },
    changeWhite(){
      this.color = '#fff'
    },
    changeBlue(){
      this.color = 'blue'}}};</script>

<style scoped >
.id {
  width: 200px;
  height: 200px;
  background-color: red;
}
</style>

Copy the code

2. Composite apis

<template>
  <p>
    <button @click="show">According to</button>
    <button @click="hide">hidden</button>
  </p>
  <div class="id" v-if="isShow">I'm a div that shows hidden</div>
  <p>
    <button @click="changeWhite">white</button>
    <button @click="changeGreen">green</button>
  </p><! --<div class="id" :style="`color:${changeColor}`">I'm a div that changes the color of the text</div> -->
  <div class="id" :style="`color:${color}`">I'm a div that changes the color of the text</div>
</template>

<script>
// ref response type, simple and complex data types (.value required)
import { ref } from "vue";
// Box display and hide
function useShow() {
  const isShow = ref(true);
  function show() {
    isShow.value = true;
  }
  function hide() {
    isShow.value = false;
  }
  return { isShow, show, hide };
}
// Function 2: Text color
function useChangeColor(){
  const color = ref(' ')
  function changeWhite(){
    color.value = '#fff'
  }
  function changeGreen(){
    color.value = 'green'
  }
  return {color,changeWhite,changeGreen}
}
export default {
  name: "App".setup() {
    const { isShow, show, hide } = useShow();
    const {color,changeWhite,changeGreen} =useChangeColor()
    return{ isShow, show, hide, color, changeWhite, changeGreen }; }};</script>

<style scoped>
.id {
  width: 200px;
  height: 200px;
  background-color: red;
}
</style>

Copy the code

3. Summary

Put the two together and write demo and you get the following

  1. In VUe2, you will find that the logic is very messy, all the methods are written in the methods, and if there is more and more data in the data, you will find it very difficult to find the data
  2. Vue3 uses Composition API (API) look at the above code you will find that the code is more troublesome to write, but the logical thinking is very clear, can be separate packaging, logic reuse, so that the functional code can be centrally extracted into a function

The Setup composite API

Setup entry function

(1)The main content

  1. The setup function is a new component option that serves as a starting point (entry function) 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
  4. Vue2 does not update the page if it changes list[0] = 1. Vue3 fixes this problem

(2)Code demo

export default {
  setup () {
    console.log('Setup executes')
    console.log(this)},beforeCreate() {
    console.log('beforeCreate executed ')
    console.log(this)}}Copy the code

2. Responsive apis

(1) reactive

role

Reactive is a function that takes in a normal object, converts the object data into a reactive object and returns it, which is used to declare reactive data

  • Parameter: incoming data (must be a reference data type)
  • Return value: Data that implements responsiveness

Note: Reactive must pass in data that references data types and cannot do reactive operations on basic data types

Example:

<template>
  <div>
    {{ msg }}
    <button @click="MSG = 'MSG '">I changed my MSG</button>
    <p v-for="item in list" :key="item">{{ item }}</p>
    <button @click="list.push(4)">Click me Add data</button>
    <button @click="List [0] =">Click on the data where I change index 0</button>
  </div>
</template>

<script>
1. Import the reactive function
import { reactive } from 'vue'
export default {
  setup() {
    // Direct declaration of variables is not reactive data, the page does not update when the data is modified
    // let list = [1, 2, 3]

    Call reactive in the setup function
    // Passing in a reference to a data type makes the data responsive
    let list = reactive([1.2.3])

    let msg = reactive('message')

    // 3. Setup returns an object into which data is placed
    return {
      list,
      msg
    }
  },
};
</script>
Copy the code

(2) the ref

role

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

  • Parameters: Incoming data supported by all data types
  • Return value: Data that implements responsiveness

Note: you must use.value when using data in setup

Example:

<template>
  {{ msg }}
  <button @click="MSG = 'MSG '"< div style = "box-sizing: border-box; color: RGB (74, 74, 74);<button @click="changeMsg">I'll change MSG in Setup</button>
  <button @click="getMsg">So I'm going to take MSG in setup</button>
  <p v-for="item in list" :key="item">{{ item }}</p>
  <button @click="list.push(4)">Click me Add data</button>
  <button @click="List [0] =">Click on the data where I change index 0</button>
  <button @click="changeList">Click on the data I changed index 0 in Setup</button>
</template>

<script>
// 1. Import ref function
import { ref, reactive } from "vue";
export default {
  setup() {
    // Direct declaration of variables is not reactive data, the page does not update when the data is modified
    // let list = [1, 2, 3]

    // 2. Call ref in setup
    let list = ref([1.2.3]);

    let msg = ref("News"); // Put the data on the value property of the object to achieve a responsive effect

    console.log("list:", list);
    console.log("msg:", msg);

    function changeMsg() {
      console.log("changeMsg"
      // MSG = 'value' // add.value
      msg.value = "Bill";
    }

    function getMsg() {
      console.log(msg.value);
    }

    function changeList() {
      list.value[0] = "Fifty";
    }

    // 3. Setup returns an object into which data is placed
    return{ list, msg, changeMsg, getMsg, changeList, }; }};</script>
Copy the code

(3) The difference between ref response function and Reactive response function

Both functions are used to declare reactive data

  • Ref supports both base and reference data types
  • Reactive only supports reference data types

Note: Ref is essentially a wrapper around Reactive, calling reactive internally to generate a reactive object and enclosing an object

(4) computed

1.role

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

  • Parameter 1: the callback function, which is the get function that evaluates the property
  • Return value: Evaluates the property

Example 2.

<template> Complete array: {{list}} <br /> All even numbers: {{evenList}} < button@click ="evenList = '111'"</button> </template><script>
Import computed functions
import { ref, computed } from "vue";
export default {
  setup() {
    const list = ref([1.2.3.4.5.6]);

    // 2. Call a computed function in setup to generate computed properties
    // const evenList = computed(() => {
    // return list.value.filter(item => item % 2 === 0)
    // })

    // Change the function passed in to an object
    const evenList = computed({
      get() {
        return list.value.filter((item) = > item % 2= = =0);
      },
      set(val) {
        console.log(val)
      },
    });

    // 3. Return calculated properties
    return{ list, evenList, }; }};</script>
Copy the code

3. Vue2 writing

 // Vue 2
  computed: {
     evenList: {
       get() {
         return 'data'
       },
       set(val){}}evenList() { // Calculate the property's get function
       return 'Test data'}},Copy the code

(5) watch

1.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
  • Parameter 1: source The source to listen for data, passed in to the function
  • Parameter 2: The function that is triggered when the data source changes
  • Parameter 3: Configuration object (deep, immediate)

2. Example:

<template> total: {{count}} < button@click ="count++"</button><hr />
  {{ list }}
  <button @click="list.push(4)"</button> </template><script>
// Target: use watch to listen for changes in count
// 1. Import watch function
import { ref, watch } from "vue";
export default {
  setup() {
    const count = ref(0);

    // 2. Call the watch function in setup
    // watch(() => {
    // // returns the data you want to listen for
    // // must contain value
    // return count.value
    // }, (newVal) => {
    // // Triggered when data changes
    // console.log(newVal)
    // })

    // It is not recommended to use. Value is not required
    // watch(count, (newVal) => {
    // // Triggered when data changes
    // console.log(newVal)
    // })

    // Deep listening: parameter 3 is passed a configuration object
    const list = ref([1.2.3]);
    watch(
      () = > { // Parameter 1: source The source to listen to the data, passed in the function
        return list.value;
      },
      () = > { // Parameter 2: the function that is triggered when the data source changes
        console.log(list.value);
      },
      { // Parameter 3: configuration object (deep, immediate)
        deep: true.// Deep listening
        immediate: true.// Listen now, execute the listener function when the page loads});return{ count, list, }; }};</script>
Copy the code

3. Vue2 writing

  Vue 2Computational property writingwatch: {
   1.Simple notation// list(newVal) {}
   2.A complete writtenlist: {
     // Enable deep listening for complex data types
     deep: true.// Enable immediate listening
     immediate: true.handler(){}}}Copy the code

3. Life cycle functions

(1) VuE3 life cycle diagram of community translation

(2) Use lifecycle hook functions in setup functions

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

Note:

  • Vue3’s composite API does not provide two hook functions for the initialization phase: onBeforeCreate onCreated
  • Because Vue3 thinks that the two phases can be done directly in setup

(3) 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

4. Father-son correspondence

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

  1. Parent component passes data to child component, property binding
  2. Define props in the child component to receive and use

Props features:

  • One-way data flow, one-way down binding (the son will synchronize if the father changes the data, but the son will not recognize the data)
  • If a reference data type is passed in, it is possible to modify the properties of the object, but ESLint checks and reports errors by default, so you need to configure or disable ESLint separately

How do I turn off ESLint

Configure the vue. Config. Js

module.exports={
   lintOnSave:false
}
Copy the code

I’m not gonna turn it off

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

Example:

// The setup hook function takes two arguments:
  // Parameter 1: The object is mounted to any data passed by the props parent
  // Argument 2: context context object, which has some global instance methods, such as emit slots attrs
  // setup(props, context) {
  setup(props, { emit }) {
    // Before using props data: this.msg
    If you want to use props data in setup, you need to accept the first parameter: props
    // console.log(props)
    // console.log(context)

    // this // 没有 this
    function sendValue() {
      // Fire a custom event here, carrying data to the parent component
      // This refers to the object returned by setup, so there is no way to call the $emit function
      $emit() = this.$emit() = this.$emit()
      // console.log(this.$emit) 
      // Parameter 1: event name
      // Parameters 2 to n: parameters to be passed
      emit('getValue'.'This is the data of your son honoring you.')

      // Why do Vue2 instance methods start with $?
      // Because Vue2 was designed with all the methods on the prototype
      // Members of data and methods are also mounted to the object itself this.msg
      // If the member on the prototype does not start with $, it is easy to name the result after the name collision
      // this.$set this.$nextTick() this.$emit() this.$mount()

      // Vue3 is not designed in this way. The above context objects are exposed to the user. With the advent of compositionAPI design, we rely less on data and methods


    }
    return {sendValue}
Copy the code

5. Dojo.provide and inject

1. Application scenarios

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

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')

Be born code

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 = 'Joe'
    // Inject key-value data using the provide configuration item
    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

3. Pass responsive 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

<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
  },
  setup() {
    // use ref to convert to response and pass
    let name = ref('Joe')
    function changeName(){
      name.value = 'pink'
    }
    provide('name', name)
    return {
      changeName
    }
  }
}
</script> 
Copy the code

Use 4.

6.TemplateRef

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
<template> <! -- Vue2 --> <! --<p ref="cuteP">This is a lovely P</p>
  <Father ref="dad"></Father>-- > <! --3.Data returned by using the REF binding on the label from which the object is to be retrieved --><p ref="cp">This is a lovely P</p>
  <Father ref="father"></Father>
</template>

<script>
import { onMounted, ref } from 'vue';
// Target: Use ref in the setup function to get the native DOM object
import Father from './components/Father.vue'
export default {
  components: {
    Father
  },

  setup() {
    // 1. Use ref to create an empty data for later correlation
    const cp = ref(null)
    const father = ref(null)

    // Can not be obtained at this time, both are null, because setup is executed before beforeCreate
    console.log(cp.value)
    console.log(father.value)

    onMounted(() = > {
      // 4. Use data.value when appropriate to access the native DOM
      // Execute after the native DOM is mounted
      console.log(cp.value)
      console.log(father.value)
    })

    // 2. Return data to template for use
    return {
      cp,
      father
    }
  }

  // mounted() {
  // // Vue2 can be obtained in Mounted
  // console.log(this.$refs.cuteP)
  // console.log(this.$refs.dad)
  // }
};
</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. The instance method $ON is removed (the existing implementation mode of eventBus is no longer supported and can be replaced with a tripartite plug-in)

event Bus
 1. Vue.prototype.$eventBus = new Vue()
 2.The component that receives the datathis.$eventBus.$on('get-msg'.(msg) = >{})3.The component that sends the datathis.$eventBus.$emit('get-msg'.'Data passed'By default, the eventBus mode in VUe3 is not supported instead of using tripartite plug-insCopy the code

2. Filter removal (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 msg')}}// What is the result of the rendering? Function return value
methods: {formatMsg(msg){
     return msg + 'zs'}}Copy the code

3. Sync syntax removed (merged with V-model syntax)

.sync syntax elementUI -> Dialog visible. Sync ="showFlag"Function: Simplify the triggering of custom events for parent-child communication. Sync -> V-model (emphasis)Copy the code

More incompatible syntax changes can be found here

If the content has the wrong place welcome to point out (feel looking do not understand uncomfortable want to make fun of completely no problem); If there is help, welcome to like and collect, please reprint the source, if there is a problem also welcome private communication