Appearance
Vue3定义全局函数和变量
globalProperties
由于Vue3 没有 Prototype 属性,使用 app.config.globalProperties 代替,然后去定义变量和函数
Vue2
js
// 之前 (Vue 2.x)
Vue.prototype.$http = () => {
}Vue3
ts
// 之后 (Vue 3.x)
const app = createApp({})
app.config.globalProperties.$http = () => {
}过滤器
在Vue3 移除了
我们正好可以使用全局函数代替Filters
案例: main.ts
ts
app.config.globalProperties.$filters = {
format<T extends any>(str: T): string {
return `$${str}`
}
}
app.config.globalProperties.$env = 'dev'
type Filter = {
format<T>(str: T): string
}
// 声明要扩充@vue/runtime-core包的声明.
// 这里扩充"ComponentCustomProperties"接口, 因为他是vue3中实例的属性的类型.
declare module '@vue/runtime-core' {
export interface ComponentCustomProperties {
$filters: Filter,
$env: string
}
}setup中使用
vue
<script>
import {getCurrentInstance} from "vue";
const app = getCurrentInstance()
console.log(app?.proxy?.$env)
</script>编写Vue3插件
插件
插件是自包含的代码,通常向 Vue 添加全局级功能。 你如果是一个对象需要有 install 方法, Vue 会帮你自动注入到 install 方法 你如果是function 就直接当install 方法去使用
使用插件
在使用 createApp() 初始化 Vue 应用程序后,你可以通过调用 use() 方法将插件添加到你的应用程序中。
实现一个Loading
- src/components/loading/Loading.vue
vue
<template>
<div v-if="isShow" class="loading">
<div class="loading-content">Loading...</div>
</div>
</template>
<script setup lang='ts'>
import {ref} from 'vue';
const isShow = ref(false)//定位loading 的开关
const show = () => {
isShow.value = true
}
const hide = () => {
isShow.value = false
}
//对外暴露 当前组件的属性和方法
defineExpose({
isShow,
show,
hide
})
</script>
<style scoped lang="less">
.loading {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
&-content {
font-size: 30px;
color: #fff;
}
}
</style>- src/components/loading/index.ts
ts
import {App, createVNode, render, VNode} from "vue";
import Loading from './index.vue'
// 需要将Loading转成vNode 挂载
// 可以导出对象或者函数(导出对象,必须得有install函数)
export default {
install(app: App) {
//createVNode vue提供的底层方法 可以给我们组件创建一个虚拟DOM 也就是Vnode
const vnode: VNode = createVNode(Loading)
//render 把我们的Vnode 生成真实DOM 并且挂载到指定节点
render(vnode, document.body)
// Vue 提供的全局配置 可以自定义
app.config.globalProperties.$_loading = {
show: () => vnode.component?.exposed?.show(),
hide: () => vnode.component?.exposed?.hide()
}
// app.config.globalProperties.$_loading.show()
}
}- src/main.ts
ts
import {createApp} from 'vue'
// @ts-ignore
import App from './App.vue'
import Loading from "./components/loading/index.ts";
// createApp(App).mount('#app')
const app = createApp(App)
app.use(Loading)
type Load = {
show: () => void
hide: () => void
}
//编写ts loading 声明文件放置报错 和 智能提示
declare module '@vue/runtime-core' {
export interface ComponentCustomProperties {
$_loading: Load
}
}
app.mount('#app')- 调用插件
vue
<template>
<div></div>
</template>
<script setup lang='ts'>
import {ref, reactive, getCurrentInstance} from 'vue'
// 获取当前组件实例
const instance = getCurrentInstance()
instance?.proxy?.$_loading.show()
setTimeout(() => {
instance?.proxy?.$_loading.hide()
}, 5000)
// console.log(instance)
</script>
<style>
* {
padding: 0;
margin: 0;
}
</style>Vue use 源码手写
在 src/main.ts 中注册,需要使用 app.use()
ts
import type {App} from 'vue'
import {app} from './main'
interface Use {
install: (app: App, ...options: any[]) => void
}
const installedList = new Set()
export function MyUse<T extends Use>(plugin: T, ...options: any[]) {
if (installedList.has(plugin)) {
return console.warn('重复添加插件', plugin)
} else {
plugin.install(app, ...options)
installedList.add(plugin)
}
}