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: 用于触发事件的方法。
在 setup 中 this 不再指向组件实例,但你可以通过 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 全局挂载插件
- 声明插件
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;
- 挂载到全局并传参
import { createApp } from 'vue';
import MyPlugin from './MyPlugin';
import App from './App.vue';
createApp(App).use(MyPlugin, { message: 'Hello, World!' }).mount('#app');
- 使用插件
<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>