컴포넌트


컴포넌트란 무엇인가

기본 HTML 엘리먼트를 확장해 재사용 가능 코드를 캡슐화 하는데 사용
Vue 컴파일러에 의해 동작이 추가된 사용자 지정 엘리먼트
경우에 따라 특별한 is 속성으로 확장 된 원시 HTML 엘리먼트로 나타날 수 있음

컴포넌트 사용하기

등록

//인스턴스 생성
new Vue({
    el: '#some-element',
})

//전역 컴포넌트 등록
Vue.component('my-component', {
    //옵션
})  

//HTML
<div id="example">
    <my-component></my-component>
</div>

//등록
Vue.component('my-component', {
    template: '<div>사용자 정의 컴포넌트 입니다!</div>'
})

//인스턴스 생성
new Vue({
    el: '#example'
})

//렌더링 후 결과
<div id="example">
    <div>사용자 정의 컴포넌트 입니다!</div>
</div>

지역 등록

컴포넌트를 components 인스턴스 옵션으로 등록함으로써 범위에서만 사용할 수 있는 컴포넌트 생성 가능

var Child = {
    template: '<div>사용자 정의 컴포넌트 입니다!</div>
}

new Vue({
    components: {
        'my-component': Child
    }
})

DOM 템플릿 구문 분석 경고

DOM을 템플릿으로 사용할 때 ( el 옵션을 사용하여 기존 콘텐츠가 있는 엘리먼트를 마운트 할 때), Vue는 템플릿 콘텐츠만 가져올 수 있기 때문에 HTML이 작동하는 방식에 고유한 몇 가지 제한 사항이 적용된다. 이는 브라우저가 구문 분석과 정규화한 후에 작동합니다. 가장 중요한 것은 <ul>, <ol>, <table><select>와 같은 일부 엘리먼트는 그 안에 어떤 엘리먼트가 나타날 수 있는지에 대한 제한을 가지고 있으며,<option>과 같이 특정 다른 엘리먼트 안에만 나타날 수 있습니다.
이러한 제한이 있는 엘리먼트가 있는 사용자 지정 컴포넌트를 사용하면 다음과 같은 문제가 발생할 수 있음

<table>
    <my-row>...</my-row>
</table>

이렇게 작성하면 <my-row>는 렌더링 시 에러를 발생함 이때 is를 사용

<table>
    <tr is="my-row"></tr>
</table>

이때 다음 세가지 중 하나에 포함되면 문자열 템플릿을 사용하는 경우에는 이러한 제한 사항이 적용되지 않음

  • <script type="text/x-template">
  • JavaScript 인라인 템플릿 문자열
  • .vue 컴포넌트

따라서 가능한 경우 항상 문자열 템플릿을 사용하는 것이 좋음

data는 반드시 함수

//HTML
<div id="example-2">
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
</div>

//JavaScript
var data = { counter: 0 }

Vue.component('simple-counter', {
  template: '<button v-on:click="counter += 1">{{ counter }}</button>',
  // 데이터는 기술적으로 함수이므로 Vue는 따지지 않지만
  // 각 컴포넌트 인스턴스에 대해 같은 객체 참조를 반환합니다.
  data: function () {
    return {
        counter: 0
       }
  }
})

new Vue({
  el: '#example-2'
})

컴포넌트 작성

컴포넌트는 부모-자식 관계에서 가장 일반적으로 함께 사용하기 위한 것이다.
Vue.js에서 부모-자식 컴포넌트 관계는 props는 아래로, events는 위로 라고 할 수 있음
=> 부모는 props로 자식에게 데이터를 넘기고, 자식은 events로 부모에게 메시지를 보냄

Props

Props로 데이터 전달하기

모든 컴포넌트 인스턴스는 범위가 있음.
즉, 하위 컴포넌트의 템플릿에서 상위 데이터를 직접 참조 할 수 없고,
이 때 props 옵션을 사용해 하위 컴포넌트로 전달 가능함

Vue.component('child', {
    // props 정의
    props: ['message'],
    templage: '<span>{{ message }}</span>'
})
<child message="안녕"></child>

위의 코드에서 messageprops로 선언을 하면 “안녕” 이라는 결과가 출력된다.

camelCase vs kebab-case

Vue.component('child', {
  // JavaScript는 camelCase
  props: ['myMessage'],
  template: '<span>{{ myMessage }}</span>'
})
<!-- HTML는 kebab-case -->
<child my-message="안녕하세요!"></child>

주석에 쓴것과 같이 JS는 camelCase, HTML은 kebab-case로 작성

동적 Props

v-bind를 사용하여 부모의 데이터에 props를 동적으로 바인딩 할 수 있음
데이터가 상위에서 업데이트 될 때마다 하위 데이터로도 전달된다.

<div>
    <input v-model="parentMsg">
    <br>
    <child v-bind:my-message="parentMsg"></child>
</div>

위와같이 코드를 작성하면 입력창에 입력하면 아랫줄에 같은 내용이 실시간으로 바인딩된다.

리터럴 vs 동작

리터럴 구문으로 문자열을 전달할 때와 숫자를 전달할 때

//문자열 "1" 전달
<comp some-prop="1"></comp>
//숫자 1 전달
<comp v-bind:some-prop="1"></comp>

단방향 데이터 흐름

모든 props는 하위 속성과 상위 속성 사이의 단방향 바인딩 형성
즉, 상위 속성이 업데이트되면 하위로 흐르지만, 반대는 안됨

우선 prop자체의 속성을 보면

  1. prop은 초기값을 전달하는데만 사용되며 하위 컴포넌트는 이후에 이를 로컬 데이터 속성으로 사용하기만 함
  2. prop은 변경되어야 할 원시 값으로 전달된다
    하위 컴포넌트 내부에서 prop을 변형하려고 시도하면 안되고, 변경하고 싶을 때 사용할 두가지 방법이 있음

  3. prop의 초기값을 초기값으로 사용하는 로컬 데이터 속성을 정의

    props: ['initialCounter'],
    data: function() {
     return { counter: this.initialCounter}
    }
    
  4. prop 값으로 부터 계산된 속성을 정의함

    props: ['size'],
    conputed: {
    normalizedSize: function() {
     return this.size.trim().toLowerCase()
     }
    }
    

