1. Use new JS native features

  2. Resolve design and architectural defects

    A proxy for ES6 was added to VUe3, which eliminates all of vue2’s limitations (such as the addition of new object attributes, and the fact that direct changes to array elements do not trigger reactive mechanisms, which many novices call bugs) and provides better performance.

    Proxy is the real meaning of an object package on a layer of Proxy to perform data interception hijacking operations, so overall this complexity is directly reduced by an order of magnitude. As long as you access or modify the object after the proxy is aware of this layer of proxy to dynamically decide what to return to you, and there is no need to repeatedly attach the selected items to the component instance’s this. Because you have this information when you’re accessing something, whether it’s props or Data or something else, the VUE just takes that information out of the corresponding data structure, and you can feel that the memory usage of the component has been cut in half.

Improvements and features of VUE3

1. Performance improvement: 41% reduction in package size, 55% faster initial rendering, 133% faster update, 54% reduction in memory usage.

2. The new Composition API makes components easier to maintain and reduces unwanted data binding pages.

4. Better TypeScript support, which can be configured directly in the create command for seamless page integration.

5.Teleport(transient components), Suspense(solve asynchronous component loading problems) and global API modification and optimization.

6.Vue3 is compatible with most of the features of Vue2, and can be developed with Vue2 code.

New point in vue3.x

1. Multi-node components

In VUE3, components officially support multi-node components, known as fragments!

2.setup

To start using the Composition API, we first need a place where we can actually use it. In Vue components, we call this location setup.

Setup execution does not create a component instance, so you cannot use this, which is undefined. Cannot access any data, computed, or methods declared in the component except props.

Note: Setup is designed to optimize performance by introducing global unification on demand

Parameters (props, context)
// Context {attrs, emit, slots} setup(props, context) { console.log(context) /** * attrs: Proxy * emit: (event, ... args) => instance.emit(event, ... args) * slots: Proxy */ }Copy the code
Setup lifecycle hooks
Hook function Setup a hook
beforeCreate There is no
created There is no
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted
errorCaptured onErrorCaptured
renderTracked onRenderTracked
renderTriggered onRenderTriggered

Because setup runs around beforeCreate and Created lifecycle hooks, you don’t need to explicitly define them. In other words, any code that should be written in these hooks should be written directly in the Setup function.

Usage:

