649 字
3 分钟
vue获取组件实例 父子组件实例
2022-02-26

前言#

最近再写弹框组件时 通过调用函数的方式调用弹框 需要获取到组件实例 在此总结一下

Vue2#

获取当前组件实例#

1 render()#
// render 获取组件实例
function create(Component, props) {
const vm = new Vue({
render: (h) => h(Component, { props }), // h() 返回vnode 虚拟dom 需要挂载才能变成真实dom
}).$mount(); // 不指定宿主元素,会创建真实dom 但是不会追加操作
// 现在vm 就是根组件实例
// 获取真实dom vm.$el 就是真实dom 将真实dom 放在body上
document.body.appendChild(vm.$el);
// Component 是组件描述对象 comp是组件的实例
const comp = vm.$children[0];
// 删除
comp.remove = () => {
document.body.removeChild(vm.$el);
vm.$destroy();
};
return comp;
}
2 Vue.extend()#
// Vue.extend() 获取组件构造函数
function create(Component, props) {
// 获取组件构造函数
const Constructor = Vue.extend(Component);
const component = new Constructor({
propsData: props,
}).$mount();
// mount 后才有$el 属性
document.body.appendChild(component.$el);
component.remove = () => {
document.body.removeChild(component.$el);
component.$destroy();
};
return component;
}

获取父组件实例#

this.$parent

获取子组件实例#

this.$children

Vue3#

获取当前组件实例#

createApp 获取组件实例

import { createApp, h } from "vue";
const div = document.createElement("div");
const app = createApp({
render() {
return h(Component, {
title: "提示",
content: "内容",
onXxx: () => {
console.log("xxx");
},
});
},
}).mount(div);
document.body.appendChild(div);

如果是title 和 content 是插槽

import { createApp, h } from "vue";
const div = document.createElement("div");
const app = createApp({
render() {
return h(
MessageBox,
{
onXxx: () => {
console.log("xxx");
},
},
{
// h 第三个参数传递插槽
title,
content,
}
);
},
}).mount(div);
document.body.appendChild(div);

获取父组件实例#

import { getCurrentInstance } from 'vue'
const instance = getCurrentInstance()
const parent = instance.parent

获取子组件实例#

Vue3 中实例没有$children 属性了 那么子组件实例如何获取呢?

1 ref#

以 form 组件为例 点击登录需要获取 loginForm 的 validate 方法

demo.vue
<template>
<x-form :model="userInfo" :rules="rules" ref="loginForm">
<x-form-item label="用户名" prop="username">
<x-input
v-model="userInfo.username"
placeholder="请输入用户名"
clear
></x-input>
</x-form-item>
<x-form-item>
<x-button @click="login" type="primary">登录</x-button>
</x-form-item>
</x-form>
</template>
<script lang=ts setup>
const loginForm = ref(null) // ref 获取loginForm 实例
const login = () => {
loginForm.value.validate(valid => {
if(valid){
openMessageBox({title: '提示',content: '登录成功'})
}
}
</script>

但是需要在loginForm 中暴露validate方法

form.vue
const validate = (callback) => {
...
};
defineExpose({validate})
2 slots.default()#

如果子组件是通过插槽的方式传递进来的 可以通过slots.default() 方法获取

setup(props,{slots}){
const children = slots.default()
}
// setup 语法糖
import { useSlots } from "vue";
const slots = useSlots();
const children = slots.default();

可以通过这种方式约束子组件标签

// 检查每个子组件的类型
import ChildCompont form './ChildChomponent'
children.forEach( tag => {
if(tag.type !== ChildCompont){
throw new Error('子组件必须是 ChildComponent')
}
})

这种方法可以获取到子组件实例 但是不能调用子组件中的方法

vue获取组件实例 父子组件实例
https://blog.cxyxiaoyu.top/posts/vue获取组件实例/
作者
小宇
发布于
2022-02-26
许可协议
CC BY-NC-SA 4.0