🌐 Web/Redux

09. 웹페이지 만들기(3)

dlalwl_jpg 2022. 9. 15. 21:44

1. create 기능(글 추가 기능)

create버튼을 클릭했을 때 글을 작성하는 화면이 나오도록 구현해보자.

main.html

<!DOCTYPE html>
<html>
    <head>
        <!--redux를 웹페이지에 로딩-->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.js"></script>
    </head>

    <body>
        <div id="subject"></div>
        <div id="toc"></div>
        <div id="control"></div>
        <div id="content"></div>
        <script>

    function subject(){
        document.querySelector('#subject').innerHTML = `
        <header>
            <h1>WEB</h1>
            Hello, WEB!
        </header>
        `
    }

    function TOC(){
        var state = store.getState();
        var i = 0;
        var liTags = '';

        while(i < state.contents.length){
            liTags = liTags + `
                <li>
                    <a onclick="
                        event.preventDefault(); <!--event가 발생했을 때 event를 발생시킨 태그의 기본 동작을 방지-->
                        var action = {type: 'SELECT', id:${state.contents[i].id}} //type은 action에서 필수적
                        store.dispatch(action); //dispatch로 action정보가 넘어감. 그리고 reducer 호출됨
                    "href="${state.contents[i].id}">
                        ${state.contents[i].title}
                    </a>
                </li>`;
            i = i + 1;
        }

        document.querySelector('#toc').innerHTML = `
        <nav>
            <ol>${liTags}</ol>
        </nav>
        `;
    }
    
    function control(){
        document.querySelector('#control').innerHTML = `
        <ul>
            <li><a onclick="
                event.preventDefaualt();

            " href="/create">create</a></li>
            <li><input type="button" value="delete"></li>
        </ul>
        `;
    }
     
    function article(){
        var state = store.getState();
        if(state.mode === 'create'){
            document.querySelector('#content').innerHTML = `
            <article>
                <form onsubmit="
                    event.preventDefault();
                    <!--form 안에 있는 name값이 title인 태그인 값 가져오기-->
                    var _title = this.title.value; <!--title에 입력한 값-->
                    var _desc = this.desc.value; <!--desc에 입력한 값-->
                    store.dispatch({ <!--dispatch가 실행되면서 reducer가 호출되면서 매개변수 action으로 값이 들어감-->
                        type:'CREATE',
                        title:_title,
                        desc:_desc
                    })
                ">
                    <p>
                        <!--placeholder는 아무 것도 입력하지 않을 때 나오는 도움말-->
                        <input type="text" name="title" placeholder="title">
                    </p>
                    <p>
                        <textarea name="desc"
                        placeholder="description"></textarea>
                    </p>
                    <p>
                        <input type="submit", value="submit">
                    </p>
                </form>
            </article>
            `
        }else if(state.mode === 'read'){
            var i = 0;
            var aTitle, aDesc;

            while(i < state.contents.length){
                
                if(state.contents[i].id === state.selected_id){
                    aTitle = state.contents[i].title;
                    aDesc = state.contents[i].desc;
                    break;
                }
                
                i = i + 1;
            }
            document.querySelector('#content').innerHTML = `
            <article>
                <h2>${aTitle}</h2>
                ${aDesc}
            </article>
            `
        }

    }

    function reducer(state, action){ //이전의 상태 값과 호출된 이후의 action 값을 받는다.

        if(state === undefined){ //초기값 셋팅
            return{
                max_id:2,
                mode:'create', //글을 쓸 수 있는 형태 (read는 글을 읽을 수 있는 형태)
                selected_id:2,
                contents:[
                    {id:1, title:'HTML', desc:'HTML is ...'},
                    {id:2, title:'CSS', desc: 'CSS is ...'}
                ]
            }
        }

        var newState;
        if(action.type === 'SELECT'){
            newState = Object.assign({}, state, {selected_id:action.id}); 
            //state의 속성값이 빈객체에 복제되고, 그것이 newState가 된다.
            //즉, newState는 기존의 값인 state에 selected_id값이 덮어쓰기 된 값이 된다.
        } else if(action.type === 'CREATE'){
            var newMaxId = state.max_id + 1;
            var newContents = state.contents.concat(); //contents는 배열이기 때문에 배열을 복제할 때는 concat을 사용하여 복제
            newContents.push({id:newMaxId, title:action.title, desc:action.desc}) //새로운 내용이 추가된 배열
            newState = Object.assign({}, state, {
                max_id:newMaxId,
                contents:newContents,
                mode:'read' //글을 작성하는 것이 끝나 create모드에서 read모드로 변환
            })
        }

        console.log(action, state, newState);
        return newState;
    }
    
    var store = Redux.createStore(reducer); //store생성
    //subscribe는 값이 바뀌면 함수를 자동으로 호출함
    store.subscribe(article);
    store.subscribe(TOC);
    subject();
    TOC();
    control();
    article();
        </script>
    </body>
</html>

 

결과화면

새로운 글을 추가하는 create하는 기능이 잘 구현된 것을 확인할 수 있다.

 

강의영상 - https://youtu.be/Ah_-BUs4uW8


2. deletee 기능(글 삭제 기능)

main.html

