본문 바로가기
Front-End (web)/Vue.js Typescript

[Vue.js/Typescript] 4. Vue-router

by 햄과함께 2019. 3. 11.
320x100

말머리에 typescript를 적긴 했지만 이번에는 거의 vue와 관련 있는 내용이다.



Vue-router 사용하기


npm install --save vue-router
cs

먼저 위 명령어로 vue-router 의존성을 추가함과 동시에 다운한다.


/* src/components/Index/Index.html */
<div>
    <router-view></router-view>
</div>
cs

인덱스 컴포넌트 템플릿을 위와 같이 바꾼다.

router-view는 경로에 따라 컴포넌트가 변경되는 곳이다.


/* src/routes/index.ts */
 
import Vue from 'vue'
import VueRouter from 'vue-router'
 
// modules
import Test1 from '../components/Test1';
import Product from '../components/Product';
 
Vue.use(VueRouter)
 
export const router = new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/',
            component: Test1
        },
        {
            path: '/product',
            component: Product
        },
        {
            path: '/test',
            component: Test1
        }
    ]
})
cs

src밑에 routes 폴더를 만들고 그 밑에 index.ts 파일을 추가하고 위와 같이 코딩한다.

위 파일에 라우터 경로, 사용 컴포넌트를 적어준다.

위 코드는 URL 경로에 따라 <router-view> 태그 위치에 어떤 컴포넌트를 쓰겠다는 것을 명시했다.

루트 경로(/) -> Test1 컴포넌트 사용

/product -> Product 컴포넌트 사용

/test -> Test1 컴포넌트 사용


/* src/index.ts*/
 
import Vue from "vue";
import Index from "./components/Index";
import {store} from './store';
import {router} from './routes' // add
 
let v = new Vue({
    el: "#app",
    template: `
    <div>
    <Index/>
    </div>`,
    components: {
        Index
    },
    store,
    router //add
});
cs

만든 router를 등록한다.


/product 경로로 접근하면 Product 컴포넌트가 사용된 것을 확인할 수 있다.



router-view name 지정(redirect)


/* src/routes/index.ts*/
 
import Vue from 'vue'
import VueRouter from 'vue-router'
 
// modules
// ...
import NotFound from '../components/NotFound'// add
 
Vue.use(VueRouter)
 
export const router = new VueRouter({
    mode: 'history',
    routes: [
        // ...
        {
            path: '/404',
            component: NotFound
        },
        {
            path: '*',
            redirect: '/404' // /404로 redirect
        }
    ]
})
cs

라우터에 /404 경로에서 미리 만들어둔 not found 컴포넌트를 보여준다.

그리고 등록되지 않은 경로인 경우 /404 로 리다이렉트하게 만들었다.


등록되어 있지 않은 경로로 접근 시

경로가 404로 바뀌고 만들어둔 Not Found 컴포넌트가 화면에 보여진다.



router-view name 지정


/* src/components/Divide/Index.html */
<div>
    Divide component
    <hr>
    <router-view></router-view>
    <hr>
    <router-view name="content"></router-view>
</div>
cs


하나의 컴포넌트에 2개 이상의 컴포넌트를 지정하려면 name 옵션을 준다.

위와 같이 Divide 컴포넌트를 하나 만들었다.

router-view 중 하나는 name을 지정하지 않았고 하나는 content라는 name을 지정했다.


/* src/routes/index.ts*/
import Vue from 'vue'
import VueRouter from 'vue-router'
 
// modules
import Index from '../components/Index'
import Test1 from '../components/Test1';
import Product from '../components/Product';
import Divide from '../components/Divide';
import NotFound from '../components/NotFound';
 
Vue.use(VueRouter)
 
export const router = new VueRouter({
    mode: 'history',
    routes: [
        // ...
        {
            path: '/divide',
            component: Divide,
            children: [
                {
                    path: 'test'// /divide/test
                    components: {
                        default: Test1,
                        content: Product
                    }
                },
                {
                    path: 'product'// /divide/product
                    components: {
                        default: Product,
                        content: Test1
                    }
                },
            ]
        },
        // ...
    ]
})
cs

중첩 라우터를 이용하기 위해서 children 옵션을 사용했다.

기본 경로는 /divide 이고 이때 Index 컴포넌트의 router-view에는 Divide 컴포넌트를 보여준다.

그리고 이후 경로에 /test가 붙는다면(/divide/test) Divide 컴포넌트 내의 

<router-view> 에는 Test1 컴포넌트를 <router-view name = content> 에는 Product 컴포넌트를 사용한다.

즉, default 는 name 옵션을 주지 않은 router-view와 매칭된다.


/divide 경로로 접근시 Divide 컴포넌트 내의 router-view에서 사용할 컴포넌트는 지정하지 않았으므로 위와 같은 화면이 나온다.


그리고 /divide/product에 접근 시 Product, Test1 컴포넌트가 위아래로 나와야 되지만 빈 화면과 함께 404 에러가 발생한다.

찍힌 에러를 보면 build.js를 가져오는 경로가 이상하다. (/build.js 를 가져와야 하는데 /divide/build.js를 참고해서 에러 발생.)


/* webpack.config.js */
 
// ...
module.exports = {
  mode: 'development',
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/'// add
    filename: 'build.js'
  },
  //...
}
cs

이를 해결하기 위해 webpack 설정에서 publicPath 옵션을 루트 경로('/')로 설정해준다.

publicPath 옵션이 정적 자원 Url 세팅할 때와 관계 있는 걸로 알고 있는데 아직 정적 자원을 사용하고 있지 않으므로 정적 자원 사용시 문제가 생긴다면 그 때 수정하도록 해야겠다.

publicPath를 설정해주면 direct url 로 접근할 수 있다.



router-link 사용하기


vue-router에서는 <a>태그를 이용하지 않고 <router-link>를 이용해서 페이지를 이동한다.

<router-link>는 <a> 태그로 렌더링된다.


/* src/components/Index/Index.html */
 
<div>
    <router-link to = "/product">product</router-link>
    <router-link to = "/test">test</router-link>
    <router-link to = "/divide">divide</router-link>
    <router-link to = "/divide/product">divide-product/test</router-link>
    <router-link to = "/divide/test">divide-test/product</router-link>
    <router-view></router-view>
</div>
cs

인덱스 컴포넌트에 라우터에 등록한 경로들을 모두 router-link 태그로 경로 지정을 해준다.


[divide 클릭시]


[product 클릭시]




참고 깃허브 : add vue-router, add publicPath

320x100

댓글