Hello everyone, my name is Dongdong, you now see is vue advanced series, if you feel good, you can click “like” collection oh, like my friends, can also add a concern duck.
The VUE Advanced series includes the following:
Vue Advanced Path: 8 ways for Components to Communicate, Have you figured it out?
Vue steps up: What is the lifecycle execution flow for parent and child components?
The Road to VUE Advancement: The five core concepts of Vuex are enough after reading this article.
The road to vUE advancement: Front-end technology changes with each passing day, the era of VUE 3.0 has come…
Vue advanced road: Ding, what are the differences between Vue2 and Vue3? Please find!
Preface:
Vue3.0 is not finished, vue3.2 is coming again, can you still learn? (Manual funny)
Vue3.2 and Vue3.0 have the following differences in syntax: Vue3.0: Variables and methods must return to be used. Vue3.2: simply add the setup attribute to the script tag, no need to return variables and methods, simpler code.
This article will focus on introducing the syntax of VUE3.2. If you have not been fully exposed to VUE3, you can go to this article to warm up. Front-end technology is changing fast, the era of VUE3.0 has arrived…
Create a project:
Vite scaffold creation project: VUE3 + VitE2 + TS
npm create vite@latest
Copy the code
I. Component structure
<script setup lang="ts"> </script> <template> //vue2 supports only one root node. Vue3 supports multiple root nodes. </template> <style scoped> </style>Copy the code
2. The data
<script setup lang="ts"> import {reactive, ref, toRefs} from 'vue' Value = 'reactive' const state = reactive({age: 24, sex: 'male'}) / / modify state. The age = 24 / / using toRefs deconstruct the template can be directly use {{name}}, {{sex}} const {age, sex} = toRefs(state) </script> <template> <h1>{{ name }}</h1> <h1>{{ state.age }}</h1> <h1>{{ sex }}</h1> </template> <style scoped> </style>Copy the code
Three method.
<script setup lang="ts"> import {reactive, toRefs} from 'vue' Const state = reactive({age: 24, sex: 'male'}) / / using toRefs deconstruct the template can be directly use {{name}}, {{sex}} const {age, Sex} = toRefs(state) // declaration method method const changeAge =()=>{state.age+=1}</ script> <template> <h1>{{age}}</h1> <! <button @click="changeAge()"> </button> </template> <style scoped> </style>Copy the code
Four computed.
<script setup lang="ts"> import {ref,computed} from 'vue' // ref declares responsive data Const count = ref(1) //computed to obtain doubleCount 'const doubleCount =computed(()=>{return count.value*2}) </script> <template> <h1>{{ count }}</h1> <h1>{{doubleCount}}</h1> </template> <style scoped> </style>Copy the code
Five. Father to son
// Parent component: < script setup lang = "ts" > / / incoming child components (component automatic registration) import HelloWorld from '. / components/HelloWorld. Vue '< / script > < template > < div style =" box-sizing: border-box! Important; word-wrap: break-word! Important;Copy the code
// Subcomponent: <script setup lang="ts"> <script setup lang="ts"> // import {defineProps} from 'vue' // defineProps in <script DefineProps: true // declare const props = defineProps({MSG: { type: String, default: "", }, }); </script> <template> {{props.msg}} <! Can be omitted, props - > < h1 > {{MSG}} < / h1 > < / template > < style scoped > < / style >Copy the code
Six. Son to father
<script setup lang="ts"> import {reactive} from "vue"; / / incoming child components (component automatic registration) import HelloWorld from ". / components/HelloWorld. Vue "; Const state = reactive({MSG: "I am the parent ",}); const changeMsg = (val) => { state.msg = val; }; </script> <template> <HelloWorld :msg='state.msg' @changeMsg="changeMsg" /> </template> <style> </style>Copy the code
<script setup lang="ts"> import {defineEmits} from "vue"; // import {defineEmits, defineProps} from 'vue' // defineEmits and defineProps are automatically available in <script setup>, // Configure [defineEmits: true] and [defineProps] in. Eslintrc.js file [globals] // declare props/const props = defineProps({MSG: {type: String, default: "",},}); // Emit const emit = defineEmits(["changeMsg"]); Const changeMsg = () => {emit("changeMsg", "I am the value sent by the child component "); }; </script> <template> {{props.msg}} <! <h1>{{MSG}}</h1> <! <button @click="changeMsg"> </button> </template> <style scoped> </style>Copy the code
7. Prototype chain binding and component use
/ / / / the main ts create instances const app = createApp vue (app) / / get the prototype const prototype = app. Config. GlobalProperties / / binding parameters Prototype. name = 'I'm a globally mounted property'Copy the code
Import {getCurrentInstance} from "vue"; import {getCurrentInstance} from "vue"; Const {proxy} = getCurrentInstance(); / / output to the console. The log (proxy. Name);Copy the code
8. Arbitrary component communication mitt.js
- Vue2. X uses EventBus for component communication, while mitt.js is recommended for Vue3.
Ix. Two-way binding V-Model
<script setup lang="ts"> import {reactive} from "vue"; / / incoming child components (component automatic registration) import HelloWorld from ". / components/HelloWorld. Vue "; Const state = reactive({MSG: "I am the parent ", age:24}); </script> <template> <div> </div> <div>{{state.msg}}</div> <input type="text" v-model="state.msg"> <HelloWorld v-model:msg='state.msg' v-model:age="state.age" /> </template> <style> </style>Copy the code
<script setup lang="ts"> import {defineEmits} from "vue"; // import {defineEmits, defineProps} from 'vue' // defineEmits and defineProps are automatically available in <script setup>, // Configure [defineEmits: true] and [defineProps] in. Eslintrc.js file [globals] // declare props/const props = defineProps({MSG: {type: String, default: "",}, age: {type: Number, default: 0,}}); // Declare emit const emit = defineEmits(["updata: MSG ", "updata:age"]); </script> <template> <div> <input type="text" V-model =" MSG "> <! Can be omitted, props - > < h1 > {{MSG}} < / h1 > < h1 > {{age}} < / h1 > < / template > < style scoped > < / style >Copy the code
Ten nextTick.
<script setup lang="ts"> import { reactive ,nextTick } from "vue"; / / incoming child components (component automatic registration) import HelloWorld from ". / components/HelloWorld. Vue "; Const state = reactive({MSG: "I am the parent ",}); NextTick nextTick(()=>{console.log("nextTick executed...") ); </script> <template> </template> </style> </style>Copy the code
<script setup lang="ts"> import {defineProps,nextTick} from "vue"; // declare const props = defineProps({MSG: {type: String, default: "",},}); NextTick nextTick(()=>{console.log("nextTick executed...") ); }) </script> <template> <h1>{{ msg }}</h1> </template> <style scoped> </style>Copy the code
Xi. Slot
<script setup lang="ts"> import {useSlots, reactive} from 'vue' const state = reactive({name: }) const defaultSlot = reactive(slots.default && slots.default().length) Console. Log ("defaultSlot",defaultSlot) const titleSlot = Reactive (slots.title && slots.title().length) console.log("titleSlot",titleSlot) // 3 </script> <template> <! -- Anonymous slot --> <slot/> <! -- named slot --> <slot name='title'/> <! <slot name="footer" :scope="state" /> </template> <style scoped> </style>Copy the code
/ / parent component: < script setup lang = "ts" > import HelloWorld from ". / components/HelloWorld. Vue "; </script> <template> <HelloWorld> <! -- Anonymous slot --> <span> I am the default slot </span> <! -- / named slot --> <template #title> <h1> I'm named slot 1</h1> <h1> I'm named slot 3</h1> </template> <! <template #footer="{scope}"> <footer> {{scope.name}}, age {{scope.age}}</footer> </template> </HelloWorld> </template> <style> </style>Copy the code
I am the default slot # I am named slot 1 # I am named slot 2 # I am named slot 3 scope slot -- name: dongdong, age 25 years oldCopy the code
Route useRoute and useRouter
Ts import {createRouter, createWebHashHistory, RouteRecordRaw} from 'vue-router'; const routes: Array<RouteRecordRaw> = [ { path: '/', redirect: '/home' }, { path: '/home', name: 'home', component: () => import('../pages/home/Index.vue'), meta: { showFooter: true, requireAuth: false, } }, { path: '/about', name: 'about', component: () => import( '../pages/about/Index.vue'), meta: { showFooter: true, requireAuth: false, } }, ]; const router = createRouter({ history: createWebHashHistory(), routes, }); export default router;Copy the code
Import {createApp} from 'vue' import App from './ app.vue 'import router from './router/index.ts' import {createApp} from 'vue' import App from './ app.vue' import router from '. const app=createApp(App) app.use(router).mount('#app')Copy the code
Import {useRouter, useRoute} from "vue-router"; import {useRouter, useRoute} from "vue-router"; // Call const router = useRouter(); const route = useRoute(); Console. log("router", router); console.log("route",route);Copy the code
13. Route guard
// Router guard route. beforeEach((to, from, next) => {console.log("to",to); console.log("from",from); next() })Copy the code
Life cycle
Mapping between the lifecycle options of the optional API and the composite API
– > usebeforeCreate
setup()
– > usecreated
setup()
beforeMount
->onBeforeMount
mounted
->onMounted
beforeUpdate
->onBeforeUpdate
updated
->onUpdated
beforeUnmount
->onBeforeUnmount
unmounted
->onUnmounted
errorCaptured
->onErrorCaptured
renderTracked
->onRenderTracked
renderTriggered
->onRenderTriggered
activated
->onActivated
deactivated
->onDeactivated
15. Store
- vuex
Vuex in Vue3 no longer provides auxiliary function writing. If you want to learn Vuex, you can follow this article. The Road to VUE Advancement: The five core concepts of Vuex are enough after reading this article.
- Pinia,
Vue3 is more recommended by Pinia. On November 24, 2021, UVU announced on Twitter that Pinia has officially become the official status library of Vue, which means that Pinia is Vuex 5. Let’s embrace Pinia!
① Basic use process
// Download pinia NPM install pinia -sCopy the code
Ts import {createApp} from 'vue' import App from '. '/ app.vue' import router from './router/index.ts' // Import pinia Import {createPinia} from 'pinia' // create vue instance const app=createApp(app) // createPinia instance const pinia = createPinia() // Use (router).use(pinia).mount('#app')Copy the code
// store/index.ts import { defineStore } from 'pinia' // 1. // Parameter 1: the container ID must be unique, and Pinia will mount all containers to the root container. Parameter 2: some option objects, namely state, getter, and action // return values: Export const useMainStore = defineStore('main',{// Similar to data in Vue2, used to store global state data, but with two requirements // 1. It must be a function to avoid cross-request data state contamination when rendering on the server. State ()=>{return {info:"hello, I am Pinia"}}, getters:{}, actions:{}})Copy the code
// Use <template> <div> <h1>{{mainStore.info}}</h1> </div> </template> <script setup lang="ts"> import {useMainStore } from ".. /.. /store/index.ts"; const mainStore = useMainStore(); </script> <style scoped> </style>Copy the code
(2) Deconstruction access of data in state
// store/index.ts import { defineStore } from 'pinia' // 1. // Parameter 1: the container ID must be unique, and Pinia will mount all containers to the root container. Parameter 2: some option objects, namely state, getter, and action // return values: Export const useMainStore = defineStore('main',{// Similar to data in Vue2, used to store global state data, but with two requirements // 1. It must be a function to avoid cross-request data state contamination when rendering on the server. State ()=>{return {info:"hello, I am Pinia", count:10}}, getters:{}, actions:{}})Copy the code
/ / components used within < template > < h1 > {{mainStore. Count}} < / h1 > < h1 > {{mainStore. Info}} < / h1 > < hr / > < h1 > {{count}} < / h1 > < h1 > {{info }}</h1> <p> <button @click="alertData"> </button> </p> </template> <script lang="ts" setup> import {toRefs} from 'vue' import { storeToRefs } from 'pinia' import { useMainStore } from ".. /.. /store"; const mainStore = useMainStore(); // Deconstruct the data, but the resulting data is not responsive, just one-time // equivalent to just... // const {count, info} = useMainStore(); Const {count, info} = toRefs(mainStore); const {count, info} = toRefs(mainStore); Const {count, info} = storeToRefs(mainStore); // 2. const alertData = () => { mainStore.count += 10 } </script> <style> </style>Copy the code
③ How to modify data in state (actions and components)
/ / the general change < template > < h1 > {{mainStore. Count}} < / h1 > < h1 > {{mainStore. Info}} < / h1 > < hr / > < h1 > {{count}} < / h1 > < h1 > {{info }}</h1> <p> <button @click="alertData"> </button> </p> </template> <script lang="ts" setup> import {toRefs} from 'vue' import { storeToRefs } from 'pinia' import { useMainStore } from ".. /.. /store"; const mainStore = useMainStore(); // Deconstruct the data, but the resulting data is not responsive, just one-time // equivalent to just... // const {count, info} = useMainStore(); Const {count, info} = toRefs(mainStore); const {count, info} = toRefs(mainStore); Const {count, info} = storeToRefs(mainStore); // 2. // mainStore.count += 10 // mainstore. count += 10 // mainstore. count += 10 // mainstore. count += 10 // mainstore. count += 10 // $patch({// count: mainstore. count + 1, // info:) $patch({// count: mainStore. "Hello" //}) A better way to batch update is to pass a function called $patch $patch(state => {state.count += 10 state.info = "Pinia batch update "+state.count})} </script> <style> </style>Copy the code
Ts import {defineStore} from 'pinia' // 1. // Parameter 1: the container ID must be unique, and Pinia will mount all containers to the root container. Parameter 2: some option objects, namely state, getter, and action // return values: Export const useMainStore = defineStore('main',{// Similar to data in Vue2, used to store global state data, but with two requirements // 1. It must be a function to avoid cross-request data state contamination when rendering on the server. State :()=>{return {info:" Hello, donc, donc, donC, donC, donC, donC, donC I am Pinia", count:10}}, getters:{}, // store/index.ts // methods similar to vue2, used to wrap business logic, modify state // // note: You can't use arrow functions to define actions, Because the arrow function binds external this actions:{changeState (){this.count += 10 this.info = "Actions modify data"}, ChangeStates (num:number){this.count += num + 2 this.info = "Actions modify data"}}})Copy the code
/ / components used within < template > < h1 > {{mainStore. Count}} < / h1 > < h1 > {{mainStore. Info}} < / h1 > < hr / > < h1 > {{count}} < / h1 > < h1 > {{info }}</h1> <p> <button @click="alertData"> </button> </p> </template> <script lang="ts" setup> import {toRefs} from 'vue' import { storeToRefs } from 'pinia' import { useMainStore } from ".. /.. /store"; const mainStore = useMainStore(); // Deconstruct the data, but the resulting data is not responsive, just one-time // equivalent to just... // const {count, info} = useMainStore(); Const {count, info} = toRefs(mainStore); const {count, info} = toRefs(mainStore); Const {count, info} = storeToRefs(mainStore); // 2. Const alertData = () => {// ChangeState () mainStore.changestates (10)} </script> <style> </style>Copy the code
③ The use of getters
// store/index.ts import { defineStore } from 'pinia' // 1. // Parameter 1: the container ID must be unique, and Pinia will mount all containers to the root container. Parameter 2: some option objects, namely state, getter, and action // return values: Export const useMainStore = defineStore('main',{// Similar to data in Vue2, used to store global state data, but with two requirements // 1. It must be a function to avoid cross-request data state contamination when rendering on the server. State :()=>{return {info:" Hello, I'm Pinia", count:10}}, // Computations similar to components used to encapsulate computed properties, Getters :{// The function takes an optional argument: Count10 (state){return state.count += 10}, count20(state){return this.count += 20}, Count11 ():number{return this.count += 11}}, // store/index.ts // Methods similar to vue2 Modify state // // You can't use arrow functions to define actions, Because the arrow function binds external this actions:{changeState (){this.count += 10 this.info = "Actions modify data"}, ChangeStates (num:number){this.count += num + 2 this.info = "Actions modify data"}}})Copy the code
/ / components used within < template > < h1 > {{mainStore. Count}} < / h1 > < h1 > {{mainStore. Info}} < / h1 > < hr / > < h1 > {{count}} < / h1 > < h1 > {{info }}</h1> <h1>{{mainstore. count10}}</h1> <p> < button@click ="alertData"> </p> </template> <script lang="ts" setup> import { toRefs } from 'vue' import { storeToRefs } from 'pinia' import { useMainStore } from ".. /.. /store"; const mainStore = useMainStore(); // Deconstruct the data, but the resulting data is not responsive, just one-time // equivalent to just... // const {count, info} = useMainStore(); Const {count, info} = toRefs(mainStore); const {count, info} = toRefs(mainStore); Const {count, info} = storeToRefs(mainStore); // 2. Const alertData = () => {// ChangeState () mainStore.changestates (10)} </script> <style> </style>Copy the code