1. Some concepts about setup
- User defined events in vue3 still need to be defined before use
- vue3 no longer uses this.emit to launch custom events, but uses context.semi to launch custom events. This is a thing of the past
- Like vue2, emit has two parameters, one is the user-defined event name, and the other is the data to be transmitted in the past. The data can be multiple or arrays
- Variables and functions defined in setup must be returned through return
- vue3 puts all hooks in 'vue' as functions and needs to be deconstructed from 'vue'
- The variables used in setup should be wrapped with ref or reactive. Ref wraps the basic data type and reactive wraps the object data type. After wrapping, it is called a responsive object.
- The wrapped basic data type is read-only and cannot be modified directly. It should be modified in the form of data. value
- The function is used in the form of assignment
- The above are annotated in the following example
Subcomponent Test.vue
<template> <h3>here is test component</h3> <h1>{{count}}</h1> <button @click="emitAddEvent">add</button> </template> <script> import {watchEffect,watch,toRefs} from 'vue' export default { name: 'Test', props: { count:Number }, //Custom events are registered outside setup emits:['add'], //Connect a parameter, a props and a context setup(props,context){ //3 and 2 are different in defining functions. They emit custom events through callback functions const emitAddEvent=()=>{ //this.emit is no longer used for launch events, but context. this is not used in 3, //The emit function is the same as that in 2. Register first and then use context.emit('add',100) } return { //If you use that variable or function, you must return it emitAddEvent } } } </script> <style scoped> </style>
Parent component app.vue
<template> <div> <!--here add It's a custom event, addcount Is a callback function for custom events --> <Test :count="mycount" @add="addcount"></Test> </div> </template> <script> import Test from './components/Test.vue' //Deconstruct and export the required functions from vue, including hooks, which are deconstructed and used in the form of functions import {reactive,ref,toRefs} from 'vue' export default { name: 'App', setup(props,context){ //The variables used should be ref wrapped const mycount=ref(1000) //The emitted emit event is parameterized, and the callback function needs to receive it with a formal parameter const addcount=(plusdata)=>{ //The data wrapped by ref is read-only and cannot be modified due to the problem of responsiveness. It needs to be disassembled to modify the value mycount.value+=plusdata } return { //Face change and callback functions should return mycount, addcount } }, components: { Test } } </script> <style> </style>
2,reatvie
- Wrap the application type data so that it is called responsive data. vue does not recommend using the original object (application type data), but directly use the wrapped data, because it is called responsive data after wrapping. If you forcibly disassemble and use the original object, you lose the responsiveness.
- The reactive event is a copy of the original object, but it is a deep copy
<template> <div> spp </div> </template> <script> import {reactive,ref,toRefs} from 'vue' export default { name: 'App', setup(props,context){ const proxyObj=reactive({ a:1, b:2, c:[ {d:3,e:4},{f:3,g:5} ] }) console.log(proxyObj) return { } }, components: { } } </script> <style> </style>
- reactive objects can be modified directly
- //Objects wrapped with reactive are automatically expanded, and state.myref is equivalent to state.value.myref
console.log(state.myref) - //You can also modify the data directly because it is actually expanded automatically
state.myref=200
console.log(state.myref)
3,ref
- Package basic data type, return the responsive ref object
- Data. value is required for modification
- If an application type is wrapped, but the actual returned type is reactive, and deep copy is supported
- return the data wrapped by ref will be merged into the render function (h function). And automatically expand the value inside, such as {{count}}, instead of {{count.value}}
- If a ref wraps data that has been wrapped by a ref, the new ref will overwrite the value of the old Ref
<template> <div> spp </div> </template> <script> import {reactive,ref,toRefs} from 'vue' export default { name: 'App', setup(props,context){ const myref=ref(100) const proxyObj=ref({ a:1, b:2, }) console.log(myref.value) console.log(proxyObj.value.a) const state=reactive({ myref }) //Objects wrapped with reactive are automatically expanded, and state.myref is equivalent to state.value.myref console.log(state.myref) //You can also modify the data directly state.myref=200 console.log(state.myref) return { myref, state } }, components: { } } </script> <style> </style>
4,ref/unref
- ref is depth responsive. Depth refers to the nested object, and the depth response indicates that the nested object can be modified according to the path
<template> <div> <h1>{{name}}</h1> <h1>{{person.homeland.city}}</h1> </div> </template> <script> import {reactive,ref,toRefs} from 'vue' export default { name: 'App', setup(props,context){ const name=ref('') name.value='zhangsan' setTimeout(()=>{ name.value='lisi' console.log(name.value) },2000) const person=ref({ name:'wanger', age:12, homeland:{ province:'hebei', city:'shijiazhuang' } }) setTimeout(()=>{ //Non depth response person.value.name='mazouri' //Depth response person.value.homeland.city='baoding' },3000) console.log(person.value.name) console.log(person.value.homeland.city) return { name, person, } }, components: { } } </script> <style> </style>
- unref if the parameter data is a ref package, it returns inner value. If it is not a ref package, it returns the data itself
- isRef function judgment
<template> <div> </div> </template> <script> import {reactive,ref,toRefs,isRef,unref} from 'vue' export default { name: 'App', setup(props,context){ const myobj={ name:'zhangsan', age:22, address:'heibei' } const obj1=isRef(myobj) ? myobj.name : myobj console.log(obj1) const obj2=ref(myobj) const obj3=isRef(obj2) ? myobj.name : myobj console.log(obj3) //unref is actually equal to obj3 above const obj4=unref(obj2) console.log(obj4) const obj5=unref(myobj) console.log(obj5) return { myobj } }, components: { } } </script> <style> </style>
5,toRef/toRefs/isRef
1. toRef: a conversion between reactive and ref
You can take out an attribute in the object and turn it into ref
<template> <div> {{myref}} </div> </template> <script> import {reactive,ref,toRef,isRef,unref} from 'vue' export default { name: 'App', setup(props,context){ const state=reactive({ name:'zhangsan', age:23 }) //Specify the attribute of the transformation. Here, pass the name attribute of the reactive wrapper object of state to myref const myref=toRef(state,'name') //Modify the converted value myref.value='lisi' console.log('11111',state.name) //Modifying state.name and myref.value will affect each other state.name='wanger' console.log('22222',myref.value) return { myref, } }, components: { } } </script> <style> </style>
2. toRefs: a transformation of creating reactive wrapper objects and refs
- Convert a reactive wrapped object into a ref wrapped object
- In this way, all the attributes of the object are converted, instead of converting one of the attributes with values like toRef. Therefore, only one conversion object parameter is required
<template> <div> urname:{{name}}<br/> urage:{{age}} </div> </template> <script> import {reactive,ref,toRef,toRefs,isRef,unref} from 'vue' export default { name: 'App', setup(props,context){ const state=reactive({ name:'zhangsan', age:23 }) //Specify the attribute of the transformation. Here, pass the name attribute of the reactive wrapper object of state to myref //It turns into an ordinary object const myrefs=toRefs(state) console.log(myrefs) console.log({ ...myrefs }) console.log('11111',myrefs.name.value)//zhangsan console.log('11111',myrefs.age.value)//23 //Modify the converted value myrefs.name.value='lisi' myrefs.age.value=33 //Modifying the converted value will affect the principle, because it is actually referenced console.log(state.name)//lisi console.log(state.age)//33 //Modifying state.name and myref.value will affect each other state.name='wanger' state.age=44 console.log('22222',myrefs.name.value) console.log('22222',myrefs.age.value) return { //Directly expand the converted myrefs, so that you can directly get the expanded name and age in the template ...myrefs, state } }, components: { } } </script> <style> </style>
3. isRef determines whether it is ref
See previous examples
6. cutomRef custom ref
For data anti shake
customRef needs a factory function as parameters, track and trigger, corresponding to getter and setter respectively
<template> <div> <span>{{text}}</span> <input type="text" v-model="text"> </div> </template> <script> import {reactive,customRef} from 'vue' function useDebounce(value,delay=200){ let time=null return customRef((track,trigger)=>{ return { get(){ //Track the old value. Before returning the old value, track the old value to prevent it from changing track() return value }, set(newvalue){ clearTimeout(time) time=setTimeout(()=>{ value=newvalue //Update value and trigger to be triggered trigger() },delay) } } }) } export default { name: 'App', setup(props,context){ const text=useDebounce('',500) return { text } }, components: { } } </script> <style> </style>
7,shallowRef
Shallow ref, because the data has a response type after using ref packaging. If using shallowRef packaging, it will become a proxy object (ordinary object) after conversion
<template> <div> <span>{{myobj1}}</span> <hr/> <span>{{myobj2}}</span> </div> </template> <script> import {ref,reactive,customRef,shallowRef} from 'vue' export default { name: 'App', setup () { const myobj1=ref({ name:'zhangsan', age:12 }) console.log(myobj1)//RefImpl myobj1.value={ name:'lisi', age:33 } console.log(myobj1.value)//Proxy const myobj2=shallowRef({ name:'zhangsan', age:12 }) console.log(myobj2)//RefImpl myobj2.value={ name:'wanger', age:55 } console.log(myobj2)//RefImpl return { myobj1, myobj2 } } } </script> <style> </style>
8,triggerRef
Manual trigger responsive operation
<template> <div> <span>{{myobj1}}</span> <hr/> <span>{{myobj2}}</span> </div> </template> <script> import {ref,reactive,customRef,shallowRef,watchEffect,triggerRef} from 'vue' export default { name: 'App', setup () { const myobj1=ref({ name:'zhangsan', age:12 }) console.log(myobj1)//RefImpl myobj1.value={ name:'lisi', age:33 } console.log(myobj1.value)//Proxy const myobj2=shallowRef({ name:'zhangsan', age:12 }) console.log(myobj2)//RefImpl myobj2.value={ name:'wanger', age:55 } console.log(myobj2)//RefImpl let name='' watchEffect(()=>{ name=myobj2.value.name console.log(name) }) myobj2.value.name='zhaoqiusun' triggerRef(myobj2) return { myobj1, myobj2 } } } </script> <style> </style>
9,computed
Returns an immutable value
The return value is also a ref
<template> <div> <span>{{superSentence}}</span> </div> </template> <script> import {ref,computed} from 'vue' export default { name: 'App', setup (props,context) { const textRef=ref('Welcome to my cabin') const superSentence=computed(()=>{ return 'Xiao Ming'+textRef.value }) console.log(superSentence.value) return { superSentence } } } </script> <style> </style>
The actual mechanism is also a get and set
<template> <div> <span>{{superSentence}}</span> </div> </template> <script> import {ref,computed} from 'vue' export default { name: 'App', setup (props,context) { const textRef=ref('Welcome to my cabin') const superSentence=computed( { get(){ return 'Xiao Ming'+textRef.value }, set(value){ console.log('I modified the value by calculating the attribute') console.log(value) } } ) console.log(superSentence.value) superSentence.value='Once I modify it, it will trigger set sentence' return { superSentence } } } </script> <style> </style>