소스 : https://github.com/donghyeon0725/vue_tutorials

 

css
<style>
[v-cloak] {
display: none;
}
#app {
display: flex;
}
.block {
display: block;
}
.f-right {
float: right;
}
.f-left {
float: left;
}
.cart-wrapper {
min-width: 130px;
background: #e6e6e6;
margin: 5px 5px;
overflow: auto;
align-justify: justify;
}
.preview-wrapper {
min-width: 130px;
background: #e6e6e6;
margin: 5px 5px;
overflow: auto;
vertical-align: center;
}
.cart {
margin-left: auto;
margin-right: auto;
margin-top: 2px;
background-color: bisque;
display: block;
width: 120px;
border: 1px solid blue;
border-radius: 5px;
text-align: center;
cursor: pointer;
}
</style>

 

 

index.html
<div id="app" v-cloak>
<!--cart-list-->
<div class="cart-wrapper">
<div v-if="cartList.length > 0" v-for="(json, key) in cartList" class="cart" :draggable="draggable" @dragstart='dragStart($event, json.content)'>{{ json.content }}</div>
</div>
<form v-on:submit.prevent="addCard">
<div class="contentWrap">
<!-- v-model을 통해 값을 연결한다. data에 있는 변수명이 내용물이 된다. -->
<textarea v-model="content" name="content" id="content" cols="30" rows="10" class="block" :placeholder="defaultContents" @drop="drop($event)" @dragover="allowDrop($event)" ></textarea>
<button type="button" class="f-left">{{ btnStr.left }}</button>
<button type="submit" class="f-right">{{ btnStr.right }}</button>
</div>
</form>
<div class="preview-wrapper">
<div v-if="previewList.length > 0" v-for="(json, key) in previewList" class="cart" @click="deleteCard(key)">{{ json.content }}</div><!-- json, key를 반대로 사용함 -->
</div>
<!--preview-->
</div>

1. 이동할 요소에 draggable="true" 어트리뷰트를 추가할 것
2. 드랍될 엘리먼트의 drop 이벤트에 event.preventDefault()를 사용할 것
드랍 될 요소에 preventDefault를 사용하지 않으면 브라우저에서 드랍 이벤트를 허용하지 않을 수 있습니다.

 

다음의 스타일을 정의할 것
-- 드래그 될 때의 스타일
-- 드래그가 다른 엘리먼트 위에 있을 때 스타일
-- 다른 엘리먼트 위에 드랍될 때의 스타일

 

