vue 暴露组件方法

发布时间 2023-09-25 15:37:48作者: bronana

loadingbar

<template>
  <div class="wrapper">
    <div ref="bar" class="bar"></div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
let speed = ref<number>(1);
let bar = ref<HTMLDivElement>();
let timer = ref<number>(0);
const startLoading = () => {
  let dom = bar.value as HTMLDivElement;
  speed.value = 1;
  timer.value = window.requestAnimationFrame(function fn() {
    if (speed.value < 90) {
      speed.value += 1;
      dom.style.width = speed.value + '%';
      timer.value = window.requestAnimationFrame(fn);
    } else {
      speed.value = 1;
      window.cancelAnimationFrame(timer.value);
    }
  });
};
const endLoading = () => {
  window.requestAnimationFrame(() => {
    let dom = bar.value as HTMLDivElement;
    setTimeout(() => {
      speed.value = 100;
      dom.style.width = '100%';
    }, 1000);
  });
};


onMounted(() => {
  // startLoading();
  // endLoading();
});

// 给组件暴露出去方法,可以让组件在外部被调用方法
defineExpose({
  startLoading,
  endLoading,
});
</script>

<style scoped lang="scss">
.wrapper {
  position: fixed;
  top: 0;
  width: 100%;
  left: 0;
  height: 10px;
  .bar {
    height: inherit;
    width: 0%;
    background: red;
  }
}
</style>

在路由守卫中使其每次都能被自动加载

import { RouteRecordRaw, createRouter, createWebHistory } from 'vue-router';
import { ElMessage } from 'element-plus';
import LoadingBar from '@/components/LoadingBar.vue';
import { createVNode, render } from 'vue';

// 把组件转成虚拟dom
const vLoadingBar = createVNode(LoadingBar);
render(vLoadingBar, document.body);

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    alias: ['/login'],
    component: () => import('@/views/Login.vue'),
  },
  {
    path: '/index',
    meta: {
      requireAuth: true,
      transition: 'animate__fadeInDownBig',
    },
    component: () => import('@/views/Index.vue'),
  },
];

const router = createRouter({
  // createRouter返回一个router实例
  history: createWebHistory(),
  routes,
});

//const whiteList = ['/'];

router.beforeEach((to, from, next) => {
  vLoadingBar.component?.exposed?.startLoading();
  if (to.meta.requireAuth) {
    if (localStorage.getItem('token')) {
      next();
    } else {
      ElMessage.error('您没有权限访问');
      next('/');
    }
  } else {
    next();
  }
  // if (whiteList.includes(to.path) || localStorage.getItem('token')) {
  //   next();
  // } else {
  //   next('/');
  // }
});

router.afterEach((to, from) => {
  vLoadingBar.component?.exposed?.endLoading();
});

export default router;