본문 바로가기
프로그래머스

[프로그래머스]커스텀 라우터

by 남민섭 2023. 3. 4.
728x90
반응형

자바스크립트로 라우터 구현

 
커스텀이벤트
자바스크립트를 사용하면 이벤트 핸들러를 할당할수 있으며
이벤트를 직접 만들수도 있습니다


1. 이벤트 생성

new CustomEvent("type",{detail:{전달객체}})     ===>이벤트객체 만듬
-type: 이벤트의 타입을 나타내는 문자열
-customEvent 두번째 인수엔 객체가 들어갈 수 있는데
detail이라는 프로퍼티를 추가해 커스텀 이벤트 관련 정보를
명시 정보를 이벤트에 전달할 수 있음

 


2. 이벤트 호출

dispatchEvent(커스텀 이벤트 객체)
이벤트 객체를 생성한 다음 dispatchEvent(이벤트객체)를 통해서
이벤트를 호출할 수 있음

 

ex) 

new customEvent("customClick",
{detail: {message: "hi"}}
)
  dispatchEvent(cuEvent)
  dispatchEvent(new customEvent("customClick",{
detail: {message: "hihi"}
}))

 

3.이벤트 핸들링

window.addEventListener("customClick", (e)=>{
console.log(e.detail.message)
})

 

 

실습

customEvent.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="divElem">커스텀 이벤트 객체에 대해 배워봅시다.</div>
    <script>
        
         //const green = new CustomEvent('nameEvent', {  이벤트 객체를 따로만들어도되고
            //detail: {name: "그린"}
        //})
        //const blue = new CustomEvent('nameEvent', {
            //detail: {name: "블루"}
        //}) 
        //클릭이벤트지만 이름이 있을경우 알아서 해주는 이벤트
        const red = new CustomEvent('nameEvent', {
            detail: {name: "레드"}  //detail말고는 안됨 detail 속성이 있음 얘는 무엇을 전달할수있음
        }) 
        window.addEventListener("nameEvent",(event) => {
            console.log(event.detail.name)
            console.log(event)
        })
        setTimeout(()=>{
            window.dispatchEvent(red)
        },1000)
        window.dispatchEvent ( new CustomEvent('nameEvent', {  //호출과 생성 둘다 같이 써도되구
            detail: {name: "오렌지"}
        }))
        window.dispatchEvent ( new CustomEvent('nameEvent', {
            detail: {name: "블루"}
        }))
    </script>
</body>
</html>

 

실습 2

customEvent.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="btn1">클릭1</button>
    <button id="btn2">클릭2</button>
    <script>
        const customSample1 = new CustomEvent("consoleEvent",{
            detail: {
                message: "하하하하"
            }
        })
        const customSample2 = new CustomEvent("consoleEvent",{
            detail: {
                message: "호호호호"
            }
        })
        window.addEventListener("consoleEvent", (e)=>{
            console.log(e.detail.message)
        })
        document.querySelector("#btn1").addEventListener("click", ()=>{
            dispatchEvent(customSample1)
        })
        document.querySelector("#btn2").addEventListener("click", ()=>{
            dispatchEvent(customSample2)
        })
    </script>
</body>
</html>

 

실습 3

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <nav class="navbar">
        <a href="/">HOME</a>
        <a href="/post/123">POST</a>
        <a href="/shop">shop</a>
    </nav>
    <div id="app"></div>
    <script src="./main.js"type="module"></script>
</body>
</html>

 

main.js

import App from "./src/app.js"
//초기html문서를 완전히 불러오고 분석했을때 발생
//html문서가 다 준비되면 실행해!!!!
window.addEventListener("DOMContentLoaded",()=>{ 
    new App({target: document.querySelector("#app")})
})

 

src폴더에

app.js

import Router from "./router.js";
import { navigate } from "./utils/navigate.js";


export default function App({target}){
    this.$container = target;
    const init = () => {
        document.querySelector(".navbar").addEventListener("click", (e)=>{
            //이벤트제거
            e.preventDefault();
            const targetUrl = e.target.href.replace("http://127.0.0.1:5500","")
            console.log(targetUrl)
            navigate(targetUrl)
        })
        new Router(this.$container)
    }
    init();
}

 

src폴더에

router.js

import { routes } from "./contants/routerInfo.js";

export default function Router($container){
    this.$container = $container;
    //routes 배열을 돌며 path속성이 location.pathname과 일치하는 객체를 리턴
    const findRoute = () => {
        //{path: /^\/$/, element: () => console.log('메인페이지')},
        const matchRoute = routes.find(route => route.path.test(location.pathname))
        const TargetPage = matchRoute.element
        new TargetPage(this.$container)
    }
    const init = () => {
        window.addEventListener('historyChange', (e)=>{
            const {to} = e.detail;
            history.pushState(null, "", to)
            findRoute()
        })
        window.addEventListener("popstate", ()=>{
            findRoute() //얘가없으면 뒤로가기 눌렀을때 현재화면안됨
        })
    }
    init()
    findRoute()
}

 

contants폴더에

routerInfo.js

//정규표현식
// const re = /표현식작성/
// const re2 = new RegExp(표현식작성)
// path: /
// ^ -->문자의 시작 $ ----> 문자의 끝 ^/$
// /shop

import Main from "../pages/Main.js";
import Post from "../pages/Post.js";
import Shop from "../pages/Shop.js";

// /^\/post\/[\w]+$/  ---> /post//dd   /post/d
export const routes = [
    {path: /^\/$/, element: Main},
    {path: /^\/post\/[\w]+$/, element: Post},
    {path: /^\/shop$/, element: Shop},
]

 

utils폴더에

navigate.js

//navigate("abc") ---> 이벤트 생성 ----> 이벤트 발생
export const navigate = (to) => {
    const historyChangeEvent = new CustomEvent("historyChange", {
        detail: {to: to}
    })
    //이벤트 발생!!!
    dispatchEvent(historyChangeEvent)

}

 

pages폴더에

Main.js

export default function Main($container){
    this.$container = $container;
    this.setState = () => {
        this.render();
    }
    this.render = () => {
        this.$container.innerHTML = `
        <main class = "mainPage"> 메인페이지입니다. </main>
        `
    }
    this.render()
}

pages폴더에

Post.js

export default function Post($container){
    this.$container = $container;
    this.setState = () => {
        this.render();
    }
    this.render = () => {
        this.$container.innerHTML = `
        <main class = "postPage"> 
            포스트페이지입니다. 
        </main>
        `
    }
    this.render()
}

pages폴더에

Shop.js

export default function Shop($container){
    this.$container = $container;
    this.setState = () => {
        this.render();
    }
    this.render = () => {
        this.$container.innerHTML = `
        <main class = "shopPage"> 샵페이지입니다. </main>
        `
    }
    this.render()
}

 

style.css

#app {
    text-align: center;
    color: #2e3e50;
    margin-top: 60px;
}
.navbar {
    margin-top: 60PX;
    text-align: center;
}
.navbar > a {
    display: inline-block;
    font-size:32px;
    text-decoration: none;
    border-radius: 18px;
    background-color: #8040ff;
    color: white;
    padding: 5px 10px;
}
.mainPage {
    background: #4a4b43;
    padding: 50px 0;
    color: white;
}
.postPage{
    background: #40d2ff;
    padding: 50px 0;
    color: white
}
.shopPage {
    background: #ff40cf;
    padding: 50px 0;
    color: white;
}

 

728x90
반응형

'프로그래머스' 카테고리의 다른 글

[프로그래머스]프로그래밍 언어 검색  (1) 2023.03.03

댓글