Table of Contents
(1) Introduction to Vue3
(2) Use vite to create projects
(3) API style
(4) setup
1. Understand
2.Two points to note
(5) Responsive basics
1.ref function
2.reactive function
3. Comparison between ref and reactive
(6) Vue3 responsive principle
1.vue2 responsive principle
2.vue3 responsive principle
(7) Calculated attribute computed
(8) Listener watch, watchEffect
1.watch monitors the data defined by ref
2.watch monitors data defined by reactive
3.watchEffect function
(1) Introduction to Vue3
1. Performance improvement
Pack size reduced by 41%
Initial rendering is 55% faster, update rendering is 133% faster
Memory reduced by 54%…
2. Source code upgrade
Use Proxy instead of defineProperty to implement responsiveness
Rewriting the implementation of virtual DOM and Tree-Shaking…
3. Embrace TypeScript
Vue3 can better support TypeScript
4. New features
1.Composition API (Composition API)
setup configuration
ref and reactive
watch and watchEffect
provide and inject
…
2. New built-in components
Fragment
Teleport
Suspense
3. Other changes
New lifecycle hooks
The data option should always be declared as a function
Remove keyCode support as a modifier for v-on
(2) Use vite to create a project
Create project
npm create vue@latest
Manually download the required plug-ins (node_modules)
npm install
Startup project
npm rundev
vue project directory structure
(3)api style
Vue’s components can be written in two different styles: Optional API and Combined API .
Optional API: Vue2 writing style, using objects containing multiple options to describe the logic of components, such as data, methods, mounted, etc.
Combined API: Use imported API functions to describe component logic. In single-file components, the composition API is often used with
(4)setup
1.Understanding
- A new configuration item in Vue3.0, the value is a function.
- The data, methods, etc. used in the component must be configured in the setup.
- There are two return values of the setup function:
- If an object is returned, the properties and methods in the object can be used directly in the template. (Focus)
- If a rendering function is returned: you can customize the rendering content. (learn)
import { h } from 'vue' export default { name: 'App', setup() { let name = 'csq' let age = 18 function addAge() { age++ } // Return an object, then the properties and methods in the object can be used directly in the template (commonly used) return { name, age, addAge, } // Return a rendering function (not commonly used) // return h=>h('h1','xxx') } }
At this time, the properties and methods of the setup object returned cannot be rendered to the page after the data is changed, so vue3 uses ref to implement responsiveness.
Note:
- Try not to mix it with Vue2.x configuration: Vue2.x configuration (data, methods, computed...) can access the properties and methods in setup, but Vue2 cannot be accessed in setup. x configuration (data, methods, computed...), if there are duplicate names, setup takes precedence
- Setup cannot be an async function because the return value is no longer the return object, but a promise, and the template cannot see the attributes in the return object.
- setup can return a promise object, provided that the Suspense component and the asynchronous component are used together
2. Two points of attention
Timing of setup execution:
Executed once before beforeCreate, this is undefined
Setup parameters:
- props: The value is an object, including: properties passed from outside the component and received inside the component.
- context:Context object
- attrs: The value is an object, including: attributes passed from outside the component but not declared in the props configuration, equivalent to this.$attrs
- slots:The received slot content is equivalent to this.$slots
- emit: The function that distributes custom events is equivalent to this.$emit
In App.vue: import demo from './components/demo.vue'; export default { name: 'App', components: { demo }, setup() { function sendHelloMsg(content) { console.log(content) } return { sendHelloMsg } } } </script> <template> <div> <demo msg="hello" @sendHelloMsg="sendHelloMsg"> <!-- named slot --> <template v-slot:msg> <p>helloVue3!</p> </template> </demo> </div> </template> In demo.vue: export default { name: 'Demo', props: ['msg'], // Receive props parameters emits: ['sendHelloMsg'], // Receive custom events setup(props, context) { console.log(props.msg); console.log(context.emit); console.log(context.slots); // Storage slots function show() { context.emit('sendHelloMsg', 'helloMsg') //Trigger custom event } return { show } }, } </script> <template> <button @click="show">show</button> <slot name="msg"></slot> </template>
(5) Responsive Basics
1.ref function
Function: Define a responsive data
Syntax: const xx = ref('xxx')
Create a reference object containing responsive data (reference object, referred to as ref object)
Operation data in JS: xxx .value
Read data in the template: ref will be automatically unpacked, no .value is needed, directly:
Receive data type:
- Basic data types: Reactive still relies on get and set of Object.defineProperty() to complete
- Reference data type: implemented with the help of reactive function
Basic data types:
Reference data type: object.value
2.reactive function
Function: Define responsive data of an object type (basic types must use the ref function)
Syntax: const proxy object=reactive (source object), receives an object (or array) and returns a proxy object (instance object of proxy)
- The responsive data defined by reactive is "deep"
- The internal Proxy implementation is based on ES6, and the internal data of the source object is operated through the proxy object.
Note:
- In vue2, arrays can only be monitored and responded to through array methods, while in vue3, after defining an array through reactive, it can be operated directly through subscripts and responded to:
-
let array = reactive(['a', 'b', 'c']) array[1] = 'abcd' //Can directly modify the value of array elements and be monitored
- Defining objects and arrays through reactive is simpler and easier than defining using ref. There is no need to write value, so individual attributes can be written together in an object, and the return value of setup can also be written less.
-
let person = reactive({ name: 'csq', age: 18, job: { a: 1, b: { c: 777 } }, arr: [1, 2, 3] }) function changeInfo() { person.age = 19 person.job.b.c = 778 } return { person, changeInfo, }
Comparison between 3.ref and reactive
Comparison from the perspective of definition data:
- ref is used to define: basic type data
- reactive is used to define: object (or array) type data
Note: ref can also be used to define object (or array) type data, which will automatically be converted into a proxy object through reactive internally.
Comparison from a principle perspective:
- ref implements responsiveness (data hijacking) through get and set of object.defineProperty()
- reactive implements responsiveness (data hijacking) by using Proxy, and operates the data inside the source object through Reflect
Comparison from a usage perspective:
- Data defined by ref: value is required to operate data, and value is not required when reading data directly from the template.
- Data defined by reactive: no value is required for operating data and reading data
(6) vue3 responsive principle
1.vue2 responsive principle
Implementation principle:
- Object type: Intercept the reading and modification of properties (data hijacking) through object.defineProperty().
- Array type: Interception is implemented by overriding a series of methods for updating arrays. (The array change method is wrapped)
There is a problem:
- When adding attributes or deleting attributes, the interface will not be updated.
- Modify the array directly through subscripts, and the interface will not update automatically.
It can be solved through vue's set, delete methods and array methods, but it will be very cumbersome.
2.vue3 responsiveness principle
Implementation principle:
- Through Proxy (agent): intercept changes to any attributes in the object, including: reading and writing attribute values, adding attributes, deleting attributes, etc.
- Through Reflect (reflection): operate on the properties of the proxy object
Proxy and Reflect described in Ruan Yifeng's documentation:
Proxy: ES6 Getting Started Tutorial
Reflect: Getting Started with ES6
// Simulate vue3 to implement responsiveness const person = { name: 'csq', age: 18 } // Using the Object object method to implement additions, deletions, and changes is not conducive to encapsulation; therefore, Reflect is used to operate the properties of the proxy object. const p = new Proxy(person, { // Get element data within person get(target, propName) { console.log(`Someone accessed ${propName}`); // return target[propName] return Reflect.get(target, propName) }, //Modify element data in person set(target, propName, value) { console.log(`Someone modified ${propName}`); // target[propName] = value return Reflect.set(target, propName, value) }, //Delete elements in person deleteProperty(target, propName) { console.log(`Someone deleted ${propName}`); // return delete target[propName] return Reflect.deleteProperty(target, propName) } })
(7) Computed attribute computed
Computed properties are a combined API and need to be introduced when using them
Simple writing:
import { reactive, computed } from 'vue' setup() { const person = reactive({ ... }) //Simple writing method read only person.fullName = computed(() => { return `${person.firstName}-${person.lastName}` }) return { person } }
Readable and writable methods:
// Complete writing method, readable and writable person.fullName = computed({ get() { return `${person.firstName}-${person.lastName}` }, set(value) { let arr = value.split('-') person.firstName = arr[0] person.lastName = arr[1] } })
Note:
- The getter of a computed property should only perform calculations without any other side effects. Do not make asynchronous requests or change the DOM in the getter.
- Avoid modifying computed property values directly? The value returned from a computed property is derived state. Think of it as a "temporary snapshot", a new snapshot is created every time the source state changes. There is no point in changing the snapshot, so the return value of a computed property should be considered read-only and should never be changed - the source state it depends on should be updated to trigger a new calculation.
(eight) listener watch, watchEffect
1.watch monitors the data defined by ref
Monitor individual data
import { ref, watch } from 'vue' setup() { let name = ref('csq') let age = ref(18) // Monitor the data defined by ref single // The first parameter: the monitored data; the second parameter: the callback of the monitored data; the third parameter: configuration (immediate, deep) watch(age, (newValue, oldValue) => { console.log('age modified', newValue, oldValue) }, { immediate: true }) ... }
Monitor multiple data
// Monitor multiple data defined by ref in the form of an array watch([name, age], (newValue, oldValue) => { console.log('name or age has been modified', newValue, oldValue); })
Monitor the object/array data defined by ref
//Monitor the object/array data defined by ref // Directly monitor person. Changes in person attributes cannot be monitored. Person.value should be monitored because person.value = proxy object. watch(person.value, (newValue, oldValue) => { console.log('The data in person has been modified', newValue, oldValue); })
2.watch monitors the data defined by reactive
Monitor all properties of a reactive defined data
Note:
- newValue and oldValue are the same because their references point to the same object/array
- Deep monitoring is enabled by default, and the deep configuration is invalid.
import { reactive, watch } from 'vue' setup() { const person = reactive({ name: 'csq', age: 18, job: { a: { salary: 100 } } }) // Monitor all properties of a reactive defined data (all) // newValue and oldValue are the same (unresolved problem) // Deep monitoring is enabled by default deep is invalid watch(person, (newValue, oldValue) => { console.log('The data in person has been modified', newValue, oldValue); }) return { person } }
Monitor a certain attribute of a reactive-defined data
// Monitor an attribute of a reactive-defined data watch(() => person.age, (newValue, oldValue) => { console.log('age in person has been modified', newValue, oldValue); })
Monitor multiple attributes within data
//Multiple attributes in the monitoring data in array form watch([() => person.name, () => person.age], (newValue, oldValue) => { console.log('The name or age in person has been modified', newValue, oldValue); })
Special circumstances:
//Special case nested data within the monitoring object //You need to enable deep monitoring to access the data in the nest. The deep configuration item is valid. watch(() => person.job, (newValue, oldValue) => { console.log('The data in the job has been accessed', newValue, oldValue); }, { deep: true }) return { person }
3.watchEffect function
The routine of watch is: specify not only the properties of monitoring, but also the callback of monitoring.
The routine of watchEffect is: you don’t need to specify which attribute to monitor, which attribute is used in the monitoring callback, then which attribute to monitor
watchEffect is a bit like computed:
But computed focuses on the calculated value (the return value of the callback function), so the return value must be written, while watchEffect focuses more on the process (the function body of the callback function), so there is no need to write the return value.
import { watchEffect } from 'vue' // There is no need to specify which attribute to monitor. Which attribute is used in the monitoring callback, then which attribute is monitored. // Call back once immediately after mounting == immediate:true watchEffect(() => { let a = person.name + 'zkj' let b = person.job.a.salary + 2000 console.log('watchEffect's callback is running and data has been changed'); })