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;
props
Represents a property passed in by the parent, and the value is reactive and the page will be updated if the value is changed. Therefore,props
Can’t be deconstructed, but can be usedtoRefs
Deconstruct it or it will become unresponsive.context
Context, which containsattrs
、slots
,emit
And 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:
reactive
Similar to theVue2
In theVue.observable()
- To make it easy to use in modules, use
toRefs
To export 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 theprovide
The use ofref
和 reactive
- computed
Computed: For calculating attributes, see the example above
- watch & watchEffect
Watch (source, cb, [options])
-
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
-
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
,watchEffect
Returns a function to stop the listenerstop
, the user can stop listening.
Note: What is the difference between watch and watchEffect?
watch
Is the attribute that needs to be passed in to listen, andwatchEffect
Is an automatic collection of dependencieswatch
You can see the values of the property changing back and forth, whilewatchEffect
There is nowatch
Is executed when the property changes, andwatchEffect
It 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
Teleport
You can move modules to the currentDOM
Elements 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 the
API
To 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:
Vue3
removed$on/$once/$off
和Vue.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:
state
: Stores the state used in the projectgetters
: To do something with some state in usemutations
: Indicates the synchronization modification statusactions
: Indicates the asynchronous modification statusindex.js
File: 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:
modules
: To store a large module of the project, such as the home page, my…index.js
File: Used for consolidationmodules
The 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
Vue2.0
usingflow
To write, andVue3.0
All source code usedTypeScript
Developed for TS support friendly (all attributes are placed inthis
Object, hard to push to the component’s data type)- Source code volume optimization: remove parts
api(filter)
, the use oftree-shaking
(a lot ofAPI
Mounted on theVue
Object prototype, difficult to implementTreeShaking
) - Data hijacking optimization:
Vue3
usingProxy
, the performance is greatly improved - Compiler optimization:
Vue3
Static template analysis and rewriting diff algorithm are implemented Composition API
: Integrate logic of business code, extract common logic (byReact Hooks
Inspiration.Vue2
usingmixin
– Naming conflicts & unclear data source)- Custom renderer: Can be used to create custom renderers, rewrite Vue underlying rendering logic
- new
Fragment
,Teleport
,Suspense
Built-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 ~