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()
})
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에 저장하고 싶은 변수를 따로 써줌으로써 그 변수만 저장하게 할 수 있다.
본 포스팅은 기본적으로 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'}" />
웹을 만들 때는 컴퓨터 환경뿐아니라 모바일환경 os환경 가로모드 세로모드등 고려해야할 부분이 많다. 그렇기 때문에 responsive 하게 동작할 수 있게 만드는 것이 굉장히 중요하다.
vw 와 vh는 viewport 의 %값을 이용하기 때문에 길이가 고정되지 않고 화면에 따라 비율값에 의해 변경된다 ->1~100의 값을 가짐
checkOrientation() {
this.isPortrait = window.screen.orientation.type === "portrait-primary";
},
//vanilla javascript 상에서 window.screen.orientation 객체의 type은 device의 가로 세로모드를 갖고 있다.
//portrait -> 세로모드 landscape -> 가로모드
<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를 설정 할 수 있다.
vue의 생명주기를 알아보자.
created: instance가 만들어지고 rendering하기전에 거의 제일 처음으로 실행되는 lifecycle hook으로 서버에서 무언가를 받아올 때 이 훅에 등록하여 받아오면 사용자 입장에서 더 빠르게 실행되게 느낄 것이다.
mounted: 렌더링 후 처음 불러오는 hook으로 event listener나 css 관련 함수를 배치하는것이 좋다.
웹 페이지를 만들 때 사용자가 웹 페이지에 접속하면 자동적으로 오디오가 플레이 되도록 만드려 했지만 불가능했다.
-> 오디오를 자동 재생하는 것이 사용자에게 불퀘한 경험이 될 수 있기 때문에 브라우저마다 자동재생을 막아놓는 경우가 존재한다(chrome)
예를 들어 모질라는 다음과 같은 정책을 갖는다(MDN 에서 확인)
- 음소거 이거나 볼륨이 0
- 사용자가 사이트와 상호작용 한 이후 (이벤트가 한번이라도 발생하여야 함)
- 사용자가 자주 이용하여 화이트리스트에 등록한 경우
- 같은 origin을 갖는 페이지의 경우
크롬도 비슷한 정책을 가지고 있다.
때문에 여러 사이트에서 처음 페이지는 단순한 정보만 보여주고 그 다음 페이지로 넘어가면서부터 same origin이나 event 정책을 이용하여 오디오를 트는 방식을 이용한다.
keydown.enter 이벤트를 사용했을 때 mac os에서는 enter를 눌렀을 때 이벤트가 2번 발생하는 문제가 생겼다 왜일까?
- 윈도우와 mac os에서 enter키의 keycode가 다르다(윈도우=10 mac=13)
- keydown.enter는 10과 13 모두 엔터키이기 때문에 이 두 입력을 다 허용한다
- keycode 10의 경우는 form의 제출용도로 사용되지만 13의 경우는 line breaking 기능이 추가되어 있다.
- 결과적으로 mac에서 submit 과 line reaking이 둘 다 일어나면서 2번의 이벤트가 발생한 것이다. (press에서 submit release에서 line breaking)
- 이 문제를 해결하기 위해 간단하게 keydown이 아닌 keypress를 이용해 submit기능에 대해서만 이벤트를 발생시키면 된다.