globalProperties
由于Vue3 没有Prototype 属性 使用 app.config.globalProperties 代替 然后去定义变量和函数
Vue2与 Vue 3的区别
// 之前 (Vue 2.x)
Vue.prototype.$http = () => {}
const app = createApp({})
app.config.globalProperties.$http = () => {}
main.ts定义全局变量
app.config.globalProperties.$env = "env";
main.ts定义全局过滤器函数
在Vue3 移除了filter函数 我们可以使用全局函数代替
// 全局函数使用案例
type Filter = {format: <T extends any>(str: T) => T;
};
// 声明要扩充@vue/runtime-core包的声明.
// 这里扩充"ComponentCustomProperties"接口, 因为他是vue3中实例的属性的类型.
declare module "@vue/runtime-core" {export interface ComponentCustomProperties {$filters: Filter;}
}
app.config.globalProperties.$filters = {format<T extends any>(str: T): string {return `coookie-${str}`;},
};
组件中使用
二种不同的方式获取值,推荐使用第二种
<template><div class="">{{ $env }}</div><div class="">{{ $filters.format("nihao") }}</div>
</template><script setup lang="ts">
import { log } from "console";
import {getCurrentInstance,ComponentInternalInstance,
} from "vue";
// 第一种方式
const { appContext } = <ComponentInternalInstance>(getCurrentInstance()
);
console.log(appContext.config.globalProperties.$env);
// 第二种方式
const app = getCurrentInstance();
console.log(app?.proxy?.$filters.format("js"));
</script><style lang="less" scoped></style>
编写全局插件
插件知识
插件有二种形式 一是导出对象形式 二是函数
导出对象形式必须包含install方法
插件是自包含的代码,通常向 Vue 添加全局级功能。你如果是一个对象需要有install方法Vue会帮你自动注入到install 方法(意思是vue.use(loading)后会自动调用loading插件的install方法) 你如果是function 就直接当install 方法去使用
loading.vue
需defineExpose对外暴露 当前组件的属性和方法
<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对外暴露 当前组件的属性和方法
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>
index.ts
createVNode vue提供的底层方法 可以给我们组件创建一个虚拟DOM 也就是Vnode
render 把我们的Vnode 生成真实DOM 并且挂载到指定节点 这里是挂载到body上
import { App, VNode, createVNode, render } from "vue";
import Loading from "./loading.vue";// 插件有二种形式 一是导出对象形式 二是函数
// 导出对象形式必须包含install方法
export default {// Vue.use(Loading) 会自动调用install方法install(app: App) {//app 是全局的console.log("loading插件被注册了", Loading); // 现在获取到的Loading无法正常使用 需要createVNode通过转成Vnode,再用render函数挂载到全局let vnode: VNode = createVNode(Loading); //createVNode vue提供的底层方法 可以给我们组件创建一个虚拟DOM 也就是Vnodeconsole.log(vnode); // 此时就是个vnode 但是component上是没有值的,故需要用render函数挂载render(vnode, document.body); // //render 把我们的Vnode 生成真实DOM 并且挂载到指定节点 这里是挂载到body上/* let el: any = document.querySelector("#app");render(vnode, el);console.log("el", el); */ // 此时setupState中就有我们index.vue组件挂载的值// console.log(vnode.component?.setupState); // 不建议使用这种方式// vnode.component?.setupState?.show();// console.log(vnode.component?.exposed); //建议使用这种方式,但index.vue需要抛出对应的defineExpose// Vue 提供的全局配置 可以自定义app.config.globalProperties.$loading = {// 需要注册为全局其他组件才能使用show: () => vnode.component?.exposed?.show(),hide: () => vnode.component?.exposed?.hide(),};// app.config.globalProperties.$loading.show(); //测试loading},
};
main.ts
import Loading from "./index.ts"; //引入插件app.use(Loading); // 加载插件
type Lod = {show: () => void;hide: () => void;
};
//编写ts loading 声明文件放置报错 和 智能提示
declare module "@vue/runtime-core" {export interface ComponentCustomProperties {$loading: Lod;}
}
declare module "vue" {export interface ComponentCustomProperties {$loading: Lod;}
}
使用插件
<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>