preface

What changes did the transition from vue2. X to vue3. This article starts with creating a VUE3 project. Let’s take a look at what changes vuE3 has made and what benefits it can bring us


First, why learn Vue3

1. The status quo

  • Released in 2020.09.18, the surrounding ecology is not supported, most developers are in wait-and-see.
  • Mainstream component libraryelement-plusvant ,ant-design-vueVue3.0 has been released, this is the trend.

2. Vue3 advantages

  • One of the hottest front end frames in the country
  • Performance improvement
  • A smaller
  • Type inference: better support for TS(supersets of JS)
  • Advanced giving exposes lower-level apis and provides more advanced built-in components
  • Do thingsOption API—–> Composition API, can better organize logic, packaging logic, reuse logic (programming style change)

3. Vue3 outlook

  • trend
  • Large projects, due to Ts friendly, more and more large projects can use VUe3.0

How to create vuE3 application

1. Create projects based on Vue scaffolding

Install vUE scaffolding globally
npm i @vue/cli -g

# create Vue project, select V3 versionVue create Project name#-------- after creation --------

# Change path
cdThe project name# Run the project
npm run serve
Copy the code

Operation steps:

  • Locate the root directory where you want to create the project and enter CMD in the address bar to open the terminal

  • Enter vue create project name

  • Select manual creation (figure)

  • Select the required configuration (select space and press Enter after selecting)

  • You can select each configuration according to the following figure

2. Analysis of import files

Vue3’s API is typically imported on demand

The chain operation

What it does: Render the App root component into the index.html page

Conclusion:

  1. Vue is instantiated based on createApp method
  2. The use method is used to configure the router and store
  3. Import on demand to improve packaging performance

3. App.vue root component structure analysis

The component template in Vue2 must have a unique root node

A template for a component in Vue3 can have no root node

Summary: Component templates in Vue3 can have no root node (contrast with Vue2)

4. Analyze the router file

Vue3 creates instance objects

Conclusion:

  1. Create a route instance object using the createRouter mode, typical Vue3 style
  2. There are changes in the way hash and history are used
    • The mode option for Vue2 is hash/history
    • Vue3 createWebHashHistory()/createWebHistory()

5. Vuex file analysis

Conclusion: Create a Store object using the createStore method instead of new

Option API and composition API

Goal: Understand what option API writing is and what composition API is

1. The options for API

Where each code is written

2. The combination of the API

Division by function

Conclusion:

  1. Option API used in the Vue2 project
    • Code style: a functional logic code dispersion
    • Advantages: Easy to learn and use, the location of the code has been agreed
    • Disadvantages: poor code organization, similar logic (function) code is not easy to reuse, logic complex
  2. Combination of API (hook)
    • Block code structure by function, making it easier to reuse functionality later

4. Combination of API related methods

1. The setup function

Usage details:

  • New component options as a starting point for using composite apis in components

  • In terms of the component lifecycle, it is executed before beforeCreate (Vue3 beforeCreate/created is deprecated and has been replaced by setup).

  • This is not yet created in the setup function, so you cannot access this; this is undefined

  • The data returned in setup is used for template use: similar to the data provided in the previous data

  • Data from Data can still be used in Vue3, but not recommended (this is how the option API is written)

  • Methods defined in Setup also need to return

Syntax format:

