개성있는 개발자 되기

[Vue.js] Ch2 Vue.js 기초 본문

Web Development/Vue.js

[Vue.js] Ch2 Vue.js 기초

정몽실이 2019. 4. 14. 22:20

1. 기본 디렉티브

 

꼭 콧수염 표현식이 아니더라도 HTML 요소 내부에 선언적 렌더링을 하는 건 아니다. 디렉티브라는 것이 있다.

 

Vue.js의 기본 디렉티브들을 알아보겠다.

...더보기
  • v-text, v-html
  • v-bind
  • v-model
  • v-show, v-if, v-else, v-else-if
  • v-for
  • v-pre, v-once

 

1.1 v-text, v-html 디렉티브

 

text를 바인딩 하는 디렉티브다.

 

<!DOCTYPE html>
<html>

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

<body>

    <div id="simple">
        <h2 v-text="message"></h2>
        <h2 v-html="message"></h2>
    </div>

    <script type="text/javascript">
        // 모델 객체
        var model = {
            message: "<i>HTML 태그는 어찌 되나?</i>",
        };

        // 뷰모델 객체
        var simple = new Vue({
            el: '#simple', // HTML 요소
            data: model // 모델 객체 참조
        });
    </script>
</body>

</html>

실행화면

v-text 와 v-html 의 차이점은 실행화면에서 볼 수 있듯이, v-text는 태그 문자열을 HTML 인코딩하여 나타내기 때문에 화면에 태그 문자열이 그대로 나타난다.

 

하지만 v-html 디렉티브는 <script>태그를 그대로 바인딩해서 화면에 html속성이 적용되어 나타나는 것이다.

 

책에서는 v-html 디렉티브는 XSS(Cross Site Scripting) 공격에 취약하다고 v-text를 사용하는 것이 더 안전하다고 한다.

...더보기

XSS : 악의적으로 사이트에 스크립트를 끼워 넣는 기법

실제로 이런 사례들은 회사에서도 몇 번 본적이 있기 때문에.. 조심해서 나쁠건 없는 것 같다.

 

1.2 v-bind 디렉티브

 

v-bind 디렉티브는 요소 객체의 속성들을 바인딩하기 위해 사용한다.

 

<!DOCTYPE html>
<html>

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

<body>

    <div id="simple">
        <input id="a" type="text" v-bind:value="message">

        <!-- v:bind 를 생략해도 된다.-->
        <input id="a" type="text" :value="message">
        <br/>
        <img v-bind:src="imagePath" />
    </div>

    <script type="text/javascript">
        // 모델 객체
        var model = {
            message: '룰루',
            imagePath: "https://postfiles.pstatic.net/20141117_263/sunmin_jsm_1416230796954OYQH8_PNG/%C0%FC%C8%AD%B1%E2.png?type=w1"
        };

        // 뷰모델 객체
        var simple = new Vue({
            el: '#simple', // HTML 요소
            data: model // 모델 객체 참조
        });
    </script>
</body>

</html>

실행화면

 

v-bind:src 를 v-bind 생략하고 그냥 :src와 같이 작성해도 된다.

 

1.3 v-model 디렉티브

 

앞의 디렉티브들은 모두 단방향 디렉티브이다. HTML 요소에서 값을 변경하더라도, 모델 객체의 값이 바뀌지 않는다.

 

text 박스의 값을 변경하더라도, 모델 객체의 값이 바뀌지 않는 것을 확인할 수 있다.

객체 요소에서 변경한 값이 모델 객체에 반영되기를 원한다면 양방향 데이터 바인딩이 필요하다. v-model 을 써보자.

<!DOCTYPE html>
<html>

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

<body>

    <div id="simple">
        <input type="text" v-model.trim="name" placeholder="이름을 입력하세요" />
        <br/> 입력된 이름 :
        <h2 v-html="name"></h2>
    </div>

    <script type="text/javascript">
        // 모델 객체
        // var model = {
        //     message: '룰루',
        //     imagePath: "https://postfiles.pstatic.net/20141117_263/sunmin_jsm_1416230796954OYQH8_PNG/%C0%FC%C8%AD%B1%E2.png?type=w1"
        // };

        // // 뷰모델 객체
        // var simple = new Vue({
        //     el: '#simple', // HTML 요소
        //     data: model // 모델 객체 참조
        // });

        // 이 뷰모델 객체에 data 모델 객체는 따로 멤버변수로 선언하지 않고 바로 생성했다.
        // 간단하다면 따로 모델객체 선언 없이 바로 생성할 수 있다.
        var twoway = new Vue({
            el: '#simple',
            data: {
                name: ''
            }
        });
    </script>
