LittleDeveloper

2. Vue.js 기초 (1) 본문

vue.js

2. Vue.js 기초 (1)

lemonjelly 2021. 12. 28. 22:47

2.1 hellovuejus 예제 분석

지난 1장에서 예제를 통해 model 객체의 속성을 변경하면 화면이 변경되는 것을 확인했다.

이 index.html이 어떻게 구성되었는지 코드를 분석해보자.

        var model = {
            message: "첫 번째 Vue.js 앱입니다.",
        };

위 코드에서 model 객체는 변수명 그대로 모델(Model) 객체로서, 데이터를 가지고 있다.

        var simple = new Vue({
            el: "#simple",
            data: model,
        });

또한 위 코드의 simple 객체는 Vue 객체이자 뷰모델(ViewModel) 객체이다.

Vue 객체의 el 속성은 HTML 요소(Element)를 나타내고,

data 속성은 모델 객체를 참조한다!

즉, Vue 객체는 HTML 요소와 데이터를 참조하고 있는 것이다. 이제 데이터(모델)가 변경되면 뷰모델 객체는 즉시 HTML 요소(뷰)에 반영된다.

 

 

HTML 요소에서는 {{ }}과 같은 템플릿 표현식으로 HTML DOM 에 데이터를 렌더링한다. 뷰모델 객체의 데이터 속성에서 해당 값을 이 위치에 나타낸다. 이 코드만으로 모든 작업은 반응형으로 이루어진다.

모델(Model)을 변경하면 뷰모델(ViewModel) 객체를 통해 HTML DOM 이 즉시 변경된다.

 

Vue.js 와 MVVM 패턴

 

2.2 기본 디렉티브

1) v-text, v-html 디렉티브

선언적 렌더링을 위해 HTML 요소 내부에 템플릿 표현식({{}}) 만 사용할 수 있는 것은 아니다. 아래 코드처럼, 

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

라고 나타낼 수도 있다. 

 

**{{}} 표현의 한계

위처럼 모델 객체의 값을 변경하면, message 속성에 입력한 HTML 태그 문자열이 인코딩되어 나타나는 것을 알 수 있다.

자바스크립트에서 innerHTML 속성은 innerText처럼 HTML 인코딩, 디코딩을 수행하지 못한다. 따라서 HTML 태그가 브라우저에서 파싱되어 화면에 나타나게 된다. 

 

v-text, {{}} innerText 속성에 연결됨. 태그 문자열을 HTML 인코딩하여 나타나기 때문에 화면에는 태그 문자열이 그대로 나타남.
v-html innerHTML 속성에 연결됨. 태그 문자열을 파싱하여 화면에 나타냄.

 

만약, 위의 코드에서 v-text를 v-html로 변경한 경우, 전혀 다른 결과가 나타나게 된다.

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

v-html

v-html 디렉티브는 <script> 태그를 그대로 바인딩한다. 이는 요즘 문제가 되는 XSS(Cross Site Scripting) 공격 등에 취약하므로, 필수가 아니면 v-text를 사용하는 것이 더 안전하다.

 

2) v-bind 디렉티브 

v-bind는 요소(Element)의 콘텐츠 영역(시작 태그와 종료 태그 사이의 영역)을 설정하는 것이 아닌, 

요소 객체의 속성들을 바인딩하기 위해 사용한다. body 태그 안쪽만 수정해서 v-bind 를 알아보자.

    <div id="simple">
        <input id="a" type="text" v-bind:value="message" />
        <br />
        <img v-bind:src="imagePath" />
    </div>
    <script type="text/javascript">
        var model = {
            message: "v-bind 디렉티브",
            imagePath: "https://newsimg.sedaily.com/2021/12/27/22VGF6RY81_1.jpg",
        };

        var simple = new Vue({
            el: "#simple",
            data: model,
        });
    </script>

위의 코드를 추가하면, 아래와 같이 v-bind 디렉티브를 통해서 HTML 요소 객체의 속성이 변경되었음을 알 수 있다.

v-bind 디렉티브를 매번 작성하는 것이 부담스럽다면 줄여 쓸 수도 있다. v-bind:src 에서 v-bind 를 생략하고 :src와 같이 작성해도 된다.

 

3) v-model 디렉티브

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

 

이처럼 텍스트 필드의 값이 변경되어도 모델 객체의 속성은 변경되지 않는다. 바로 단방향으로 데이터 바인딩이 적용된 것이다. 하지만 Element에서 변경한 값이 모델 객체에 반영되기를 원하는 경우도 있다. 이러한 경우를 위해 양방향 데이터 바인딩이 필요하다. 이때 사용할 수 있는 디렉티브가 v-model 이다. 

 

 

위처럼 텍스트 박스에 이름을 입력해보면 바인딩된 <h2>태그와 모델 객체의 속성이 변경된 것을 알 수 있다.

