跳到主要内容

Vue3 问题总结

vue3 获取组件实例

在 Vue 3 的 setup 函数中,this 不再指向组件实例,这与 Vue 2 的选项 API 有所不同。在 setup 中获取组件实例的方法是使用 getCurrentInstance 函数,该函数返回当前组件的实例。

import { getCurrentInstance } from 'vue';

export default {
setup() {
const instance = getCurrentInstance();
console.log(instance); // 打印组件实例

return {};
}
};

getCurrentInstance 返回的是组件实例对象的内部表示形式,包含了许多有用的属性和方法:

  • proxy: 组件实例的代理对象(可以通过它访问 $props$emit$slots 等)。
  • appContext: 当前应用的上下文。
  • type: 组件的类型(即组件的定义对象)。
  • props: 当前组件的属性对象。
  • emit: 用于触发事件的方法。

setupthis 不再指向组件实例,但你可以通过 instance.proxy 来访问组件的属性和方法,例如:

import { getCurrentInstance } from 'vue';

export default {
setup() {
const instance = getCurrentInstance();
// 访问组件的 props
const props = instance.proxy.$props;
// 触发事件
instance.proxy.$emit('custom-event', 'event data');
return {};
}
};

nextTick

Composition API 中有了更直接的替代方法。可以使用 nextTick 函数,它可以从 vue 包中导入并在 setup 函数或其他 Composition API 钩子中使用。

<script setup>
import { ref, nextTick } from 'vue';

// 定义响应式状态
const count = ref(0);

// 增加计数的函数
function increment() {
count.value++;
nextTick(() => {
console.log('DOM updated');
});
}
</script>

<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>

setup 函数

<script>
import { ref, computed, watch, onMounted, nextTick, getCurrentInstance } from 'vue';

export default {
name: 'AppName',
setup() {
const instance = getCurrentInstance();
console.log('instance', instance); // 打印组件实例

// 定义响应式状态
const count = ref(0);
// 定义计算属性
const doubleCount = computed(() => count.value * 2);

// 定义方法
function increment() {
count.value++;
nextTick(() => {
console.log('DOM 更新');
});
}

// 侦听器
watch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`);
});

// 生命周期钩子
onMounted(() => {
console.log('Mounted instance:', instance);
console.log('Component props:', instance.proxy.$props);
});

return {
count,
doubleCount,
increment
};
}
};
</script>

<template>
<div>
<p>Count: {{ count }}</p>
<p>Double Count: {{ doubleCount }}</p>
<button @click="increment">Increment</button>
</div>
</template>

在 App 全局挂载插件

  1. 声明插件
import type { App, Plugin } from 'vue';

interface MyPluginOptions {
message: string;
}

const MyPlugin: Plugin = {
install(app: App, options: MyPluginOptions) {
app.config.globalProperties.$myPluginMessage = options.message;
}
};

export default MyPlugin;
  1. 挂载到全局并传参
import { createApp } from 'vue';
import MyPlugin from './MyPlugin';

import App from './App.vue';

createApp(App).use(MyPlugin, { message: 'Hello, World!' }).mount('#app');
  1. 使用插件
<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
name: 'MyComponent',
computed: {
message(): string {
return this.$myPluginMessage;
}
}
});
</script>

<template>
<div>{{ message }}</div>
</template>

<!--
setup 语法糖:
<script setup lang="ts">
import { getCurrentInstance, computed } from 'vue'

const instance = getCurrentInstance()

// 获取插件提供的全局属性
const message = computed(() => {
return instance.appContext.config.globalProperties.$myPluginMessage
})
</script>
-->

Teleport

<Teleport> 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。

<button @click="open = true">Open Modal</button>

<Teleport to="body">
<div v-if="open" class="modal">
<p>Hello from the modal!</p>
<button @click="open = false">Close</button>
</div>
</Teleport>