Common Composition API
setup
- Vue3.0 is a newly added configuration item. The value is a function
- setup is the of all composition APIs
- The data and methods used in the component need to be configured in the setup function
- There are two return values of the setup function:
- If the return is an object, the attributes and methods in the object can be used directly in the template
- If you return a rendering function, you can customize the rendering content
- Two precautions for setup:
- Execution timing of setup: execute it once before beforeCreate. this is undefined
- setup parameters:
- props: the value is an object, including the attributes passed externally and declared and received internally by the component
- Context: context object
- Attrs: the value is an object, including attributes passed from outside the component but not declared in the configuration in props, which is equivalent to this$ attrs
- Slots: the contents of the received slot, equivalent to this$ slots
- Emit: distribute the function of custom time, free corundum this$ emit. (it should be noted that when using emit in Vue3, you need to use emit to receive the data and props from the parent component
(almost)
PS:
- Try not to mix with Vue2 configuration items:
- Vue2 configuration items (data,methods,computed...) can access the properties and methods in setup.
- However, the configuration in Vue2 cannot be accessed in setup
- If there are duplicate names, setup takes precedence
- The setup function cannot be an async function (it's OK to learn about asynchronous components later. It needs the cooperation introduced by suspend and asynchronous components), because the return value is not a return object, but promise. The template cannot see the attributes in the return object
<template> <h1>{{name}}</h1> <button @click="sayHi"></button> </template> <script> exprot default { name: 'App', setup(props,context) { const name = "Sedum" // Not responsive data function sayHi() { console.log(`Hi,I am ${name}`) } // The return value is an object return { name, sayHi } // The return value is a rendering function return () => h('h1','This is what the rendering function renders') } } </script>
ref function
- Function: define a responsive data, or generate a reference implementation object
- Syntax: const xxx = ref(initValue)
- Create a reference object (reference object) that contains responsive data
- Operation data in JS: XXX value
- Reading data from the template: you can use it directly
PS:
- The data received by ref can be basic type data or object type data
- Basic type of data: the response type depends on Object. get and set of defineProperty() are completed
- Data of object type: reactive function is used internally
<template> <h1>{{name}}</h1> <h1>{{age}}</h1> <button @click="sayHi"></button> </template> <script> import {ref} from 'vue' exprot default { name: 'App', setup() { const name = ref("Sedum") const age = ref(18) const job = ref({ type: 'front end', money: '30K' }) // In fact, Vue3 calls the reactive function for you // To access the basic data type defined by ref in setup, you need to Value to get value function sayHi() { name.value = 'Feipeng' age.value = '1000' job.value.money = '60K' } return { name, age, job, sayHi } } } </script>
reactive function
- Function: defines the responsive data of an object type
- Syntax: const proxy object = reactive (source object) parameter is an object or array that returns a proxy object (proxy instance object, proxy object for short)
- The responsive data defined by reactive is deep-seated
- The internal Proxy implementation based on ES6 operates the internal data of the source object through the Proxy object
<template> <h1>{{name}}</h1> <h1>{{age}}</h1> <button @click="sayHi"></button> </template> <script> import {ref, reactive} from 'vue' exprot default { name: 'App', setup() { const name = ref("Sedum") const age = ref(18) const job = reactive({ type: 'front end', money: '30K' }) const hobby = ['smoking', 'drink', 'Hot head'] function sayHi() { name.value = 'Feipeng' age.value = '1000' job.money = '60K' // unwanted. value hobby[0] = 'having dinner' } return { name, age, job, hobby, sayHi } // ref defines the basic types of data value is a little annoying. We can change our thinking and make it semantic const person = reactive({ name: 'Sedum', age: 18, jon: { type: 'front end', money: '30K' }, hobby: ['smoking', 'drink', 'Hot head'] }) return { person } } } </script>
computed
The abbreviation and full version are the same as Vue2, but the use is different. It needs to be introduced and used separately, which has become a function
<template> <h1><input v-model="firstName" /></h1> <h1><input v-model="lastName" /></h1> <div>{{fullName}}</div> </template> <script> import {reactive,computed} from 'vue' exprot default { name: 'App', setup() { const person = reactive({ firstName + : 'Sedum', lastName: 18, }) // Or it can be bound to the person object // person.fullName = computed(()=>{ let fullName = computed(()=>{ // In short, the full version of get and set is the same as Vue2 return person.firstName + person.lastName }) return { person, fullName } } } </script>
watch
- Basically similar to Vue2, the configuration is the same
- Two pits:
- When monitoring the responsive data defined by reactive: oldVal cannot be obtained correctly, and deep monitoring is forced on (the deep configuration is invalid)
- When monitoring a property (object) in reactive defined responsive data: the deep configuration is valid
<template> <h1>{{num}}</h> <h1>{{msg}}</h> </template> <script> import {ref,reactive,watch} from 'vue' exprot default { name: 'App', setup() { let num = ref(0) let msg= ref('news') let p = reactive({ name: 'Sedum', age: 18, a: { b: { c: 100 } } }) // 1. Monitor a responsive data defined by ref watch(num,(newVal,oldVal)=> { console.log(newVal,oldVal) },{immediate:true}) // 2. Monitor multiple responsive data defined by ref watch([num,msg],(newVal,oldVal)=> { console.log(newVal,oldVal) },{immediate:true}) // 3. Monitor a reactive data defined by reactive. // Note: oldVal cannot be obtained correctly here // Note: the depth monitor is forced on (the deep configuration is invalid) watch(p,(newVal,oldVal)=> { console.log(newVal,oldVal) },{deep:false}) // The deep here is invalid // 4. Monitor an attribute in a responsive data defined by reactive. Function required watch(()=>p.name,(newVal,oldVal)=> { console.log(newVal,oldVal) }) // 5. Monitor some attributes in a responsive data defined by reactive. watch([()=>p.name,()=>p.age],(newVal,oldVal)=> { console.log(newVal,oldVal) },{deep:false}) // exceptional case watch(()=>p.a,(newVal,oldVal)=> { console.log(newVal,oldVal) },{deep:true}) // Here, because a property (object) in the object defined by reactive is monitored, the deep configuration is valid return { num, msg, p } } } </script>
watchEffect function
- watch: you need to specify the monitored attribute and the monitored callback
- watchEffect: you don't need to specify which vertical to monitor or which attribute to use in the monitored callback, you can monitor that attribute
- watchEffect is somewhat similar to computed:
- computed focuses on the calculated value, so the return value must be written
- watchEffect focuses more on the process, so there is no need to write the return value
<template> <h1>{{num}}</h> <h1>{{msg}}</h> </template> <script> import {ref,reactive,watchEffect} from 'vue' exprot default { name: 'App', setup() { let num = ref(0) let msg= ref('news') let p = reactive({ name: 'Sedum', age: 18, a: { b: { c: 100 } } }) watchEffect(()=> { const x1 = sum.value const x2 = age.value console.log('watchEffect Called') }) return { num, msg, p } } } </script>
toRef
- Function: create a ref object whose value points to an attribute in another object, which is responsive
- Syntax: const name = toRef(person,'name')
- Application: a property in the responsive object should be provided separately for external use
- Extension: the functions of toRefs and toRef are always, but multiple ref objects can be created in batch. The syntax is toRefs(person)
// As mentioned above, data can be defined as reactive to avoid value. But in this case, we need person Name uses it like this, so you can try it like this return { ...toRefs(person) }
Other composition APIs
shallowReactive and shallowRef
- shallowReactive: value handles the response of the outermost attribute of the object (shallow response)
- shallowRef: only handle the response of basic data type, and handle the data of basic type. It is no different from ref and does not handle the response of object
- When will it be used?
- If there is an object data with a shallow structure, but only the outer attributes change when it changes, use shallowReactive
- If there is an object data, the subsequent function will not modify the attributes in the object, but generate a new object to replace it. Use shallowRef
readonly and shallowReadonly
- readonly: make a responsive data read-only (deep read-only)
- shallowReadonly: make a responsive data read-only (shallow read-only), but the outermost attribute value will not be changed
- Usage scenario: when you don't want the data to be changed, such as the data defined by others, you use it, but the change will affect others. You can use readonly(person) first when using it, so you won't be afraid of being changed.
toRaw and markRaw
- toRaw:
- Function: convert a responsive object generated by reactive into a normal object. toRaw(person)
- Scenario: used to read the ordinary object corresponding to the responsive object. All operations on this ordinary object will not cause the page to be updated
- markRaw
- Purpose: mark an object so that it will never become a responsive object again
- Scenario:
- Some values should not be set to be responsive, such as third-party libraries
- Skipping responsive conversion can improve performance when rendering large lists with immutable data
customRef
- Function: create a custom ref and explicitly control its dependency tracking and update trigger.
demo: realize input data and anti shake effect
<template> <input v-model="keyword"> <div>{{keyword}}</div> </template> <script> import { customRef } from 'vue' export default { name: 'demo', setup() { // Customize a ref named myRef function myRef(value,delay) { let timer // Use vue's customRef to configure our myRef. The parameter is a function. This function has two parameters that can be used directly // track: // trigger: return customRef((track,trigger)=> { // It is required to return an object containing get and set return { get() { // Notify vue to track the change of value track() return value }, set(neValue) { clearTimeout(timer) timer = setTimeout(()=> { value = newValue // Notify vue to re resolve the template trigger() },delay) } } }) } } let keyword = myRef('Hello',100) return { keyword } } </script>
Use of provide and inject in Vue3
- Function: realize the communication between grandson components, that is, the definition of parent components, which can be used by all subsequent child components
- Routine: the parent component has a provide option to provide data, and the descendant component has an inject option to start using these data
// Ancestor component import {reactive} from 'vue' setup() { let car = reactive({ name: 'audi', price: '100W' }) provide('car',car) } // Descendant component import {inject} from 'vue' setup(props,context) { const car = inject('car') return { car } }
Judgment of responsive data
- isRef: check whether a value is a ref object
- isReactive: check whether an object is a responsive proxy created by reactive
- isReadonly: check whether an object is a read-only proxy created by readonly
- isProxy: check whether an object is a proxy created by the racive or readonly method
New components in Vue3
Fragment
It is equivalent to a virtual container. In Vue, each component needs a root component, but it is not required in Vue3. In fact, Vue3 helps us call this component, which will not be rendered on our page
Teleport
When there are always some contents in our component that do not want to be displayed in our own component, we can use this component. For example, we have a pop-up window that wants to be displayed in the body tag
// to tags are supported here // to support css Tags // <teleport to="body"> <teleport to="#main"> <div class="dialog"> This is a dialog box </div> </teleport>
Suspense
Experimental
Suspend is an experimental new feature whose API may change at any time. It is hereby declared so that the community can provide feedback on the current implementation.
Do not use in production environment.
The above is an official warning!
- Wait for the asynchronous component to render some additional content, so that the application has a better user experience
- The < suspend > component has two slots. They all receive only one direct child node. The nodes in the default slot will be displayed as much as possible. If not, the node in the fallback slot is displayed.
- This is what I mentioned earlier when talking about setup. The return value of setup cannot be asynchronous, but if you use asynchronous functions to introduce sub components like the following, the sub components can use asynchronous, such as Promise.
<template> <div> <Suspense> // The two slot names are fixed // defalut: what is written here is the components and code we normally want to display // fallback: what is written here is the emergency code, which is the code when the normal code is not displayed <template v-slot:defalut:> <Child/> </template> <template v-slot:fallback> <div>Loading...</div> </template> </Suspense> </div> </template> <script> // import Child from './component/Child.vue '/ / normally used static import // Here is asynchronous import import { defineAsyncComponent } from 'vue' const Child = defineAsyncComponent(()=> import('./component/Child.vue')) export default { name: 'app', components: { Child } setup() { } } </script>