ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [HTML5] HashChange Event 해쉬 변경 이벤트 처리 PushState와 popState 메서드
    프로그래밍/HTML5 Web 2016. 7. 11. 21:46
    반응형


    Sammy.js 라이브러리를 통해 히스토리를 관리하여 해시를 사용하여 뒤로가기 버튼을 활용해보았습니다. 다만 Sammy.js 라이브러리를 사용하지 않고 해시 이벤트를 구현해보도록하겠습니다.


    HTML5에서 hashchange 이벤트로 해시 변경을 검사합니다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!DOCTYPE html>
     
    <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="utf-8" />
        <title>Hash Change</title>
        <script>
            //Connect Event
            window.addEventListener('hashchange'function () {
                //Show
                alert(location.hash);
            });
        </script>
    </head>
    <body>
        <a href="#point_a">Move To Point_A</a>
        <a href="#point_b">Move To Point_B</a>
    </body>
    </html>
    cs


    코드를 실행하고 a 태그를 각자 클릭하면 해시가 변경되면서 이벤트 리스너가 실행됩니다. 이후에 아래와 같이 각자 출력됩니다.



    이로써 Sammy.js 라이브러리를 사용하지 않고 직접 HTML5으로만으로도 해시 변경 이벤트를 구현해보았습니다.


    이번에는 hashchange 이벤트로 Sammy.js 라이브러리의 get() 메서드처럼 GET요청을 처리하는 기능을 구현해보겠습니다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    <!DOCTYPE html>
    <html>
    <head>
        <title>Hash Change</title>
        <!-- 모듈 구현 -->
        <script>
            (function () {
                // 변수를 선언합니다.
                var router = {};
                // 메서드를 추가합니다.
                location.get = function (url, callback) {
                    // router 객체에 콜백 함수를 추가합니다.
                    if (router[url]) {
                        router[url].push(callback);
                    } else {
                        router[url] = [callback];
                    }
                    // 리턴합니다.
                    return location;
                };
                // 이벤트를 연결합니다.
                window.addEventListener('hashchange'function () {
                    if (router[location.hash]) {
                        router[location.hash].forEach(function (item) {
                            item();
                        });
                    }
                });
            })();
        </script>
        <!-- 진행 코드 -->
        <script>
            window.onload = function () {
                // 라우터를 생성합니다.
                location.get('#/'function () {
                    document.body.style.background = 'white';
                }).get('#/red'function () {
                    document.body.style.background = 'red';
                }).get('#/green'function () {
                    document.body.style.background = 'green';
                }).get('#/blue'function () {
                    document.body.style.background = 'blue';
                });
                // 초기 페이지를 이동합니다.
                location.hash = '#/';
            };
        </script>
    </head>
    <body>
        <a href="#/">white</a>
        <a href="#/red">red</a>
        <a href="#/green">green</a>
        <a href="#/blue">blue</a>
    </body>
    </html>
    cs


    location 객체에 get() 메서드를 생성한후 hashchange 이벤트를 구성하여 최종적으로 위의 코드를 구성합니다.

    각자의 a 태그를 클릭하면 배경색상이 변겨되는데 뒤로가기 버튼으로 이전페이지로 돌아갈수도있습니다.


    하지만 구버전의 인터넷 익스플로러라면 hashchange 이벤트를 사용할수 없는데요. 이러한 경우에는 아래와 같이 구현이 가능합니다.




    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <!DOCTYPE html>
    <html>
    <head>
        <title>History Basic</title>
        <script>
            // 변경 이벤트
            function hashChange() {
                console.log(location.hash);
            }
            // 1초에 10번 해시가 변경되는지 검사합니다.
            var beforeURL = location.hash;
            setInterval(function () {
                if (beforeURL != location.hash) {
                    hashChange();
                }
                beforeURL = location.hash;
            }, 1000 / 10);
        </script>
    </head>
    <body>
        <a href="#/">Page_Index</a>
        <a href="#/page_a">Page_A</a>
        <a href="#/page_b">Page_B</a>
    </body>
    </html>
    cs


    타이머 기능이 쓸데없이 동작하지만 해시가 변경되는지 검사가 가능합니다. 결과값은 개발자 콘솔로 확인이 가능합니다.


    Sammy.js 라이브러리를 사용하면서 아쉬운점이 있다면 뒤로가기를 할 때에도 웹 요청이 발생한다는 점입니다. 이러한 문제점을 해결하기 위해 HTML5에서는 이전상태를 저장하는 pushState() 메서드와 popState 이벤트를 지원합니다.


    현재 상태를 저장할 때는 pushState() 메서드를 사용합니다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <!DOCTYPE html>
     
    <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="utf-8" />
        <title>Push State</title>
        <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
     
        <script>
            $(document).ready(function () {
                //변수 선언
                var count = 1;
     
                //이벤트 연결
                $('button').click(function () {
                    //출력
                    $('h1').text('Count - ' + count);
     
                    //상태를 저장
                    history.pushState({
                        data: count
                    }, 'Push State''#' + count);
     
                    //카운트 변수 증가
                    count = count + 1;
                });
            });
        </script>
    </head>
    <body>
        <h1>Count - 0</h1>
        <button>Click</button>
    </body>
    </html>
    cs


    Click 이벤트 리스너에서 화면에 변수 count를 출력하고 pushState() 메서드로 변수 count를 저장하는데 코드를 실행하고 버튼을 누르면 버튼이 활성화되고 count 숫자가 증가합니다.


    주의 사항이 존재하는데 history.pushState() 메서드의 세번쨰 매개변수는 해시 형태가 아닌 문자열을 입력해도 됩니다. 

    pushState() 메서드의 첫 번째 매개변수에 입력한 데이터는 popstate 이벤트의 이벤트 객체로 전달이 됩니다. 이벤트 객체의 state 속성을 사용하면 이전 상태의 값을 추출할 수 있습니다. 아래 코드는 popstate 메서드를 추가한 코드입니다. 뒤로가기를 누르게되면 전의 변수값또한 저장이 되어 다시 되돌아가는것을 확인할수있습니다.




    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    <!DOCTYPE html>
     
    <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="utf-8" />
        <title>Push State</title>
        <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
     
        <script>
            $(document).ready(function () {
                //변수 선언
                var count = 1;
     
                //이벤트 연결
                $('button').click(function () {
                    //출력
                    $('h1').text('Count - ' + count);
     
                    //상태를 저장
                    history.pushState({
                        data: count
                    }, 'Push State''#' + count);
     
                    //카운트 변수 증가
                    count = count + 1;
                });
            });
     
            $(window).on('popstate'function (event) {
                if (event.originalEvent.state) {
                    $('h1').text('Count - ' + event.originalEvent.state.data);
                }
            });
        </script>
    </head>
    <body>
        <h1>Count - 0</h1>
        <button>Click</button>
    </body>
    </html>
    cs


    원래 추가적으로 Twitter API를 활용하여 검색하는 프로그램을 추가하려했으나 최근에 트위터 API가 인증시스템으로 변경된 까닭으로.. 다음 API를 활용하여 HashChange 이벤트를 사용하여 처리하여보겠습니다. 다만 제가 다음 API를 활용해보지 않아 조금 연구할 시간이 필요할듯하네요 ㅎㅎ;;

    반응형

    댓글

Designed by Tistory.