ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [가이드] 리스트 렌더링 - 필수요소 | Vue
    Front-end/Vue.js 2020. 8. 13. 13:16
    반응형

    v-for로 배열을 요소에 매핑

    v-for 지시문을 사용하여 배열을 기반으로 목록을 렌더링할 수 있습니다. v-for 지시문을 사용하려면 item in items 형식의 특수 구문이 필요합니다. 여기서 items은 소스 데이터 배열이고 item은 반복될 배열 요소의 별칭입니다.

    <ul id="ex1">
      <li v-for="item in items" :key="item.message">
        {{ item.message }}
      </li>
    </ul>
    
    <script>
      var example1 = new Vue({
        el: '#ex1',
        data: {
          items: [
            { message: 'Foo' },
            { message: 'Bar' }
          ]
        }
      })	
    </script>

    v-for 블록 내부에서는 부모 범위 속성에 대한 전체 액세스 권한이 있습니다. v-for는 현재 항목의 인덱스에 대해 선택적 두 번째 인수를 지원합니다.

    <ul id="ex2">
      <li v-for="(item, index) in items">
        {{ parentMessage }} - {{ index }} - {{ item.message }}
      </li>
    </ul>
    
    <script>
      var example2 = new Vue({
        el: '#ex2',
        data: {
          parentMessage: 'Parent',
          items: [
            { message: 'Foo' },
            { message: 'Bar' }
          ]
        }
      })
    </script>

    in 대신에 of 구분자를 사용하여 iterators에 대한 JavaScript 구문에 더 가깝습니다.

    <div v-for="item of items"></div>

     

     

    객체와 v-for

    v-for를 사용하여 객체의 속성을 반복할 수도 있습니다.

    <ul id="ex3">
      <li v-for="value in object">
        {{ value }}
      </li>
    </ul>
    
    <script>
      var ex3 = new Vue({
        el: "#ex3",
        data: {
          object: {
            title: "Hello Vue",
            author: "AGAL",
            data: "2020-08-13"
          }
        }
      })
    </script>

    속성 이름(예: 키)에 대한 두 번째 인수를 제공할 수도 있습니다.

    <li v-for="(value, name) in object">
      {{ name }} : {{ value }}
    </li>

    인덱스에 대한 또 다른 예 : 

    <li v-for="(value, name, index) in object">
      {{index}}. {{ name }} : {{ value }}
    </li>
    객체를 반복할 때 순서는 Object.keys()의 열거 순서에 기반합니다. 이 순서는 JavaScript 엔진 구현 간에 일관성이 보장되지 않습니다.

     

     

    상태 유지

    Vue는 v-for로 렌더링된 요소 목록을 업데이트할 때 기본적으로 "in-place patch" 전략을 사용합니다. 데이터 항목의 순서가 변경된 경우 항목 순서와 일치하도록 DOM 요소를 이동하는 대신 Vue는 각 요소를 제자리에 패치하고 특정 인덱스에서 렌더링해야 하는 항목을 반영하는지 확인합니다. 이는 Vue 1.x에서 track-by="$index"의 동작과 유사합니다.

     

    이 기본 모드는 효율적이지만 목록 렌더링 출력이 하위 구성 요소 상태 또는 임시 DOM 상태(예: 양식 입력 값)에 의존하지 않는 경우에만 적합합니다.

     

    Vue가 각 노드의 ID를 추적하여 기존 요소를 재사용하고 재정렬 할 수 있도록 힌트를 제공하려면, 각 항목에 대해 고유한 key 속성을 제공해야합니다 .

    <div v-for="item in items" v-bind:key="item.id">
      <!-- content -->
    </div>

    반복된 DOM 콘텐츠가 단순하지 않거나 성능 향상을 위해 의도적으로 기본 동작에 의존하는 경우가 아니라면 가능하면 v-for에 key 속성을 제공하는 것이 좋습니다.

    Vue가 노드를 식별하는 일반적인 메커니즘이기 때문에 key에는 v-for에 특별히 연결되지 않은 다른 용도가 있습니다. 이 용도는 가이드 뒷부분에서 확인할 수 있습니다.

    객체 및 배열과 같은 기본이 아닌 값을 v-for키로 사용하지 마십시오 . 대신 문자열 또는 숫자 값을 사용하십시오.

     

    key 속성 의 자세한 사용법은 key API 문서 를 참조하십시오.

     

     

    배열 변경 감지

    Mutation 메서드

    Vue는 관찰된 배열의 Mutation 메서드를 래핑하여 뷰 업데이트도 트리거합니다. 래핑된 메서드는 다음과 같습니다.

     

    • push()

    • pop()

    • shift()

    • unshift()

    • splice()

    • sort()

    • reverse()

     

    콘솔을 열고 Mutation 메서드를 호출 하여 이전 예제의 items 배열로 재생할 수 있습니다 . 예 :

    example1.items.push({ message: 'Baz' })

     

    배열 교체

    이름에서 알 수 있듯이 Mutation 메서드는 호출된 원래 배열을 변경합니다. 이에 비해 원래 배열을 변경하지 않고 항상 새 배열을 반환하는 변경되지 않는 메서드 (예: filter(), concat()및 slice())도 있습니다. 비 Mutation 메서드로 작업 할 때 이전 배열을 새 배열로 바꿀 수 있습니다.

    example1.items = example1.items.filter(function (item) {
      return item.message.match(/Foo/)
    })

    이렇게 하면 Vue가 기존 DOM을 버리고 전체 목록을 다시 렌더링할 것이라고 생각할 수 있습니다. 운 좋게도 그렇지 않습니다. Vue는 일부 smart heuristics를 구현하여 DOM 요소 재사용을 극대화하므로 배열을 중복 객체가 포함된 다른 배열로 교체하는 것이 매우 효율적인 작업입니다.

     

    주의 사항

    JavaScript의 제한으로 인해 Vue가 배열 및 객체로 감지 할 수 없는 변경 유형이 있습니다. 이러한 내용은 반응성 섹션에서 설명합니다.

     

     

    필터링 / 정렬된 결과 표시

    때때로 우리는 원래 데이터를 실제로 변경하거나 재설정하지 않고 배열의 필터링되거나 정렬된 배열을 표시하려고합니다. 이 경우 필터링되거나 정렬된 배열을 반환하는 computed 속성을 만들 수 있습니다.

    <ul id="ex4">
      <li v-for="n in evenNumbers">
        {{ n }}
      </li>
    </ul>
    <script>
      var ex4 = new Vue({
        el: "#ex4",
        data: {
          numbers: [1, 2, 3, 4, 5]
        },
        computed: {
          evenNumbers: function(){
            return this.numbers.filter(function(number){
              return number % 2 === 0
            })
          }
        }
    
      })
    </script>

    computed 속성이 실행 가능하지 않은 상황 (예 : 중첩 v-for 루프 내부)에서는 메서드를 사용할 수 있습니다.

    <div id="ex5">
      <ul v-for="set in sets">
        <li v-for="n in even(set)">{{ n }}</li>
      </ul>
    </div>
    <script>
      var ex5 = new Vue({
        el: "#ex5",
        data: {
          sets: [
            [1, 2, 3, 4, 5],
            [6, 7, 8, 9, 10]
          ]
        },
        methods: {
          even: function (numbers) {
            return numbers.filter(function(number){
              return number % 2 === 0
            })
          }
        }
      })
    </script>

     

     

    Range 와 v-for

    v-for 정수를 취할 수도 있습니다. 이 경우 템플릿을 여러 번 반복합니다.

    <div>
      <span v-for="n in 10">{{ n }} </span>
    </div>
    <!-- 결과: 1 2 3 4 5 6 7 8 9 10 -->

     

     

    <template>에서 v-for

    v-if <template>과 마찬가지로 <template>태그에서 v-for를 사용하여 여러 요소의 블록을 렌더링 할 수도 있습니다. 예를 들면 :

    <ul>
      <template v-for="item in items">
        <li>{{ item.msg }}</li>
        <li class="divider" role="presentation"></li>
      </template>
    </ul>

     

     

    v-for 와 v-if 함께 사용

    v-if와 v-for를 함께 사용하는 것은 권장되지 않습니다. 자세한 내용은 스타일 가이드를 참조하세요.

    동일한 노드에 존재하는 v-for는 v-if 보다 높은 우선 순위를 가집니다. 즉, 루프의 각 반복에서 v-if가 별도로 실행됩니다. 다음과 같이 일부 항목에 대해서만 노드를 렌더링하려는 경우에 유용합니다 .

    <li v-for="todo in todos" v-if="!todo.isComplete">
      {{ todo }}
    </li>

     

    위는 완료되지 않은 todo만 렌더링합니다.

     

    대신 루프 실행을 조건부로 건너뛰는 경우 v-if를 wrapper 요소 (또는 <template>)에 배치 할 수 있습니다 . 예를 들면 :

    <ul v-if="todos.length">
      <li v-for="todo in todos">
        {{ todo }}
      </li>
    </ul>
    <p v-else>No todos left!</p>

     

     

    컴포넌트와 v-for

    이 섹션에서는 컴포넌트에 대한 지식이 있다고 가정합니다 . 건너 뛰고 나중에 다시 오셔도됩니다.

     

    일반 요소와 같이 사용자 지정 컴포넌트에서 v-for를 직접 사용할 수 있습니다.

    <my-component v-for="item in items" :key="item.id"></my-component>
    2.2.0+에서는 컴포넌트와 함께 v-for를 사용할 때 key가 필요합니다.

     

    그러나 구성 요소에는 자체 범위가 분리되어 있으므로 구성 요소에 데이터가 자동으로 전달되지 않습니다. 반복된 데이터를 컴포넌트로 전달하려면 props도 사용해야합니다.

    <my-component
      v-for="(item, index) in items"
      v-bind:item="item"
      v-bind:index="index"
      v-bind:key="item.id"
    ></my-component>

    구성 요소에 item을 자동으로 주입하지 않는 이유는 컴포넌트가 v-for의 작동 방식과 밀접하게 연결되기 때문입니다. 데이터의 출처를 명시하면 다른 상황에서 컴포넌트가 재사용될 수 있습니다.

     

    다음은 간단한 Todo List의 완전한 예입니다.

    <div id="todo-list-example">
      <form v-on:submit.prevent="addNewTodo">
        <label for="new-todo">Add a todo</label>
        <input
          v-model="newTodoText"
          id="new-todo"
          placeholder="E.g. Feed the cat"
        >
        <button>Add</button>
      </form>
      <ul>
        <li
          is="todo-item"
          v-for="(todo, index) in todos"
          v-bind:key="todo.id"
          v-bind:title="todo.title"
          v-on:remove="todos.splice(index, 1)"
        ></li>
      </ul>
    </div>

     

    is="to-do-item" 속성에 유의하십시오. 이는 DOM 템플릿에서 필요한데, 이는 <li> 요소만 <ul> 내에서 유효하기 때문입니다. 이것은 <todo-item>과 같은 작업을 하지만 잠재적인 브라우저 구문 분석 오류를 중심으로 작동합니다. 자세한 내용은 DOM 템플릿 구문 분석 주의사항을 참조하시기 바랍니다.

     

    Vue.component('todo-item', {
      template: '\
        <li>\
          {{ title }}\
          <button v-on:click="$emit(\'remove\')">Remove</button>\
        </li>\
      ',
      props: ['title']
    })
    
    new Vue({
      el: '#todo-list-example',
      data: {
        newTodoText: '',
        todos: [
          {
            id: 1,
            title: 'Do the dishes',
          },
          {
            id: 2,
            title: 'Take out the trash',
          },
          {
            id: 3,
            title: 'Mow the lawn'
          }
        ],
        nextTodoId: 4
      },
      methods: {
        addNewTodo: function () {
          this.todos.push({
            id: this.nextTodoId++,
            title: this.newTodoText
          })
          this.newTodoText = ''
        }
      }
    })

     

    $emit() 

    이벤트 발생은 컴포넌트의 통신 방법 중 하위 컴포넌트에서 상위 컴포넌트로 통신하는 방식입니다.

    <!-- 상위 컴포넌트의 템플릿 -->
    <div id="app">
      <child-component v-on:이벤트 명="상위 컴포넌트의 실행할 메서드 명 또는 연산"></child-component>
    </div>
    
    <script>
      // 하위 컴포넌트의 내용
      this.$emit('이벤트 명');
    </script>

     

     

     

    반응형

    댓글

Luster Sun