Vue.js

강민수·2023년 1월 11일
0

Router

vue add router -> vue cli상에서 router 설치->src/router/views 폴더가 생성됨
app.vue에서 router-link to tag를 통해 router 기능 사용 가능
Home

router 폴더 아래 index.js에서 라우터 설정

import { createRouter, createWebHistory } from 'vue-router'
const routes=[
	{path -> 접속 url
     component -> 지정된 path로 들어올 때 보여줄 컴포넌트
    }
]

const rouuter = createRouter({routes})
export default router

추가적으로 라우팅 경로와 history mode에 대한 설정도 할 수 있다.
->navigation guard

  {
    path: "/game",
    name: "game",
    component: gameview,
    beforeEnter: (to, from, next) => {
      if (store.state.score === 0) {
        next('/')
      } else {
        next()
      }
    }
   	// 새로운 페이지에 입장하기전에 vuex에 저장된 score값이 0이면 다음페이지로 넘어가지 않고 첫페이지로 돌아간다.
  }, // 라우팅 경로를 설정해줄 때 같이 설정해줄 수 있다.(navigation guard)
  
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
  mode: 'history',
}); // 라우터를 정의 할 때 history mode를 추가할 수 있다.
  

vue 파일에서도 다른 파일로 화면을 넘기기 위해서 router을 사용해야한다.

this.$router.push({path:'/',params={score:1})

//composition api
import { useRouter } from "vue-router";
const router = useRouter();
router.push({ path: "/" });

main.js에서

import router from './router'

app.use(router)

를 통해서 사용 가능하다.

라우터 함수에서 추가적인 라우터 설정을 할 수 있는데, 특정 사이트로 접근하기 위한 경로 과정을 지정하거나 첫 시작 페이지를 지정하는 등의 행위를 할 수 있다.

router.beforeEach((to, from, next) => {
  if (firstVisit && to.path !== '/') {
    firstVisit = false
    return next('/')
  }
  next()
})

VUEX

npm install vuex --save

vuex는 여러 component에서 공통적으로 쓰이는 전역변수나 함수를 지정할 수 있는 공간이다.

    state (){
        return{
			number:1,
        }
    }, // 변수를 state 안에 지정해준다
    
    mutations:{
    	setNumber(state,num){
        	state.number=num
        } // 외부에서 vuex 변수를 변경하기 위한 함수를 정의한다
    },
    getters:{
    	//computed처럼 쓰일 수 있다.
    }
    

이런식의 파일을 store/store.js로 지정해 주고 main.js에 등록해 준다.

이렇게 등록된 vuex는 외부에서 아래와 같이 쓰일 수 있다.

	this.$store.commit(setNumber,1) // vuex에 값을 push
    this.number = this.$store.state.number // vuex에서 값을 가져옴
	// composition api
    import { useStore } from "vuex";
    const store = useStore();
    
    store.commit(setNumber,1)
    number.value = store._state.data.number

하지만 vuex는 유저가 웹 페이지에 대한 refresh 행위를 하면 모든 정보가 초기화 된다는 것이다.
웹을 refresh 한다는 것은 refresh-> reload javascript -> restart vue app 이런 과정을 거치기 때문이다. 그렇기 때문에 빈번한 유저의 새로고침 행위에도 정보를 저장하기 위해선 vuex만으로는 불충분하다.

-> vuex-persistedstate를 이용하여 해결할 수 있다.
local storage의 공간은 약 5mb 정도인데 여기에서 쿠키 유지를 위해 2.5mb를 또 따로 사용하기 때문에 실질적으로는 2.5mb 정도의 데이터를 저장할 수 있다. 이는 다른 storage(indexeddb, service worker 약 50mb)에 비교하여 굉장히 적은 수치이기 때문에, 용량을 잘 고려하여서 사용해야한다. 용량이 적은대신, 굉장히 간단하게 사용할 수 있다는 장점이 있는 것이다.

npm install --save vuex-persistedstate

vuex-persistedstate는 vuex에 저장한 값을 각 브라우저의 local storage에 저장함으로써 새로고침을 해도 값을 유지할 수 있게 된다.

import createPersistedState from "vuex-persistedstate";
createStore{
    plugins : [ 
        createPersistedState({})
    ],
} //여기에 createPersistedState 안에 local storage에 저장하고 싶은 변수를 따로 써줌으로써 그 변수만 저장하게 할 수 있다.

Layout

본 포스팅은 기본적으로 vue3+vuetify3를 사용한다.
vuetify 2.x버전 부터는 row와 col을 이용한 flex 구조를 사용하는 것 같다.
row와 col이라는 것은 하나의 화면을 12x12로 나누어서 사용한다는 뜻이다.
기본적으로

<v-row>
	<v-col></v-col>
</v-row> // 기본적인 layout 구조

<v-row>
	<v-col cols=6> // 12개의 column중 6개의 영역을 사용하겠다.
</v-row> 
	
<v-col class='d-flex justify-center'>
	<v-col />
</v-row> //bootstrap과 같은 flex 구조를 이용하여 layout을 조절할 수 있다

-justify (가로정렬)
	-start (왼쪽 끝)
    -center (중앙)
    -end (오른쪽 끝)
    
-align (세로 정렬
	-start (위)
    -center (중앙)
    -end (아래)
    
해당 class 를 이용하면 바로 아래 child의 layout을 정렬할 수 있다.

<v-row>
	<v-col class='mb-10' /> // margin을 이와 같이 쉽게 조절할 수 있다.
</v-row>

m(margin) + t(top)/b(bottom)/l(left)/r(right) - 10(px 0~16)
ex) mb-10 / mt-16
- 이 방법은 px단위 임으로 반응형 제작엔 어울리지 않는다는 것을 참고해야 한다.
-> 반응형을 이용하려면 inline 이나 밖에 css를 지정해주어야한다.
ex) <v-col :stye="{'margin-top':'10vh'}" />