<template> <div class="home"> {{ name }}</div> <ul> <li v-for="item in list" :key="item" @click="show(item)">{{ item }}</li> </ul> </div> </template> <script lang="ts"> import { defineComponent, ref } from "vue"; Export default defineComponent({name: "Home", components: {}, props:[' MSG '], setup(context) {// The setup function is a function between the life cycle beforeCreate and Created hook functions, so it is not possible to use data and methods in the setup function. Methods, etc., can use data returned from setup. /* the first argument to the function is props, for receiving props. MSG This is a responsive Proxy object that cannot be deconstructed because it will not respond. ToRefs let {MSG} = toRefs(props) // But if ref = msg.value, props Emit Because there is no Vue instance created in the setup function, it is not possible to use vm.$attrs, vM. $slots, and vM. $emit, so these attributes are used in the same way. Note: Context. attrs and vm.$attrts contain attributes (except class and style) that are not recognized by the declaration in the instance vm.props. So variables exposed in props in setup() are not exposed in context.attrs. Context. Slots and vm.$slots can only access named slots. Unnamed slots or v-slot:default are not exposed. Attrs and slots for context are stateful and update in real time when components are updated, so don't deconstruct them either. Unlike props, however, they are not reactive, and their use in setup() should remain read-only, and if changed can be done in the periodic function onUpdated. Context. emit and vm.$emit can trigger listening events on instances. */ const list = ref([" s0 ", "s0 "]); const name = ref(""); Const show = (index: string) => {name. Value = index; // const show = (index: string) => {name. }; // Note: The template cannot be used without returning data. return { list, name, show }; }}); </script>Copy the code

Reactive (

<template> <div class="home"> {{ data.name }}</div> <ul> <li v-for="item in data.list" :key="item" @click="data.show(item)">{{ item }}</li> </ul> </div> </template> <script lang="ts"> import { defineComponent, reactive } from "vue"; export default defineComponent({ name: "Home", components: {}, setup() { const data = reactive({ list: [" shenzhen ", "Beijing", "Shanghai"], name: "", show: (index: string) = > {data. The name = index; }}); return { data }; }}); </script>Copy the code

Usage three: toRefs() optimization

<template> <div class="home"> {{ name }}</div> <ul> <li v-for="item in list" :key="item" @click="show(item)">{{ item }}</li> </ul> </div> </template> <script lang="ts"> import { defineComponent,reactive,toRefs } from "vue"; export default defineComponent({ name: "Home", components: {}, setup() { const data = reactive({ list: [" shenzhen ", "Beijing", "Shanghai"], name: "", show: (index: string) = > {data. The name = index; }}); const refData = toRefs(data); // Can not be directly resolved... Data must be returned with toRefs() {... refData }; }}); </script>Copy the code

jsx

setup() {
    const root = ref(null)
    return () => <div ref={root} />
}
Copy the code
Get the method for sample this in Setup

Setup this points to window, and the composition document doesn’t say how to get the component instance.

We can get the component instance via getCurrentInstance() :

Setup () {// getCurrentInstance() can get component instances const instance = getCurrentInstance() console.log(instance); OnMounted (()=>{// The context of the component instance is the familiar this console.log(instance.ctx.foo); // 'foo' console.log(instance.ctx.bar()); // 'I am a bar method'}) return {}},Copy the code

However, we soon get confused. This component instance is not like this. If we access this.foo directly, we still don’t find the data.

The component instance structure in VUe3 is as follows, and this in each option is actually CTX or proxy

If you look closely at CTX, you will find that it is not a Proxy object, that is, it has only values but no responsiveness. Therefore, if you want to make use of responsiveness, you will need to use the Proxy property to return the context object. If you only want data, there is a data that is also a Proxy.

Setup () {const {proxy, data} = getCurrentInstance() WatchEffect (() => {console.log(proxy.foo) // foo changes output console.log(data.foo) // foo changes output})},Copy the code

Finally, note that setup() is executed at a very early point in time, even before created, so foo and bar access would be missing if it were not specifically placed inside onMounted.

setup() {

  const instance = getCurrentInstance()

  console.log(instance.ctx.foo); // undefined

  console.log(instance.ctx.bar()); // undefined

},
Copy the code

Common solutions:

What if setup function is too long?

setup(){

  let { val, todos, addTodo } = useTodo()

  let {count,double,add} = useCounter() 

  let {x, double:doubleX} = useMouse()

  return {

    val, todos, addTodo,

    count,double,add,

    x,doubleX

  }

}
Copy the code

The return context is too long. We can use vue3 setup script to optimize the setup configuration and export each function once

<script setup>

import useCounter from './counter'

import useMouse from './mouse'

import useTodo from './todos'



let { val, todos, addTodo } = useTodo()

export {val, todos, addTodo}



let {count,double,add} = useCounter()

export {count,double,add}



let {x, double:doubleX} = useMouse()

export {x,doubleX}

</script>
Copy the code

Why is my property not responding

Here is the code I wrote for the first time

Setup ({foo, bar}) {watchEffect(() => {console.log(foo, bar) // foo, bar changes, no output})}Copy the code

Props is a Proxy object, and when you deconstruct it, it becomes unresponsive, so be gentle with props and don’t split it

Setup (props) {watchEffect(() => {console.log(props. Foo, props. Bar) // foo, bar changed, output})}Copy the code

You can split it if you want. How do you like it

Setup (props) {const {foo, bar} = toRefs(props) watchEffect(() => {console.log(foo.value, bar.value) // foo, bar changed, There will be output})}Copy the code

How to send custom events?

$emit() this.$emit() will emit events on this.

It is possible to distribute events via component instances, such as:

Setup () {getCurrentInstance().emit('ooxx')} Setup (props, CTX) {ctx.emit('ooxx')} setup(props, {emit}) {emit('ooxx')}Copy the code

Vue3 gets the route of the current page

import { getCurrentInstance } from 'vue'

setup() {
  const { ctx } = getCurrentInstance()
  console.log(ctx.$router.currentRoute.value)
}
Copy the code
import { useRoute } from 'vue-router'
import { toRaw } from 'vue'

setup () {
  const route = useRoute()
  console.log(toRaw(route))
}
Copy the code

The parent component calls the child component method

// Parent <Listmodify :isShow="isShow" ref="child"></Listmodify> setup(context) {const child = ref(); const handleEdit = () => { child.value.str(); }; return { handleEdit, child }; } // Subcomponent setup(props, context) {const STR = () => {console.log(" I was called by the parent component "); }; return { str }; }Copy the code

3. Teleport

(Do not mount to app to solve style conflicts)

Teleport provides A way to control which parent object in the Dom renders HTML without resorting to global state or splitting it into two parts.

The use of the Teleport

Example 1:

1. Build a VUE3 project first

2. Start using examples:

 <div id="app"></div>
 <div id="teleport-target"></div>
 <div id="modal-container"></div>
Copy the code
<button @click="showToast" class=" BTN "> </button> <! <div v-if="visible" class=" toastle-wrap "> <div class=" toastle-msg" Toast copy </div> </div> </teleport>Copy the code
import { ref } from 'vue'; Export default {setup() {// Toast encapsulation const Visible = ref(false); let timer; const showToast = () => { visible.value = true; clearTimeout(timer); timer = setTimeout(() => { visible.value = false; }, 2000); } return { visible, showToast } } }Copy the code

3. Use with Vue Components — Modal-wrapped components

<div id="app"></div>
  <div id="teleport-target"></div>
   <div id="modal-container"></div>
  <script type="module" src="/src/main.js"></script>
Copy the code
<teleport to="#modal-container"> <! -- use the modal component, pass in the prop --> <modal :show="showModal" @close="showModal = false"> <template #header> <h3>custom header</h3> </template> </modal> </teleport>Copy the code
import { ref } from 'vue'; import Modal from './Modal.vue'; Export default {components: {Modal}, setup() {// Encapsulate Modal const showModal = ref(false); return { showModal } } }Copy the code

In this case, even if Modal is rendered in a different place, it will still be a child of the current component (the component that invokes Modal) and will receive show Prop from it

Example 2:
  1. Add a new insertion point to the index.html page (it will be mounted under the #headTitie DOM)
<div id="headTitie"></div>

<div id="app"></div>
Copy the code
  1. Create a new headtitle. vue in the Components directory
<template> <teleport to="#headTitie"> <div class="head"> <h1>{{ title }}</h1> </div> </teleport> </template> <script lang="ts"> import { defineComponent, ref } from "vue"; Export default defineComponent({name: "headTitie", setup() {const title = ref("Vue3 new feature example "); return { title, }; }}); </script>Copy the code
  1. In the App. Vue
<template>
  <headTitle />
  <router-view />
</template>

<script lang="ts">
import headTitle from "./components/headTitle.vue";
    
export default {
  name: "App",
  components: {
    headTitle,
  },
};

</script>
Copy the code

4. Watch to monitor

Introducing a watch from vUE can be seen in point 4: Reactivity

  1. Listen for reactivity data for ref declarations
  2. Listen for reactive data on reactive statements
  3. Listen to the data in props
<script> import {ref, watch} from 'vue' setup(props) {// Let count = ref(0) watch(count, (val,) Old) => {// new data, old data}) 5}) watch(() => person. Age, (val, old) => {reactive([1, 2, 3]) watch(arr, (val, old) => {// props watch(() => props. Testkey, Return return {count, person, arr}} </script>Copy the code
<script lang="ts"> import { defineComponent, ref, reactive, toRefs, watch } from "vue"; Export default defineComponent({name: "Home", Components: {}, setup() {const text = ref(" test single value "); Const data = reactive({list: [" 表 ", "表 "," 表 "], show: (index: string) => {data.name = index; }}); //watch([text,()=>data.name]) () = > data. The name to compatible vue2 watch ([text, () = > data. The name], (newValue, oldValue) = > {the console. The log (` new - > ${newValue} `); console.log(`old--->${oldValue}`); }); const refData = toRefs(data); return { ... refData, }; }}); </script>Copy the code

What’s the difference between watchEffect and Watch?

These two methods are very similar in that they both observe responsive data and perform side effect functions, but they have the following differences:

  • Watch needs to explicitly specify monitoring targets
Watch (() => state.counter, (val, prevVal) => {}) //watchEffect not required watchEffect(() => {console.log(state.counter)})Copy the code
  • Watch can get the value before and after the change
  • Watch is lazily executed and is equivalent to vue2this.$watch()In order to collect dependencies, the watchEffect is executed immediately

Can I write more than one lifecycle hook?

Of course you can write more than one, and they will be executed in the order they were registered:

setup() {

  onMounted(() => {})

  onMounted(() => {})

  onMounted(() => {})

}
Copy the code

You can even split multiple hooks of the same lifecycle into separate functions

Function fun1() {onMounted(() => {})} function fun2() {onMounted(() => {})} {}) } setup() { fun1() fun2() onMounted(() => {}) }Copy the code

5. Computed attributes

Introduce computed from VUE

<script> import {ref, Computed} from 'vue' setup(props) {let count = ref(0) // Calculation properties of the current component let countCom = computed(() => {return count.value * Let countCom2 = computed(() => {return props. PropsKey * 2})} </script>Copy the code

Extension –

  • Computed Creates read-only computing properties

Passing a function to computed() yields a read-only computed property:

Const count = ref(1) Make its value 1 greater than count const bigCount = computed(() => count.value + 1) console.log(bigcount.value) // Output 2 bigcount.value ++ // The error is to writeCopy the code
  • Computed To create readable and writable compute properties
Const count = ref(1) // Create a computed property and pass in an object const bigCount = computed({// get: () => (count. Value + 1), // set: Val => {count. Value = val - 1}}) The count value is updated console.log(count.value) // 8Copy the code

6. Setup lifecycle hook usage

  1. Setup’s onMounted execution precedes the mounted of the entire component
  2. OnMounted execution of setup follows execution of the Setup synchronization component
  3. Setup onMounted and setup cannot use this
<script> import {onMounted} from 'vue' mounted () { console.log(4) }, setup () { onMounted(() => { console.log(1) }) console.log(2) setTimeout(() => { console.log(3) }, OnMounted (() => {console.log(this)}) // print //undefined} </script>Copy the code

7. Dojo.provide and inject

Import parent component provide from VUE

<script> import {provide} from 'vue' export default { setup () { provide('person', { name: 'Bob', age: 18}) provide('city', 'hangzhou ')}} </script>Copy the code

Descendant component Core

<script> import {inject} from 'vue' export default {setup () {// Data provided by parent components let person = inject('person') let City = inject('city') // Value not provided by parent component, Let noProvide = inject('noProvide', 'noProvide HAH ')}} </script>Copy the code

Provide reactive data parent component value changes and descendant component values change accordingly

<script> import {provide} from 'vue' export default {setup () {let city = ref(' binriver ') provide('city', city) } } </script>Copy the code

Provide a function

<script>
import {provide} from 'vue'

export default {
    setup () {
        let provideFun = () => {
            console.log('provide fun')
        }
        provide('provideFun', provideFun)
    }
}
</script>
Copy the code
Import {ref,provide} from 'vue'; Setup (){let init = ref(1); // provide() accept two parameters (name: string,data: passed data) setup(){let init = ref(1); Function change(){init.value += 1} provide('init',init) provide('update',change) Return {change,init}} // subcomponent import {inject,readonly} from 'vue'; return {change,init}} // subcomponent import {inject,readonly} from 'vue'; // inject() accepts two parameters (name: the name to receive the provide,data: Don't fill in, Setup (){const oneInit = inject('init') // Receive data from above const updateUser = inject(' updateA1 ',readonly(oneInit)) // {oneInit, updateUser}} return {oneInit, updateUser}}Copy the code

8.Reactivity

One of Vue’s most unique features is its unobtrusive reaction system.

When you pass a pure JavaScript object to an application or component instance as a data option, Vue will iterate over all of its properties and convert them to Proxies using handlers with getters and setters

  • Trace the function that changes it: effect this operation in the getter of the agent
  • Trigger the function so that it can update the final value: operate trigger in the setter in the agent
Declare reactivity data

Ref, Reactive, and Readonly are commonly used to declare data

  • Ref declares the base type
  • Reactive declares the reference type
  • Readonly Specifies the read-only reference type
import { ref, reactive, Readonly} from 'vue' export default {setup () {reactive let count = ref(0) / {{count}} let state = reactive({name: 'Bob'}) // use state. Name in script, use {{state. Name}} in template. 1}) ⚠️ can be used normally, but cannot be made reactive(10) 10 // readonly // The same as reactive, but only the same as reactive warning alert let person = readonly({age: 18}) setTimeout(() => {// timer modification warning ⚠️ person.age = 10 // Set operation on key "age" failed: target is readonly}); Return {count, state, obj1}}} {return {count, state, obj1}}}Copy the code

Count Indicates the printed data

RefImpl {_rawValue: 0, _shallow: false, __v_isRef: true, _value: 0}
    __v_isRef: true
    _rawValue: 0
    _shallow: false
    _value: 0
    value: 0
Copy the code

State Indicates the printed data

ƒ deleteProperty(target, key) get: ƒ (Target, key, Receiver) has: ƒ has(target, key) Owner: ƒ ownKeys(Target) set: ƒ (target, key, value, Receiver) [[target]]: Object name: "Bob" [[IsRevoked]]: falseCopy the code

Obj1 Prints the data

RefImpl {_rawValue: {... }, _shallow: false, __v_isRef: true, _value: Proxy} __v_isRef: true _rawValue: {count: 1} _shallow: false _value: Proxy {count: 1} value: Proxy [[Handler]]: Object [[Target]]: Object count: 1 [[IsRevoked]]: falseCopy the code

Num1 Indicates the printed data

10
Copy the code
The template used in
<! -- Use basic types defined by ref directly --> <! Direct reference types defined by Reactive. --> <div class="vue3_pro"> count: {{count}} state: {{state.name}} </div>Copy the code

9. Vue3 lifecycle function usage

Need to introduce (note: vue2 life cycle function does not affect)

<script lang="ts"> import { defineComponent,ref,reactive,toRefs, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onActivated, onDeactivated, onErrorCaptured, onRenderTracked, onRenderTriggered } from "vue"; Export Default defineComponent({name: "Home", Components: {}, setup() {//setup() is executed before beforeCreate and created to start creating components. Const data = reactive ({list: [" shenzhen ", "Beijing", "Shanghai"]}); OnBeforeMount (()=>{// Function executed before the component is mounted to the node. }) onMounted(()=>{// Function executed after the component is mounted. }) onBeforeUpdate(()=>{// Function executed before component update}) onUpdated(()=>{// Function executed after component update is complete. }) onBeforeUnmount(()=>{// Function executed before component unmounts. }) onUnmounted(()=>{// Function executed after the component is unmounted. }) onActivated(()=>{// The component contained in <keep-alive> will have two more lifecycle hook functions. Executed when activated. }) onDeactivated(()=>{// Switch from component A to component B when component A disappears. }) onErrorCaptured(()=>{// Activate the hook function when you catch an exception from a descendant component. }) //< debug onRenderTracked((event)=>{// Tracks all states firing console.log(event); }); OnRenderTriggered ((event) => {console.log(event); //oldValue oldValue //target current page response variables and functions}); /> const refData = toRefs(data); return { ... refData }; }, mounted(){console.log("vue2 lifecycle "); }}); </script>Copy the code

10.Vue3 modular reuse (optimize mixins)

1. Create the usetime. ts file

import { ref } from "vue";
const time = ref("00:00:00");
const getTime = () => {
    const now = new Date();
    const h= now.getHours() < 10 ? "0" + now.getHours() : now.getHours();
    const m = now.getMinutes() < 10 ? "0" + now.getMinutes() : now.getMinutes();
    const s= now.getSeconds() < 10 ? "0" + now.getSeconds() : now.getSeconds();
    time.value = h + ":" + m + ":" + s;
    setTimeout(getTime, 1000);
};
export { time, getTime }
          
Copy the code

2. The introduction of

<template> <div class="home"> {{time}} < button@click ="startTime"> start </button></div> </template> <script lang="ts"> import {defineComponent, ref } from "vue"; import { time, getTime } from './useTime'; export default defineComponent({ name: "Home", components: {}, setup() { const startTime = () => { getTime(); }; return { startTime, time }; }}); </script>Copy the code

Suspense Asynchronous request components

  1. A new Demo. Vue
<template> <div class="Demo"> {{ name }}</div> </div> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ name: "Demo", components: {}, setup() { return new Promise((resolve, reject) => { setTimeout(() => { return resolve({ name: "I am Suspense asynchronous request component"}); }, 2100); }); }}); </script>Copy the code
  1. Use the import home.vue
< the template > < div class = "home" > < Suspense > < # default template > < Demo / > < / template > < # template fallback > < p > loading... </p> </template> </Suspense> </div> </template> <script lang="ts"> import { defineComponent } from "vue"; import Demo from "./Demo.vue"; export default defineComponent({ name: "Home", components: {Demo} }); </script>Copy the code

Composition – Api:

12.ref()

The ref() function creates a reactive data object based on a given value. The return value is an object containing only a.value attribute.

  • Create a reactive object with ref
Ref import {ref} from '@vue/composition-api' setup() {const count = ref(0); return { count } }Copy the code
  • Use reactive objects
<p> {{count}}</p> <button @click="count++">Copy the code

To change this value in JS, add an additional value:

  • Precautions for ref
  1. In the setup() function, the reactive data created by ref() returns objects, so it needs to be accessed with.value;

    Outside the setup() function, you don’t need.value, just access it.

  2. Reactive data created by the ref() function can be accessed in a Reactive object.

  3. The new ref() overwrites the old ref().

Ref data response listening, and react-hook seems similar. The ref function passes in a value as an argument and returns a responsive REF object based on that value, which is tracked whenever its value is changed or accessed. Just like in our modified example code, changing the count.value value triggers a re-rendering of the template to display the latest value

13.reactive()

Reactive is used to define more complex data types, but the variables are no longer reactive Ref object data

Reactive () takes a normal object and returns a reactive object.

In vue2.x, we only need to define a data in data() to make it reactive. In Vue3.0, reactive data is created using reactive functions such as Reactive or ref.

  • Create reactive objects using Reactive
Reactive import {reactive} from '@vue/ composition-api' setup() {reactive import {reactive} from '@vue/ composition-api' setup() { count:0 }); // Use return state to expose the responsive object to the template; }Copy the code
  • Use reactive objects
<p> <button @click="count++">Copy the code

Composition-api introduces a stand-alone data-responsive method reactive, which handles incoming objects in a reactive manner:

const state = reactive({ foo: 'foo',}) watchEffect(() => {console.log(state.foo)}) state.foo = 'foooooo' // output 'foooooo'Copy the code

This approach, similar to the data option we set up, solves most of our requirements. But there are also the following problems:

  • When we export the state directly, we prefix the state in the template
ToRefs setup() {const state = reactive({}) return {state}}< div>{{state.foo}}</div state = reactive({}) return { ... toRefs(state) } } <div>{{ foo }}</div>Copy the code

The choice between REF and Reactive

For single-valued objects, ref is recommended, even for single-valued objects

A business concern has multiple values, and reactive is recommended

14. readonly()

Pass in a reactive object, plain object, or ref, and return a read-only object proxy. The proxy is deep and the data inside the object is read only.

const state = reactive({ count: 0}) const copy = readonly(state) watchEffect(() => {// dependency trace console.log(copy.count)}) // Changes on state trigger listening on copy State. count++ // the read-only property cannot be changed copy.count++ // warning!Copy the code

15. watchEffect()

WatchEffect () executes the incoming function immediately, listens for its dependencies in a responsive manner, and rerunts the function when its dependencies change.

  • Basic usage
WatchEffect (() => console.log(count.value)) setTimeout(() => {const count = ref(0), watchEffect(() => console.log(count. Trigger function prints 1 count.value++}, 1000)Copy the code
  • Stop listening

WatchEffect () returns a function when used, and stops listening when the returned function is executed.

const stop = watchEffect(() => { /* ... */}) // Stop listening stop()Copy the code

Composition-api depends on tools

1. isRef()

IsRef (), as its name implies, is the value that determines whether a value is a response created by ref().

It is used when you need to expand a reactive value that might be created for ref() :

import { isRef } from '@vue/composition-api'

const unwrapper = isRef(foo) ? foo.value : foo
Copy the code

2.toRefs()

ToRefs () converts reactive objects created by Reactive () into normal objects with ref-reactive values

Before we understand the use of toRefs(), we need to understand the difference between reactive() and ref() objects:

  1. withreactive()Create a reactive object, the whole object is reactive, and each item in the object is a normal value. When you expand it with the expansion operator, the normal value of the whole object is not reactive;
  2. withref()Reactive values created are themselves reactive and do not depend on other objects.

So when you need to expand reactive objects created by Reactive () without making them less reactive, you need toRefs() to transform them:

Mport {toRefs} from '@vue/composition-api' setup() { 0}) const add = () => {state.count++} At the same time, all its attributes are converted to the reactive data in the form of REF... toRefs(state), add } }Copy the code
</button> </div> </template> </button> </div> </template>Copy the code

Changes of VUe3 and VUe2

This is all a trial run

router-link

The improvements are as follows:

  • deletetagProp – Uses scope slots instead
  • deleteeventProp – Uses scope slots instead
  • increasescoped-slot API
  • Stop automatic transferclickEvents are assigned to internal anchor points
  • addcustomProp to fully support customrouter-linkApply colours to a drawing

In vue2-router, to render

into some kind of tag, such as

<router-link ="/" tag="button"> </router-link>! <button> </button>Copy the code

You may need to do this later:

<router-link
  to="/foo"
  v-slot="{ href, route, navigate, isActive, isExactActive }"
>
  <li
    :class="[isActive && 'router-link-active', isExactActive && 'router-link-exact-active']"
  >
    <a :href="href" @click="navigate">{{ route.fullPath }}</a>
  </li>
</router-link>
Copy the code

The object of slot prop contains the following properties:

Href: the parsed URL. Will be the href attribute of an A element. 2. Route: normalized address after parsing. Navigate: the function that triggers the navigation. Automatically blocks events when necessary, as with router-link. IsActive: True if the active class needs to be applied. Allows an arbitrary class to be applied. IsExactActive: True if exactactive classes need to be applied. Allows an arbitrary class to be applied.