https://tragramming.tistory.com/105
v-bind는 속성에 데이터를 바인딩하는 것으로 :속성명으로 사용할 수 있다.
v-model과 v-if를 활용한 입력제한에 따른 텍스트 실시간 변경 기능
<template>
<div>
이름: <input type="text" v-model="name"> <span v-if="name.length>=4">4글자 이하여야합니다.</span><br>
나이: <input type="text" v-model="age"> <span v-if="age<10 || age>120">10이상 120이하</span>
<hr>
이름길이:<span>{{ name.length }}</span>
나이:<span>{{ age }}</span>
</div>
</template>
<script>
export default {
props:{
}, data: function(){
return {
name:"",
age:""
};
}
}
</script>
키없으면 렌더링 안됨
순서 기억
배열: (내용, 인덱스)
객체: (내용, 키, 인덱스)
키값에 같은 이름의 변수 사용하면 안된다. 흠...
https://zzang9iu.tistory.com/101
https://mine-it-record.tistory.com/657
<template>
<div>
<!-- <v-for="contact in contacts" v-bind:key="유일값"> -->
<h1>index없임</h1>
<ul>
<li v-for="name in names" v-bind:key="name">
{{ name }}
</li>
</ul>
{{ name }}
<h1>index 지정</h1>
<ul>
<li v-for="(name, index) in names" v-bind:key="index">
{{ index }} : {{ name }}
</li>
</ul>
</div>
</template>
<script>
export default {
name:"HelloWorld",
props:{
}, data: function(){
return {
names: ["홍길동", "이순신", "유관순"]
}
}
}
</script>
require 역할 알아보기
이미지 경로가 src/assets일떄 vuejs에서는 @/assets로 사용할 수 있다.
@ 기능 알아보기
아마 ecma 쪽 문법 배운 것 중 하나일거임
<template>
<div>
<h1>도서목록 {{ bookList.length }}</h1>
<ul>
<li v-for=" book in bookList" v-bind:key="book.id">
<img v-bind:src="require(`@/assets/image/${book.img}.jpg`)" width="100" height="100">
<!-- 이미지 경로가 src/assets일떄 vuejs에서는 @/assets로 사용할 수 있다. -->
{{ book.name }}
{{ book.img }}
</li>
</ul>
</div>
</template>
<script>
export default {
props:{
bookList : Array
}, data: function(){
return {
};
}
}
</script>
<style>
</style>
json 객체를 v-for디렉티브로 순회할 시에는 아래와 같다.
<태그명 v-for="(value, key, index) in 객체명" v-bind:key="key나 index 등">
<template>
<div>
<ul>
<li v-for="(value, key, index) in person" :key="key">
{{ index }} : {{ key }} / {{ value }}
</li>
</ul>
<table border="1">
<tr v-for="(value, key, index) in person" :key="key">
<td>{{ index }}</td>
<td>{{ key }}</td>
<td>{{ value }}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
props:{
}, data: function(){
return {
person:{
name:"홍길동",
age:10,
address:"서울"
}
};
}
}
</script>
<select>태그사용<template>
<div>
<select v-model="result">
<option disabled selected> 과일을 선택하세요.</option>
<option v-for="(v, k ,i) in fruits" :key="i">
{{ v }}
</option>
</select><br>
선택한 과일은: {{ result }}
</div>
</template>
<script>
export default {
props:{
}, data: function(){
return {
fruits:{
apple:"사과",
banana: "바나나",
melon : "멜론"
},
result:""
};
}
}
</script>
div 태그는 반복하면 div가 흔적이 남는다.
template 태그는 반면에 흔적을 아예 남기지 않는다.
그래서 여러 요소를 그룹핑하여 반복처리용 태그로 사용한다.
오류발생 고치기
<template>
<div>
<h1>1. 기본</h1>
<div v-for="(name, idx) in names" :key="idx">
{{ idx }} : {{ name }}님
</div>
<hr>
<h1>2. div태그로 그룹핑: div 태그가 흔적으로 남음</h1>
<div v-for="(name, idx) in names" :key="idx+10">
<span>{{ idx }} : {{ name }}님</span>
</div>
<h1>3. template태그 그룹핑: template태그가 흔적으로 안남음</h1>
<div class="hello">
<template v-for="(v,i) in names">
<span :key="i+100">{{ v }}님</span>
</template>
</div>
<h1>4. </h1>
</div>
<span v-for="(v, i) in names" :key="i+1">{{ v }}</span>
</div>
</template>
<script>
export default {
props:{
}, data: function(){
return {
names:["홍길동","이순신","유관순"]
};
}
}
</script>
v-on:이벤트="실행할 함수" = @이벤트="실행할 함수"
함수는 methods에서 선언
이벤트 인자로 전달 가능
<template>
<div>
<h1>v-on:이벤트명="처리함수" 또는 @이벤트명="처리함수"</h1>
<button v-on:click="handleEvent"> v-on:click</button><br>
<button @click="handleEvent"> @click</button><br>
<button v-on:click="xxx('홍길동')"> v-on:click</button><br>
<button @click="xxx('홍길동')"> @click</button><br>
<button @click="xxx('홍길동', $event)"> @click('홍길동', $event)</button><br>
</div>
</template>
<script>
export default {
props:{
}, data: function(){
return {
num:10
};
},
methods:{
handleEvent: function(e){
console.log("handleEvent==========", e);
},
xxx: function(s, e){
console.log(s, e);
}
}
}
</script>
데이터 저장은 예전에 쓰던 방식 그대로 씀
data-xxx=""
하지만 사용하는 방식은 달라짐
이전에는 this를 통해 쉽게 접근이 가능했는데
여기서 this는 vuecomponent다.
따라서 이벤트 객체를 이용해서 접근을 한다
event.target => 이벤트가 발생한 태그를 가르킨다.
event.target.dataset => DOMStringMap {my: 'aaa', my2: '{"name":"홍길동", "age":"20"}'} 이런 형식의 데이터를 뽑아 쓸 수 있는 DOM객체가 반환된다.
여기서 my2는 json 객체를 문자열의 형식으로 태그에 저장했다.
관건은 작은 따옴표가 밖에 있어야 json형식을 위배하지 않기에 중요하다.
또한 사용하는 곳에서 값에 접근하려면 JSON.parse를 이용해야한다.
<template>
<div>
<h1>v-on:이벤트명="처리함수" 또는 @이벤트명="처리함수"</h1>
<button v-on:click="handleEvent"> v-on:click</button><br>
<button @click="handleEvent"> @click</button><br>
<button v-on:click="xxx('홍길동')"> v-on:click</button><br>
<button @click="xxx('홍길동')"> @click</button><br>
<button @click="xxx2('홍길동', $event)"> @click('홍길동', $event)</button><br>
<!-- $event 사용 주의
속성을 이용한 데이터 전달시 속성이름에 data-을 사용
함수에서는 data-를 제외한 부분을 사용하게 됨 이벤트.target.dataset으로 확인 -->
<button v-on:click="handleEvent2"
data-my="aaa"
data-my2='{"name":"홍길동", "age":"20"}'>속성을 이용한 데이터 전송</button><br>
<!-- 문자열로 만들기 위해 "{'name':'홍길동', 'age':'20'}" 주의 -->
<!-- 연습용 버튼 -->
<button v-on:click="handleEvent3"
data-my="aaa"
data-my2='{"name":"홍길동", "age":"20"}'>속성을 이용한 데이터 전송</button><br>
</div>
</template>
<script>
export default {
props:{
}, data: function(){
return {
num:10
};
},
methods:{
handleEvent: function(e){
console.log("handleEvent==========", e);
},
xxx: function(s,){
console.log(s);
},
xxx2: function(s, e){
console.log(s, e);
},
handleEvent2: function(e){
console.log(this); //vuecomponent
console.log("handleEvent2==== event", e);
console.log(e.target);
console.log(e.target.dataset);
console.log("my: ", e.target.dataset.my);
console.log("my2: ", e.target.dataset.my2);
console.log("my2.name: ", e.target.dataset.my2.name); //문자열이라 당연히 접근이 안됨
console.log("my2.age: ", e.target.dataset.my2.age); //문자열이라 당연히 접근이 안됨
let data = JSON.parse(e.target.dataset.my2);
console.log("my2.name: ", data.name);
console.log("my2.age: ", data.age);
},
handleEvent3: function(e){
let target = e.target; // 이벤트발생 태그
let dataset = e.target.dataset; // 데이터가 들어있는 객체
let jsonData = JSON.parse(e.target.dataset.my2); // 데이터
console.log(jsonData.name); // 데이터 세부요소 접근
}
}
}
</script>
<style>
</style>
v-once가 설정된 태그는 단 한번만 렌더링 되게 만든다.
Data
<template>
<div>
{{ username }}
<button v-on:click="changeName">changeName</button><br>
기본:<span>{{ username }}</span><br>
v-once1:<span>{{ username }}</span><br>
v-once2:<span v-once>{{ username }}</span><br>
</div>
</template>
<script>
export default {
props:{
}, data: function(){
return {
username: "홍길동"
};
}, methods:{
changeName: function(){
this.username = "이순신";
}
}
}
</script>
간단 요약 : 배열 순회하고 새로운 배열을 리턴시킨다.
배열메서드인 map은 콜백함수를 인자로 받는다.
콜백함수의 인자로는 element, index, array가 있으며, 일반적으로 element, index를 주로 사용한다.
array.map(callback(element, index, array));
여기까지만 보면 forEach와 다를 것이 없지만, 차이점은 마지막줄에서 확인한 것처럼 이 메서드가 실행된 자리에 리턴되는 배열이 있느냐이다.
결과적으로 map은 메서드를 호출한 배열의 길이 만큼의 새로운 배열을 만들어내는 게 핵심인데, 콜백 함수의 return 값을 통해 새로운 배열들의 각 요소를 변형할 수 있다는 특징이 있는 것이다.
간혹 forEach의 기능을 포괄한다고 생각해서, 이런 류의 작업을 모두 map으로만 사용하는 경우도 있는데, 개인적으로는 가급적 목적에 맞는 최적화된 문법을 사용하는 것이 좋다고 생각한다.
<template>
<div>
<h1>{{ mesg }}</h1>
<div v-for="(v,i) in bookList" :key="i">
<input type="checkbox" v-model="books" v-bind:value="v">
{{ v.name }}의 정석
<span>{{ v.price }}</span>
</div>
<hr>
선택교재: <br>
<div v-for="(v, i) in books" :key="i+10">
{{v.name}} 정석
</div>
전체가격 : {{ [getTotal(), total] }}
</div>
</template>
<script>
export default {
props:{
mesg: String
}, data: function(){
return {
bookList:[
{name:"자바", price:"2000"},
{name:"jsp", price:"4000"},
{name:"spring", price:"5000"},
{name:"jquery", price:"6000"},
{name:"angular", price:"7000"},
],
books:[], //선택된 책목록 저장
total:0 //총액
};
},
methods:{
getTotal: function(){
// var sum=0;
// for(var i =0;i<this.books.length;i++){
// sum+=parseInt(this.books[i].price);
// }
// this.total = sum;
// console.log(this.total);
var sum=0;
var totalbook= this.books;
totalbook.map(
function(ele, idx){
console.log(idx, ele.name, ele.price);
sum=sum+parseInt(ele.price)
}
);
this.total = sum;
console.log(this.total);
return this.total;
}
}
}
</script>
<style>
</style>
한번만 호출되는 녀석. 거의 쓰지 않아서 스킵.
1. 주로 긴 시간을 필요로 하는 비동기처리에 사용
2. 데이터가 변경되었을 때 함수가 자동 호출된다.
3. 반드시 함수명과 data 속성명이 일치해야한다.
<template>
<div>
<h1>watch 속성</h1>
값: <input type="text" v-model.number="num"><br>
변경된 값 : {{ num }}
</div>
</template>
<script>
export default {
props:{
}, data: function(){
return {
num:10
};
},
// 1. watch함수명과 속성변수명이 동일해야함
// 2. mdethod와 computed는 명시적으로 호출해야하지만
// 3. watch는 자동으로 호출됨
watch:{
num:function(changeValue){
console.log("watch함수 실행======", this.num, "\t", changeValue);
}
}
}
</script>
<template>
<div>
<h1>{{ mesg }}</h1>
<div v-for="(v,i) in bookList" :key="i">
<input type="checkbox" v-model="books" v-bind:value="v">
{{ v.name }}의 정석
<span>{{ v.price }}</span>
</div>
<hr>
선택교재: <br>
<div v-for="(v, i) in books" :key="i+10">
{{v.name}} 정석
</div>
전체가격 : {{ total }}
</div>
</template>
<script>
export default {
props:{
mesg: String
}, data: function(){
return {
bookList:[
{name:"자바", price:"2000"},
{name:"jsp", price:"4000"},
{name:"spring", price:"5000"},
{name:"jquery", price:"6000"},
{name:"angular", price:"7000"},
],
books:[], //선택된 책목록 저장
total:0 //총액
};
},
methods:{
},
watch:{
books:function(cv){
var sum = 0;
this.books.map(
(ele, index)=>{sum+=parseInt(ele.price);}
)
this.total=sum;
}
}
}
</script>
v-on:[변수], @[변수]
<template>
<div>
<h1>{{ msg }}</h1>
<!-- <button @click="처리함수", button v-on=:[속성이름]="처리함수",
@[속성이름]="처리함수" -->
<button v-on:[aaa]="handleEvent">v-on:[aaa]</button> <br>
<button @[bbb]="handleEvent">@[bbb]</button> <br>
<button @[ccc]="handleEvent">@[ccc]</button> <br>
<button @[aaa]="handleEvent2" data-my="홍길동"
data-my2='{"name":"이순신","age":20}'
>@[aaa] handleEvent2</button> <br>
</div>
</template>
<script>
export default {
props:{
msg:String
}, data: function(){
return {
aaa: "click",
bbb: "mouseover",
ccc: "mouseleave"
};
},
methods:{
handleEvent:function(e){
console.log("handleEvent====", e)
},
handleEvent2:function(e){
console.log("handleEvent2====", e);
console.log(e.target.dataset.my);
console.log(JSON.parse(e.target.dataset.my2).name);
}
}
}
</script>