본문 바로가기
Programming/Vue

[실습] 뷰(Vue)로 로그인 화면 구현하기 - UI 및 기능 개발

by 돌방로그 2023. 3. 15.


오늘의 실습 목표는 "로그인 화면 만들어보기!" 입니다.
본 게시글에서 다루는 사항은 로그인 화면을 구현하는 과정입니다.


로그인 화면 구현하기 - UI 및 기능 개발

사전 준비

아래 사항에 대해서 사전 준비가 완료되지 않으신 분들은 아래 링크를 참조하여 사전 준비를 진행합니다.

 


결과 이미지

구현하기에 앞서 본 글을 따라하시면 아래와 같이 화면의 레이아웃을 구성하실 수 있습니다.

좌: 로그인 정보가 없는 경우 우: 로그인 정보가 있는 경우

 


소스 코드

src\components\common\UserLogin.vue

관리자 포털의 로그인 화면의 주요 기능이 담겨있는 컴포넌트 파일입니다.

전체 코드를 확인하실 분들은 아래 더보기를 클릭해주세요.

더보기
<template>
  <v-container>
    <div id="idTitle">
      <h1>Admin Portal</h1>
    </div>

    <div>
      <v-text-field
        text
        outlined
        dense
        clearable
        :rules="[rules.required, rules.employeeNo]"
        v-model="id"
        label="ID (Employee No.)"
      ></v-text-field>

      <v-text-field
        text
        outlined
        dense
        clearable
        :rules="[rules.required]"
        :type="password"
        v-model="password"
        label="Password"
      ></v-text-field>
    </div>

    <div class="d-flex justify-end">
      <v-btn text outlined dense class="mx-md-1 elevation-2" @click="clickLogin"
        >Login
      </v-btn>
    </div>
  </v-container>
</template>

<script>
export default {
  data() {
    return {
      rules: {
        required: (value) => !!value || "Required.",
        employeeNo: (value) =>
          value.length == 6 || "ID(직원번호)는 6자리로 구성되어야 합니다.",
      },
      id: "",
      password: "",
    };
  },
  methods: {
    clickLogin: function () {
      if (this.id.trim() === "") {
        alert("ID Field is empty.");
      } else if (this.password.trim() === "") {
        alert("Password Field is empty.");
      } else {
        alert("Attempted to login.");
        // TODO: Login 시도 횟수는 최대 5번까지. 5번 실패시 Lock
      }
    },
  },
};
</script>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  position: relative;
  justify-content: center;
  width: 40%;
  height: 100%;
}

#idTitle {
  display: flex;
  justify-content: center;

  margin: 5%;
}
</style>

 

<template>

<template>
  <v-container>
    <div id="idTitle">
      <h1>Admin Portal</h1>
    </div>

    <div>
      <v-text-field
        text
        outlined
        dense
        clearable
        :rules="[rules.required, rules.employeeNo]"
        v-model="id"
        label="ID (Employee No.)"
      ></v-text-field>

      <v-text-field
        text
        outlined
        dense
        clearable
        :rules="[rules.required]"
        :type="password"
        v-model="password"
        label="Password"
      ></v-text-field>
    </div>

    <div class="d-flex justify-end">
      <v-btn text outlined dense class="mx-md-1 elevation-2" @click="clickLogin"
        >Login
      </v-btn>
    </div>
  </v-container>
</template>
  • 수직 구조로 타이틀, ID, Password, 로그인 시도 버튼이 구성되어 있음

 

<script>

<script>
export default {
  data() {
    return {
      rules: {
        required: (value) => !!value || "Required.",
        employeeNo: (value) =>
          value.length == 6 || "ID(직원번호)는 6자리로 구성되어야 합니다.",
      },
      id: "",
      password: "",
    };
  },
  methods: {
    clickLogin: function () {
      if (this.id.trim() === "") {
        alert("ID Field is empty.");
      } else if (this.password.trim() === "") {
        alert("Password Field is empty.");
      } else {
        alert("Attempted to login.");
        // TODO: Login 시도 횟수는 최대 5번까지. 5번 실패시 Lock
      }
    },
  },
};
</script>
  • data
    • rules: 로그인 화면 내 입력값 규칙을 지정하는 변수
    • id: 로그인할 사용자의 아이디를 입력한 값이 저장되는 변수
    • password: 로그인할 사용자의 비밀번호를 입력한 값이 저장되는 변수
  • methods
    • clickLogin(): Login 버튼을 클릭했을 때 호출되는 함수
      • ID/Password에 대한 필드값 및 로그인 시도 횟수 확인
      • 체크해야할 사항이 모두 PASS되는 경우 진행할 BE와 연결되는 코드는 향후 기능 구현시 구현 예정

 

<style>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  position: relative;
  justify-content: center;
  width: 40%;
  height: 100%;
}