</body>

</html>

 

실행화면

 

여기서 짚고 넘어갈 점은 twoWay 이 뷰모델 객체에 data 모델 객체는 따로 멤버변수로 선언하지 않고 바로 생성했다.

간단하다면 따로 모델객체 선언 없이 바로 생성할 수 있다.


v-model 디렉티브는 특별한 기능을 추가하는 문법 요소들이 있다.

 

  • lazy : 텍스트 박스 > 입력 후 포커스가 이동하거나 할 때 데이터 옵션값이 변경된다. 안쓴다면, 텍스트 박스에서 문자열이 변경될 때마다 즉각즉각 변경된다.
  • number : 숫자가 입력될 경우 number 타입의 값으로 자동 형변환된다.
  • trim : 문자열의 앞뒤 공백을 자동으로 제거한다.

위 기능들은 기본적인 validation을 정말 간단하게 추가할 수 있다. 상품 상세 페이지에서 굉장히 유용하게 쓰일 것 같다.

 

1.4 v-show, v-if, v-else, v-else-if 디렉티브

 

v-show 디렉티브는 자바스크립트에서 요소 객체의 disaplay를 block 할지, none할지 결정할 수 있는 기능이다.

v-if 를 써서 비슷한 기능을 구현할 수 있지만 차이점이 있다.

 

v-show는 일단 HTML요소를 렌더링한 후에 display 스타일 속성으로 화면에 보여주는 반면, v-if 디렉티브는 조건에 부합되지 않으면 아예 렌더링 자체를 하지 않는다.

 

1.5 v-for

 

반복 디렉티브다. data에는 배열이나 유사배열이 들어갈 수 있다. 

 

<!DOCTYPE html>
<html>

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

<body>

    <div id="example">
        <table id="list">
            <thead>
                <tr>
                    <th>번호</th>
                    <th>이름</th>
                    <th>전화번호</th>
                    <th>주소</th>
                </tr>
            </thead>
            <tbody id="contacts">
                <tr v-for="contact in contacts">
                    <td>{{contact.no}}</td>
                    <td>{{contact.name}}</td>
                    <td>{{contact.tel}}</td>
                    <td>{{contact.address}}</td>
                </tr>
            </tbody>
        </table>
    </div>

    <script type="text/javascript">
        var modelEx = {
            "pageno": 1,
            "pagesize": 10,
            "totalcount": 100,
            "contacts": [{
                "no": 100,
                "name": "설현",
                "tel": "1111",
                "address": "서울"
            }, {
                "no": 100,
                "name": "설현",
                "tel": "1111",
                "address": "경기"
            }]
        }

        var list = new Vue({
            el: "#example",
            data: modelEx

        });
    </script>
</body>

</html>

실행화면

위 코드는 객체 배열이다. 객체일 경우, 키를 이용해 값에 접근하는 HashMap 구조이기 떄문에 Key, Value 값을 얻어낼 수 있는 구조를 사용한다.

 

v-for 디렉티브를 사용하면서 인덱스가 필요할 경우에는 다음과 같이 작성하면 된다.

 

...더보기

<tr v-for="(conatct, index) in contacts"> ... </tr>

<option v-for="(val, key, index) in regions"> ... </option>

 

하나의 포문 안에, 여러 요소를 동시에 돌려야 한다면 <template> 태그를 사용하면 된다.

 

Vue.js는 가상 DOM을 지원한다. 가상 DOM은 렌저링 속도를 빠르게 하기 위해 변경된 부분만을 업데이트 한다.

-> v-for로 렌더링한 배열 데이터의 순서가 변경되면 DOM요소를 이동시키지 않고, 기존 DOM요소에 데이터만 변경한다는 뜻이다.

 

