Vue3 全局API转移到应用对象

Vue3 全局API转移到应用对象

一、回顾vue2的问题

在vue2中,我们写全局API的时候会这样写

vue 复制代码
Vue.component('my-component', { ... });
Vue.directive('focus', { ... });
Vue.mixin({ ... });
Vue.prototype.$http = axios;

这样的缺点就是全局注册的内容会污染整个Vue环境,如果你在一个页面里运行两个不同的Vue的项目,这个全局配置就会互相干扰;

所以Vue3引入了应用实例的概念,每个应用都是独立的

vue 复制代码
const app = Vue.createApp({ ... });
app.component(...);   // 只属于这个 app

二、创建一个计数器案例

vue 复制代码
//index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Vue3 全局API迁移演示</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .demo-area { border: 1px solid #ddd; padding: 15px; margin: 15px 0; border-radius: 8px; }
        button { margin: 5px; padding: 6px 12px; cursor: pointer; }
    </style>
</head>
<body>
    <div id="app"></div>   <!-- Vue 应用会挂载到这里 -->
</body>
</html>
vue 复制代码
<template>
  <div class="demo-area">
    <h2>{{ message }}</h2>
    <p>当前计数:{{ count }}</p>
    <button @click="count++">点我 +1</button>
    <button @click="greet">打招呼</button>
  </div>
</template>
<script setup>
import { ref } from 'vue';

let message = ref("Hello Vue3!")
let count = ref(0)

function greet() {
  alert(message.value);
}

</script>

<style scoped>
body {
  font-family: Arial, sans-serif;
  margin: 20px;
}

.demo-area {
  border: 1px solid #ddd;
  padding: 15px;
  margin: 15px 0;
  border-radius: 8px;
}

button {
  margin: 5px;
  padding: 6px 12px;
  cursor: pointer;
}
</style>
vue 复制代码
//main.ts
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount('#app')

这里,vue.createAPP()替代了vue2的new Vue();所以返回的app拥有了所有vue的方法,通过app.mount,将应用渲染到页面中,所以你在页面上就看到了一切

为了演示,我们在建立两个组件,一个子组件,另一个演示全局API

三、添加全局组件(app.component)

  • 例如,我们现在再main.ts中注册一个新的组件,Hello.vue
vue 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import Hello from './Hello.vue'
const app = createApp(App)
app.component('Hello', Hello)
app.mount('#app')
  • 然后我们再Hello.vue写一点东西
vue 复制代码
<template>
    <div style="background:#eef; padding:8px;">🎉 我是全局组件Hello!欢迎学习 Vue3</div>
</template>
<script setup>


</script>

<style scoped></style>
  • 然后我们就可以再任何地方使用它了
vue 复制代码
<template>
  <div class="demo-area">
    <Hello></Hello>
    <h2>{{ message }}</h2>
    <p>当前计数:{{ count }}</p>
    <button @click="count++">点我 +1</button>
    <button @click="greet">打招呼</button>
  </div>

  <Child />
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

let message = ref("Hello Vue3!")
let count = ref(0)

function greet() {
  alert(message.value);
}

</script>

<style scoped>
body {
  font-family: Arial, sans-serif;
  margin: 20px;
}

.demo-area {
  border: 1px solid #ddd;
  padding: 15px;
  margin: 15px 0;
  border-radius: 8px;
}

button {
  margin: 5px;
  padding: 6px 12px;
  cursor: pointer;
}
</style>

四、添加自定义指令(app.directive)

  • 我们简单写一个v-highlight指令,让按钮变量
vue 复制代码
//main.ts
app.directive('highlight', {
    //当指令绑定的元素首次被传入DOM时调用
    mounted(el, binding) {
        //bingding.value式传给指令的值
        el.style.backgroundColor = binding.value || 'yellow';
        el.style.transition = '0.3s';
    },
    //当指令所在的组件发生了更新时调用
    updated(el, binding) {
        el.style.backgroundColor = binding.value || 'yellow'
    }
})
  • 然后就可以再任意组件调用了
vue 复制代码
    <button @click="count++" v-highlight="'lightblue'">点我 +1</button>
    <button @click="greet" v-highlight="'lightgreen'">打招呼</button>

五、添加全局混入(app.mixin)

混入mixin可以把一些公共逻辑注入到所有组件中,这里我们注入一个数据和一个钩子

vue 复制代码
app.mixin({
    data() {
        return {
            globalInfo: '(来自全局混入的额外信息)'
        }
    },
    created() {
        console.log('[混入]组件被创建了');
    }
})
  • 然后我们就可以再根组件中使用了
vue 复制代码
  <p>📢 {{ globalInfo }}</p>

这个根组件自动拥有了golbalInfo属性,并且控制台也会打印日志,但是混入虽然用起来很方便,滥用会导致代码根本不知道在哪,谨慎使用;

六、添加全局属性(app.config.globalProperties)

  • 在vue2中,我们使用Vue.prototype.$http = axios来添加全局方法,Vue3写法如下:
vue 复制代码
app.config.globalProperties.$myUtil = function (msg: any) {
    console.log(`[全局工具]${msg}`);
};

注意:在模板中无法直接使用$myUtil,只能在选项式API的this上下文使用;

但是我们可以像以下来使用它

vue 复制代码
<template>
  <div class="demo-area">
    <Hello></Hello>
    <h2>{{ message }}</h2>
    <p>当前计数:{{ count }}</p>
    <p>📢 {{ globalInfo }}</p>
    <button @click="count++" v-highlight="'lightblue'">点我 +1</button>
    <button @click="greet" v-highlight="'lightgreen'">打招呼</button>
    <button @click="$myUtil('这是全局工具')">调用全局工具</button>
  </div>

七、卸载应用(app.unmount)

  • 这里我们结合以下全局组件,用全局组件来定义一个工具,这个工具就是来卸载应用的
vue 复制代码
app.config.globalProperties.$unmountAPP = () => {
    app.unmount()
    console.log('app应用已经被卸载');
}
vue 复制代码
    <button @click="$unmountAPP">调用全局工具</button>
相关推荐
程序员黑豆4 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
To_OC5 小时前
踩了个 TS 的坑之后,我终于把 type 和 interface 掰明白了
前端·react.js·typescript
GreenTea5 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
浮生望5 小时前
前端API工程化:用 Mock 数据与 Axios 配置实现独立于后端的并行开发
前端
万少6 小时前
给 DeepSeek Harness 装个"应用商店":一条命令,595 个插件随你逛
前端·javascript·后端
波波0076 小时前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
Brown.alexis7 小时前
es6知识点1-自备使用
前端·ecmascript·es6
小爬的老粉丝7 小时前
JavaScript 纯前端预览 WPS:先识别容器,再路由解析器
前端·javascript·wps
计算机魔术师8 小时前
新兴多智能体系统的模式与问题
前端
用户059540174469 小时前
AI Agent 上下文污染踩坑实录:用 pytest + Redis 揪出 3 类记忆串号 bug,排查 6 小时
前端·css