Responsive

웹을 만들 때는 컴퓨터 환경뿐아니라 모바일환경 os환경 가로모드 세로모드등 고려해야할 부분이 많다. 그렇기 때문에 responsive 하게 동작할 수 있게 만드는 것이 굉장히 중요하다.

  1. vw,vh 사용

    vw 와 vh는 viewport 의 %값을 이용하기 때문에 길이가 고정되지 않고 화면에 따라 비율값에 의해 변경된다 ->1~100의 값을 가짐

  2. 가로 세로에 따라 다르게 디자인
    checkOrientation() {
      this.isPortrait = window.screen.orientation.type === "portrait-primary";
    }, 
//vanilla javascript 상에서 window.screen.orientation 객체의 type은 device의 가로 세로모드를 갖고 있다.
//portrait -> 세로모드 landscape -> 가로모드
  1. 화면의 크기에 따라 다르게 디자인한다(모바일 /랩탑 /컴퓨터)

    위 사진처럼 vuetify는 디바이스의 크기에 따라 종류를 나누어 따로 디자인을 할 수 있게 만들어 놓았다.
<v-row>
	<v-col cols=2 sm=4 md=6 lg=10 xl=12 /> //디바이스에 따라 column을 몇개 쓸것인지를 다르게 정할 수 있다.
</v-row>

<v-row>
	<v-col cols=3 md=6> xs~sm은 3개 md이상은 6개를 사용한다.
</v-row>

<v-row class='d-none d-sm' /> // sm이상의 디바이스에서만 볼 수 있다.
-> d-none은 모두 안보이게 한다는 뜻이고 d-sm은 sm이상부터만 볼 수 있게한다는 뜻이다 합치면 xs에서만 안보인다는 뜻이 된다
-> 이를 이용해 특정 디바이스에서만 보이게 만들 수 도 있다.
<v-row class='d-none d-sm d-none-md' /> //md부터는 다시 안보이게 만들어 sm에서만 보이게 한다.


