preface

The appearance of Vue3 perfectly solves the defects of Vue2 in some aspects. Next, let’s walk into Vue3 and see what changes it brings to us

Vue3

Vue3 is faster and smaller than Vue2, with a 41% reduction in size, a 33% increase in rendering speed and a 54% reduction in memory usage. More flexible Composition API and perfect TypeScript support. Through these numbers and advantages, it is well worth us to learn a wave of Vue3! Let’s take a closer look at the Compsition API commonly used in Vue3.

Vue3 Chinese document

Composition API

Composition API Chinese document

  • setup

The setup function is an entry function in which we define variables, functions, life cycles, and so on, and export them to be accessed on the page. The specific steps are as follows:

<template>
    <p>The numbers are: {{num}}</p>
    <p>{{double}}</p>
    <button @click="sum">cumulative</button>
</template>
<script>
import { ref, onMounted, computed } from "vue"; // Import the core methods in Vue3
export default{... .// You can define some options for Vue2
    setup() {
        const num = ref(Awesome!); // Define a responsive constant
        
        const sum = (a, b) = > a + b; // Define a method
        
        const double = computed(() = > num.value+1) // Define a calculated property
        
        onMounted(() = > {
            console.log('Lifecycle hook function executed after page loads')})/ /... And so on can be defined in the setup function
        
        return { // Export defined variables and methods to be used in the template
            num,
            sum,
            double
        }
    }
}
</script>
Copy the code

Note that the setup function accepts two arguments: props, context;

  1. propsRepresents a property passed in by the parent, and the value is reactive and the page will be updated if the value is changed. Therefore,propsCan’t be deconstructed, but can be usedtoRefsDeconstruct it or it will become unresponsive.
  2. contextContext, which containsattrsslots,emitAnd so on. It is not reactive, so it can be deconstructed

When setup is executed, the component instance is not created and can only access properties such as props, attrs, slots, and emit. Other options cannot be accessed: computed, methods, and so on.

Next, we’ll take a closer look at the common core methods in Vue3!

  • ref

Ref: Values of basic data types are generally set to reactive values

<template>
    <p v-show="flag">Whether or not shown</p>
    <p>My name: {{name}}</p>
    <p>My age: {{age}}</p>
    <p ref="refDom">Hello.</p>
</template>
<script>
import { ref } from "vue";
export default {
    setup() {
        const flag   = ref(false); // Define a Boolean variable
        const age    = ref(25);    // Define a variable of type Number
        const name   = ref('tmc'); // Define a variable of type String
        const refDom = ref(null);  // You can access Dom elements
        
        return {
            flag,
            age,
            name,
            refDom
        }
    }
}
</script>
Copy the code

Note: variables defined by ref are automatically expanded in the template, so there is no need to use.value. Using these variables in the setup function does not require.value

  • reactive

Reactive: Typically values of reference types are set to reactive values

<template>
    <p>My name: {{state.name}}</p>
    <p>My age: {{state.age}}</p>
</template>
<script>
import { reactive } from "vue";
export default {
    setup() {
        const state = reactive({
            name: 'tmc'.age: 25
        })
        
        return {
            state
        }
    }
}
</script>
Copy the code

Note:

  1. reactiveSimilar to theVue2In theVue.observable()
  2. To make it easy to use in modules, usetoRefsTo export
  3. ref(variable)Is equivalent toreactive({value: variable})
  • toRefs

ToRefs: Converts reactive objects into normal objects

<template>
    <p>My name: {{name}}</p>
    <p>My age: {{age}}</p>
</template>
<script>
import { toRefs, reactive } from "vue";
export default {
    setup() {
        const data = reactive({
            name: 'tmc'.age: 25
        })
        
        return {
            ...toRefs(data)
        }
    }
}
</script>
Copy the code

Note: toRefs returns all attributes converted to ref; Therefore, responsiveness is not lost when deconstructing

  • toRaw

ToRaw: Returns ordinary objects that have been transformed into reactive proxies by reactive or Readonly methods

<template>
    <! -... -->
</template>
<script>
import { toRaw, reactive, ref } from "vue";
export default {
    setup() {
        const data1 = reactive({
            name: 'tmc'.age: 25
        })
        const data2 = ref(Awesome!)
        
        const changeData1 = toRaw(data1)
        const changeData2 = toRaw(data2.value)
        
        return {
            ...toRefs(data)
        }
    }
}
</script>
Copy the code

Note: When converting a ref object, you need to pass.value

  • provide & inject

Provide & Inject: The parent component provides data through the provide option, and the child component accepts and uses the provided data through the Inject option

<! -- Parent component -->
<template>
    <my-test></my-test>