javascript
<script>
const CARD_STORAGE_KEY = "cardStorage";
const PREVIEW_STORAGE_KEY = "previewStorage";
// localStorage.getItem(CARD_STORAGE_KEY) || "[]" => 자바스크립트의 논리연산자 ||은 참거짓을 반환하는게 아닌, 피연산중 true인 것을 반환하는 연산자이다!!!
let cartStorage = {
fetch: () => JSON.parse(localStorage.getItem(CARD_STORAGE_KEY) || "[]"),
save: card => localStorage.setItem(CARD_STORAGE_KEY, JSON.stringify(card)),
removeAll: () => localStorage.removeItem(CARD_STORAGE_KEY)
};
cartStorage.removeAll();
let previewStorage = {
fetch: () => JSON.parse(localStorage.getItem(PREVIEW_STORAGE_KEY) || "[]"),
save: card => localStorage.setItem(PREVIEW_STORAGE_KEY, JSON.stringify(card)),
removeAll: () => localStorage.removeItem(PREVIEW_STORAGE_KEY)
};
/*cartStorage.removeAll();
previewStorage.removeAll();*/
//previewStorage.save({name:'sds',content:'내용'});
let app = new Vue({
el: '#app',
data: {
btnStr: {
left : '비동기로 데이터 요청',
right : '카드 삽입하기'
},
content: '',
cartList: cartStorage.fetch(),
previewList: previewStorage.fetch()
},
methods: {
addCard(event) {
if (!this.content) {
return;
}
this.previewList.push({content: this.content});
this.content = "";
},
deleteCard(key) {
console.log(key);
this.previewList.splice(key, 1);
},
dragStart(evt, content) {
evt.dataTransfer.dropEffect = 'move'
evt.dataTransfer.effectAllowed = 'move'
evt.dataTransfer.setData('itemID', content)
},
allowDrop(event) {
event.preventDefault();
},
drop:function(evt) {
evt.preventDefault();
const itemID = evt.dataTransfer.getData('itemID')
this.content = itemID;
}
},
computed: {
defaultContents() {
return '내용을 입력해주세요.';
},
draggable() {
return true;
}
},
beforeCreate() {
console.log('beforeCreate', this.btnStr);
},
created() {
console.log('beforeCreate', this.btnStr);
this.cartList.push({content: '내용1'});
this.cartList.push({content: '내용2'});
},
beforeMount() {
alert('beforeMount => 랜더링 이전(내부 노드 추가 안된 상태)');
},
mounted() {
alert('mounted => 랜더링 이후');
},
beforeUpdate() {
alert('beforeUpdate')
},
updated() {
alert('updated')
},
beforeDestroy() {
},
destroyed() {
},
// 변화를 보고 있다가 변화발생 시 작동할 옵션
watch: {
previewList: {
handler: function(aa) {
previewStorage.save(aa);
},
deep: true
},
cartList:{
handler: function(aa) {
cartStorage.save(aa);
},
deep: true
}
}
});
</script>

 

  • localStorage 라는 키워드를 통해 로컬에 값을 저장함. 저장된 값은 리스트에 json 데이터가 저장된 형태이다.
  • 한편 자바스크립트의 논리연산자 "||"은 자바스크립트의 논리연산자 ||은 참거짓을 반환하는게 아닌, 피연산중 true인 것을 반환하는 연산자이다
  • watch 라는 프로퍼티로 와쳐를 관리하고, data 내부의 데이터를 보고 있다가 변화가 생기면 같은 이름의 프로퍼티를 호출한다.
  • created() (created: function() 의 설탕문법)와 같이 생애주기에 해당하는 메소드를 프로퍼티로 추가함으로써 생애주기를 관리할 수 있다. 주요한 생에주기는 아래와 같다.

 

  • beforeCreate : 인스턴스의 내부 이벤트와 라이프 사이클 상태가 초기화 된 후에 호출
  • created : 인스턴스(vm)의 주입과 반응형 시스템이 초기화 된 후 호출. 이때부터 data 객체에 접근 가능
  • beforeMount : 인스턴스는 생성이 되었고 vue.js가 템플릿들의 컴파일을 마친 시점. 생성된 DOM을 랜더링 할 준비가 된 후 호출된다. 이때 개발자 도구를 열면 내부에 아직 DOM 요소가 부착되어 있지 않다.
  • mounted : DOM이 랜더링 된 이후. 사용자가 DOM 요소들을 확인할 수 있다.
  • beforeUpdate : 데이터가 변경 되기 전에 호출 됨. 옵저버 패턴으로 데이터를 보고 있어서 가능함.
  • activated: keep-alive 컴포넌트가 활성화 될 때 => 추상 엘리먼트로(태그) 주로 엘리먼트를 보존하거나 재 랜더링 하는데 사용
  • deactivated: keep-alive 컴포넌트가 비활성화 될 때
  • updated : 데이터가 변경 된 후 호출
  • beforeDestroy : 생성 된 인스턴스가 파괴 되기 전에 호출 됨. 이 때 인스턴스는 아직 제 기능을 할 수 있음.
  • destroyed: 인스턴스가 파괴된 후 호출. 인스턴스의 모든 지시자 바인딩이 해제 됨. 이벤트 리스너가 제거되고 모든 하위 인스턴스가 파괴됨.
  • errorCaptured: 자손컴포넌트에서 에러가 검출 될 때마다 호출

 

실행결과


라이프사이클

 

댓글

댓글을 사용할 수 없습니다.