수식어 살펴보기
앞서 살펴본것처럼 v-model은 입력 값에 바인딩할 수 있다. 해당 값은 각각의 입력 이벤트에 따라 업데이트 된다.
v-model 지시자와 수식어를 사용하면 작동방식을 바꿀 수 있다.
예를들어, .number를 사용해서 값을 숫자타입으로 변환하거나, 입력에 .trim을 사용하여 양쪽 공백을 제거 할 수도 있다.
number 수식어 사용
.number 수식어는 v-model 지시자 값을 숫자로 변환할 때 사용한다.
HTML은 type="number"라고 명시해도 항상 문자열을 반환하지만 .number 수식어를 사용하면 해당 현상을 방지하고 숫자를 반환한다.
사용방법
<input v-model.number="order.zip" type="number" />
trim 수식어 사용
폼 정보를 가져올때 앞이나 뒤에있는 여백은 사용하지 않는다. vue.js는 trim수식어로 자동으로 제거 할 수 있다
<input v-model.trim="order.firstName"/>
.lazy v-model 수식어
v-model 지시자는 키입력마다 동기화 된다. 반면 lazy 수식어는 대신 on change 이벤트에 동기화한다.
체크박스를 클릭하거나 라디오 버튼을 클릭하면 change 이벤트가 발생한다. 입력박스에 포커스가 사라지면 change 이벤트가 발생한다.
모든웹브라우저가 동일하게 동작하지 않는다는것을 명심한다.
<input v-model.lazy="order.firstName"/>
컴포넌트
vue.js에서 컴포넌트는 코드 베이스를 줄이고 단순화하는 강력한 구성요소이다.
<div>
<ul>
<p> 안녕 나는 컴포넌트 </p>
</ul>
<div>
해당 HTML 요소는,
<my-component> </my-component> 라는 컴포넌트 하나로 캡슐화 된다.
컴포넌트 생성
Vue.js 루트 인스턴스를 생성한다.
전역 컴포넌트는 애플리케이션 전체에서 사용 가능하고, 지역 컴포넌트는 컴포넌트가 생성된 Vue.js 인스턴스 내에서만 사용할 수 있다.
전역등록
컴포넌트에 정보를 표시하려면 템플릿 속성을 추가해야 한다. 템플릿은 HTML요소들이 있는곳이다.
모든 템플릿은 태그로 감싸야 한다는 점을 명심한다! 그렇지 않으면 콘솔에서 에러를 출력하고 화면에 템플릿이 렌더링 되지 않는다.
컴포넌트가 제대로 렌더링 되기위해 마지막으로 해야 할 일은 컴포넌트를 부모 템플릿에 추가하는 것이다.
특별한 요소 is
DOM에서 컴포넌트를 사용할 때 특정 제약들이 있다. <ul>, <ol>, <table>, <select>..는 해당 태그 내에 들어갈 수 있는 요소 타입이 제한되어있다.
이는 DOM컴포넌트를 잘못된 내용으로 처리하는 방법때문이다.
<table><tr is="my-row"></tr></table>
처럼 HTML 태그 내에 컴포넌트를 추가하는 대신, Element에 직접 컴포넌트를 추가 할 수 있다. tr요소는 이제 my-row 컴포넌트와 연결되어, 원하는 기능과 일치하는 tr 컴포넌트를 만들 수 있다.
지역 등록
지역등록은 Vue 인스턴스 하나로 범위를 제한한다.
컴포넌트가 지역적으로 등록되고 난 후에는 등록한 Vue 인스턴스만 해당 컴포넌트에 접근할 수 있다.
컴포넌트의 관계
Vue.js에서 전달된 데이터를 props라고 한다(properties의 줄임말) 자식컴포넌트는 각각 명시적으로 props 옵션을 사용해서 받아야 할 속성을 명시한다.
부모컴포넌트는 자식 컴포넌트로 데이터 전달이 가능하다(자식 컴포넌트에 명시적으로 props 옵션을 사용해서)
컴포넌트는 단방향 데이터 바인딩을 형성한다. 부모가 속성을 업데이트 하면 속성은 자식 컴포넌트로 흘러가지만 반대로는 흐르지 않는다.
이는 실수로 자식이 부모의 상태를 바꾸는것을 방지한다. 자식이 부모 상태를 변경하면 에러가 발생한다.
모든 값은 참조로 전달되기 때문에 객체나 배열이 자식내에서 변경되면 이는 부모 상태에 영향을 준다. 미리 방지해야 한다. 후에 이벤트를 이용해서 자식에서 부모 데이터를 변경할 수 있는 방법을 살펴보자.
속성을 사용해서 데이터 전달
속성은 부모에서 자식 컴포넌트로 데이터를 전달할 때 쓴다. 단방향 통신에만 사용된다.
리터럴 속성
템플릿요소 안에 text속성으로 리터럴로 데이터를 전송한다.
<div id="app">
<my-component text="WOrld"></my-component>
</div>
const MyComponent = {
template: '<div> 안녕 {{ text }}! </div>',
props: ['text']
}
var app = new Vue({
el: '#app',
components: {'my-component' : MyComponent}
});
text로 world라는 단어를 자식컴포넌트인 my-component에 전달 후 자식컴포넌트는 props로 받아서 template에 넣은후 그것을 렌더링한 모습이다.
동적 속성
동적 속성은 변경될 수 있는 속성을 가지고 있는 부모에게서 전달받은 속성이다.
v-bind 지시자를 사용해서 올바르게 전달되었는지 확인할 수 있다.
속성 text를 새로운 message에 연결한다. messagem는 데이터 함수에서 선언된 속성이다.
<my-component v-bind:text="message"></my-component>
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
//만약 const counter = {counter: 0}; 을 선언하면, 전역변수가 카운터 된다.. 전부 같은 counter를 바라보게됨...
const MyComponent = {
template: '<div><button v-on:click="counter +=1"> {{ counter}} </button></div>'
,data(){
return {
counter: 0 //자기 자신 객체의 counter만 증가한다.
}
}
}
var app = new Vue({
el: "#app",
components: {'my-component': MyComponent}
})
속성 검증
Vue.js는 부모에게 받은 속성의 유효성 여부를 검증하는 '속성 검증'기능이 있다. 많은사람이 같은 컴포넌트를 사용하는 팀프로젝트에 유용햐다.
Vue.js는 다음 속성타입에 대한 순수 생성자를 제공한다.
* 문자열
* 숫자
* 불
* 함수
* 객체
* 배열
* 기호
type 옵션으로 'required'또는 기본값'default'를 추가 할 수 있다. 기본값은 속성에 아무 값도 전달되지 않았을 때의 값을 의미한다.
# 속성 타입이 객체라면 반드시 기본값이 할당되어야 한다. 필수속성은 말 그대로 템플릿에서 컴포넌트가 생성될 때 필요한 속성이다. #
커스텀 유효성 검사자: 사용자가 임의로 작성한 유효성 검사자. 예를들어 값이 짝수인지 아닌지를 검사 할 수 있다. boolean값을 반환해야 한다.
% 단일콜론(:)은 v-bind의 약자이다.
<div id="app">
<!-- 부모에 선언된 passedString, myNumber등의 데이터를 :이름 으로 받는다 -->
<my-component :num="myNumber" v-bind:str="passedString"
:even="myNumber" :obj="passedObject"></my-component>
</div>
const MyComponent = {
template: `<div>숫자: {{ num }}<br/> 문자열 {{ str }}
<br/>짝수?: {{ even ? '짝수' : '홀수'}}<br/> 객체: {{obj.message}} </div>`,
props: {
num: { //숫자는 반드시 검증해야 한다.
type: Number,
required: true
},
str: { //문자열 검증은 기본값을 포함한다.
type: String,
default: "hello! default msg!"
},
obj: {
type: Object,
default(){
return {message: 'default obj message!!'}
}
},
even: {
validator(value){
return (value % 2 === 0)
}
}
}
,data(){
return {
counter: 0
}
}
}
var app = new Vue({
el: "#app",
components: {'my-component': MyComponent},
data(){
return{
passedString: 'hello from parents!',
myNumber: 43,
passedObject: {message: '넘겨준 객체입니다'}
}
}
})
그동안 부모가 내려주는 변수이름이랑, 자식에서 받는 이름이랑 통일시켜서 잘 몰랐는데.. 이름이 달라지니까 헷갈린다 ㅠ
템플릿 컴포넌트 정의
인라인 템플릿 문자열 사용
가장 쉬운 방법중 하나. 부모 템플릿에 추가될때 자식 컴포넌트 안에 템플릿 정보를 포함해야 한다.
인라인 템플릿은 Vue에 my-component 시작과 끝 태그 내에 있는 모든 컴포넌트 콘텐츠를 렌더링 하게 한다.
한가지 단점은 나머지 컴포넌트 정의에서 템플릿을 분리한다는 것이다. 대형애플리케이션에는 추천하지 않는다.
<div id="app">
<my-component :my-info="message" inline-template>
<div>
<p>
inline-template - {{ myInfo }}
</p>
</div>
</my-component>
</div>
const MyComponent = {
props: ['myInfo']
}
new Vue({
el: '#app',
components: {'my-component': MyComponent},
data(){
return {
message: '아아안녀어엉1'
}
}
})
위 예제에서 너무너무너무 헷갈리는점... 부모컴포넌트에서 message props를 받을때, element안에는 소문자랑 하이픈 쓰는 규칙(이름이 잘 생각이 안나네)
을 사용하는데.. {{ }}이나 props에 들어가는 이름은 카멜케이스네... 어떻ㄱ 내부적으로 맵핑하는지 정말 모르겠다 헷갈린다. 맵핑규칙에 대해 찾아봐야 겠다.
text/x-template 스크립트 요소
스크립트 태그의ㅣ 타입을 text/x-template로 생성한다.
*type="text/x-template로" 스크립트를 정의해야만 작동한다는점을 주의한다.
*템플릿에서 컴포넌트 정의를 분리한다는 점이 인라인템플릿과 마찬가지로 큰 단점이다.
<div id="app">
<my-component :my-info="message"/>
</div>
<script type="text/x-template" id="my-component">
<div>
<p>
{{ myInfo }}
</p>
</div>
</script>
const MyComponent = {
props:['myInfo'],
template: '#my-component'
}
new Vue({
el: '#app',
components: {'my-component':MyComponent},
data(){
return {
message: '아진짜 너무헷갈린다! '
}
}
})
+ 여기서 헷갈렸던점. text/x-template 스크립트요소로 템플릿 컴포넌트를 root컴포넌트 내에 선언했을때
"Property or method "myInfo" is not defined on the instance but referenced during render." 경고가 발생했었다.
초기화 되기전에 참조된다,, 라는 의미같은데 props나 data에 초기화하는 코드를 넣어도 마찬가지였음.
알고보니... 루트컴포넌트 안쪽이 렌더링 범위인데, 그 범위안에 text/x-template 스크립트요소를 선언하면,렌더링 대상이 되는데, 그때는 아직 myInfo 값이 초기화 되지 않아서
에러가 났던거였음.. 렌더링이 필요한 컴포넌트만 루트컴포넌트 안에 선언하도록 하자.
단일파일 컴포넌트
더는 문자열 템플릿이나 익숙하지 않은 스크립트 태그를 다루지 않아도 된다!
단일 파일 컴포넌트는 템플릿과 정의를 하나의 .vue파일로 합쳐준다.
각 컴포넌트는 각각의 범위를 가지며, 모든 컴포넌트에 유일한 이름을 지을 필요도 없다!
CSS또한 각 컴포넌트의 범위를 가진다. 대형 애플리케이션에서 굉장히 유용한 방법.
* 단일파일 컴포넌트를 사용하려면 현대 빌드 도구를 조금 알아야 한다. 웹팩이나 브라우저리파이 같은 도구를 사용해야 .vue 코드를 빌드 할 수 있다.
* 응 혼자는 .vue파일 빌드 못한다. 다음장에서 빌드도구를 공부해야 한다. 공부할게 늘었네 이런.
* 아니 이럴거였으면 ㅠㅠ 많이 안쓴다고 이야기를 해주지.. .vue파일을 많이쓰고 vue파일의 특징은 하나의 파일에 독립된 namespage의 컴포넌트를 만들수있다고 알려주면 좀 좋나
export default {
name: 'hello',
data(){
return {
msg: '단일 파일 컴포넌트가 가장 많이 쓰일것 같아.'
}
}
}
<template>
<div class="hello">
{{ msg }}
</div>
</template>
<!-- CSS 범위 지정을 위해 해당 컴포넌트에만 "scoped"속성을 추가한다. -->
<style scoped>
.hello{
/*...*/
}
</style>
'Today I learned' 카테고리의 다른 글
tistory 기본 캘린더를 이용해서 일일포스팅 똥글뱅이 만들어보기 (0) | 2020.07.10 |
---|---|
vue.js 스터디 1주차 (0) | 2020.07.07 |
[vue.js] vue.js 코딩공작소 책 요약 (0) | 2020.07.06 |
[vue.js] 본격 생존코딩! 밥벌이를 해보자! (4) 컴포넌트 (0) | 2020.07.02 |
[vue.js] 본격 생존코딩! 밥벌이를 해보자! (3) (0) | 2020.06.30 |
댓글