export default {
    setup() {
       // return ... }}Copy the code

Conclusion:

  1. The Setup option is the basis for implementing the composite API
  2. Trigger time:
  3. This problem
  4. The return value of setup

2. Life cycle

Vue2. X lifecycle hook functions:

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • beforeDestory
  • destroyed

Recognize vue3.0 lifecycle hook functions (the same lifecycle function can fire multiple times)

  • setupBefore creating an instance
  • onMountedMount after the DOM
  • onBeforeUpdateBefore updating components
  • onUpdatedAfter updating components
  • onBeforeUnmountBefore unloading and destruction
  • onUnmounted: After uninstallation and destruction

Syntax format:

import { mounted } from 'vue'

export default {
    setup () {
    	mounted(() = > {
        	console.log('xxx')}}}Copy the code

Conclusion:

  1. The VUe3 lifecycle function has changed
  2. Remove two:beforeCreateandcreatedTo add setup
  3. Method names changed: The method name was preceded by an ON with a hump in the middle
  4. Uninstall component lifecycle changes:onBeforeUnmount,onUnmounted
  5. Features: The same life cycle can trigger multiple times

5. Data responsiveness

Data responsiveness: Changes in data cause views to change automatically.

1. The reactive function

A complex data type can be defined

Syntax format:

Use obj.msg in the template

import { reactive } from 'vue'

export default{
	setup(){
		const obj = reactive({
    		msg: 'Hello'}}})Copy the code

Note: Object properties in Reactive lose their responsiveness if they are reassigned

2. ToRef function

Requirement: The template does not add obj prefix, directly obtain the attribute

Pull out individual attributes from the object to ensure that the data is responsive

Syntax format:

import { toRef } from 'vue'

export default {
    const obj = {
    	msg: 'hello'
	}
    const msg = toRef(obj,'msg')
    
    setup() {
        return {msg}
    }
}
Copy the code

Code demo:

<template>
  <div>
    <div>{{ msg }}</div>
    <div>{{ info }}</div>
    <button @click="handleClick"</button> </div> </template> <script> import {reactive, toRef} from'vue'
export default {
  name: 'App'.setup() {
    const obj = reactive({
      msg: 'hello',
      info: 'Leo'
    })

    const msg = toRef(obj, 'msg')
    const info = toRef(obj, 'info')

    const handleClick = () => {
      obj.msg = 'hi'
    }

    return { msg, info, handleClick }
  }
}
</script>

<style lang="less"></style>

Copy the code

Conclusion: toRef method can extract single attribute from object and ensure responsiveness

3. ToRefs function

Syntax format:

import { toRefs } from 'vue'

export default {
    setup() {
        const obj = reactive({
      		msg: 'hello'.info: 'Leo'
    	})
        // deconstruct the attributes in obj
        const {msg,info} = toRefs(obj)
        
        return {msg, info}
    }
}
Copy the code

Conclusion: toRefs is a method that can batch convert properties in objects to independent responsive data

4. Ref function

It is used to define common (basic) data and ensure responsiveness

Syntax format:

import {ref} from 'vue'
export default {
    setup () {
        const count = ref(0)

		const handleClick = () = > {
   		 	// the value attribute is used when operating in js
   		 	count.value += 1}}}Copy the code

Code demo:

<template>
  <div>
    <div>{{ count }}</div>
    <button @click="handleClick"</button> </div> </template> <script> import {ref} from'vue'
export default {
  name: 'App'.setup() {const count = ref(0) const handleClick = () => {// count += 1}return { count, handleClick }
  }
}
</script>

<style lang="less"></style>

Copy the code

Conclusion:

  1. If it is primitive type data, you can define it using ref
  2. Ref can actually define an object, but the value attribute is required to access it

conclusion

  • Normal data returned directly from SETUP is not reactive
  • Wrapping objects around Reactive can be called reactive data
  • To simplify access to objects (without prefixes), optimization can be done using toRef
  • To get multiple properties in an object, you can use toRefs to simplify things further
  • For simple data types, the ref definition is more appropriate

5. Computed attributes

Note: Computed properties in VUe3 are also composed API style

  1. The callback must return, and the result is the result of the calculation
  2. If the data on which the calculated property depends changes, the calculation is recalculated
  3. Do not perform asynchronous operations in computed properties
  • Modifies the value of the calculated property

Sample code:

<template> <div> This year: {{age}} age <br /> Next year: {{nextAge}} age <br /> < button@click ="nextAge = 28"> Click </button> </div> </template> <script> import {ref, computed} from'vue'
export default {
  name: 'App'.setupConst age = ref(0) // read-only // const nextAge = computed(() => {//returnValue + 1 //}) const nextAge = computed({get() {
        return age.value + 1
      },
      set(v) {
        age.value = v - 1
      }
    })
    return { age, nextAge }
  }
}
</script>

<style lang="less"></style>

Copy the code

Conclusion:

  1. Calculated properties can be read or modified directly
  2. If you want to implement modification operations for computed properties, the computed arguments should be objects
    • Reading data triggers the GET method
    • Modifying data triggers the set function, which takes the assigned value as its parameter

6. Watch listener

Triggers a listener callback when the information being listened for changes

Typical scenario: After route parameters change, the interface is invoked again to obtain component data

  • Listen for reactive data defined by ref

Syntax format:

import {ref, watch} from 'vue'

