40일차(1) : Vue.js 예제(4)
- Vue.js로 이벤트 발생시키기
Step08_eventEmit
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Step08_eventEmit.html</title>
</head>
<body>
<h1>자식 component 에서 발생하는 이벤트</h1>
<div id="app">
<my-component v-on:mom="feed"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("my-component", {
template:`
<div>
<button v-on:click="callMom">엄마!</button>
</div>
`,
methods:{
callMom(){
// this.$emit("이벤트명", 전달할 data)
this.$emit("mom", "배고파");
}
}
});
let app=new Vue({
el:"#app",
methods:{
feed(data){
alert(data);
}
}
});
</script>
</body>
</html>
- root component 는 자식 component를 가질 수 있다.
- 자식 component를 분리한다는 것은 어떤 작업을 나누어 분업화한다는 면에서 의미가 있다.
- root component 는 전체를 조율하는 개념이다.
- 자식 component 안에서 어떤 이벤트가 발생할 수 있다.(drag, submit, click, mousemove, ...)
- 보통은 자식 component 안에서 해결하지만,
때로는 자식 component에서 발생하는 이벤트를 부모 component에 알려야 할 수 있다.
- 부모로부터 데이터를 받아서 사용한다거나 하는 경우!
ex) 1페이지를 부모로부터 받아서 사용자에게 보여주고 있는데 사용자가 2페이지를 클릭하는 경우.
부모 component에 2페이지의 데이터가 필요하다고 요청하기
자식-부모 간의 소통이 필요한 경우가 있다. 이런 경우에 사용하는 것이 이벤트 발생시키기!
v-on:mom
- 자식 → 부모 이벤트 발생시키기
- 어떤 버튼이 있다고 예시를 들면
button v-on:click="clicked" : 이 버튼에 클릭 이벤트가 일어나면 " " 함수를 호출할 것이라는 뜻이다.
- <my-component v-on:mom="feed"> 는
mom이라는 이벤트가 일어나면 feed함수를 호출할 것이라는 의미가 된다.
- 이 컴포넌트에 어떻게 mom이라는 이벤트가 발생할까?
- 아래에 this.$emit 으로 지정해둔다.
- 이벤트명은 마음대로 지정할 수 있고, 전달할 인자가 있으면 같이 전달하면 된다.
- '엄마' 버튼을 누르면 이벤트 발생. this.$emit 로 이벤트를 발생시키는 것이다.
- 클릭하면 methods 안에 들어있는 mom-feed함수가 실행된다.
- method의 feed함수를 발생시키면서 인자도 함께 전달한다.
- 버튼 클릭시 alert(data) 가 실행된다.
Step08_eventEmit2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Step08_eventEmit2.html</title>
</head>
<body>
<h1>event emit 예제</h1>
<div id="app">
<friend-component
v-bind:list="members"
v-on:delete="deleteMember"></friend-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("friend-component",{
template:`
<ul>
<li v-for="(item, index) in list">
{{item}}
<button v-on:click="deleteItem(index)">삭제</button>
</li>
</ul>
`,
props:["list"],
methods:{
deleteItem(i){
this.$emit("delete", i);
}
}
});
let app=new Vue({
el:"#app",
data:{
members:['바나나','딸기','복숭아']
},
methods:{
deleteMember(index){
//members 모델(배열) 에서 index 에 해당하는 아이템 1개 삭제
this.members.splice(index, 1);
}
}
});
</script>
</body>
</html>
- "list" property 를 받고, "delete" 이벤트를 발생시킨다.
- Component 안에 list라는 property를 갖고있으니까 list를 바인딩할 수 있고,
delete라는 이벤트를 가지고 있으니까 delete 해당 이벤트에 대해서 on: 할 수 있는 것이다.
- list 를 전달받아서 for문을 돌면서 li를 여러개 만들어낸다. 배열[ ] (빨간 화살표)
- 배열의 아이템 인덱스를 얻어내면서 index 를 deleteItem 함수에 전달하고,
이벤트를 발생시키면서 부모 component에 전달한다. (분홍 화살표)
- 자식 component 에서 버튼을 누르면 삭제되는데, 삭제되는 이유는
delete 이벤트를 발생시키면서 부모 component에 데이터를 전달하면,
delete 이벤트가 일어나면서 deleteMember 함수를 호출한다.
이 deletemember(){} 함수가 실행되면서 삭제도 되고, index값도 전달되는 것이다.
- 부모component 입장에서 보면 배열에 변화를 가하는 것이다.
삭제하기만 하면 자식 component에 자동으로 전달된다.
- 부모가 가진 모델의 원본을 수정하는 것만으로도 자식에게 그 값이 전달된다.
Step08_eventEmit3 - 수정 기능도 있다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Step08_eventEmit3.html</title>
</head>
<body>
<h1>event emit 예제</h1>
<div id="app">
<friend-component
v-bind:list="members"
v-on:delete="deleteMember"
v-on:update="updateMember"></friend-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("friend-component",{
template:`
<ul>
<li v-for="(item, index) in list">
{{item}}
<button v-on:click="updateItem(index)">수정</button>
<button v-on:click="deleteItem(index)">삭제</button>
</li>
</ul>
`,
props:["list"],
methods:{
deleteItem(i){
this.$emit("delete", i);
},
updateItem(i){
const newName=prompt("수정할 이름을 입력하세요");
//this.$emit("update", {i:i, newName:newName});
this.$emit("update", {i, newName});
}
}
});
let app=new Vue({
el:"#app",
data:{
members:['바나나','딸기','복숭아']
},
methods:{
deleteMember(index){
this.members.splice(index, 1);
},
updateMember(data){
//아래처럼 배열을 변경하면 변경이 감지가 안되기 때문에 화면 업데이트가 안된다.
//this.members[data.i] = data.newName;
//아래의 2가지 방법중 하나로 배열을 변경해야 한다.
//Vue.set(this.members, data.i, data.newName);
// $set(수정할배열의참조값, 수정할 인덱스, 수정할 값)
this.$set(this.members, data.i, data.newName);
}
}
});
</script>
</body>
</html>
- 부모 component 가 갖고 있는 members 배열 전달
- 이벤트 발생시 delete, update 함수 실행
this.$emit("update", {i, newName});
- 이름(newName)을 입력받아서
update라는 함수를 발생시키면서 두개의 값을 전달한다.(i값과 newName)
- 그런데 object의 값이 좀 특이하다.
- 위와 같이 {i:i, newName:newName} 으로 작성해야하는데, {i, newName} 으로만 적는다.
- 보통 object의 방의 이름을 지역변수의 이름과 일치시켜 사용하는 경우가 많다.
- 그래서 방의 이름은 지역변수 그대로 하고, 지역변수의 값을 value로 하여 { 변수명, 변수명 } 으로만 써도
이렇게만 써도 알아서 {변수명1:value1, 변수명2:value2}로 object를 만들어준다!
- update 이벤트가 들어가면, 이 위치에는 object가 전달된다.
참고) Vue에서 배열 모델을 사용하는 경우의 주의사항
- 위와 같은 경우 수정으로 간주되므로 UI는 자동으로 업데이트된다.
[ Vue에서 배열을 모델로 사용하는 경우 ]
- 배열에 저장된 아이템을 반복문 돌면서 참조해서 여러개의 UI를 만들어낸다.
- 배열이 수정되면, UI는 자동으로 update된다. → 꼭 그런것은 아니다.
- 여기서 수정의 기준이 애매하다. 배열을 수정했을 때 수정이라고 간주되는 것이 있고 아닌 것이 있다.
- 배열의 특정 인덱스를 삭제해서 배열의 사이즈가 변경된 경우 → 수정O (업데이트된다)
- 새로운 배열의 참조값으로 대체(덮어쓰기) → 수정O (업데이트된다)
- 배열의 특정 인덱스에 저장된 아이템을 다른 아이템으로 대체하는 경우 → 수정X
- 이 안의 어디에선가 this.members=[10,20,30] 로 값을 바꾸어 넣을 수 있다. 이것은 수정으로 간주된다.
- 수정으로간주되므로 UI는 자동으로 업데이트된다.
let nums=[10,20,30]
nums[1]=999;
- 하지만 위와 같이 배열의 특정 인덱스에 저장된 아이템을 다른 아이템으로 대체하는 경우에는
배열이 변경되었다고 간주하지 않기 때문에, 추가적인 작업이 필요한 것!
- 이 경우 배열의 값을 바꿨다고해서 UI가 바로 업데이트 되는 것은 아니다.
- 배열을 수정하고 업데이트도 하게 하고 싶다면 this.$set 을 쓰는 것이다.
Vue.set(this.members, data.i, data.newName);
$set(수정할 배열의 참조값, 수정할 인덱스, 수정할 값)
- 이 경우 둘 중 하나를 작성해줌으로써 배열도 수정되고 UI도 업데이트되도록 해주어야 한다.
'국비교육(22-23)' 카테고리의 다른 글
42일차(1)/JSTL(1) : JSTL 사용법, 작성법 (1) | 2022.12.06 |
---|---|
41일차(1)/GitHub : 외부 저장소에서 Fork-Clone 하기 / Pull Request 사용법 (0) | 2022.12.05 |
39일차(2) : Vue.js 예제(3) (0) | 2022.12.01 |
39일차(1) : javascript로 작성했던 폼 Vue.js로 수정하기 (0) | 2022.12.01 |
38일차(3) : Vue.js 예제(2) (0) | 2022.12.01 |