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>
相关推荐
波哥学开发2 小时前
基于 OPFS 的前端缓存实践:图片与点云数据的本地持久化
前端
whuhewei2 小时前
useCountDown (React Hooks)倒计时
前端·javascript·react.js
DanCheOo2 小时前
流式输出:让 AI 回复像 ChatGPT 一样打字机效果
前端·全栈
HelloReader2 小时前
Qt Quick 布局Positioners、Anchors 与 Layouts(九)
前端
HelloReader2 小时前
Qt 信号与槽对象通信的核心机制(十)
前端
终端鹿2 小时前
插槽(slot):默认插槽、具名插槽、作用域插槽实战
前端·javascript·vue.js
千百元2 小时前
HBuilderX蓝牙功能打包有BUG
前端
Amumu121383 小时前
工程化: webpack介绍和基础用法
前端·javascript·工程化