개성있는 개발자 되기

[Vue.js] Ch5 스타일 적용 본문

Web Development/Vue.js

[Vue.js] Ch5 스타일 적용

정몽실이 2019. 5. 9. 20:49

1. 인라인 스타일

인라인 스타일이란 HTML 요소의 style 프로퍼티에 CSS를 기술하는 방식을 뜻한다. 가능하다면 인라인 스타일은 사용하지 않는 것이 바람직하다.

Vue.js에서는 v-bind:style로 인라인스타일을 작성할 수 있다.

 

- 이벤트가 일어날 때마다 style1의 데이터 속성을 변경한다.

- 변경된 속성은 v-bind:style="style1"을 통해 데이터에 바인딩 된다.

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>05-02</title>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
</head>

<body>
    <div id="example">
        <button id="a" v-bind:style="style1" @mouseover.stop="overEvent" @mouseout.stop="outEvent">테스트</button>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#example",
            data: {
                style1: {
                    backgroundColor: "aqua",
                    border: 'solid 1px gray',
                    with: '100px',
                    textAlign: 'center'
                }
            },
            methods: {
                overEvent: function(e) {
                    this.style1.backgroundColor = "purple";
                    this.style1.color = "yellow";
                },
                outEvent: function(e) {
                    this.style1.backgroundColor = "aqua";
                    this.style1.color = "black";
                }
            }
        })
    </script>
</body>

</html>

 

- 여러개의 스타일 객체를 바인딩 할수도 있다.

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>05-04</title>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
</head>

<body>
    <div id="example">
        <button id="btn1" v-bind:style="[myColor,myLayout]">버튼1</button>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#example",
            data: {
                myColor: {
                    backgroundColor: 'purple',
                    color: 'yellow'
                },
                myLayout: {
                    width: '150px',
                    height: '80px',
                    textAlign: 'center'
                }
            }
        })
    </script>
</body>

</html>

실행화면

 

2. CSS 클래스 바인딩

v-bind:class를 사용한다. boolean 값을 이용해 지정하는데, 개별적인 클래스 단위로 true가 되면 클래스가 주어진다.

 

- 클래스 이름을 데이터 속성명으로 사용해서, v-model에 바인딩 해주면 해당 값의 true/false 여부에 따라 스타일이 반영된다.

    <style>
        .set1 {
            background-color: aqua;
            color: purple;
        }
        
        .set2 {
            text-align: center;
            width: 120px;
        }
        
        .set3 {
            border: sandybrown dashed 1px;
        }
    </style>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
</head>

<body>
    <div id="example">
        <button id="btn1" v-bind:class="mystyle">버튼1</button>
        <p>
            <input type="checkbox" v-model="mystyle.set1" value="true" />set1 디자인<br/>
            <input type="checkbox" v-model="mystyle.set2" value="true" />set2 디자인<br/>
            <input type="checkbox" v-model="mystyle.set3" value="true" />set3 디자인<br/>
        </P>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#example",
            data: {
                mystyle: {
                    set1: false,
                    set2: false,
                    set3: false
                }
            }
        })
    </script>

실행화면

 


위 사진과 같이 checkbox 요소에 v-model을 mystyle의 이상한 값으로 설정해두면, 이 체크박스가 true여도 스타일이 바뀌지 않는다. 이 예제는 css 클래스는 true/false로 작동한다는 것을 알 수 있다.

 

3. 계산형 속성, 메서드를 이용한 스타일 적용

 

계산형 속성을 이용해서 스타일을 적용할 수 있다. input의 값이 변경될 때마다 스타일을 적용하기에 적합하다.

- score 가 1부터 크고 100보다 작으면 스타일 warning을 false로 만들어서 스타일이 적용되지 않게 하고 있다.

- input text는 기본적으로 스타일 score를 가지고 있다.

- v-model.number="score" 로 데이터 속성을 바인딩 해주는데, v-model="score"로 해도 무방하다.

- v-bind:class="info"로 info 계산형 속성을 class에 바인딩한다.

    <div id="example">
        <div>
            <p>1부터 100까지만 입력가능합니다.</p>
            <div>
                점수 : <input type="text" class="score" v-model.number="score" v-bind:class="info" />
                <img src="images/error.png" class="warnimage" v-show="info.warning" />
            </div>
        </div>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#example",
            data: {
                score: 0
            },
            computed: {
                info: function() {
                    if (this.score >= 1 && this.score <= 100)
                        return {
                            warning: false
                        };
                    else
                        return {
                            warning: true
                        };
                }
            }
        })
    </script>

 

4. 컴포넌트에서의 스타일 적용

 

Vue 컴포넌트는 Vue.component()를 이용해 작성할 수 있다. 

 

        Vue.component('center-box', {
            template: '<div class="center">중앙에 위치</div>'
        })

이렇게 컴포넌트를 만들었다면 <center-box></center-box>와 같이 사용할 수 있다.

    <div id="example">
        <center-box v-bind:class="boxstyle"></center-box>
    </div>