</template>
<script>
import { provide } from "vue";
import MyTest from './MyTest';
export default {
    components: {
        MyTest
    },
    setup() {
        provide('name'.'tmc')
        // Multiple provides can be provided
        return {
            // ...}}}</script>
Copy the code

Note: provide takes two parameters, the first is key and the other is value

<! -- Subcomponent -->
<template>
    <p> {{name}} </p>
</template>
<script>
import { inject } from "vue";
export default {
    components: {
        MyTest
    },
    setup() {
        const name = inject('name');
        // inject('name', 'xxx'); // You can specify a default value
        return {
            name
        }
    }
}
</script>
Copy the code

Note: Inject the first parameter is key, the second parameter specifies the default value (optional).

If you want to provide and inject reactive values, you can provide them in theprovideThe use ofrefreactive

  • computed

Computed: For calculating attributes, see the example above

  • watch & watchEffect

Watch (source, cb, [options])

  1. Watch listens for reactive data created by the REF

    <template>
        <! -... -->
    </template>
    <script>
    import { watch, ref } from "vue";
    export default {
        setup() {
            const name = ref('tmc');
            
            watch(name, (newVal, oldVal) = > {
                console.log('New value:' + newVal)
                console.log('Old value:' + oldVal)
            })
            
        }
    }
    </script>
    Copy the code
  2. Watch listens to reactive data created by Reactive

    <template>
        <! -... -->
    </template>
    <script>
    import { watch, reactive } from "vue";
    export default {
        setup() {
            const data = reactive({
                name: 'tmc'.age: 25
            });
            
            // Listen for a single attribute
            watch(() = > data.name, (newVal, oldVal) = > {
                console.log('New value:' + newVal)
                console.log('Old value:' + oldVal)
            })
            
            // Listen for multiple attributes
            watch(() = > [data.name, data.age], ([newName, oldName], [newAge, oldAge]) = > {
                console.log('New value:' + newName)
                console.log('Old value:' + oldName)
                console.log('New value:' + newAge)
                console.log('Old value:' + oldAge)
            })
            
        }
    }
    </script>
    Copy the code

watch,watchEffectReturns a function to stop the listenerstop, the user can stop listening.

Note: What is the difference between watch and watchEffect?

  1. watchIs the attribute that needs to be passed in to listen, andwatchEffectIs an automatic collection of dependencies
  2. watchYou can see the values of the property changing back and forth, whilewatchEffectThere is no
  3. watchIs executed when the property changes, andwatchEffectIt is executed once by default, and property changes are also executed
  • .

For more information about the usage and precautions of the Composition API, see the Vue Composite API

The life cycle

Basic usage for each lifecycle:

<template>
    <! -... -->
</template>
<script>
import { onMounted, onUpdated, onUnmounted } from "vue";
export default {
    setup() {
        onMounted(() = > {
          console.log('mounted! ')   / / a mount
        })
        onUpdated(() = > {
          console.log('updated! ')   / / update
        })
        onUnmounted(() = > {
          console.log('unmounted! ') / / destroy}}})</script>
Copy the code

Differences from 2.x version

  • beforeCreate– > usesetup
  • created– > usesetup
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

New hook functions:

  • onRenderTracked
  • onRenderTriggered

Custom function Hooks

Drop down to load more

// hooks/useLoadMore.ts
import { computed, onMounted, Ref } from 'vue';
import { IGlobalState } from '@/store';
import { Vuex } from 'vuex';
import _ from 'lodash';

export function useLoadMore(refreshEle: Ref<null | HTMLElement>, store: Store<IGlobalState>, type: string) {
    let element: HTMLElement; // The element that needs scrolling
    
    function _loadMore() {
        let containerHeight = element.clientHeight; // Get the height of the viewable area
        let scrollTop = element.scrollTop; // Get the height of the scroll
        let scrollHeight = element.scrollHeight; // Get the height of the list
        
        if(containerHeight + scrollTop + 25 >= scrollHeight) {
            store.dispatch(type); Distributed / / action
        }
    }
    
    onMounted(() = > {
        element = refreshEle.value as HTMLElement;
        
        element.addEventListener('scroll', _.debounce(_loadMore, 200)); / / image stabilization
    })
    
    // State loading and hasMore can be changed
    const isLoading = computed(() = > {
        return store.state.home.homeList.loading
    })
    const hasMore = computed(() = > {
        return store.state.home.homeList.hasMore
    })
}
Copy the code

Use in pages

// index.vue
<template>.<div ref="refreshEle">.<HomeList :xxx="xxx"></HomeList>.</div>.</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { Store, useStore } from 'vuex';
import { IGlobalState } from '@/store';
import { useLoadMore } from '@/hooks/useLoadMore';
export default defineComponent({
    ...
    setup() {
    	let store = useStore<IGlobalState>();
   		let refreshEle = ref<null | HTMLElement>(null);
    	const { isLoading, hasMore } = useLoadMore(refreshEle, store, `home/${types.SET_HOME_LIST}`);
    
    	return {
            refreshEle,
            isLoading,
            hasMore
        }
	}
    ...
})
</script>
Copy the code

Built-in component

Teleport Teleport component

  • TeleportYou can move modules to the currentDOMElements other than the location of the technology
// index.html
<html>.<div id="app"></div>
    <div id="teleport-toast"></div>
</html>


// components/index.vue
<button @click="showToast">According to toast</button>
<teleport to="#teleport-toast">
    <div v-show="showFlag">
        <div>Display Toast content</div>
    </div>
</teleport>
Copy the code
import { defineComponent, ref } from 'vue';
export default defineComponent({
	setup() {
        const showFlag = ref(false);
        const showToast = (() = > {
        	showFlag.value = true;    
        });
        
        return {
            showFlag,
            showToast
        }
    }  
})
Copy the code

, but the state of the teleport is completely controlled by the internal Vue component.

Suspense loads components asynchronously

<Suspense>
    <! -- #default -->
	<template #default>
    	<xxxx>Xyz component</xxxx>
    </template>
    <template #fallback>
    	<div>Loading...</div>
    </template>
</Suspense>
Copy the code

Note: #default, #fallback are abbreviations for named slots; Example: V-slot: TMC === # TMC

Extension: React also includes a component called Suspense>, often used with react.lazy ()

// Basic usage
import React, { Suspense } from 'react';

const Page = React.lazy(() = > import('./Page'));

<Suspense fallback={<div> Loading... </div>} ><Page />
</Suspense>
Copy the code

DefineAsyncComponent in Vue3 is similar to react.lazy ()

Fragement

In Vue2. X, a component can have only one root DOM. In Vue3, a component can have multiple root DOM

Global API

  • getCurrentInstance
  • Changes to the way components are registered
// import Vue from 'Vue' using Vue.component; import Test from './Test.vue'; Vue.component('Test', Test); Import {createApp, h} from 'vue'; // Vue3 uses createApp(). Component import {createApp, h} from 'vue'; import Test from './Test.vue'; CreateApp (Test). The component (" Comp ", {render: (a) = > h (' div ', 'custom components')})Copy the code
  • Part of theAPITo change the way in which thetree-shaking
// Vue2
import Vue from 'vue';

Vue.nextTick(() => {})

// Vue3
import { nextTick } from 'vue';

nextTick(() => {})
Copy the code
  • Examples of application
import { createApp } from 'vue'; const app = createApp(); // app is an application instanceCopy the code
Global API Vue2. X Vue3 application instance API
Vue.config app.config
Vue.config.productionTip remove
Vue.use app.config.isCustomElement
Vue.component app.use
. .

Note:

  1. Vue3removed$on/$once/$offVue.filter

Vue-Router

Vue-router Indicates the official address

Basic usage

import { createRouter, createWebHashHistory } from 'vue-router';
import Home from '@/views/home.vue';

const routes = [
    {
        path: '/'.name: 'Home'.component: Home
    },
    {
        path: '/about'.name: 'About'.component: () = > import(/* webpackChunkName: "about" */ '.. /views/About.vue'); }]const router = createRouter({
    histroy: createWebHashHistory(),
    routes
})

export default router;
Copy the code

Vuex

Vuex official address

Basic usage

// store
import { createStore } from 'vuex';

export default createStore({
	state: {}, / / state
    getters: {}, // Get the status
	mutations: {}, // Synchronize the status change
    actions: {}, // Change the status asynchronously
    modules: {} / / module
})
Copy the code
// template
<template>.</template>
<script>
import { useStore } from 'vuex';
export default defineComponent({
    setup() {
        const store = useStore(); // Create a store instance. }})</script>
Copy the code

Complete Store structure design

If the project is small, refer to this directory structure

Create four subdirectories and one file under the store directory:

  1. state: Stores the state used in the project
  2. getters: To do something with some state in use
  3. mutations: Indicates the synchronization modification status
  4. actions: Indicates the asynchronous modification status
  5. index.jsFile: Used for consolidationstate,getters,mutations,actions

If the project is large, refer to this directory structure

Create a directory and a file under the store directory:

  1. modules: To store a large module of the project, such as the home page, my…
  2. index.jsFile: Used for consolidationmodulesThe module

For those who are not familiar with Vuex, you can read this article: Mastering the core API usage and fundamentals of Vuex at work

Vue2.x & Vue3

  1. Vue2.0usingflowTo write, andVue3.0All source code usedTypeScriptDeveloped for TS support friendly (all attributes are placed inthisObject, hard to push to the component’s data type)
  2. Source code volume optimization: remove partsapi(filter), the use oftree-shaking(a lot ofAPIMounted on theVueObject prototype, difficult to implementTreeShaking)
  3. Data hijacking optimization:Vue3usingProxy, the performance is greatly improved
  4. Compiler optimization:Vue3Static template analysis and rewriting diff algorithm are implemented
  5. Composition API: Integrate logic of business code, extract common logic (byReact HooksInspiration.Vue2usingmixin– Naming conflicts & unclear data source)
  6. Custom renderer: Can be used to create custom renderers, rewrite Vue underlying rendering logic
  7. newFragment,Teleport,SuspenseBuilt-in components such as

conclusion

The best way to learn a new technology is to use it to write a project, slowly explore, constantly climb the pit will slowly be able to ~