vuetify에서 이런 기능을 제공하지만 css단에서도 이런 처리를 할 수 있다.
@media only screen and (max-width: 480px) {
  .icon-size {
    width: 2vh;
    height: 2vh;
  }
}
@media only screen and (min-width: 480px) {
  .icon-size {
    width: 5vh;
    height: 5vh;
  }
}
// @media를 이용해 width나 height를 이용하여 그 값마다 다르게 css를 설정 할 수 있다.

Life Cycle

vue의 생명주기를 알아보자.

created: instance가 만들어지고 rendering하기전에 거의 제일 처음으로 실행되는 lifecycle hook으로 서버에서 무언가를 받아올 때 이 훅에 등록하여 받아오면 사용자 입장에서 더 빠르게 실행되게 느낄 것이다.
mounted: 렌더링 후 처음 불러오는 hook으로 event listener나 css 관련 함수를 배치하는것이 좋다.

vuetify tag 활용과 주의점

  • v-file-input: v-model을 사용할 수 없다. 파일 입력을 양방향 바인딩 한다는 것 자체가 말이 안된다. js에서 default 값을 지정해준다면 사용자 화면에는 어떻게 나와야 할까? 그렇기 때문에 양방향 바인딩을 사용할 수 없다.
  • v-overlay: 특정 부분을 강조하고 싶다면 z-index 속성을 활용해야 한다. css 상에서 강조하고 싶은 부분의 z-index를 조절하면 된다.
  • v-text-input: 입력창의 크기를 조절할 수 없다.(v-select도)
  • v-icon: 기본적으로 mdi에서 제공하는 아이콘만 사용할 수 있다. 이외는 외부라이브러리를 이용해 등록하거나 직접 template 코드를 작성해서 넣어줘야 한다.

오디오 정책

웹 페이지를 만들 때 사용자가 웹 페이지에 접속하면 자동적으로 오디오가 플레이 되도록 만드려 했지만 불가능했다.
-> 오디오를 자동 재생하는 것이 사용자에게 불퀘한 경험이 될 수 있기 때문에 브라우저마다 자동재생을 막아놓는 경우가 존재한다(chrome)

예를 들어 모질라는 다음과 같은 정책을 갖는다(MDN 에서 확인)

  • 음소거 이거나 볼륨이 0
  • 사용자가 사이트와 상호작용 한 이후 (이벤트가 한번이라도 발생하여야 함)
  • 사용자가 자주 이용하여 화이트리스트에 등록한 경우
  • 같은 origin을 갖는 페이지의 경우

크롬도 비슷한 정책을 가지고 있다.

때문에 여러 사이트에서 처음 페이지는 단순한 정보만 보여주고 그 다음 페이지로 넘어가면서부터 same origin이나 event 정책을 이용하여 오디오를 트는 방식을 이용한다.

mac keydown bug?

keydown.enter 이벤트를 사용했을 때 mac os에서는 enter를 눌렀을 때 이벤트가 2번 발생하는 문제가 생겼다 왜일까?

  1. 윈도우와 mac os에서 enter키의 keycode가 다르다(윈도우=10 mac=13)
  2. keydown.enter는 10과 13 모두 엔터키이기 때문에 이 두 입력을 다 허용한다
  3. keycode 10의 경우는 form의 제출용도로 사용되지만 13의 경우는 line breaking 기능이 추가되어 있다.
  4. 결과적으로 mac에서 submit 과 line reaking이 둘 다 일어나면서 2번의 이벤트가 발생한 것이다. (press에서 submit release에서 line breaking)
  5. 이 문제를 해결하기 위해 간단하게 keydown이 아닌 keypress를 이용해 submit기능에 대해서만 이벤트를 발생시키면 된다.

0개의 댓글