만일, DOM 요소의 위치를 직접 변경하고자 한다면, DOM 요소에 :key 속성을 부여해서, 요소의 PK ID를 지정해주면 된다.

 

v-for 디렉티브로 배열을 렌더링 할때, 배열 데이터가 변경되어도 추적이 불가한 케이스가 있다.

배열 데이터를 인덱스 번호를 이용해 직접 변경하는 경우이다.

 

list.contacts[0] = {no:100, name"다혜"}; //인덱스에 직접 접근해서 배열요소를 통쨰로 바꾸는 경우 Vue 인스턴스 내부의 감시자가 추적하지 못한다.



list.contacts[0].name = "다혜"; // 이렇게 속성값을 직접 변경하는 경우에는 추적이 가능하다.

 

기존 배열 값을 직접 변경하기 위해서는 Vue.set 메서드를 사용해야 한다.

 

Vue.set(list.contacts, 0, {no:100, name"다혜"});

1.6 v-pre, v-once

 

v-pre 디렉티브 : HTML 요소에 대한 컴파일을 수행하지 않는다.

v-once : HTML요소를 단 한번만 렌더링 한다. 초기값이 주어지면 변경되지 않는 UI를 만들 때 사용할 수 있따.

v-clock : 화면 초기에 컴파일되지 않은 템플릿은 나타나지 않도록 할 수  있다.

 

2. 계산형 속성

Vue 객체를 만들 때, computed 라는 속성과 함께 함수를 등록해두면 마치 속성처럼 이용할 수 있다.

 

num 객체에 숫자를 입력하면, 1부터 num까지 더한 합을 출력해주는 코드이다.

        var vmSum = new Vue({
            el: "#example",
            data: {
                num: 0
            },
            computed: {
                sum: function() {
                    var n = Number(this.num);

                    if (Number.isNaN(n) || n < 1) return 0;
                    return ((1 + n) * n) / 2;
                }
            }

        });

 

자바스크립트 스터디 할때도, this 를 사용할 때 주의해야 한다고 했었다.

        var model = {
            countryname : "" ,
            countries : [
                {no:1, name:"미국"} ,
                {no:3, name:"한국"} ,
                {no:4, name:"중국"} ,
            ]
        }

        var clist = new Vue({
            el: "#example",
            data: model,
            computed: {
                filtered: function() {
                    var cname = this.country.name.trim();
                    return this.countries.filter(function(item, index) {
                        if (item.name.indexOf(cname) > -1) {
                            return true;
                        }
                    })
                }
            }
        });

위 코드를 보면, countryname에 할당된 값을 가져와서 model에 있는 배열 리스트들 중에 countryname이 포함된 문자열이 있는 배열 리스트만 리턴해주는 뷰모델이다.

 

filter함수의 콜백함수 안에 this.country.name을 쓰지 못한 이유는 콜백함수 내부의 this는 뷰객체가 아니라 전역객체(Global Object)이기 때문에 별도의 변수로 받아둬서 사용한 것이다.

 


v-model 디렉티브는 한글 입력 시에 이벤트가 발생하거나, 엔터키를 입력해주어야 바인딩이 일어나는 문제가 있다.

v-on 디렉티브는 input 이벤트나 keyup이벤트 처리를 수행할 수 있다.

 

<input type="text" @input="nameChanged"/>

        var clist = new Vue({
            el: "#example",
            data: model,
            computed: {
                filtered: function() {
                    var cname = this.country.name.trim();
                    return this.countries.filter(function(item, index) {
                        if (item.name.indexOf(cname) > -1) {
                            return true;
                        }
                    })
                }
            },
            methods: {
                nameChanged: function(e) {
                    this.countryname = e.target.value;
                }
            }
        });

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

[Vue.js] Ch6 컴포넌트 기초  (0) 2019.05.13
[Vue.js] Ch5 스타일 적용  (0) 2019.05.09
[Vue.js] Ch4 이벤트 처리  (0) 2019.05.02
[Vue.js] Ch3 Vue 인스턴스  (0) 2019.04.25
[Vue.js] Ch1 Vue.js 시작하기  (0) 2019.04.14
Comments