vue3:vue2中protoType更改為config.globalProperties問題
protoType替換為config.globalProperties
在main.js中:
vue2
Vue.prototype.$verson = '1.0.0'
使用
this.$verson
vue3
Vue.config.globalProperties.$verson = '1.0.0'
使用
<script setup lang="ts"> import {getCurrentInstance} from 'vue' console.log(getCurrentInstance().appContext.config.globalProperties.$verson) </script>
Vue3 vs Vue2
Vue3 的新組件
Fragment
Vue2 中:組件必須有一個(gè)根標(biāo)簽
Vue3 中:可以沒有根標(biāo)簽,內(nèi)部會(huì)添加根標(biāo)簽 <fragment> </fragment>
好處:減少標(biāo)簽層級(jí),減少內(nèi)存消耗
<template> ? ? <h1>App</h1> ? ? <p>superman</p> </template> <script> export default { name: "App" }; </script>
Teleport
用于將組件的 HTML 結(jié)構(gòu)移動(dòng)到指定位置
用法:
① 用 Teleport 標(biāo)簽將需要移動(dòng)的 HTML 結(jié)構(gòu)包裹住
② 設(shè)置 to 屬性,屬性值為 選擇器,以指定移動(dòng)到的位置
默認(rèn)情況下,子組件的 HTML 結(jié)構(gòu)會(huì)顯示到父組件的 HTML 結(jié)構(gòu)里面;
使用 Teleport 標(biāo)簽包裹子組件的 HTML 標(biāo)簽,則能將該 HTML 結(jié)構(gòu)顯示到指定的位置
<template> <div class="box"> <h1>App</h1> <button @click="bol = !bol">顯示 / 隱藏</button> <Son v-if="bol" /> </div> </template> <script> import { ref } from "vue"; import Son from "./components/Son.vue"; export default { name: "App", components: { Son }, setup() { let bol = ref(false); return { bol }; }, }; </script> <style> .box { width: 200px; height: 200px; background: palevioletred; position: relative; } </style>
<template> <!-- 默認(rèn)情況下,顯示到 .box 里面 --> <h2>Son</h2> <!-- 通過 Teleport 標(biāo)簽,將 HTML 結(jié)構(gòu)顯示到 body 里面 --> <Teleport to="body"> <h2>Teleport Son</h2> </Teleport> </template> <script> export default { name: "Son" }; </script>
Suspense
等待異步組件時(shí),渲染一些額外的內(nèi)容,提升用戶體驗(yàn)感
用法:
① 在父組件中,異步引入組件:defineAsyncComponent + 懶加載
② 在子組件中,配置 Suspense 標(biāo)簽
③ 在 Suspense 標(biāo)簽內(nèi),用 template 標(biāo)簽設(shè)置具名插槽
default 插槽的內(nèi)容:為異步引入的組件
fallback 插槽的內(nèi)容:為加載時(shí)顯示的內(nèi)容
此時(shí),異步引入的組件中 setup 可以是 async 函數(shù)
<template> <div class="box"> <h1>App</h1> <Suspense> <!-- 需要顯示的異步組件 --> <template v-slot:default> <Son></Son> </template> <!-- 異步組件顯示之前,暫時(shí)先顯示的內(nèi)容 --> <template #fallback> 加載中... </template> </Suspense> </div> </template> <script> // 靜態(tài)引入 // import Son from "./components/Son.vue"; // 異步引入 import { defineAsyncComponent } from 'vue'; const Son = defineAsyncComponent(() => import("./components/Son.vue")); export default { name: "App", components: { Son }, }; </script>
<template> <h2>Son: {{ p }}</h2> </template> <script> export default { name: "Son", // 此時(shí) setup 也可以是 async 函數(shù) async setup() { let p = await new Promise((resolve, reject) => { setTimeout(() => { resolve("superman") }, 1000); }); return { p }; } }; </script>
文件對(duì)比
main.js
Vue2
import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' Vue.config.productionTip = false new Vue({ router, store, render: h => h(App) }).$mount('#app')
Vue3
引入的不再是 Vue 構(gòu)造函數(shù),而是工廠函數(shù) createApp:
構(gòu)造函數(shù):通過 new 關(guān)鍵字調(diào)用,首字母大寫
工廠函數(shù):直接調(diào)用,首字母小寫
createApp 返回:應(yīng)用實(shí)例對(duì)象 (相當(dāng)于 Vue2 中的 vm,但比 vm 輕)
可以在 createApp 之后鏈?zhǔn)秸{(diào)用其它方法
import { createApp } from 'vue' // 引入 createApp 方法 import App from './App.vue' import router from './router' import store from './store' createApp(App).use(store).use(router).mount('#app') // 鏈?zhǔn)秸{(diào)用
store 文件
Vue2
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: {}, mutations: {}, actions: {}, modules: {} })
Vue3
import { createStore } from 'vuex' // 引入 createStore 方法 export default createStore({ state: {}, mutations: {}, actions: {}, modules: {} })
Vuex 的使用
先配置好 store 文件:
import { createStore } from 'vuex' export default createStore({ state: { name: "superman", arr: [1, 2, 3] }, mutations: { muModify(state, val) { console.log("commit muModify", val) state.name += val } }, actions: { acModify(context, val) { console.log("dispatch acModify", val) context.commit("muModify", val) } }, getters: { getArr(state) { return state.arr.map(item => item * 2) } }, modules: {} })
Vue3 中需要通過 useStore 方法使用 vuex
<template> <p>普通使用:</p> <p>$store.state.name: {{ $store.state.name }}</p> <p>$store.state.arr: {{ $store.state.arr }}</p> <p>$store.getters.getArr: {{ $store.getters.getArr }}</p> <hr /> <p>Vue 3:</p> <p>name: {{ name }}</p> <p>arr: {{ arr }}</p> <p>getArr: {{ getArr }}</p> <hr /> <button @click="coModify">coModify name</button> | <button @click="diModify">diModify name</button> </template> <script> import { useStore } from "vuex"; export default { name: "App", setup() { // 通過 useStore 使用 Vuex const store = useStore(); // 獲取數(shù)據(jù) let name = store.state.name; let arr = store.state.arr; let getArr = store.getters.getArr; // 調(diào)用 dispatch 方法 function diModify() { store.dispatch("acModify", "(Actions)"); } // 調(diào)用 commit 方法 function coModify() { store.commit("muModify", "(Mutations)"); } return { name, arr, getArr, coModify, diModify }; }, }; </script>
但是,通過該方法獲取的數(shù)據(jù)不是響應(yīng)式的
響應(yīng)式數(shù)據(jù)設(shè)置如下:需要配合 computed 方法使用
let name = computed(() => store.state.name); let arr = computed(() => store.state.arr); let getArr = computed(() => store.getters.getArr);
router 文件
Vue2
import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' Vue.use(VueRouter) const routes = [{ path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: () => import('../views/About.vue') } ] const router = new VueRouter({ mode: 'history', // 設(shè)置路由模式為 history base: process.env.BASE_URL, // 根據(jù) webpack 環(huán)境,設(shè)置 [根路徑] routes }) export default router
Vue3
import { createRouter, // 引入 createRouter 方法 createWebHistory // 引入 createWebHistory 方法 } from 'vue-router' import Home from '../views/Home.vue' const routes = [{ path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: () => import('../views/About.vue') } ] const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes }) export default router
vue-router 的使用
先配置 router 文件
import { createRouter, createWebHistory } from 'vue-router' import Home from '../views/Home.vue' const routes = [{ path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: () => import('../views/About.vue') } ] const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes }) export default router
Vue3 中需要通過 useRoute 方法使用 vue-router
<template> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> <router-view /> </template> <script> export default { name: "App", }; </script>
<template> <h1>About</h1> </template> <script> import { useRoute, useRouter, onBeforeRouteLeave, onBeforeRouteUpdate, } from "vue-router"; export default { name: "About", setup() { // 當(dāng)前路由對(duì)象 let route = useRoute(); console.log("route", route); // 總路由對(duì)象 let router = useRouter(router); console.log("router", router); // 路由守衛(wèi) onBeforeRouteLeave(() => { console.log("onBeforeRouteLeave:離開路由時(shí)觸發(fā)"); }); onBeforeRouteUpdate(() => { console.log("onBeforeRouteUpdate:復(fù)用路由時(shí)觸發(fā)"); }); return {}; }, }; </script>
<template> <h1>Home</h1> </template> <script> export default { name: "Home" }; </script>
全局 API
在 Vue3 中,全局和內(nèi)部 API 都經(jīng)過了重構(gòu)
全局 API 現(xiàn)在只能作為 ES 模塊構(gòu)建的命名導(dǎo)出進(jìn)行訪問
import { nextTick } from 'vue' nextTick(() => { // 一些和DOM有關(guān)的東西 })
Vue.XXX
→ app.XXX
全局 directive
Vue2 - Vue.directive("自定義指令名", 配置對(duì)象)
import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false Vue.directive("focus", { bind() { console.log("指令與元素綁定時(shí)觸發(fā)"); }, inserted(el) { console.log("指令所在元素插入頁面時(shí)觸發(fā)"); el.focus(); }, update(el) { console.log("模板重新渲染時(shí)觸發(fā)"); el.focus(); } }); new Vue({ render: h => h(App) }).$mount('#app')
也可以使用簡寫(回調(diào)函數(shù)執(zhí)行完后,DOM 才會(huì)插入到頁面中):
Vue.directive("focus", (el, msg) => { console.log(el, msg); // el:掛載的元素;val:掛載的信息 console.log(msg.value); // 獲取指令的屬性值 });
Vue3 - app.directive("自定義指令名", 配置對(duì)象)
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) // 自定義指令,指令具有一組生命周期鉤子: app.directive('myIns', { // 在綁定元素的 attribute 或事件監(jiān)聽器被應(yīng)用之前調(diào)用 created() {}, // 在綁定元素的父組件掛載之前調(diào)用 beforeMount() {}, // 在綁定元素的父組件掛載之后調(diào)用 mounted() {}, // 在包含組件的 VNode 更新之前調(diào)用 beforeUpdate() {}, // 在包含組件的 VNode 及其子組件的 VNode 更新之后調(diào)用 updated() {}, // 在綁定元素的父組件卸載之前調(diào)用 beforeUnmount() {}, // 在綁定元素的父組件卸載之后調(diào)用 unmounted() {} }); app.mount('#app')
鉤子函數(shù)接收 2 個(gè)參數(shù):
el
:指令綁定到的元素,可用于直接操作 DOM。eg:el.focus()binding
:配置對(duì)象instance
:使用指令的組件實(shí)例value
:傳遞給指令的值oldValue
:先前的值,僅在 beforeUpdate 和 updated 中可用。無論值是否有更改都可用arg
:傳遞給指令的參數(shù)(如果有的話)eg
:v-my-directive:foo 中,arg 為 "foo"。modifiers
:修飾符對(duì)象(如果有的話)eg
:v-my-directive.foo.bar 中,修飾符對(duì)象為 {foo: true,bar: true}dir
:配置對(duì)象本身
全局屬性
- 全局屬性:在任何組件中都可以訪問
- 與組件的屬性發(fā)生命名沖突時(shí),組件的屬性優(yōu)先級(jí)更高
Vue2 - Vue.prototype
import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false Vue.prototype.$myData = "superman" // 設(shè)置全局屬性 new Vue({ render: h => h(App) }).$mount('#app')
Vue3 - app.config.globalProperties
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.config.globalProperties.$myData = "superman" // 設(shè)置全局屬性 app.mount('#app')
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue如何實(shí)現(xiàn)分批加載數(shù)據(jù)
這篇文章主要介紹了Vue如何實(shí)現(xiàn)分批加載數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Ant Design Vue 添加區(qū)分中英文的長度校驗(yàn)功能
這篇文章主要介紹了Ant Design Vue 添加區(qū)分中英文的長度校驗(yàn)功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下功能,2020-01-01VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲
這篇文章主要介紹了VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲,需要的朋友可以參考下本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-04-04Vue Computed中g(shù)et和set的用法及Computed與watch的區(qū)別
這篇文章主要介紹了Vue Computed中g(shù)et和set的用法及Computed與watch的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11