다음 계획

  • JavaScript30 완료 (끝!)
  • Vue 공부하며 예제 만들어보기
  • Vue 심화 자료 포스팅
  • Nuxt 공부


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

Nuxt 토이 프로젝트(포트폴리오 페이지)  (0) 2017.05.08
Vue.js 정리  (0) 2017.04.25
10. 컴포넌트  (0) 2017.04.06
9. 폼 입력 바인딩  (0) 2017.03.31
8. 이벤트 핸들링(v-on)  (0) 2017.03.31

컴포넌트


컴포넌트란 무엇인가

기본 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
9. 폼 입력 바인딩  (0) 2017.03.31
8. 이벤트 핸들링(v-on)  (0) 2017.03.31
7. 리스트 렌더링(v-for, v-if)  (0) 2017.03.31

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

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

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

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

블로그 운영시 참고 사이트, 프로그램


마크다운

하루패드
한국어도 지원되며 마크다운 작성시 아주 편하고 디자인도 예쁨


Jekyll 블로그

Github에서 개발한 사이트 개발 툴
블로그로 사용하기 아주 깔끔함
공식 홈페이지
만드는 방법


+꾸준히 추가 예정


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

개발 좋은 글 모음  (3) 2017.07.02
자료구조 소트 쉽게 이해하기  (0) 2017.04.07
스타트업 관련 정보 사이트  (2) 2017.03.29

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

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

'개발 > 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
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
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

+ Recent posts