export const focus = {
inserted(el, binding) {
if (binding.value) {
el.focus()
}
},
update(el, binding) {
if (binding.value) {
el.focus()
}
},
}
<a href="#"
class="comment__edit"
@click.prevent="editComment(comment.IDX)"
v-if="editingComment !== comment.IDX"
>
<font-awesome-icon :icon="icons.pencil" />
</a>
<!-- -->
<a
href="#"
class="comment__editDone"
@click.prevent="editDoneComment(comment.IDX)"
v-if="editingComment === comment.IDX"
>
<font-awesome-icon :icon="icons.save" />
</a>
- data(){} editingComment = null로 초기에 설정
- 수정 버튼을 클릭하면 editComment()에 해당 댓글의 id값을 넘겨주고, editingComment의 값을 받은 id로 변경한다.
- 수정, 저장 버튼은 v-if 디렉티브를 통해서 editingComment의 값과 자신의 id값을 비교해서 렌더링 여부를 결정한다.
- 저장 버튼을 클릭하면 데이터의 변경 여부를 체크하고, 변경 시 비밀번호 입력 결과가 같으면 HTTP Request를 보내고,
- 틀릴 경우, 입력 오류 알림창을 보여준다.
// NOTE 댓글 수정 시작 함수
editComment(idx) {
this.editingComment = idx
},
// NOTE 댓글 수정 완료 함수
editDoneComment(idx) {
console.log(idx)
this.editingComment = null
},
- editComment 함수는 idx값을 받아서 editingComment의 값을 idx으로 갱신한다.
- editingComment가 갱신되면 Vue가 다시 렌더링 되고, 수정, 저장 버튼의 v-if디렉티브를 통해서 렌더링 여부를 변경한다.
- editDoneComment 함수는 반드시 editingComment의 값을 null로 갱신해줘야 한다.
<!-- 이부분 삭제 : author는 수정하지 못한다. -->
<span class="comment__author">
<font-awesome-icon :icon="icons.user" />
<span v-if="editingComment !== comment.IDX">
{{ comment.AUTHOR }}
</span>
<!-- 댓글 수정 시 보이는 Input Tag -->
<input
type="text"
:value="comment.AUTHOR"
class="comment__author__edit"
v-if="editingComment === comment.IDX"
v-focus="true"
/>
</span>
<div class="comment__content">
<p v-if="editingComment !== comment.IDX">
{{ comment.COMMENT }}
</p>
<!-- 댓글 수정시 보이는 input Tag -->
<textarea
rows="1"
:value="comment.COMMENT"
v-if="editingComment === comment.IDX"
class="comment__content__edit"
></textarea>
</div>
- 수정 중이지 않을 경우 : editingComment와 자신의 IDX값이 같지 않으므로 span이 보여진다.
- 수정 중인 경우 : editingComment와 자신의 IDX값이 같으므로 input tag가 보여진다.
- input tag는 사용자 지정 디렉티브(focus)를 이용해서 v-if를 통해 inserted된 경우 자동으로 focus되도록 설정했다.
4. 데이터 수정(변경) 여부 확인
5. CommentEdit 컴포넌트 작성
- $emit을 이용해서 부모 컴포넌트에 이벤트 전달, 부모 컴포넌트에서 comment update api호출
//CommentEdit.vue
//Template
<form class="editComment__form" @submit.prevent="onSubmit">
<input
type="text"
v-model="comment"
v-auto-focus="true"
class="editComment__input form-control"
/>
<button type="submit" class="editComment__submit btn btn-primary">수정 완료</button>
</form>
//Script
props: ["cid", "data"],
data() {
return {
comment: "",
};
},
created() {
this.comment = this.data;
},
methods: {
onSubmit() {
this.$emit("edit-comment", {
cid: this.cid,
comment: this.comment.trim(),
});
},
},
directives: {
"auto-focus": focus,
},
- $emit을 통해서 "edit-comment"라는 이벤트를 방출, 부모 컴포넌트에서 이벤트를 전달받아서 api를 호출하는 방식
- api호출을 위한 댓글의 idx값과, 댓글 내용을 "Props" 속성으로 받아온후, 댓글 내용은 v-model로 바인딩하기 위해서 created 훅에서 comment라는 변수에 담았다.
- 수정한 값이 있는지 여부를 체크, 값이 변했으면 api 요청, 변하지 않았으면 수정 컴포넌트를 페이지에서 없앤다.
- const { bid, pid } = this.$data;, 자주 접근하는 bid, pid를 $route.params에서 가져와 data의 프로퍼티로 만들었다. data(){}에 있는 변수를 사용할 때는 $data를 통해서 접근한다.