[Vue] Vue시작(3) - 기본 디렉티브

권준혁·2020년 12월 6일
0

vue

목록 보기
3/8
post-thumbnail

기본 디렉티브

선언적 렌더링을 위해서 {{}} 템플릿 표현식만 사용할 수 있는 것은 아니다.

  • v-text : 해당 태그의 text를 설정할 수 있다. innerText속성에 연결됨

  • v-html : innerHTML속성에 연결됨. (XSS공격등에 취약)

  • v-bind : 요소 객체의 속성들을 바인딩하기위해 사용.

    v-bind:valuev-bind:src 에 Vue인스턴스의 속성을 바인드하고있다.
    줄여서 :value :src로 쓸 수 있다.

v-bind, v-text, v-html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>basic directive</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" />
      <div> {{ message }} </div>
      <br />
      <img v-bind:src="imagePath" />
    </div>
    <script>
      const model = {
        message: "첫 번 째 Vue.js앱입니다.",
        imagePath: "http://sample.bmaster.kro.kr/photos/61.jpg",
      };
      const simple = new Vue({
        el: "#simple",
        data: model,
      });
    </script>
  </body>
</html>

  • v-model: model과 요소간 양방향 데이터 바인딩 해준다.

    input을 변경하면 바로 아랫줄의 div의 데이터가 변경된다.
    data가 변경됐을 때 UI를 업데이트하고, UI에서 input에 입력하면 모댈객체의 data도 변경된다.
    주의할 점은 IME관련 이슈이다

v-model은 텍스트 박스 뿐 아니라 여러가지 입력폼 필드에서도사용할 수 있다.
checkbox의 경우에는 배열 형태로 저장되고, select태그나 select태그 같은 경우는 단일값과 연결된다.

v-model에서는 몇가지 수식어를 지원한다.
v-model.lazy의 경우 입력폼에서 이벤트가 발생할 때 입력한 값을 데이터와 동기화한다.
v-model.number의 경우 number타입 값으로 자동으로 형변환해서 데이터를 변경한다.
v-model.trim은 문자열의 앞뒤 공백을 자동으로 제거한다.

checkbox에서 v-model
  <body>
    <div id="simple">
      <div>좋아하는 과일을 모두 골라주세요 :</div>
      <input type="checkbox" value="1" v-model="fruits" />사과,
      <input type="checkbox" value="2" v-model="fruits" />키위,
      <input type="checkbox" value="3" v-model="fruits" />포도,
      <input type="checkbox" value="4" v-model="fruits" />수박,
      <input type="checkbox" value="5" v-model="fruits" />참외,
    </div>
    <div id="simple2">선택한 과일들 : <span v-html="fruits"></span></div>
    <script>
      const model = {
        fruits: [],
      };
      const simple1 = new Vue({
        el: "#simple",
        data: model,
      });
      const simple2 = new Vue({
        el: "#simple2",
        data: model,
      });
    </script>
  </body>

  • v-if : 조건부 렌더링을 위한 디렉티브, 일치할 시 렌더링한다.

  • v-else-if : 조건부 렌더링을 위한 디렉티브

  • v-show : if와 유사하지만 if와 다르게 실제 렌더링이 발생하고, display속성을 통해 화면에 보여줄지 여부를 결정한다. 조건을 만족하지 않는다면 display:none이 된다.

v-if는 조건에 부합되지 않으면 렌더링을 하지 않는다. 그렇기 때문에 자주화면이 변경되는 컴포넌트라면 v-show를 이용하는 것이 좋다.

input값이 변경될 때마다 조건부 렌더링
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>basic directive</title>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
  </head>
  <body>
    <div id="account">
      잔고 : <input type="text" v-model="balance" />
      <br />
      <span v-if="balance >= 100000"> Gold </span>
      <span v-else-if="balance >= 50000"> Silver </span>
      <span v-else-if="balance >= 10000"> Bronze </span>
    </div>
    <script>
      const simple1 = new Vue({
        el: "#account",
        data: {
          balance: 0,
        },
      });
    </script>
  </body>
</html>

  • v-for : 반복 렌더링 디렉티브

리액트의 map과 동작은 다르지만 비슷하게 사용된다.

<div v-for="item in list">
  <span> {{item.name}} </span>
  <span> {{item.tel}} </span>
  <span> {{item.address}} </span>