export default {
    setup() {
        const count = ref(0)
        
        // Listen for data changes based on listeners
        // The audit office to be monitored must be responsive
        watch (count, (newVal,oldVal) = > {
            // newVal indicates the modified value
            // oldVal indicates the value before modification
            console.log(newVal,oldVal)
        })
        
        return {count}
    }
}

Copy the code

Summary: Listening for normal data can get the value before and after modification. The data being listened must be responsive

  • Listen for reactive data defined by Reactive

Syntax format:

import {reactive, watch} from 'vue'

export default {
    setup () {
        const obj = reactive({
            msg: 'tom'
        })
        
        watch(obj,() = > {
            // Get the latest value directly
            console.log(obj)
        })
    }
}
Copy the code

Conclusion: If you are listening on an object, then the two arguments to the listener’s callback function are the same result, representing the latest object data. In this case, the listener can also be read directly, and the value is also the latest.

  • Listen for multiple responsive data

Syntax format:

import {ref, watch} from 'vue'

export default {
    setup () {
        const n1 = ref(1)
        const n2 = ref(2)
        
        watch ([n1, n2], (v) = > {
            // v represents the latest value of all data being listened on, of type array
            console.log(v)
        })
        
        const handleClick = () = > {
            n1.value = 3
            n2.value = 4
        }
        
    
        return {n1, n2}
    }
}
Copy the code

Conclusion:

  1. You can get the values before and after the update
  2. The result of listening is also an array of data in the same order
  • Listen to a property of reactive data defined by Reactive

Syntax format:

<template> <div> name: {{user.name}}<br /> Year: {{user.age}} age <br /> < button@click ="user.age = 13"</button> </div> </template> <script> import {reactive, watch} from'vue'
export default {
  name: 'App'.setup() {
    const user = reactive({
      name: 'Ming',
      age: 12
    })
    watch(
      () => user.age,
      v => {
        console.log(v)
      }
    )
    return { user }
  }
}
</script>

<style lang="less"></style>

Copy the code

Conclusion:

  1. If you are listening for a property in an object, you need to use the function method
  2. Listening for less data improves performance
  • Watch configuration items

Syntax format:

import {} from 'vue'