컴포넌트를 만들 때, center 클래스를 적용했지만, <center-box>에 추가적으로 class를 적용할 수 있다.

 

5. TodoList 예제

지금까지 학습한 내용을 바탕으로 간단한 예제를 작성해보겠다. 간단히 일 목록을 작성하고 저장, 삭제, 완료 처리를 할 수 있는 기능을 제공한다.

 

5.1 마크업 작성

    <div id="todolistapp">
        <div id="header" class="header">
            <h2>Todo List App</h2>
            <input class="input" type="text" id="task" placeholder="입력 후 엔터!">
            <span class="addbutton">추 가</span>
        </div>
        <ul id="todolist">
        	// 추후 v-for 디렉티브로 구현할 것이다.
            <li>
                <span>Task 1</span>
                <span class="close">&#x00D7;</span>
            </li>
            <li class="checked">
                <span>Task2</span>
                <span> (완료)</span>
                <span class="close">&#x00D7;</span>
            </li>
            <li>
                <span>Task3</span>
                <span class="close">&#x00D7;</span>
            </li>
        </ul>
    </div>

 

5.2 데이터, 메서드들을 정의할 Vue 인스턴스 작성

- 아직 요소들에 메서드들을 바인딩하지 않았기 때문에 아무 반응이 없다.

    <script type="text/javascript">
        var vm = new Vue({
            el: "#todolistapp", // 바인딩할 요소
            data: { // 데이타
                todo: "",
                todolist: [{
                    id: 1,
                    todo: "영화보기",
                    done: false
                }, {
                    id: 2,
                    todo: "주말 산책",
                    done: true
                }, {
                    id: 3,
                    todo: "ES6 학습",
                    done: false
                }, {
                    id: 4,
                    todo: "잠실 야구장",
                    done: false
                }]
            },
            methods: { // 메서드
                checked: function(done) {
                    if (done) return {
                        checked: true
                    };
                    else return {
                        checked: false
                    };
                },
                addTodo: function(e) {
                    if (this.todo.trim() !== "") {
                        // 객체요소를 배열에 PUSH
                        this.todolist.push({
                            id: new Date().getTime(),
                            todo: this.todo.trim(),
                            done: false
                        });
                        this.todo = "";
                    }
                },
                deleteTodo: function(id) {
                    var index = this.todolist.findIndex(function(item) {
                            // id가 같은 배열 요소를 찾음
                            return item.id === id;
                        })
                        // 해당 요소를 자름
                    this.todolist.splice(index, 1);
                },
                doneToggle: function(id) {
                    var index = this.todolist.findIndex(function(item) {
                        return item.id === id;
                    })
                    this.todolist[index].done = !this.todolist[index].done;
                }
            }
        })
    </script>

 

5.3 뷰 인스턴스 마크업에 연결

 

- v-model.trim="todo" : todo 데이터의 공백을 제거하고 양방향 데이터로 바인딩했다.

- v-on:keyup.enter="addTodo" : 엔터키를 입력하면 addTodo메서드를 실행한다.

- v-for="a in todolist" : todolist 배열에 있는 객체들을 반복문을 이용해서 뿌려준다.

- v-bind:class="checked(a.done)" : todoList 객체의 donce 속성(true/false)로 클래스의 적용 유무를 제어한다.

- v-if="a.done" : if 문을 이용해 a.done이 true 면 (완료) 텍스트를 보여준다.

    <div id="todolistapp">
        <div id="header" class="header">
            <h2>Todo List App</h2>
            <input class="input" type="text" id="task" v-model.trim="todo" placeholder="입력 후 엔터!" v-on:keyup.enter="addTodo">
            <span class="addbutton" v-on:click="addTodo">추 가</span>
        </div>
        <ul id="todolist">
            <li v-for="a in todolist" v-bind:class="checked(a.done)" v-on:click="doneToggle(a.id)">
                <span>{{ a.todo }}</span>
                <span v-if="a.done"> (완료)</span>
                <span class="close" v-on:click.stop="deleteTodo(a.id)">&#x00D7;</span>
            </li>
        </ul>
    </div>

- v-on:click.stop="deleteTodo(a.id)" : 온클릭 이벤트에 stop 수식어를 사용했다. 이벤트 버블링에 의해서 상위 요소의 클릭이 호출되지 않도록 하는 것이다.

- 아래와 같이 작성하면 콘솔에서는 delete 이벤트를 거슬러올라가 상위요소의 divClicked까지 이벤트를 버블링한다.

                <div v-on:click="divClicked">
                    <span class="close" v-on:click="deleteTodo(a.id)">&#x00D7;</span>
                </div>

'Web Development > Vue.js' 카테고리의 다른 글

[Vue.js] Ch7 ECMAScript 2015  (0) 2019.06.06
[Vue.js] Ch6 컴포넌트 기초  (0) 2019.05.13
[Vue.js] Ch4 이벤트 처리  (0) 2019.05.02
[Vue.js] Ch3 Vue 인스턴스  (0) 2019.04.25
[Vue.js] Ch2 Vue.js 기초  (0) 2019.04.14
Comments