-
iptime의 ddns 기능을 활용해 ngrok을 사용하지 않고 외부 접속이 가능하도록 설정합니다.
-
node.js를 통해 vue.js 프론트앤트 페이지를 띄울때 포트가 8080이므로 아래와 같이 설정합니다.
-
-
졸업 프로젝트의 프론트앤드단의 기본 UI/UX를 고려해 보았습니다.
-
로그인 여부에 따라 사용자가 접근할 수 있는 페이지를 구분하고 기능에 따라 구분지었습니다.
-
서비스 소개 페이지와 메인 페이지 : HomeView.vue
-
로그인 페이지 : SigninView.vue
-
회원가입 페이지 : SignupView.vue
-
회원정보 수정 페이지 : ProfileView.vue
-
포인트 페이지 : PointView.vue
-
클라이언트(=> 졸업 프로젝트의 PA서비스 제공단) 페이지 : ClientView.vue
-
-
Vue.js Router 설정
-
위 에서 작성한 vue 파일들을 URL을 통해 접근할 수 있도록 설정합니다.
-
src/router/index.js
import Vue from 'vue' import Router from 'vue-router' import HomeView from '@/components/HomeView' import SigninView from '@/components/SigninView' import SignupView from '@/components/SignupView' import ProfileView from '@/components/ProfileView' import PointView from '@/components/PointView' import ClientView from '@/components/ClientView' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'home', component: HomeView }, { path: '/signin', name: 'signin', component: SigninView }, { path: '/signup', name: 'signup', component: SignupView }, { path: '/profile', name: 'profile', component: ProfileView }, { path: '/point', name: 'point', component: PointView }, { path: '/client', name: 'client', component: ClientView } ] })
-
-
App.vue Navigation 설정
-
accessToken은 우선 쿠키를 이용해 저장합니다. 로그인 과정에서 항상 사용자가 인증되었다고 가정하고 토큰도 간단하게 생성해 저장합니다.
-
src/components/SigninView.vue
- html 부분
<template> <main class="mdl-layout__content"> <div class="mdl-card mdl-shadow--6dp"> <div class="mdl-card__title"> <h2 class="mdl-card__title-text">Welcome</h2> </div> <div class="mdl-card__supporting-text"> <form @submit="onSignIn"> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label"> <input class="mdl-textfield__input" type="text" id="username" v-model="username" /> <label class="mdl-textfield__label" for="username">아이디</label> </div> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label"> <input class="mdl-textfield__input" type="password" id="password" v-model="password" /> <label class="mdl-textfield__label" for="password">비밀번호</label> </div> <button type="submit" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect">SignIn</button> <router-link to="/signup" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect">SignUp</router-link> </form> </div> </div> </main> </template>
- script 부분
<script> export default { name: 'singin', data () { return { username: '', password: '' } }, methods: { onSignIn () { if (this.username === '' || this.password === '') { return } // TODO api/auth/signin [POST] document.cookie = `accessToken=${(this.username + this.password)}` this.$router.push('/') location.reload() } } </script>
-
accessToken을 이용해 항상 인증이 되었다고 가정을 하고 토큰의 존재 여부에 따라 Navagation에서 접근할 수 있는 페이지를 다르게 설정합니다. 로그아웃을 했을 경우 token 값을 비워줍니다. *.vue 파일이 마운트되기 전에 인증을 나타내는 변수 auth를 계산하여 router-link를 다르게 렌더링합니다.
-
scr/App.vue
- html 부분
<template> <div class="mdl-layout mdl-js-layout mdl-layout--fixed-header"> <header class="mdl-layout__header"> <div class="mdl-layout__header-row"> <span class="mdl-layout-title">프린트애니웨어</span> </div> </header> <div class="mdl-layout__drawer"> <span class="mdl-layout-title">프린트애니웨어</span> <nav class="mdl-navigation" v-if="auth"> <router-link class="mdl-navigation__link" to="/" @click.native="hideMenu" replace>Home</router-link> <router-link class="mdl-navigation__link" to="/profile" @click.native="hideMenu" replace>Profile</router-link> <router-link class="mdl-navigation__link" to="/point" @click.native="hideMenu" replace>Point</router-link> <router-link class="mdl-navigation__link" to="/client" @click.native="hideMenu" replace>Client</router-link> <router-link class="mdl-navigation__link" to="/" @click.native="unAuth" replace>Logout</router-link> </nav> <nav class="mdl-navigation" v-else> <router-link class="mdl-navigation__link" to="/" @click.native="hideMenu" replace>Home</router-link> <router-link class="mdl-navigation__link" to="/signin" @click.native="hideMenu" replace>SignIn</router-link> <router-link class="mdl-navigation__link" to="/signup" @click.native="hideMenu" replace>SignUp</router-link> </nav> </div> <main class="mdl-layout__content"> <div class="page-content"> <router-view></router-view> </div> </main> </div> </template>
- script 부분
<script> require('material-design-lite') export default { name: 'app', data () { return { auth: false } }, beforeMount () { this.setAuth() }, methods: { hideMenu: function () { document.getElementsByClassName('mdl-layout__drawer')[0].classList.remove('is-visible') document.getElementsByClassName('mdl-layout__obfuscator')[0].classList.remove('is-visible') location.reload() }, unAuth: function () { document.cookie = `accessToken=` document.getElementsByClassName('mdl-layout__drawer')[0].classList.remove('is-visible') document.getElementsByClassName('mdl-layout__obfuscator')[0].classList.remove('is-visible') location.reload() }, setAuth: function () { var value = document.cookie.match('(^|;) ?' + 'accessToken' + '=([^;]*)(;|$)') if (value[2] === '') { this.auth = false } else { this.auth = true } } } } </script>
-
-
ListView.vue v-for 임시 데이터로 렌더링 설정
-
임시데이터를 생성하여 리스트뷰를 구현합니다.
-
src/test/files.js
fileData: [ { 'fileId': 0, 'fileName': 'Test File 1', 'fileType': 'pdf', 'fileSize': 1000, 'fileUploadDate': '2018-11-18 10:40:22', 'isReserved': false }, { 'fileId': 1, 'fileName': 'Test File 2', 'fileType': 'pdf', 'fileSize': 1000, 'fileUploadDate': '2018-11-18 09:22:33', 'isReserved': true }, { 'fileId': 2, 'fileName': 'Test File 3', 'fileType': 'pdf', 'fileSize': 1000, 'fileUploadDate': '2018-11-18 09:12:45', 'isReserved': true }, { 'fileId': 3, 'fileName': 'Test File 4', 'fileType': 'pdf', 'fileSize': 1000, 'fileUploadDate': '2018-11-18 15:33:22', 'isReserved': false }, { 'fileId': 4, 'fileName': 'Test File 5', 'fileType': 'pdf', 'fileSize': 1000, 'fileUploadDate': '2018-11-18 16:22:11', 'isReserved': false } ]
-
서버로부터 위 데이터를 받았다고 가정한뒤 바인딩하여 v-for 구문으로 나타냅니다.
-
src/components/homeView.vue
-
html 부분
<template> <div class="mdl-layout__content mdl-cell mdl-cell--12-col-desktop mdl-cell--8-col-tablet mdl-cell--4-col-phone"> <div v-for="file in this.filelist" :key="file.id" v-bind:class="{'mdl-color--teal-100' : file.isReserved}" class="mdl-card mdl-cell mdl-cell--12-col-desktop mdl-cell--8-col-tablet mdl-cell--4-col-phone mdl-shadow--4dp"> <div class="mdl-card__title"> <h2 class=mdl-card__title-text v-text="file.fileName"></h2> </div> <div class="mdl-card__supporting-text file-info"> <div>Size : <span v-text="file.fileSize"></span></div> <div>Uploaded : <span v-text="file.fileUploadDate"></span></div> </div> <div class="mdl-card__actions mdl-card--border"> <button @click.native="onReserve(file.fileId)" v-if="file.isReserved" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored">UnReserve</button> <button @click.native="onUnReserve(file.fileId)" v-else class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored">Reserve</button> <button @click.native="onDelete(file.fileId)" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">Delete</button> </div> <div class="mdl-card__menu"> <i @click.native="onDownload(file.fileId)" class="material-icons">cloud_download</i> </div> </div> </div> </template>
-
script 부분
<script> import files from '../temp/files' require('material-design-lite') export default { name: 'home', data () { return { welcome: '님 환영합니다.', auth: false, 'filelist': files.fileData } }, methods: { setAuth () { var value = document.cookie.match('(^|;) ?' + 'accessToken' + '=([^;]*)(;|$)') if (value[2] === '') { this.auth = false } else { this.auth = true } }, onReserve (fileId) { // TODO api/files/{fileId} [PUT] }, onUnReserve (fileId) { // TODO api/files/{fileId} [PUT] }, onDelete (fileId) { // TODO api/files/{fileId} [DELETE] }, }, beforeMount () { this.setAuth() } } </script>
-
-
-
이후 작업을 위해 axios를 설치해둡니다.
npm install axios