</div>
객체를 이용하는 v-for디렉티브
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>basic directive</title>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
  </head>
  <body>
    <div id="example">
      <select id="regions">
        <option disabled="disabled" selected> 지역을 선택하세요 </option>
        <option v-for="(val, key) in regions" v-bind:value="key">{{val}}</option>
      </select>
    </div>
    <script>
      const simple1 = new Vue({
        el: "#example",
        data: {
          regions: {
            "A": "Asia",
            "B": "America",
            "C": "Europe",
            "D": "Africa",
            "E": "Oceania"
          }
        },
      });
    </script>
  </body>
</html>

배열 데이터인 경우
<tr v-for="(item, index) in list">

객체 데이터인 경우
<option v-for"(val, key, index) in list>


  • v-for와 v-if 함께 사용

v-for디렉티브와 v-if는 함께 사용될 수 있다. 유의할 점은 v-for가 먼저 수행되고 v-if가 적용된다는 것.

<tr v-for="(item, index) in list" v-if="item.address.includes("서울")">

리스트 요소의 address가 "서울"을 포함한 데이터만 출력된다.


  • v-pre : v-pre디렉티브는 컴파일되지 않는다.

  • v-once : 한 번만 렌더링한다. 데이터가 변경되더라도 렌더링을 수행하지 않는다.

컴파일되지 않는 v-pre
  <body>
    <div id="example">
      <span v-pre>{{message}}</span>
    </div>
    <script>
      const simple1 = new Vue({
        el: "#example",
        data: {
          message: "hello world",
        },
      });
    </script>
  </body>


  • v-cloak

때때로 많은 데이터를 출력할 때 콧수염 표현식이 화면에 일시적으로 나타나는 경우가 있다. Vue인스턴스가 el옵션의 템플릿을 컴파일 할 때 발생하는 시간때문에 일어나는 현상이다.

v-cloak을 사용하면 화면 초기에 컴파일 되지 않은 템플릿은 나타나지 않도록 할 수 있다.


계산형 속성

computed라는 Vue인스턴스의 속성이다. React에서 props를 받아서 어떤 연산을 수행하는 경우에 해당한다.

  <body>
    <div id="example">
      <input type="text" v-model="num" /> <br />
      1부터 입력된 수 까지의 합 : <span> {{sum}} </span>
    </div>
    <script>
      const a = new Vue({
        el: "#example",
        data: { num: 0 },
        computed: {
          sum() {
            const n = Number(this.num);
            if (Number.isNaN(n) || n < 1) return 0;
            return ((1 + n) * n) / 2;
          },
        },
      });
    </script>
  </body>

주의할 점은 this를 사용할 때 기본적으로 Vue인스턴스 자신을 참조하지만, 함수 내부에서 콜백 함수를 실행하거나 했을 때는 this가 다른 값으로 연결될 수 있으므로 주의해야 한다.

한 가지 더 주의할 점은 HTML요소 내부에서 모두 문자열로 다루어 지기 때문에 명시적으로 형변환을 해줄 필요가 있다.

[O] filter함수 내에서 화살표 함수를 사용했기 때문에 정상적으로 동작한다.

화살표 함수가 this바인딩을 생성하지 않으므로 화살표 함수 내부에서도 Vue객체로접근이 가능한 것

computed: {
  filtered: function () {
    return this.countries.filter((item, index) => {
      const cname = this.countryname.trim();
      if (item.name.indexOf(cname) > -1) {
        return true;
      }
    });
  },
},
[X] 일반 함수로 선언하면 this바인딩을 생성하기 때문에 this가 Vue객체를 가리키지 않는다.
        computed: {
          filtered: function () {
            return this.countries.filter(function (item, index) {
              const cname = this.countryname.trim();
              if (item.name.indexOf(cname) > -1) {
                return true;
              }
            });
          },
        },

에러가 발생한다.

[O] 배열메서드 바깥에서 this에 접근했기 때문에 일반함수로 선언하더라도 접근이 가능하다.
        computed: {
          filtered: function () {
            const cname = this.countryname.trim();
            return this.countries.filter(function (item, index) {
              if (item.name.indexOf(cname) > -1) {
                return true;
              }
            });
          },
        },

배열메서드를 어떻게 사용하느냐에 따라서 Vue객체에 접근 가능할 수도 불가능 할 수도 있다. 가능하면 배열메서드 외부에서 접근하도록 하자


profile
웹 프론트엔드, RN앱 개발자입니다.

0개의 댓글