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 中:組件必須有一個根標(biāo)簽
Vue3 中:可以沒有根標(biāo)簽,內(nèi)部會添加根標(biāo)簽 <fragment> </fragment>
好處:減少標(biāo)簽層級,減少內(nèi)存消耗
<template>
? ? <h1>App</h1>
? ? <p>superman</p>
</template>
<script>
export default { name: "App" };
</script>Teleport
用于將組件的 HTML 結(jié)構(gòu)移動到指定位置
用法:
① 用 Teleport 標(biāo)簽將需要移動的 HTML 結(jié)構(gòu)包裹住
② 設(shè)置 to 屬性,屬性值為 選擇器,以指定移動到的位置
默認(rèn)情況下,子組件的 HTML 結(jié)構(gòu)會顯示到父組件的 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
等待異步組件時,渲染一些額外的內(nèi)容,提升用戶體驗(yàn)感
用法:
① 在父組件中,異步引入組件:defineAsyncComponent + 懶加載
② 在子組件中,配置 Suspense 標(biāo)簽
③ 在 Suspense 標(biāo)簽內(nèi),用 template 標(biāo)簽設(shè)置具名插槽
default 插槽的內(nèi)容:為異步引入的組件
fallback 插槽的內(nèi)容:為加載時顯示的內(nèi)容
此時,異步引入的組件中 setup 可以是 async 函數(shù)
<template>
<div class="box">
<h1>App</h1>
<Suspense>
<!-- 需要顯示的異步組件 -->
<template v-slot:default>
<Son></Son>
</template>
<!-- 異步組件顯示之前,暫時先顯示的內(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",
// 此時 setup 也可以是 async 函數(shù)
async setup() {
let p = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve("superman")
}, 1000);
});
return { p };
}
};
</script>
文件對比
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í)例對象 (相當(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)前路由對象
let route = useRoute();
console.log("route", route);
// 總路由對象
let router = useRouter(router);
console.log("router", router);
// 路由守衛(wèi)
onBeforeRouteLeave(() => {
console.log("onBeforeRouteLeave:離開路由時觸發(fā)");
});
onBeforeRouteUpdate(() => {
console.log("onBeforeRouteUpdate:復(fù)用路由時觸發(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("自定義指令名", 配置對象)
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
Vue.directive("focus", {
bind() {
console.log("指令與元素綁定時觸發(fā)");
},
inserted(el) {
console.log("指令所在元素插入頁面時觸發(fā)");
el.focus();
},
update(el) {
console.log("模板重新渲染時觸發(fā)");
el.focus();
}
});
new Vue({ render: h => h(App) }).$mount('#app')
也可以使用簡寫(回調(diào)函數(shù)執(zhí)行完后,DOM 才會插入到頁面中):
Vue.directive("focus", (el, msg) => {
console.log(el, msg); // el:掛載的元素;val:掛載的信息
console.log(msg.value); // 獲取指令的屬性值
});
Vue3 - app.directive("自定義指令名", 配置對象)
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 個參數(shù):
el:指令綁定到的元素,可用于直接操作 DOM。eg:el.focus()binding:配置對象instance:使用指令的組件實(shí)例value:傳遞給指令的值oldValue:先前的值,僅在 beforeUpdate 和 updated 中可用。無論值是否有更改都可用arg:傳遞給指令的參數(shù)(如果有的話)eg:v-my-directive:foo 中,arg 為 "foo"。modifiers:修飾符對象(如果有的話)eg:v-my-directive.foo.bar 中,修飾符對象為 {foo: true,bar: true}dir:配置對象本身
全局屬性
- 全局屬性:在任何組件中都可以訪問
- 與組件的屬性發(fā)生命名沖突時,組件的屬性優(yōu)先級更高
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')以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue如何實(shí)現(xiàn)分批加載數(shù)據(jù)
這篇文章主要介紹了Vue如何實(shí)現(xiàn)分批加載數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04
Ant Design Vue 添加區(qū)分中英文的長度校驗(yàn)功能
這篇文章主要介紹了Ant Design Vue 添加區(qū)分中英文的長度校驗(yàn)功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下功能,2020-01-01
VUE+Canvas實(shí)現(xiàn)財神爺接元寶小游戲
這篇文章主要介紹了VUE+Canvas實(shí)現(xiàn)財神爺接元寶小游戲,需要的朋友可以參考下本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2021-04-04
Vue Computed中g(shù)et和set的用法及Computed與watch的區(qū)別
這篇文章主要介紹了Vue Computed中g(shù)et和set的用法及Computed與watch的區(qū)別,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11