v-model 디렉티브는 텍스트 박스뿐만 아니라 여러 가지 입력 폼 필드에서도 사용할 수 있다. 

여러 개의 아이템을 선택할 수 있는 <input type="checkbox" />나 <select multiple></select>의 경우는 모델 객체의 배열 객체와 연결된다. (단일 아이템만을 선택할 수 있는 <input type="radio" />나 <select></select>의 경우는 모델 객체의 단일 값과 연결됨.) 아래의 예시를 통해 살펴보자.

 

    <div id="simple1">
        <div>필요한 초능력을 골라주세요.</div>
        <input type="checkbox" value="1" v-model="ability">Rocket Puncher,
        <input type="checkbox" value="2" v-model="ability">Armamenter,
        <input type="checkbox" value="3" v-model="ability">Xenoglossy,
        <input type="checkbox" value="4" v-model="ability">Ed.Hacker
    </div>
    </div>
    <hr/>
    <div id="simple2">
        선택한 초능력: <span v-html="ability"></span>
    </div>

    <script type="text/javascript">
        var model = {
            ability: []
        };

        var simple1 = new Vue({
            el: "#simple1",
            data: model
        })
        var simple2 = new Vue({
            el: "#simple2",
            data: model
        })
    </script>

위의 코드를 통해 하나의 모델 객체를 2개의 Vue 객체에서 참조할 수 있다.

simple1이 바인딩하는 Vue 객체(뷰모델)는 v-model을 이용해 양방향 데이터 바인딩하여 사용자가 입력하는 값(input)을 뷰모델 객체를 통해 model 객체의 ability 배열 값을 즉시 변경한다.

 

 

한 개의 모델과 여러 개의 뷰모델

이로써 변경된 결과는 simple2라는 이름의 Vue 객체를 통해 <span>태그에 바인딩되어 나타난다. 또한 여러 개의 체크박스가 선택된 경우 ability 속성 값이 배열 값으로 설정됨을 알 수 있다. 

 

4) v-show, v-if, v-else, v-else-if 디렉티브

v-if 디렉티브는 Vue 객체의 data 속성 값에 따라 렌더링 여부를 결정할 수 있는 기능이다.

js, java, C 언어 등에서 많이 쓰이는 if 문과 동일한 개념으로 생각할 수 있다. 

 

비슷한 기능을 가진 것으로 v-show 디렉티브가 있다. v-show 와 v-if 의 차이는 실제 렌더링 여부에 있다. 

v-if : 조건 충족 못하면 렌더링 NO

v-show: 일단 HTML 요소를 렌더링한 후에 display 스타일 속성으로 화면에 보여줄지 여부를 결정함.

 

예제를 작성하기 전에 images 디렉터리를 만들고 error.png 파일을 저장하자.

 

    <div id="account">
        예금액 : <input type="text" v-model="amount" />
        <img v-if="amount < 0" src="images/error.png" 
        title="마이너스는 허용하지 않습니다" 
        style="width: 15px; height: 15px; vertical-align: middle" />
    </div>

    <script type="text/javascript">
        var simple1 = new Vue({
            el: "#account",
            data: {
                amount: 0,
            },
        });
    </script>

 v-if 는 조건에 부합되지 않으면 렌더링을 하지 않는다.

마이너스 값이면 error.png 가 표시됨

따라서 자주 화면이 변경되는 부분에 대해서는 v-if 디렉티브보다는 v-show 디렉티브를 사용하는 것이 바람직하다. v-show 는 조건을 만족하지 않을 때 display 스타일 속성을 none으로 설정해 화면에 보이지 않도록 처리한다. (실제로는 렌더링을 함.)

 

위의 코드에서 v-if 대신 v-show를 쓰고 개발자 도구의 Elements 탭에서 확인해보자. 

v-if 대신 v-show를 쓰면...

 

이제 v-if, v-else, v-else-if 를 사용해보자. 이 디렉티브들을 이용해 계좌 잔고에 따라 고객의 등급을 평가하는 예제를 만들어보자.

    <div id="account">
        잔고 : <input type="text" v-model="balance" /> <br /> 
        회원님의 등급 :
        <span v-if="balance >= 1000000">Gold</span>
        <span v-else-if="balance >= 50000">Silver</span>
        <span v-else-if="balance >= 20000">Bronze</span>
        <span v-else>Basic</span>
    </div>

    <script type="text/javascript">
        var simple1 = new Vue({
            el: "#account",
            data: {
                balance: 0,
            },
        });
    </script>

위와 같이 텍스트 박스에 계좌 잔고를 입력하면 그에 따른 고객 등급이 출력된다!

 

 

 

 

 

 

 

'vue.js' 카테고리의 다른 글

2. Vue.js 기초 (3)  (0) 2021.12.29
배열 데이터를 변경하는 경우  (0) 2021.12.29
2. Vue.js 기초 (2)  (0) 2021.12.29
1. Vue.js를 시작하며  (0) 2021.12.28