Vue-Admin 템플릿: 권한 기반 내비게이션 및 전체화면 기능 구현

이번 글에서는 이전에 작업한 Vue-admin 프로젝트에 Breadcrumb(이동 경로)와 Screenfull(전체화면) 기능을 추가하는 과정을 다룹니다.

Breadcrumb 컴포넌트 구현

Element-UI의 el-breadcrumbel-breadcrumb-item을 활용하여 현재 경로를 표시하는 내비게이션을 만듭니다. 기본적인 사용 예시는 다음과 같습니다.

<el-breadcrumb separator-class="el-icon-arrow-right">
  <el-breadcrumb-item :to="{ path: '/' }">홈</el-breadcrumb-item>
  <el-breadcrumb-item>설정</el-breadcrumb-item>
  <el-breadcrumb-item>계정</el-breadcrumb-item>
</el-breadcrumb>

핵심 아이디어는 현재 라우트 정보를 기반으로 최상위 경로까지 순회하며 breadcrumb 항목을 동적으로 생성하는 것입니다.

src/components 디렉토리에 Breadcrumb 폴더를 생성하고, 그 안에 index.vue 파일을 작성합니다. 아래는 스타일이 적용된 기본 템플릿입니다.

<template>
  <div>
    <el-breadcrumb class="app-breadcrumb" separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/' }">홈</el-breadcrumb-item>
      <el-breadcrumb-item>설정</el-breadcrumb-item>
      <el-breadcrumb-item>계정</el-breadcrumb-item>
    </el-breadcrumb>
  </div>
</template>

<script>
export default {
  // data, methods 등은 이후 추가
};
</script>

<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
  display: inline-block;
  font-size: 14px;
  line-height: 50px;
  margin-left: 8px;

  .no-redirect {
    color: #97a8be;
    cursor: text;
  }
}
</style>

이제 라우트 정보를 기반으로 breadcrumb를 동적으로 생성하고, breadcrumb 클릭 시 사이드바 메뉴가 자동으로 선택되도록 해야 합니다.

라우트 설정 수정

초기 router.js에서 다중 레벨 메뉴의 meta 속성과 name 설정이 제대로 되어 있지 않아 breadcrumb 생성이 올바르지 않았습니다. 이를 수정하고, 테이블 관련 라우트를 별도 모듈로 분리했습니다. src/router/modules/table.js 파일을 생성하여 다음과 같이 작성합니다.

import Layout from "@/layouts";

const tableRouter = {
  path: "/table",
  component: Layout,
  name: "table",
  meta: {
    title: "Table",
    icon: "table",
    affix: true,
    roles: ["user"]
  },
  alwaysShow: true,
  redirect: "/table/basic-table",
  children: [
    {
      path: "/table/basic-table",
      name: "basicTable",
      meta: { title: "Basic Table", icon: "table", roles: ["user"] },
      component: () =>
        import(/* webpackChunkName: "table" */ "@/views/tables/basictable.vue")
    },
    {
      path: "/table/page-table",
      name: "pageTable",
      meta: { title: "Paginated Table", icon: "table", roles: ["user"] },
      redirect: "/table/page-table0",
      component: { render: h => h("router-view") },
      children: [
        {
          path: "/table/page-table0",
          name: "pageTable0",
          meta: { title: "Page 0", icon: "table", roles: ["user"] },
          component: () =>
            import(
              /* webpackChunkName: "table" */ "@/views/tables/pagetable/pagetable0.vue"
            )
        },
        {
          path: "/table/page-table1",
          name: "pageTable1",
          meta: { title: "Page 1", icon: "table", roles: ["user"] },
          component: () =>
            import(
              /* webpackChunkName: "table" */ "@/views/tables/pagetable/pagetable1.vue"
            )
        }
      ]
    }
  ]
};
export default tableRouter;

그리고 src/router/index.js에서 이 모듈을 임포트하여 사용합니다.

라우트 redirect 문제 해결

일부 라우트에 redirect 속성이 누락되어 breadcrumb 이동 시 오류가 발생했습니다. 예를 들어, form 관련 라우트를 다음과 같이 수정했습니다.

{
    path: "/form",
    component: Layout,
    name: "form",
    redirect: "/form/basic-form",
    meta: {
      title: "Form",
      icon: "form",
      affix: true,
      roles: ["admin", "user"]
    },
    children: [
      {
        path: "/form/basic-form",
        name: "basicForm",
        meta: {
          title: "Basic Form",
          icon: "form",
          affix: true,
          roles: ["admin", "user"]
        },
        component: () =>
          import(/* webpackChunkName: "form" */ "@/views/forms/basicForm.vue")
      }
      // ...
    ]
  }

그러나 홈으로 이동하는 breadcrumb가 여전히 정상 작동하지 않아 getBreadlist() 메서드를 수정했습니다. 첫 번째 경로가 대시보드가 아닌 경우, 수동으로 홈 경로를 추가하고 redirect 속성을 포함시켰습니다.

if (!this.isDashboard(first)) {
    matched = [
      {
        path: "/",
        meta: { title: "Home" },
        redirect: "/dashboard"
      }
    ].concat(matched);
}

Screenfull 전체화면 기능

전체화면 기능을 위해 screenfull 라이브러리를 설치합니다.

yarn add screenfull

src/components 디렉토리에 Screenfull 폴더를 생성하고 index.vue 파일을 만듭니다. 컴포넌트는 다음 사항을 처리해야 합니다.

  • 초기 로드 시 전체화면 상태 확인 및 아이콘 변경
  • 전체화면 상태 변경 이벤트 리스닝 및 리소스 정리

참고: 최신 버전의 screenfull 라이브러리는 screenfull.enabled 대신 screenfull.isEnabled를 사용합니다.

<template>
  <div>
    <svg-icon
      :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'"
      @click="click"
    />
  </div>
</template>

<script>
import screenfull from "screenfull";

export default {
  name: "Screenfull",
  data() {
    return {
      isFullscreen: false
    };
  },
  mounted() {
    this.init();
  },
  beforeDestroy() {
    this.destroy();
  },
  methods: {
    click() {
      if (!screenfull.isEnabled) {
        this.$message({
          message: "Your browser does not support fullscreen.",
          type: "warning"
        });
        return;
      }
      screenfull.toggle();
    },
    change() {
      this.isFullscreen = screenfull.isFullscreen;
    },
    init() {
      if (screenfull.isEnabled) {
        screenfull.on("change", this.change);
      }
    },
    destroy() {
      if (screenfull.isEnabled) {
        screenfull.off("change", this.change);
      }
    }
  }
};
</script>

screenfull API 주요 메서드

  • .request(): 요소를 전체화면으로 전환. 기본값은 document.documentElement.
  • .exit(): 전체화면 종료.
  • .toggle(): 현재 상태에 따라 전체화면 전환/해제.
  • .on(event, callback): 'change' 또는 'error' 이벤트 리스너 등록.
  • .off(event, callback): 등록된 리스너 제거.
  • .isFullscreen: 전체화면 활성 여부 (Boolean).
  • .element: 현재 전체화면 중인 요소 (없으면 null).
  • .isEnabled: 전체화면 사용 가능 여부 (Boolean).
  • .raw: 내부에서 사용하는 원시 속성 노출.

이제 Breadcrumb와 Screenfull 컴포넌트를 NavBar에 통합하여 사용자 경험을 향상시킬 수 있습니다.

태그: vue JavaScript Element-UI breadcrumb screenfull

6월 18일 23:23에 게시됨