---
date: 2022-08-03
title: Vue3 将组件挂载到指定 Dom
category: experience
cover: https://tse1-mm.cn.bing.net/th/id/OIP-C.Ko-vkqS8ZJSwVrq2tIf1igHaDt?pid=ImgDet&rs=1
location: 甘肃
tags:

- Vue3
- 组件

---

做个小小的记录，因为需要在 `Dialog` 弹窗旁边显示一个悬浮的目录栏，但是这个 `Dialog` 组件又是引用别人二次封装好框架里面的不太好修改。

[//]: # (![演示]&#40;/images/vue3-mount-dom.webp&#41;)

可以跟随 Dialog 的显隐进行组件的挂载与卸载。

```ts
// index.vue
let sidebarShow: any;
const createDialog = async (visible: boolean, data
        ?: any
    ) => {
        const HelloWorld = (await import("../components/Sidebar.vue")).default;
        let app = createApp(
            h(HelloWorld, {
                visible,
                data,
            })
        );
        if (!sidebarShow) sidebarShow = app;
        if (visible) {
            sidebarShow.mount(".hahaah");
        } else {
            sidebarShow.unmount();
            sidebarShow = null;
        }
    }
;
```

```vue
// sidebar.vue
<template>
  <div v-show="visible">
    <ul class="sidebar">
      <li v-for="item in shareStatusList" :key="item" style="list-style-type:none;margin-bottom:5px;"><a
          onmouseover="this.style.color='red'" onmouseout="this.style.color='#606266'" style="cursor: pointer;"
          @click="jump(item.value)">
        {{item.label}}</a></li>
    </ul>
  </div>
</template>

<script lang="ts">
import {defineComponent, ref} from "vue";

export default defineComponent({
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
    data: Array,
  },
  setup(props, context) {
    const shareStatusList = ref(props.data);
    context.emit("update:visible", props.visible);

    const jump = (name: string) => {
      let docu = document.getElementsByName(name) as NodeListOf<HTMLElement>;
      docu[0].scrollIntoView({behavior: "smooth"});
      console.log(docu);
    };
    return {shareStatusList, jump};
  },
});
</script>

<style lang="scss" scoped>
.sidebar {
  z-index: 99999999;
  position: absolute;
  top: 0;
  right: 0%;
  background: rgba(255, 255, 255, 0.8);
  border-radius: 8px;
  padding: 10px;
}
</style>
```

然后在 Dialog 对应的打开与关闭方法里面添加以下代码

```js
/**
 * 打开时的钩子
 */
const opOpen = async (isEdit: any, data: any) => {
        createDialog(true, shareStatusList.value);
    };

// shareStatusList.value 是我需要传到组件内的数据 
```

```js
/**
 * 关闭的钩子
 */
const onClose = async (done: any) => {
        await createDialog(false);
        done();
    }; 
```