export default {
    setup () {
        // immediate: true Indicates that the component is triggered immediately after rendering
        watch(() = > stuInfo.friend, () = > {
            console.log('stuInfo')
        },{
            immediate: true.// What is being listened on needs to be written as a function
            deep: true // Deep listening}}})Copy the code

Conclusion:

  1. Immediate: true, indicates the history call during component rendering
  2. Deep: true: indicates a subproperty of a deep listening object (the object being listened on needs to be a function)

7. Ref attribute

To obtain a DOM or component instance, you can use the ref attribute, which is separate from Vue2.0

Vue2 rules in

Conclusion:

  1. Vue2 allows direct manipulation of individual DOM and components via ref
  2. In VUe2, DOM and components can be manipulated in batches via refs

Vue3 rules in

  • Ref operates on a single DOM element

    Code demo:

    <template>
      <div>
        <div ref="info">hello</div>
        <button @click="handleClick"</button> </div> </template> <script> import {ref} from'vue'
    export default {
      name: 'App'.setup() {const info = ref(null) const handleClick = () => { // You can use info.value.innerhtml to print the contents of the DOM console.log(info.value.innerhtml)}return { info, handleClick }
      }
    }
    </script>
    
    <style lang="less"></style>
    
    Copy the code

    Summary: The flow of manipulating a single DOM or component

    1. Define a reactive variable
    2. Return the variable to the template for use
    3. Bind the above returned data in the template
    4. You can manipulate the DOM or components through variables
  • The batch operation

    Code demo:

    <template>
      <div>
        <ul>
          <li :ref="setFruits" v-for="item in fruits" :key="item.id">{{ item.name }}</li>
        </ul>
        <button @click="handleClick"</button> </div> </template> <script> import {ref} from'vue'
    export default {
      name: 'App'.setup() {
        const fruits = ref([
          { id: 1, name: 'apple' },
          { id: 2, name: 'banana' },
          { id: 3, name: 'pear'}]) const arr = [] const setFruits = el => {// el represents a single DOM element arr.push(el.innerhtml)} const handleClick = () => { console.log(arr) }return { fruits, handleClick, setFruits }
      }
    }
    </script>
    
    <style lang="less"></style>
    
    Copy the code

    Summary: the flow of ref batch manipulating elements

    1. Define a function
    2. Bind this function to ref (must be bound dynamically)
    3. In a function, you get a single element as an argument, and that element can be placed in an array
1. Define a function 2. Bind the function to ref (** must dynamically bind **) 3. In a function, you can get a single element as an argument. This element can normally be placed in an array. Batch elements can be manipulated through the array aboveCopy the code

8. Father-son communication

Vue2 writing

  1. Parent component passes data to child component: custom property props
  2. Child component passes data to parent component: custom event $emit()

Vue3 writing

The parent passes value to the child

steps

  • The setup function return
  • The subcomponent props receives

Code demo

If you want setup in a child component, pass in the parameter setup

Note: The props value is read-only and cannot be modified directly in a child component

  • The parent component
<template> <div> Parent <hr> <son :money="money"></son>
 </div>
</template>

<script>
import Son from './Son.vue'
import { ref } from 'vue'
export default {
  name: 'App'.setup () {
    const money = ref(100)

    return { money }
  },
  components: {
    Son
  }
}
</script>

<style lang="less">

</style>

Copy the code
  • The child components

Custom attributes can be used directly in templates

< the template > < div > child components -- -- -- -- -- {{money}} < / div > < / template > < script >export default {
  name: 'Son',
  props: {
    money: {
      type: Number,
      default: 0
    }
  },
  setup (props) {
    console.log(props.money)
  }

}
</script>

<style>

</style>

Copy the code
  • jsNeed to write the following code
setup(props) {
    const getMoney = () = > {
        console.log(props.xxx)
    }
    
    return { getMoney }
}
Copy the code

Conclusion:

  1. Property values in props can be obtained directly from the subcomponent template
  2. You need to get it from the first parameter in setup in your js code

Children pass values to their parents

steps

  • Child componentsetupThe second parameter passed in throws a custom event to the parent component
  • Define custom events in the parent component to complete the following operations

Code demo

  • The child components

Setup also has a second parameter, whose name can be customized

Note: emits must be written, do not write vue will have the following warning. If there are other custom events, you can continue to add them to the array.

<template> <div> child component -----{{money}}</div>+ 
</template>

<script>
export default {
  name: 'Son',
+ emits: ['sendToPar']
  props: {
    money: {
      type: Number,
      default: 0
    }
  },
+ setup (props, context) {
    console.log(props.money)

+ const handleClick = () => {
+ context.emit('sendToPar', 50)
+}

+ return { handleClick }
  }

}
</script>

<style>

</style>

Copy the code

Conclusion:

  1. A custom event is emitted via the context.emit method as argument 2 to the setup functioncontext.emit('xxx',xx)
  2. Custom events triggered by sub-components need to be declared in the emits option to see which custom events are triggered by the component
  • The parent component
<template> <div> Parent component <hr>+ 
      
 </div>
</template>

<script>
import Son from './Son.vue'
import { ref } from 'vue'
export default {
  name: 'App',
  setup () {
    const money = ref(100)

+ const getMoney = (val) => {
      console.log(val)
+ money.value = money.value - val
+}

+ return { money, getMoney }
  },
  components: {
    Son
  }
}
</script>

<style lang="less">

</style>

Copy the code

Dependency injection

Usage scenario: There is a parent component, which has child components, descendant components, there are many descendant components, share the parent component data

The parent component passes data to the descendant component

steps

  • Used in the parent componentprovidePass out data
  • Use of descendant componentsinjectReceives data from the ancestor component

Code demo

  • The parent component

Dojo.provide – >

<template> <div> parent <hr> <son :money="money" @sendtopar ="getMoney"></son> </div> </template> <script> import son from './Son.vue'+import { ref, provide } from 'vue'Export default {name: 'App', setup () {const money = ref(100) // Pass data to descendant components+ provide('moneyInfo', 1000)// Const getMoney = (val) => {console.log(val) money.value = money.value - val} return {money, getMoney } }, components: { Son } } </script> <style lang="less"> </style>Copy the code
  • inChild componentsTo register descendant components in
< the template > < div > child components -- -- -- -- -- {{money}} < / div > < button @ click = "handleClick" > click < / button > < hr >+ 
      
</template>

<script>
+import GrandSon from './GrandSon.vue'

export default {
  name: 'Son',
  emits: ['sendToPar'],
  props: {
    money: {
      type: Number,
      default: 0
    }
  },
  setup (props, context) {
    console.log(props.money)

    const handleClick = () => {
      context.emit('sendToPar', 50)
    }

    return { handleClick }
  },
+ components: {
+ GrandSon
+}

}
</script>

<style>

</style>
Copy the code
  • Sons of components

Inject – > injection

<template> <div> Grandson component -----{{money}}</div> </template> <script> import {inject} from'vue'
export default {
  name: 'GrandSon'.setup () {
    const money = inject('moneyInfo')

    return { money }
  }

}
</script>

<style>

</style>

Copy the code

Conclusion:

  1. Parental descendant data: Use provide
  2. Grandchildren get data: use Inject

Descendant components pass data to parent components

steps

  • The ancestor component passes a function to the descendant component
  • The descendant component receives and passes an argument to the ancestor component

Code demo

  • The parent component

Pass a function to the descendant component

<template> <div> parent <hr> <son :money="money" @sendtopar ="getMoney"></son> </div> </template> <script> import son from './Son.vue' import { ref, provide } from 'vue' export default { name: 'App', setup () {const money = ref(100) // Pass a function to descendant components+ const handleMoney = (val) => {
+ console.log(' data passed back by descendant component ', val)
+}
+ provide('handleMoney', handleMoney)// Const getMoney = (val) => {console.log(val) money.value = money.value - val} return {money, getMoney } }, components: { Son } } </script> <style lang="less"> </style>Copy the code
  • Sons of components
<template> <div> grandchild component+ 
  </div>
</template>

<script>
import { inject } from 'vue'
export default {
  name: 'GrandSon',
  setup () {
+ const handleMoney = inject('handleMoney')

+ const handleSend = () => {
+ handleMoney(200)
+}

+ return { handleSend }
  }

}
</script>

<style>

</style>
Copy the code

Summary: The child component passes data to the parent component by providing a function

  1. The grandparent component passes a function and then retrieves data from the function’s parameters
  2. The grandson component gets and calls this function to pass the data

10. Do thingsV – model syntactic sugar

Review of vue2 use

V-model is the syntax sugar for value and @input

The essence is a combination of attribute binding and event binding

<input type="text" :value="uname" @input="uname=$event.target.value">

  • V-models can also be used on components
<my-com v-model="info"></my-com>

<my-com :value="info" @input="info=$event"></my-com>
Copy the code
  1. If it is a native DOM event, then $event represents the js native event object
  2. If it is a component custom event, then $event is the data that #emit passes

Summary: Application scenarios of V-Model in VUe2

  1. Used on form elements: $event represents the event object
  2. Used on components: $event represents data passed by child components

New v-Model features in VUE3

The essence of v-Model is the binding of modelValue and @update:modelValue

Code demo

  • The parent component
<template> <div> Parent component {{info}} {{MSG}} <hr> <text-event V-model :modelValue="info" v-model:msg="msg"></text-event> <! --> <! -- <text-event :modelValue="info" @update:modelValue="info=$event" /> -->
 </div>
</template>

<script>
import { ref } from 'vue'// Import TextEvent from'./TextEvent.vue'
export default {
  name: 'App', components: {// register component TextEvent},setup () {
    const info = ref('hi~')
    const msg = ref('Leo')
    
    return { info, msg }
  }

}
</script>
Copy the code
  • Child components

Gets the value passed by the parent component

<template> <div> child component {{modelValue}} {{MSG}} < button@click ="handleClick"</button> </div> </template> <script>export default {
  name: 'TextEvent',
  props: {
    modelValue: {
      type: String,
      default: ' '
    },
    msg: {
      type: String,
      default: ' '
    }
  }
}
</script>
Copy the code

Modifies the value passed by the parent component

<template> <div> subcomponent {{modelValue}} {{MSG}} < button@click ="handleClick"> Click </button> </div> </template> <script> export default { name: 'TextEvent', props: { modelValue: { type: String, default: '' }, msg: { type: String, default: '' } },+ setup (props, context) {
+ const handleClick = () => {
+ context.emit('update:modelValue', 'hello')
+ context.emit('update:msg', 'leo')
+}
+ return { handleClick }
+}

}
</script>

<style>

</style>

Copy the code

Conclusion:

  1. V-models can pass multiple values to child components by binding multiple properties and ensure bidirectional binding
  2. Can replace vue2.syncModifier (sync modifier is deprecated in VUe3)

conclusion

This series will continue to be updated, if you help my friends, please remember to like + bookmark oh ~