Prop 검증

컴포넌트가 prop에 대한 요구사항을 지정할 수 있음
요구사항이 충족되지 않으면 Vue에서 경고를 내보냄
즉, prop을 문자열 배열로 정의하는 대신 유효성 검사 요구사항이 있는 객체 사용

Vue.component('example', {
    props: {
        // 기본 타입 확인 ('null'은 어느 타입이든 가능하는 뜻)
        propA: Number,
        // 여러개의 타입
        propB: [String, Number],
        // 문자열이며 꼭 필요할 때
        propC: {
            type: String,
            required: true
        },
        // 숫자이며 기본값 가짐
        propD: {
            type: Number,
            default: 100
        },
        // 객체/배열의 기본값은 팩토리 함수에서 반환
        propE: {
            type: Object,
            default: function () {
                return { message: 'hello' }
            }
        },
        // 사용자 정의 유효성 검사
        propF: {
            validator: function (value) {
                return value > 10
            }
        }
    }
})

type 종류

String
Number
Boolean
Function
Object
Array
또한 커스텀 생성자 함수가 될 수 있고, assertion(정확히 무슨의민지 모르겠음)은 instanceof 체크로 만들어 질 것
prop 유효성 검사가 실패하면 Vue는 콘솔 경고 생성

사용자 정의 이벤트

prop이 부모가 자식에게 데이터를 전달하는 것이라면, 사용자 정의 이벤트로 자식은 부모에게 문제를 알림

v-on을 이용한 사용자 지정 이벤트

모든 Vue 인스턴스는 다음과 같은 이벤트 인터페이스를 구현함

  • $on(eventName) - 이벤트 감지(자식 컴포넌트에서 보낸 이벤트 감지 x)
  • $emit(eventName) - 이벤트 트리거
    addEventListener, dispatchEvent와 별개

또한 부모 컴포넌트는 자식 컴포넌트가 사용되는 템플릿에서 직접 v-on을 사용하여 이벤트를 들을 수 있음

//HTML
<div id="counter-event-example">
    <p>{{ total }}</p>
    <button-counter v-on:increment="incrementTotal"></button-counter>
    <button-counter v-on:increment="incrementTotal"></button-counter>
</div>

//JavaScript
Vue.component('button-counter', {
    template: '<button v-on:click="increment">{{ counter }}</button>',
    data: function () {
        return {
            counter: 0
        }
    },
    methods: {
        increment: function () {
            this.counter += 1
            this.$emit('increment')
        }
    }
})

new Vue({
    el: '#counter-event-example',
    data: {
        total: 0
    },
    methods: {
        incrementTotal: function () {
            this.total += 1
        }
    }
})

이때 하위 컴포넌트가 외부에서 발생하는 것과 완전히 분리된다는 점을 유의해야 함

컴포넌트에 네이티브 이벤트 바인딩

컴포넌트의 루트 엘리먼트에서 네이티브 이벤트를 수신하려 할 때
v-on.native 수식자를 사용

<my-component v-on:click.native="doTheThing"></my-component>

사용자 정의 이벤트를 사용하여 폼 입력 컴포넌트 만들기

사용자 정의 이벤트는 v-model에서 작동하는 사용자 정의 입력을 만드는데도 사용 가능

<input v-model="something">
//위,아래 코드는 같음
<input
    v-bind:value="something"
    v-on:input="something = $event.target.value">

컴포넌트와 같이 사용하면 다음과 같이 된다

<custom-input
    :value="something"
    @input="value => { something = value }">
</custom-input>
  • value prop을 가진다
  • 새로운 값으로 input 이벤트를 내보냄

컴포넌트의 v-model 사용자 정의

기본적으로 컴포넌트의 v-modelvalue를 보조변수로 사용하고 input을 이벤트로 사용하지만
체크박스와 라디오 버튼과 같은 일부 입력 타입은 다른 목적으로 value 속성을 사용할 수 있음 => model 옵션 사용

//HTML
<my-checkbox v-model="foo" value="some value"></my-checkbox>

//JavaScript
Vue.component('my-checkbox', {
    model: {
        prop: 'checked',
        event: 'change'
    },
    props: {
        //다른 목적을 위해 `value` prop을 사용
        value: String
    },
    // ...
})

아래 코드와 같다

<my-checkbox
    :checked="foo"
    @change="val => { foo = val }"
    value="some value">
</my-checkbox>


'개발 > Vue.js' 카테고리의 다른 글

Vue.js 정리  (0) 2017.04.25
Vue 기본자료 포스팅 완료!  (0) 2017.04.06
10. 컴포넌트  (0) 2017.04.06
9. 폼 입력 바인딩  (0) 2017.03.31
8. 이벤트 핸들링(v-on)  (0) 2017.03.31
7. 리스트 렌더링(v-for, v-if)  (0) 2017.03.31

Flex Panel Gallery


flex-box를 이용한 레이아웃 및 효과를 공부하는 시간

기본 코드

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex Panels 💪</title>
  <link href='https://fonts.googleapis.com/css?family=Amatic+SC' rel='stylesheet' type='text/css'>