<!DOCTYPE html>
<html>
    <head>
        <!--redux를 웹페이지에 로딩-->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.js"></script>
    </head>

    <body>
        <div id="subject"></div>
        <div id="toc"></div>
        <div id="control"></div>
        <div id="content"></div>
        <script>

    function subject(){
        document.querySelector('#subject').innerHTML = `
        <header>
            <h1>WEB</h1>
            Hello, WEB!
        </header>
        `
    }

    function TOC(){
        var state = store.getState();
        var i = 0;
        var liTags = '';

        while(i < state.contents.length){
            liTags = liTags + `
                <li>
                    <a onclick="
                        event.preventDefault(); <!--event가 발생했을 때 event를 발생시킨 태그의 기본 동작을 방지-->
                        var action = {type: 'SELECT', id:${state.contents[i].id}} //type은 action에서 필수적
                        store.dispatch(action); //dispatch로 action정보가 넘어감. 그리고 reducer 호출됨
                    "href="${state.contents[i].id}">
                        ${state.contents[i].title}
                    </a>
                </li>`;
            i = i + 1;
        }

        document.querySelector('#toc').innerHTML = `
        <nav>
            <ol>${liTags}</ol>
        </nav>
        `;
    }
    
    function control(){
        document.querySelector('#control').innerHTML = `
        <ul>
            <li><a onclick="
                event.preventDefaualt();
                store.dispatch({
                    type:'CHANGE_MODE',
                    mode:'create'
                })
            " href="/create">create</a></li>
            <li><input onclick="
                store.dispatch({
                    type:'DELETE'
                    <!--삭제 기능은 특정 토픽이 선택된 상태에서 하기 때문에--> 
                    <!--store의 state값이 seleted_id로 셋팅되어 있어 id값이 별도 지정 필요 없음-->

                });
            " type="button" value="delete"></li>
        </ul>
        `;
    }
     
    function article(){
        var state = store.getState();
        if(state.mode === 'create'){
            document.querySelector('#content').innerHTML = `
            <article>
                <form onsubmit="
                    event.preventDefault();
                    <!--form 안에 있는 name값이 title인 태그인 값 가져오기-->
                    var _title = this.title.value; <!--title에 입력한 값-->
                    var _desc = this.desc.value; <!--desc에 입력한 값-->
                    store.dispatch({ <!--dispatch가 실행되면서 reducer가 호출되면서 매개변수 action으로 값이 들어감-->
                        type:'CREATE',
                        title:_title,
                        desc:_desc
                    })
                ">
                    <p>
                        <!--placeholder는 아무 것도 입력하지 않을 때 나오는 도움말-->
                        <input type="text" name="title" placeholder="title">
                    </p>
                    <p>
                        <textarea name="desc"
                        placeholder="description"></textarea>
                    </p>
                    <p>
                        <input type="submit", value="submit">
                    </p>
                </form>
            </article>
            `
        }else if(state.mode === 'read'){
            var i = 0;
            var aTitle, aDesc;

            while(i < state.contents.length){
                
                if(state.contents[i].id === state.selected_id){
                    aTitle = state.contents[i].title;
                    aDesc = state.contents[i].desc;
                    break;
                }
                
                i = i + 1;
            }
            document.querySelector('#content').innerHTML = `
            <article>
                <h2>${aTitle}</h2>
                ${aDesc}
            </article>
            `
        } else if(state.mode === 'welcome'){
            document.querySelector('#content').innerHTML = `
            <article>
                <h2>Welcome</h2>
                Hello, Redux!!!
            </article>
            `
        }

    }

    function reducer(state, action){ //이전의 상태 값과 호출된 이후의 action 값을 받는다.

        if(state === undefined){ //초기값 셋팅
            return{
                max_id:2,
                mode:'welcome', //글을 쓸 수 있는 형태 (read는 글을 읽을 수 있는 형태)
                selected_id:2,
                contents:[
                    {id:1, title:'HTML', desc:'HTML is ...'},
                    {id:2, title:'CSS', desc: 'CSS is ...'}
                ]
            }
        }

        var newState;
        if(action.type === 'SELECT'){
            newState = Object.assign(
                {}, 
                state, 
                {selected_id:action.id, mode:'read'}); 
            //state의 속성값이 빈객체에 복제되고, 그것이 newState가 된다.
            //즉, newState는 기존의 값인 state에 selected_id값이 덮어쓰기 된 값이 된다.
        } else if(action.type === 'CREATE'){
            var newMaxId = state.max_id + 1;
            var newContents = state.contents.concat(); //contents는 배열이기 때문에 배열을 복제할 때는 concat을 사용하여 복제
            newContents.push({id:newMaxId, title:action.title, desc:action.desc}) //새로운 내용이 추가된 배열
            newState = Object.assign({}, state, {
                max_id:newMaxId,
                contents:newContents,
                mode:'read' //글을 작성하는 것이 끝나 create모드에서 read모드로 변환
            })
        } else if(action.type === 'DELETE'){
            var newContents = [];
            var i = 0;
            while(i < state.contents.length){
                if(state.selected_id !== state.contents[i].id){

                    newContents.push(
                        state.contents[i]
                    );
                }
                i = i + 1;
            }
            newState = Object.assign({}, state, {
                contents:newContents,
                mode:'welcome'
            })
        }else if(action.type === 'CHANGE_MODE'){
            newState = Object.assign({}, state, {
                mode:action.mode
            });
        }

        console.log(action, state, newState);
        return newState;
    }
    
    var store = Redux.createStore(reducer); //store생성
    //subscribe는 값이 바뀌면 함수를 자동으로 호출함
    store.subscribe(article);
    store.subscribe(TOC);
    subject();
    TOC();
    control();
    article();
        </script>
    </body>
</html>

 

결과화면

CSS를 클릭하교 delete 버튼을 눌렀을 때 잘 삭제되는 것을 확인할 수 있다.

 

강의영상 - https://youtu.be/2s6s4IHzGSs