#idTitle {
  display: flex;
  justify-content: center;

  margin: 5%;
}
</style>
  • .container: 화면 전체 Layout 구조를 잡기 위한 설정
  • #idTitle: 로그인 화면 타이틀의 Layout 구조를 잡기 위한 설정

 

src\views\BaseMain.vue

로그인 정보가 있는 경우에 로드되는 관리자 포털 루트 컴포넌트 파일입니다.

기존 App.vue 파일에 구현된 코드는 로그인 여부에 따라 화면 전환하기 위해 BaseMain.vue 파일로 내용을 분리하였습니다. 

전체 코드를 확인하실 분들은 아래 더보기를 클릭해주세요.

더보기
<template>
  <v-container>
    <v-navigation-drawer v-model="drawer" app>
      <v-list dense>
        <!-- User(Employee) information -->
        <v-list-item>
          <v-list-item-avatar>
            <v-img src="https://cdn.vuetifyjs.com/images/john.png"></v-img>
          </v-list-item-avatar>
        </v-list-item>
        <v-list-item link>
          <v-list-item-content>
            <v-list-item-title class="text-h6">Sylvia Park</v-list-item-title>
            <v-list-item-subtitle>ardiums@gmail.com</v-list-item-subtitle>
          </v-list-item-content>
        </v-list-item>
        <v-divider></v-divider>

        <!-- Menu/Navigation Bar list -->
        <v-list-item-group v-model="selectedItem" color="primary">
          <v-list-item
            v-for="(item, i) in navBasicItems"
            :key="'common' + i"
            :to="item.to"
          >
            <v-list-item-icon>
              <v-icon v-text="item.icon"></v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>

          <v-divider></v-divider>

          <v-subheader>User Web</v-subheader>
          <v-list-item
            v-for="(item, i) in navUserWebItems"
            :key="'user-web' + i"
            :to="item.to"
          >
            <v-list-item-icon>
              <v-icon v-text="item.icon"></v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>

          <v-divider></v-divider>

          <v-subheader>Admin Web</v-subheader>
          <v-list-item
            v-for="(item, i) in navAdminWebItems"
            :key="'admin-web' + i"
            :to="item.to"
          >
            <v-list-item-icon>
              <v-icon v-text="item.icon"></v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-navigation-drawer>

    <v-app-bar app>
      <v-app-bar-nav-icon @click="drawer = !drawer"></v-app-bar-nav-icon>

      <v-toolbar-title>Admin Portal</v-toolbar-title>
    </v-app-bar>

    <v-main>
      <v-container fluid>
        <router-view></router-view>
      </v-container>
    </v-main>

    <v-footer app>
      <!-- -->
    </v-footer>
  </v-container>
</template>

<script>
export default {
  data: () => ({
    drawer: null,

    // For Menu/Navigation Bar
    selectedItem: 0,

    navBasicItems: [
      {
        text: "Dashboard",
        icon: "mdi-view-dashboard",
        to: "/page/dashboard",
      },
      {
        text: "Setting",
        icon: "mdi-cog-outline",
        to: "/page/setting",
      },
    ],
    navUserWebItems: [
      {
        text: "Notice",
        icon: "mdi-file-outline",
        to: "/page/user-web/notice",
      },
      {
        text: "User Management",
        icon: "mdi-account",
        to: "/page/user-web/users",
      },
      {
        text: "Menu Management",
        icon: "mdi-lan-check",
        to: "/page/user-web/menu",
      },
    ],
    navAdminWebItems: [
      {
        text: "User Management",
        icon: "mdi-account-supervisor-circle",
        to: "/page/admin-web/users",
      },
      {
        text: "Rights Management",
        icon: "mdi-lock-open",
        to: "/page/admin-web/rights",
      },
    ],
  }),
};
</script>

<style></style>

 

src\App.vue

관리자 포털이 구동될 때 가장 먼저 로드되는 화면 컴포넌트 파일입니다.

기존 App.vue 파일에 구현된 코드는 로그인 여부에 따라 화면 전환하기 위해 BaseMain.vue 파일로 내용을 분리하였습니다. 

<template>
  <v-app>
    <Login v-if="false"></Login>
    <!-- TODO: Login 성공 후 Login 정보를 Main에서도 사용할 수 있도록 전달 필요 -->
    <Main v-else></Main>
  </v-app>
</template>

<script>
import Login from "./components/common/UserLogin.vue";
import Main from "./views/BaseMain.vue";

export default {
  name: "App",
  components: {
    Login,
    Main,
  },
  data: () => ({}),
};
</script>
  • 로그인 여부 정보에 따라 보여지는 화면 컴포넌트가 상이하도록 'v-if/v-else' 사용
    • 로그인 정보 없음: 로그인 화면 컴포넌트(UserLogin.vue) 표시
    • 로그인 정보 있음: 관리자 포털 루트 화면 컴포넌트(BaseMain.vue) 표시
  • 로그인 여부는 향후 화면 기능 구현시 구현될 예정

 

 


댓글