</head>
<body>
  <style>
    html {
      box-sizing: border-box;
      background:#ffc600;
      font-family:'helvetica neue';
      font-size: 20px;
      font-weight: 200;
    }
    body {
      margin: 0;
    }
    *, *:before, *:after {
      box-sizing: inherit;
    }

    .panels {
      min-height:100vh;
      overflow: hidden;
    }

    .panel {
      background:#6B0F9C;
      box-shadow:inset 0 0 0 5px rgba(255,255,255,0.1);
      color:white;
      text-align: center;
      align-items:center;
      /* Safari transitionend event.propertyName === flex */
      /* Chrome + FF transitionend event.propertyName === flex-grow */
      transition:
        font-size 0.7s cubic-bezier(0.61,-0.19, 0.7,-0.11),
        flex 0.7s cubic-bezier(0.61,-0.19, 0.7,-0.11),
        background 0.2s;
      font-size: 20px;
      background-size:cover;
      background-position:center;
    }


    .panel1 { background-image:url(https://source.unsplash.com/gYl-UtwNg_I/1500x1500); }
    .panel2 { background-image:url(https://source.unsplash.com/1CD3fd8kHnE/1500x1500); }
    .panel3 { background-image:url(https://images.unsplash.com/photo-1465188162913-8fb5709d6d57?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&w=1500&h=1500&fit=crop&s=967e8a713a4e395260793fc8c802901d); }
    .panel4 { background-image:url(https://source.unsplash.com/ITjiVXcwVng/1500x1500); }
    .panel5 { background-image:url(https://source.unsplash.com/3MNzGlQM7qs/1500x1500); }

    .panel > * {
      margin:0;
      width: 100%;
      transition:transform 0.5s;
    }

    .panel p {
      text-transform: uppercase;
      font-family: 'Amatic SC', cursive;
      text-shadow:0 0 4px rgba(0, 0, 0, 0.72), 0 0 14px rgba(0, 0, 0, 0.45);
      font-size: 2em;
    }
    .panel p:nth-child(2) {
      font-size: 4em;
    }

    .panel.open {
      font-size:40px;
    }

  </style>


  <div class="panels">
    <div class="panel panel1">
      <p>Hey</p>
      <p>Let's</p>
      <p>Dance</p>
    </div>
    <div class="panel panel2">
      <p>Give</p>
      <p>Take</p>
      <p>Receive</p>
    </div>
    <div class="panel panel3">
      <p>Experience</p>
      <p>It</p>
      <p>Today</p>
    </div>
    <div class="panel panel4">
      <p>Give</p>
      <p>All</p>
      <p>You can</p>
    </div>
    <div class="panel panel5">
      <p>Life</p>
      <p>In</p>
      <p>Motion</p>
    </div>
  </div>

  <script>

  </script>
</body>
</html>

목표

CSS 속성인 display: flex를 사용해 레이아웃을 구성해보고 자바스크립트 효과를 익힘

과정

  1. display: flex 적용
  2. 각 패널의 크기, 내용의 위치 조정
  3. 패널 안의 구성요소 정렬
  4. 패널의 효과 적용
  5. 자바스크립트 효과 적용

코드 분석

  1. display: flex 적용

     .panels {
         display: flex;
     } 

     

    위 코드를 적용 시키면 각 패널의 레이아웃이 다음과 같이 바뀐다

  2. 각 패널의 크기, 내용의 위치 조정

    .panel {
     display: flex;
     flex: 1;
     justify-content: center;
     align-items: center;
     flex-direction: column;
    }
    

    display속성을 flex로 설정을 해주고,
    flex: 1을 적용하면서 브라우저 크기에 맞춰 모든 패널의 크기가 동일하게 설정이 됨
    justify-content: center로 수평정렬,
    align-items: center로 수직정렬
    flex-direction: column으로 정렬 축을 세로로 바꿔줌 기본값은 row
    ```

  3. 패널 안의 구성요소 정렬

     .panel > * {
         flex: 1 0 auto;
         display:flex;
         justify-content: center;
         align-items: center;
     }
    

    패널 안의 요소들을 2번과같은 설명으로 정렬하면 각 컨텐츠의 위치가 고르게 잡힌다.

  4. 패널의 효과 적용

     .panel > *:first-child { transform: translateY(-100%);}
     .panel.open-active > *:first-child { transform: translateY(0);}
     .panel > *:last-child { transform: translateY(100%);}
     .panel.open-active > *:last-child { transform: translateY(0);}
    

    패널의 첫번째 요소의 수직 위치를 위로 옮겨 숨기고, 마지막 요소를 아래로 옮겨 숨기게 설정한 뒤,
    open-active속성이 생기면 제자리로 돌아오도록 코드를 작성

  5. 자바스크립트 효과 적용

     <sctipt>
         const panels = document.querySelectorAll('.panel');
    
         function toggleOpen() {
             this.classList.toggle('open');
         }
    
         function toggleActive(e) {
             if(e.propertyName.includes('flex')) {
                 this.classList.toggle('open-active');
             }
         }
    
         panels.forEach(panel => panel.addEventListener('click', toggleOpen));
         panels.forEach(panel => panel.addEventListener('transitionend', toggleActive));
    

    panels에 모든 panel 클래스 인자를 담고,
    이벤트 발생 시open 클래스가 토글되는 toggleOpen() 함수와,
    flex라는 속성이 있으면 open-active 클래스가 토글되는 toggleActive() 함수를 생성 후
    각 panel에 대해서 click(클릭)할때 toggleOpen, transitionend(변화가 끝날때) toggleAcrive()함수를 실행하도록 코드를 작성해준다.

찾아본 내용, 알게된 내용들

flex: 1 - 위의 경우에서는 panel이 모두 1씩 flex값을 가지고 있으므로 너비가 동일하게 표현되는것,
클릭했을때 flex:5가 적용되면서 차지하는 비율이 5로 증가
:first-child - 요소 선택자의 종류로 첫 번째 자식 요소에 대해 속성을 적용하는 것
transform: translateY() - Y축의 값을 현재 위치(0을기준)에서 얼만큼 움직이겠다는 뜻


끝!


'개발 > JavaScript30' 카테고리의 다른 글

7. Array Cardio Day 2  (0) 2017.04.07
6. Type Ahead  (0) 2017.04.06
5. Flex Panel Gallery  (0) 2017.04.05
4. Array Cardio Day 1  (0) 2017.04.04
3. CSS Variables  (0) 2017.04.03
2. CSS + JS Clock  (0) 2017.04.03

Array Cardio Day 1


제목처럼 자바스크립트 배열과 배열제어에 대해서 공부하는 시간


기본코드

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Array Cardio 💪</title>
</head>
<body>
  <p><em>Psst: have a look at the JavaScript Console</em> 💁</p>
  <script>
    // Get your shorts on - this is an array workout!
    // ## Array Cardio Day 1

    // Some data we can work with

    const inventors = [
      { first: 'Albert', last: 'Einstein', year: 1879, passed: 1955 },
      { first: 'Isaac', last: 'Newton', year: 1643, passed: 1727 },
      { first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 },
      { first: 'Marie', last: 'Curie', year: 1867, passed: 1934 },
      { first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 },
      { first: 'Nicolaus', last: 'Copernicus', year: 1473, passed: 1543 },
      { first: 'Max', last: 'Planck', year: 1858, passed: 1947 },
      { first: 'Katherine', last: 'Blodgett', year: 1898, passed: 1979 },
      { first: 'Ada', last: 'Lovelace', year: 1815, passed: 1852 },
      { first: 'Sarah E.', last: 'Goode', year: 1855, passed: 1905 },
      { first: 'Lise', last: 'Meitner', year: 1878, passed: 1968 },
      { first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 }
    ];

    const people = ['Beck, Glenn', 'Becker, Carl', 'Beckett, Samuel', 'Beddoes, Mick', 'Beecher, Henry', 'Beethoven, Ludwig', 'Begin, Menachem', 'Belloc, Hilaire', 'Bellow, Saul', 'Benchley, Robert', 'Benenson, Peter', 'Ben-Gurion, David', 'Benjamin, Walter', 'Benn, Tony', 'Bennington, Chester', 'Benson, Leana', 'Bent, Silas', 'Bentsen, Lloyd', 'Berger, Ric', 'Bergman, Ingmar', 'Berio, Luciano', 'Berle, Milton', 'Berlin, Irving', 'Berne, Eric', 'Bernhard, Sandra', 'Berra, Yogi', 'Berry, Halle', 'Berry, Wendell', 'Bethea, Erin', 'Bevan, Aneurin', 'Bevel, Ken', 'Biden, Joseph', 'Bierce, Ambrose', 'Biko, Steve', 'Billings, Josh', 'Biondo, Frank', 'Birrell, Augustine', 'Black, Elk', 'Blair, Robert', 'Blair, Tony', 'Blake, William'];

    // Array.prototype.filter()
    // 1. Filter the list of inventors for those who were born in the 1500's

    // Array.prototype.map()
    // 2. Give us an array of the inventors' first and last names

    // Array.prototype.sort()
    // 3. Sort the inventors by birthdate, oldest to youngest

    // Array.prototype.reduce()
    // 4. How many years did all the inventors live?

    // 5. Sort the inventors by years lived

    // 6. create a list of Boulevards in Paris that contain 'de' anywhere in the name
    // https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris


    // 7. sort Exercise
    // Sort the people alphabetically by last name

    // 8. Reduce Exercise
    // Sum up the instances of each of these
    const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck' ];

  </script>
</body>
</html>

목표

자바스크립트의 배열제어 방법을 코드로 구현해보며 익힘

과정

  1. filter()
  2. map()
  3. sort()
  4. reduce()

코드 분석

  1. filter

     // Array.prototype.filter()
     // 1. Filter the list of inventors for those who were born in the 1500's
     const fifteen = inventors.filter(inventor => (inventor.year >= 1500 && inventor.year < 1600));
    
     console.table(fifteen);
    

    filter() 메소드로 inventors 배열 중 1500년대에 태어난 사람을 정렬
    inventors 배열 내의 모든 요소 각각 값들 중 year이 1500이상이면서 1600이하인 것들을 추출하고,
    새로운 배열 fifteen안에 담아 console.table(fifteen)을 통해 콘솔로 출력

  2. map()

     // Array.prototype.map()
     // 2. Give us an array of the inventor first and last names
     const fullNames = inventors.map(inventor => `${inventor.first} ${inventor.last}`);
    
     console.log(fullNames);
    

    map() 메소드로 inventors 배열 각각 값들의 first, last만 꺼내 새로운 배열을 만듦
    inventors 배열 내의 모든 요소 각각 값들 중 firstlast를 공백으로 구분지어 연결하고,
    새로운 배열 fullNames에 담아 conloe.log(fullNames)로 콘솔에 출력

  3. sort()

     // Array.prototype.sort()
     // 3. Sort the inventors by birthdate, oldest to youngest
     // const ordered = inventors.sort(function(a, b) {
     //   if(a.year > b.year) {
     //     return 1;
     //   } else {
     //     return -1;
     //   }
     // });
    
     const ordered = inventors.sort((a, b) => a.year > b.year ? 1 : -1);
     console.table(ordered);
    

    sort() 메소드로 inventors 배열의 값들을 생일순으로 정렬(나이많은순서대로)
    주석으로 되어있는 코드를 짧게 줄인것이 아래의 코드이니 비교해보면 된다.
    Arrow function( => )에 익숙해지는것이 좋음
    inventors안의 두 값을 year 속성으로 비교 후 참이면 1, 거짓이면 -1을 반환하고,
    ordered라는 새로운 배열에 담아서 console.table(ordered)로 콘솔에 출력

  4. reduce()

     // Array.prototype.reduce()
     // 4. How many years did all the inventors live?
     const totalYears = inventors.reduce((total, inventor) => {
         return total + (inventor.passed - inventor.year);
     }, 0);
    
     console.log(totalYears);
    

    reduce() 메소드로 inventors 배열 값들의 총 수명을 구함
    total 인자에 inventors 배열의 수명을 누적으로 더해주고(뒤의 0은 초기값),
    totalYears에 담아 콘솔에 출력

찾아본 내용, 알게된 내용들

.prototype - Vue에서 공부했던 인스턴스와 같은 개념(객체지향적 개발을 할 수 있게 해주는 메소드)
filter() - 말그대로 필터, 범위를 설정해 만족하는 값을 반환
map() - 배열 내의 모든 요소 각각에 대해 callback 호출 후, 결과를 모아 새로운 배열을 반환
sort() - 정렬, 알고리즘 공부가 추가적으로 필요함/ 정렬의 종류
reduce() - 누산기 > 누적계산기


'개발 > JavaScript30' 카테고리의 다른 글

6. Type Ahead  (0) 2017.04.06
5. Flex Panel Gallery  (0) 2017.04.05
4. Array Cardio Day 1  (0) 2017.04.04
3. CSS Variables  (0) 2017.04.03
2. CSS + JS Clock  (0) 2017.04.03
1. JavaScript Drum Kit  (0) 2017.03.30

3. CSS Variables

이번 강의를 보면서 CSS에도 변수가 있다는걸 처음알았다
고수의 길은 정말 멀고도 멀다를 다시한번 느꼈음(ㅠㅠ)
각설하고 강의 내용을 분석해보자


기본코드

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Scoped CSS Variables and JS</title>
</head>
<body>
  <h2>Update CSS Variables with <span class='hl'>JS</span></h2>

  <div class="controls">
    <label for="spacing">Spacing:</label>
    <input id="spacing" type="range" name="spacing" min="10" max="200" value="10" data-sizing="px">

    <label for="blur">Blur:</label>
    <input id="blur" type="range" name="blur" min="0" max="25" value="10" data-sizing="px">

    <label for="base">Base Color</label>
    <input id="base" type="color" name="base" value="#ffc600">
  </div>

  <img src="https://source.unsplash.com/7bwQXzbF6KE/800x500">

  <style>

    /*
      misc styles, nothing to do with CSS variables
    */

    body {
      text-align: center;
    }

    body {
      background: #193549;
      color: white;
      font-family: 'helvetica neue', sans-serif;
      font-weight: 100;
      font-size: 50px;
    }

    .controls {
      margin-bottom: 50px;
    }

    input {
      width:100px;
    }
  </style>

  <script>
  </script>

</body>
</html>

#목표

사진에서 두가지의 레인지 조절 기능과 colorpicker 기능을 넣으려 한다

#과정

  1. CSS 변수를 만든다(base색상, 기본 여백(spacing), 기본 흐림정도(blur))
  2. CSS변수를 통한 이미지, 텍스트 효과 지정
  3. 자바스크립트로 CSS 변수가 작동하도록 코드 작성

1. CSS 변수를 만든다(base색상, 기본 여백(spacing), 기본 흐림정도(blur))

:root {
    --base: #ffc600;
    --spacing: 10px;
    --blur: 10px
}

:root - HTML 요소중 가장 상위 요소에 적용한다는 뜻
--base - base라는 CSS 변수를 생성
위와같이 :root에 변수를 선언하는 것은 전역변수를 생성한다는 뜻


2. CSS변수를 통한 이미지, 텍스트 효과 지정

img {
    padding: var(--spacing);
    background: var(--base);
    filter: blur(var(--blur));
}

.h1 {
    color: var(--base);
}

변수를 불러올 때 var(--spacing)과 같이 불러옴


3. 자바스크립트로 CSS 변수가 작동하도록 코드 작성

const inputs = document.querySelectorAll('.controls input');

function handleUpdate() {
    const suffix = this.dataset.sizing || '';
    document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);
}

inputs.forEach(input => input.addEventListener('change', handleUpdate));
inputs.forEach(input => input.addEventListener('mousemove', handleUpdate));

inputs 라는 변수에 controls 클래스 하위의 input 태그들을 담고
handleUpdate()라는 함수에서 suffixinputdata-sizing 또는 공백을 담는다 위의 HTML코드를 보면 range-bar로 이루어진 두개의 input태그는 data-sizing="px"이고 colorpicker input태그는 data-sizing속성이 존재하지 않기 때문에 둘을 or연산자로 엮어서 suffix에 담은 것 

document.documentElement.style.setProperty(`--${this.name}`, this.value +suffix); document의 최상위 태그 html에 style 요소를 부여하고 그 내용을 name: value로 채움

(글로 적으려니 정리가 안돼서 어려워 보이지만 직접 코드를 보는게 이해가 빠름!)

마지막 코드는 inputs 변수의 각각 내용(두개의 range-bar, colorpicker)에서 change 이벤트와 mousemove 이벤트가 일어날때 handleUpdate()를 실행하는 addEventListener메소드를 넣음.
이때 mousemove를 넣지 않으면 range-bar를 드래그 하면서 동시에 결과를 볼수 없고 마우스를 떼야만 결과가 출력되어 두가지를 같이 써주는게 보기가 훨씬 편함

찾아본 내용, 알게된 내용들

filter: blur(~~) - 번짐효과 설정

.dataset - data-~~로 이루어진 내용들 데이터정보 호출 ex) data-sizing속성은 dataset.sizing으로 호출

document.documentElement.style.setProperty - document의 최상위 요소에 style 요소 적용 후 속성 적용

:root - HTML 최상위 요소 선택자

--name var(--name) - CSS 변수선언,호출

끝!


'개발 > JavaScript30' 카테고리의 다른 글

5. Flex Panel Gallery  (0) 2017.04.05
4. Array Cardio Day 1  (0) 2017.04.04
3. CSS Variables  (0) 2017.04.03
2. CSS + JS Clock  (0) 2017.04.03
1. JavaScript Drum Kit  (0) 2017.03.30
0. JavaScript30 Challenge  (0) 2017.03.30

CSS + JS Clock

자바스크립트로 현재시간 받을 수 있는건 알았지만
CSS로 아날로그 시계를 구현할 수 있어서 신기했다
자바스크립트공부를 하려고 시작했는데 CSS도 많이 알게 되는것 같음

기본 코드

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JS + CSS Clock</title>
</head>
<body>


    <div class="clock">
      <div class="clock-face">
        <div class="hand hour-hand"></div>
        <div class="hand min-hand"></div>
        <div class="hand second-hand"></div>
      </div>
    </div>


  <style>
    html {
      background:#018DED url(http://unsplash.it/1500/1000?image=881&blur=50);
      background-size:cover;
      font-family:'helvetica neue';
      text-align: center;
      font-size: 10px;
    }
    body {
      margin: 0;
      font-size: 2rem;
      display:flex;
      flex:1;
      min-height: 100vh;
      align-items: center;
    }
    .clock {
      width: 30rem;
      height: 30rem;
      border:20px solid white;
      border-radius:50%;
      margin:50px auto;
      position: relative;
      padding:2rem;
      box-shadow:
        0 0 0 4px rgba(0,0,0,0.1),
        inset 0 0 0 3px #EFEFEF,
        inset 0 0 10px black,
        0 0 10px rgba(0,0,0,0.2);
    }
    .clock-face {
      position: relative;
      width: 100%;
      height: 100%;
      transform: translateY(-3px); /* account for the height of the clock hands */
    }
    .hand {
      width:50%;
      height:6px;
      background:black;
      position: absolute;
      top:50%;
    }
  </style>

  <script>
  </script>
</body>
</html>

목표

현재 시간을 아날로그 시계로 구현

과정

  1. 시계바늘 중심위치 잡기, 효과 적용
  2. 시계바늘 변수로 등록
  3. 시계바늘 현재 시간에 맞게 설정

코드 분석

  1. 시계바늘 중심위치 잡기, 효과 적용

    .hand {
     transform-origin: 100%;
     transform: rotate(90deg);
     transition: all 0.05s;
     transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
    }
    

    transform - 변형 효과를 줄 때 기준 설정
    hand 클래스에 위의 코드를 추가해
    기준축을 100% 즉 가장 오른쪽으로 잡고, 방향을 90도만큼 돌려서
    시침, 분침, 초침이 12시 방향에 있도록 바꿔줌
    transition - 변형 효과를 줄 때 효과 설정
    all 0.05s - 모든곳에 효과를 주며 0.05초에 실행완료하겠다
    transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1) - 속성의 중간값을 계산하는 방법을 정의하며 cubic-bezier는 가장 많이 사용되는 속성으로 네 점에 의해 정의되며, 그래프로 제공해서 명시할 수 있음
    괄호안의 값은 대충 그래프로 시계 움직임처럼 찍은 값을 적은것

  2. 시계바늘을 변수로 등록

    const secondHand = document.querySelector('.second-hand');
    const minsHand = document.querySelector('.min-hand');
    const hourHand = document.querySelector('.hour-hand');
    

    세개의 바늘을 HTML요소에서 클래스로 찾아서 변수로 등록

  3. 시계바늘을 현재 시간에 맞게 설정

    function setDate() {
     const now = new Date();
    
     const seconds = now.getSeconds();
     const secondsDegrees = ((seconds / 60) * 360) + 90;
     secondHand.style.transform = `rotate(${secondsDegrees}deg)`;
    
     const mins = now.getMinutes();
     const minsDegrees = ((mins / 60) * 360) + ((seconds/60)*6) + 90;
     minsHand.style.transform = `rotate(${minsDegrees}deg)`;
    
     const hour = now.getHours();
     const hourDegrees = ((hour / 12) * 360) + ((mins/60)*30) + 90;
     hourHand.style.transform = `rotate(${hourDegrees}deg)`;
    
    setInterval(setDate, 1000);
    setDate();
    }
    

    setDate라는 함수에 현재 시간에 대한 정보를 담는 now라는 변수를 만들고
    초, 분, 시 단위로 변수를 만들어 시간에 맞게 돌아가도록 각도를 계산해주고
    각 시계바늘에 transform: rotate 속성을 삽입해줌
    이때 각도 조절값은 곰곰이 생각해보시길..(적기가 넘나힘든것)
    setIntervalsetDate를 1000ms(1초) 마다 실행한다는 뜻
    마지막 코드 setDate()는 켰을 때 바로 함수 한번 실행함을 나타내고,
    그 뒤부터는 위의 setInterval이 1초마다 실행해줌

찾아본 내용, 알게된 내용들

transform-origin - 변형 효과를 줄 때 원점을 지정해줌
transform: rotate() - 원점으로부터 회전 각도를 설정할 때 사용
transition - 변형 효과를 줄때 애니메이션 속도를 조절할 때 사용
setInterval - 특정 시간마다 함수를 실행할 때 사용

끝!

'개발 > JavaScript30' 카테고리의 다른 글

5. Flex Panel Gallery  (0) 2017.04.05
4. Array Cardio Day 1  (0) 2017.04.04
3. CSS Variables  (0) 2017.04.03
2. CSS + JS Clock  (0) 2017.04.03
1. JavaScript Drum Kit  (0) 2017.03.30
0. JavaScript30 Challenge  (0) 2017.03.30

폼 입력 바인딩

기본 사용법


v-model 디렉티브를 사용하여 폼 input과 textarea 엘리먼트에 양방향 데이터 바인딩 생성 가능
입력 유형에 따라 엘리먼트를 업데이트하는 방법을 자동으로 선택함
이때 v-model은 기본적으로 사용자 입력 이벤트에 대한 데이터를 업데이트하는 “syntax sugar”이며 일부 경우에는 주의해야 함

v-model은 모든 form 엘리먼트 초기 value, checked, selected 속성 무시,
컴포넌트의 data 옵션 안에 있는 JavaScript에서 초기값을 선언해야 한다.

v-model는 한국어가 업데이트가 되지 않으므로 input을 사용해야 함.

문자열

<input v-model="message" placeholder="수정해보세요">
<p>메시지: {{ message }}</p>


 

박스에 내용을 넣으면 실시간으로 message에 바인딩되어 결과가 나타남

여러줄을 가진 문장

<span>여러 줄을 가지는 메시지:</span>
<p style="white-space: pre">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="여러줄 입력하세요"></textarea>

마찬가지로 message에 바인딩 되어 결과 나타남
이때 <textarea>{{ text }}</textarea> 는 작동하지 않음

체크박스

하나의 체크박스는 단일 boolean 값을 가짐

<input type="checkbox" id="checkbox" v-model="checked">
</label for="checkbox">{{ checked }}</label>

//HTML
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>체크한 이름: {{ checkedNames }}</span>

//JavaScript
new Vue({
  el: '...',
  data: {
    checkedNames: []
  }
})

라디오

<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>선택: {{ picked }}</span>

셀렉트

//HTML
<select v-model="selected">
    <option disabled value="">Please select one</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
</select>
<span>선택함: {{ selected }}</span>

//JavaScript
new Vue({
    el: '...',
    data: {
        selected: ''
    }
})

<select v-model="selected" multiple>을 쓰면 다중선택 가능

v-for를 이용한 동적 욥션 렌더링

//HTML
<select v-model="selected">
    <option v-for="option in options" v-bind:value="option.value">
        {{ option.text }}
    </option>
</select>
<span>Selected: {{ selected }}</span>

//JavaScript
new Vue({
    el: '...',
    data: {
        selected: 'A',
        options: [
            { text: 'One', value: 'A' },
            { text: 'Two', value: 'B' },
            { text: 'Three', value: 'C' }
        ]
    }
})

값 바인딩하기


라디오, 체크박스, 셀렉트 옵션의 경우 v-model 바인딩 값은 보통 정적인 문자열이다

<!-- `picked` 는 선택시 문자열 "a" 입니다 -->
<input type="radio" v-model="picked" value="a">

<!-- `toggle` 는 true 또는 false 입니다 -->
<input type="checkbox" v-model="toggle">

<!-- `selected`는 "ABC" 선택시 "abc" 입니다 -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

그러나 동적 속성에 바인딩 할때는 v-bind를 사용하면 되고, 이것을 사용하면 입력값을 문자열이 아닌 값에 바인딩 할 수 있다.

체크박스

//HTML
<input type="checkbox"
           v-model="toggle"
           v-bind:true-value="a"
           v-bind:false-value="b"
          >

//JavaScript
// 체크 하면:
vm.toggle === vm.a
// 체크하지 않으면:
vm.toggle === vm.b

라디오

//HTML
<input type="radio" v-model="pick" v-bind:value="a">

//JavaScript
vm.pick === vm.a

셀렉트 옵션

//HTML
<select v-model="selected">
    <!-- inline object literal -->
    <option v-bind:value="{ number: 123 }">123</option>
</select>

//JavaScript
typeof vm.selected 
vm.selected.number

수식어


.lazy

기본적으로, v-model은 각 입력 이벤트 후 입력과 데이터를 동기화 함
.lazy를 추가해 change이벤트 이후에 동기화 할 수 있음

<!-- "input" 대신 "change" 이후에 동기화 됩니다. -->
<input v-model.lazy="msg>

뭔말인지 모르겠다..

.number

사용자 입력이 자동으로 숫자로 바뀌게 하려면 다음과 같이 사용

<input v-model.number="age" type="number">

.trim

input을 자동으로 trim 하려면 다음과 같이 하면 된다.

<input v-model.trim="msg">

추가적으로 재사용 가능한 input을 컴포넌트로 만들 수 있고 v-model에도 작동함

'개발 > Vue.js' 카테고리의 다른 글

Vue 기본자료 포스팅 완료!  (0) 2017.04.06
10. 컴포넌트  (0) 2017.04.06
9. 폼 입력 바인딩  (0) 2017.03.31
8. 이벤트 핸들링(v-on)  (0) 2017.03.31
7. 리스트 렌더링(v-for, v-if)  (0) 2017.03.31
6. 조건부 렌더링(v-if, v-else-if, v-else, v-show)  (0) 2017.03.30

이벤트 핸들링

이벤트 청취


v-on 디렉티브를 사용, DOM 이벤트를 듣고 트리거 될 때 JavaScript 실행 가능

//HTML
<div id="example-1">
    <button v-on:click="counter += 1">Add 1</button>
    <p>버튼 클릭 횟수는 {{ counter }} 입니다.</p>
</div>

//JavaScript
var example1 = new Vue({
    el: '#example-1',
    data: {
        counter: 0
    }
});

메소드 이벤트 핸들러


많은 이벤트 핸들러의 로직은 복잡할 것이므로, Javascript를 v-on속성값으로 보관하는 것은 간단하지 않음. 이 때문에 v-on이 호출하고자 하는 메소드의 이름을 받는 이유이다

//HTML
<div id="example-2">
    <button v-on:click="greet">Greet</button>
</div>

//JavaScript
var example2 = new Vue({
    el: '#example-2',
    data: {
        name: 'Vue.js'
    },
    methods: {
        greet: function (event) {
            alert('Hello ' + this.name + '!' )
            if (event) {
                alert(event.target.tagName)
            }
        }
    }
})
example2.greet()

인라인 메소드 핸들러


//HTML
<div id="example-3">
    <button v-on:click="say('hi')">Say hi</button>
    <button v-on:click="say('what')">Say what</button>
</div>

//JavaScript
new Vue({
    el: '#example-3',
    methods: {
        say: function (message) {
            alert(message)
        }
    }
})

때로 인라인 명령문 핸들러에서 원본 DOM 이벤트에 엑세스 해야할 수도 있음
$event를 사용함

//HTML
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
    Submit
</button>

//JavaScript
methods: {
    warn: function (message, event) {
        if (event) event.preventDefault()
        alert(message)
    }
}

이벤트 수식어


이벤트 핸들러 내부에서 event.preventDevault() 또는 event.stopPropagation()를 호출하는 것은 매우 보편적인 일이다.
메소드 내에서 쉽게 이 작업을 할 수 있지만, DOM 이벤트 세부 사항을 처리하는 대신 데이터 로직에 대한 메소드만 사용할 수 있으면 더 좋을 것같다

고 문서에 써있는데 무슨말인지 잘 모르겠지만, 저걸 해결하기 위해 v-on 이벤트에 이벤트 수식어를 제공함 

- .stop
- .prevent
- .capture
- .self
- .once

<!-- 클릭 이벤트 전파가 중단됩니다 -->
<a v-on:click.stop="doThis"></a>
<!-- 제출 이벤트가 페이지를 다시 로드 하지 않습니다 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 수식어는 체이닝 가능합니다 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 단순히 수식어만 사용할 수 있습니다 -->
<form v-on:submit.prevent></form>
<!-- 이벤트 리스너를 추가할 때 캡처모드를 사용합니다 -->
<!-- 즉 내부 엘리먼트를 대상으로 한  이벤트가 해당 엘리먼트에서 처리되기 전에 처리됩니다. -->
<div v-on:click.capture="doThis">...</div>
<!-- event.target이 엘리먼트 자체인 경우에만 트리거를 처리합니다 -->
<!-- 자식 엘리먼트에서는 안됩니다 -->
<div v-on:click.self="doThat">...</div>
<!-- 클릭 이벤트는 최대 한번만 트리거 됩니다. -->
<a v-on:click.once="doThis"></a>

키 수식어


키보드 이벤트를 청취할 때 v-on에 키 수식어를 추가할 수 있음
키코드를 전부 기억하는 것은 어렵기 때문에 Vue는 일반적으로 사용되는 키의 별칭을 제공함

<!-- keyCode가 13일 때만 vm.submit()을 호출합니다 -->
<input v-on:keyup.13="submit">
<!-- 위와 같습니다 -->
<input v-on:keyup.enter="submit">
<!-- 약어 사용도 가능합니다 -->
<input @keyup.enter="submit">
  • .enter
  • .tab
  • .delete
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right
  • .ctrl
  • .alt
  • .shift
  • .meta (맥에서 commad, 윈도우는 윈도우키)
    마우스 수식어
  • .left
  • .right
  • .middle
    위에 없는 별칭을 만들고 싶으면 아래와 같이 하면 된다.
// v-on:keyup.f1 이 가능합니다
Vue.config.keyCodes.f1 = 112

HTML로 된 리스너를 사용하는 이유


HTML로 된 리스너를 사용하는 이유를 모른다면 왜 HTML에 JS요소를 넣어서 쓰냐 하고 이해하기 힘들 수 있다. 다음은 그 이유다

  1. HTML 템플릿을 간단히 하여 JavaScript 코드 내에서 핸들러 함수 구현을 찾는 것이 더 쉽다
  2. JavaScript에서 이벤트 리스너를 수동으로 연결할 필요가 없으므로 ViewModel 코드는 순수 로직과 DOM이 필요하지 않고, 이렇게 하면 테스트가 쉬워짐
  3. ViewModel이 파기되면 모든 이벤트 리스너가 자동으로 제거되어 이벤트 제거에 대한 걱정이 필요 없어집니다.


리스트 렌더링

v-for


v-for 디렉티브를 사용해 배열기반 리스트 렌더링
item in items 형태로 특별한 문법이 필요험(items은 원본 데이터 배열, item은 반복되는 배열의 값) / in 대신 of 사용 가능

기본 사용방법

//HTML
<ul id="example-1">
    <li v-for="item in items">
        {{ item.message }}
    </li>
</ul>

//JavaScript
var example1 = new Vue({
    el: "#example-1",
    data: {
        items: [
            { message: "Foo" },
            { message: "Bar" }
        ]
    }
})

위의 코드는 렌더링 되어 아래와 같은 결과가 나온다

  • Foo
  • Bar

v-for 블록 안에는 부모 범위 속성에 대한 모든 권한이 있고 현재 항목의 인덱스에 대한 두 번째 전달인자 옵션을 제공

//HTML
<ul id="example-2">
    <li v-for="(item, index) in items">
        {{ parentMessage }} - {{ index }} - {{ item.message }}
    </li>
</ul>

//JavaScript
var example2 = new Vue({
    el: "#example-2",
    data: {
        parentMessage: "Parent",
        items: [
            { message: "Foo" },
            { message: "Bar" }
        ]
    }
})

결과는 아래와 같다
- Parent - 0 - Foo
- Parent - 1 - Bar

v-for 템플릿

템플릿 v-if와 마찬가지로, 태그를 사용해 여러 엘리먼트의 블럭을 렌더링 할 수 있음

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

v-for과 객체

v-for을 사용하여 객체의 속성을 반복할 수도 있음

//HTML
<ul id="repeat-object" class="demo">
     <li v-for="value in object">
         {{ value }}
    </li>
</ul>

//JavaScript
new Vue({
    el: "#repeat-object",
    data: {
        object: {
            firstName: "John",
            lastName: "Doe",
            age: 30
        }
    }
})

결과
- John
- Doe
- 30

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

컴포넌트와 v-for

나중에 다시 작성 예정



v-for와 v-if

v-forv-if가 같은 노드에 존재하면 v-for이 우선 순위를 가짐.
둘을 같이 쓰는건 아래 코드와 같이 일부 항목만 렌더링 할때 유용함

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

위의 경우는 완료되지 않은 todo가 렌더링 된다

엘리먼트를 전부 렌더링 하고, 조건문으로 보여지고 싶은 부분만 추리고 싶으면
v-if를 래퍼 엘리먼트로 옮기면 된다

<ul v-if="shouldRenderTodos">
    <li v-for="todo in todos">
        {{ todo }}
    </li>
</ul>

key


v-for에서 렌더링된 엘리먼트 목록을 갱신할 때 “in-place patch” 전략 사용
데이터 항목의 순서가 변경된 경우 항목의 순서와 일치하도록 DOM요소를 이동하는 대신 Vue는 각 요소를 적절한 위치에 패치하고 해당 인덱스에서 렌더링할 내용을 반영하는지 확인함

이때 재정렬 할 수 있도록 각 항목에 고유속성 key를 제공해야 함

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

v-for에는 항상 key를 추가하는 것이 좋음
예외 : 반복되는 DOM 내용이 단순하지 않거나, 의도적인 성능 향상을 위해 기본 동작에 의존하는 경우 => 그냥 복잡하게 반복문을 썼을때를 제외하고는 key를 쓰라는 것.

배열 변경 감지


변이 메소드

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()
    ps. 루비랑 똑같다

배열 대체

  • filter()
  • concat()
  • slice()
    위 세가지 메소드를 사용하면 항상 새 배열을 반환
    이때 Vue는 기존 DOM을 버리고 새로 렌더링을 하는것이 아니라
    겹치는 객체가 포함된 다른 배열로 대체해 효율적임

주의

JavaScript의 제한으로 Vue는 2가지 경우를 감지할 수 없음
1. 인덱스로 배열에 있는 항목을 직접 설정하는 경우 vm.items[indexOfItem] = newValue
=> Vue.set(example1.items, indexOfItem, newValue) 사용
2. 배열의 길이를 수정하는 경우 vm.items.length = newLength
=> splice 사용

+ Recent posts