vue3动态创建组件,等同于vue2的Vue.extend

作者: 小枫枫

临枫的项目经历分享给你们啦~

扫码交朋友

标签:

特别声明:文章有少部分为网络转载,资源使用一般不提供任何帮助,特殊资源除外,如有侵权请联系!

233835-16413971154717.jpeg

vue2的在这篇文章:

使用Vue.extend来动态创建Toast组件

 

vue3 动态创建一个 Loading 组件 :

目录结构

--- components
---|---Loading
---|---|--- index.ts
---|---|--- index.vue

......
--- views
---|---Home.vue

 

index.vue

 

<template>
  <div class="loader">
    <div class="loader-inner">
      <div class="loader-line-wrap">
        <div class="loader-line"></div>
      </div>
      <div class="loader-line-wrap">
        <div class="loader-line"></div>
      </div>
      <div class="loader-line-wrap">
        <div class="loader-line"></div>
      </div>
      <div class="loader-line-wrap">
        <div class="loader-line"></div>
      </div>
      <div class="loader-line-wrap">
        <div class="loader-line"></div>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, defineExpose } from "vue";
const show = ref<boolean>(true);
const msg = "通过instance可以读取到的变量";
//使用了setup语法糖 需要手动暴露
defineExpose({
  show,
  msg,
});
</script>
<style lang="less" scoped>
.loader {
  background: rgba(0, 0, 0, 0.7);
  bottom: 0;
  left: 0;
  overflow: hidden;
  position: fixed;
  right: 0;
  top: 0;
  z-index: 99999;
}

.loader-inner {
  bottom: 0;
  height: 60px;
  left: 0;
  margin: auto;
  position: absolute;
  right: 0;
  top: 0;
  width: 100px;
}

.loader-line-wrap {
  animation: spin 2000ms cubic-bezier(0.175, 0.885, 0.32, 1.275) infinite;
  box-sizing: border-box;
  height: 50px;
  left: 0;
  overflow: hidden;
  position: absolute;
  top: 0;
  transform-origin: 50% 100%;
  width: 100px;
}
.loader-line {
  border: 4px solid transparent;
  border-radius: 100%;
  box-sizing: border-box;
  height: 100px;
  left: 0;
  margin: 0 auto;
  position: absolute;
  right: 0;
  top: 0;
  width: 100px;
}
.loader-line-wrap:nth-child(1) {
  animation-delay: -50ms;
}
.loader-line-wrap:nth-child(2) {
  animation-delay: -100ms;
}
.loader-line-wrap:nth-child(3) {
  animation-delay: -150ms;
}
.loader-line-wrap:nth-child(4) {
  animation-delay: -200ms;
}
.loader-line-wrap:nth-child(5) {
  animation-delay: -250ms;
}

.loader-line-wrap:nth-child(1) .loader-line {
  border-color: hsl(0, 80%, 60%);
  height: 90px;
  width: 90px;
  top: 7px;
}
.loader-line-wrap:nth-child(2) .loader-line {
  border-color: hsl(60, 80%, 60%);
  height: 76px;
  width: 76px;
  top: 14px;
}
.loader-line-wrap:nth-child(3) .loader-line {
  border-color: hsl(120, 80%, 60%);
  height: 62px;
  width: 62px;
  top: 21px;
}
.loader-line-wrap:nth-child(4) .loader-line {
  border-color: hsl(180, 80%, 60%);
  height: 48px;
  width: 48px;
  top: 28px;
}
.loader-line-wrap:nth-child(5) .loader-line {
  border-color: hsl(240, 80%, 60%);
  height: 34px;
  width: 34px;
  top: 35px;
}

@keyframes spin {
  0%,
  15% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>

 

index.ts

 

import { Component, createApp } from "vue";
import Loading from "./index.vue";
let instance: any, unmount: () => void;
function mountComponent(RootComponent: Component) {
    const app = createApp(RootComponent);
    const root = document.createElement('div');
    document.body.appendChild(root);
    return {
        instance: app.mount(root),
        unmount() {
            console.log("unmount");
            // app.unmount(root);
            document.body.removeChild(root);
        },
    };
}
// 创建一个loading组件
export function $showLoading() {
    ({ instance, unmount } = mountComponent(Loading));
    console.log(instance);
}
// 销毁loading组件
export function $hiddenLoading() {
    instance && unmount();
}

 

这样一个Loading组件就创建好了  我们在 Home.vue使用一下

 

 

<template>
  <div></div>
</template>
<script setup lang='ts'>
// 引入
import { $showLoading, $hiddenLoading } from "@/components/Loading/index";
// 使用loading组件
$showLoading();
setTimeout(() => {
  // 卸载loading组件
  $hiddenLoading();
}, 3000);
</script>
<style lang='scss' scoped>
 
</style>

 

本文最后更新于2022-3-3,已超过 1 年没有更新,如果文章内容或图片资源失效,请留言反馈,我们会及时处理,谢谢!
分享到:
打赏

作者: 小枫枫, 转载或复制请以 超链接形式 并注明出处 小枫枫不疯喔
原文地址: 《vue3动态创建组件,等同于vue2的Vue.extend》 发布于2022-3-3

评论

  1. #1
    xiao 游客 Lv.1

    你好,createApp()这种方式,传递的组件  Loading  里如果有自定义指令的话,自定义指令会无法使用,你遇到过这个问题么?

    • 小枫枫 站长已认证

      回复了xiao:可以尝试这样改动代码:
      return {
              instance: app..directive('focus', {
                mounted(el) {
                el.focus();
        }
      }).mount(root),
      unmount() {
                  console.log("unmount");
                  // app.unmount(root);
                  document.body.removeChild(root);
              },

切换注册

登录

您也可以使用第三方帐号快捷登录

切换登录

注册

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