越努力,越幸运,做个ccode~

0%

vue获取组件实例 父子组件实例

前言

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

Vue2

获取当前组件实例

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

获取父组件实例

1
this.$parent

获取子组件实例

1
this.$children

Vue3

获取当前组件实例

createApp 获取组件实例

1
import { createApp, h } from "vue";
2
const div = document.createElement("div");
3
const app = createApp({
4
  render() {
5
    return h(Component, {
6
      title: "提示",
7
      content: "内容",
8
      onXxx: () => {
9
        console.log("xxx");
10
      },
11
    });
12
  },
13
}).mount(div);
14
document.body.appendChild(div);

如果是title 和 content 是插槽

1
import { createApp, h } from "vue";
2
const div = document.createElement("div");
3
const app = createApp({
4
  render() {
5
    return h(
6
      MessageBox,
7
      {
8
        onXxx: () => {
9
          console.log("xxx");
10
        },
11
      },
12
      {
13
        // h 第三个参数传递插槽
14
        title,
15
        content,
16
      }
17
    );
18
  },
19
}).mount(div);
20
document.body.appendChild(div);

获取父组件实例

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

获取子组件实例

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

1 ref

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

1
<!-- demo.vue -->
2
<template>
3
  <x-form :model="userInfo" :rules="rules" ref="loginForm">
4
    <x-form-item label="用户名" prop="username">
5
      <x-input
6
        v-model="userInfo.username"
7
        placeholder="请输入用户名"
8
        clear
9
      ></x-input>
10
    </x-form-item>
11
    <x-form-item>
12
      <x-button @click="login" type="primary">登录</x-button>
13
    </x-form-item>
14
  </x-form>
15
</template>
16
<script lang=ts setup>
17
  const loginForm = ref(null) // ref 获取loginForm 实例
18
  const login = () => {
19
    loginForm.value.validate(valid => {
20
    if(valid){
21
      openMessageBox({title: '提示',content: '登录成功'}) 
22
    } 
23
  }
24
</script>

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

1
// form.vue
2
const validate = (callback) => {
3
  ...
4
};
5
defineExpose({validate})
2 slots.default()

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

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

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

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

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