vue3 의 Composition API <script setup> 을 이용하여 store 와 mitt 그리고 watch 에 대해서 사용법을 알아보도록 하겠습니다.
vuex / mitt 설치는 아래 링크를 참고하세요
https://trytoso.tistory.com/1628
컴포넌트 구조
컴포넌트는 n-test.vue 와 W1101.vue 두개의 컴포넌트를 사용하겠습니다.
n-test.vue
html 부분을 아래와 같습니다.
<template>
<div>
<h1>n-test.vue</h1>
<button @click="logout" v-if="loginStatus">Logout</button>
<button @click="login" v-else>Login</button>
<pre>loginStatus: {{ loginStatus }}</pre>
<pre>id: {{ id }}</pre>
</div>
</template>
Composition API 를 사용하기 위해 기본적인 모듈을 적재합니다.
추가할 사항이 있으면 추가하시면 됩니다.
<script setup>
import {
ref,
computed,
onMounted,
watch,
inject,
} from 'vue';
import { useStore } from 'vuex';
const store = useStore();
const bus = inject('emitter');
...
console.log 를 편하게 하기 위해 함수 dd() 를 하나 만들었습니다.
const dd = (data, header = false) => {
let now = new Date();
let h = now.getHours();
let m = now.getMinutes();
let s = now.getSeconds();
let ms = now.getMilliseconds();
console.log(`>>>>>: ${h}:${m}:${s} ${ms}`)
if(header) {
console.log(`-------${header}------`);
console.log(data);
}
else console.log(data);
};
1. vuex 의 store 사용법
onMounted : 라이프 사이클 훅인 mounted 의 setup 내부에서 호출 하는 방법입니다.
component 로딩 되었으면 afterLogin() 할수 를 호출합니다.
onMounted(_=>{
dd('on Mounted');
afterLogin(); // afterLogin() 함수 호출
});
afterLogin 함수는 어떠한 필요 정보를 받아온후 store 에 저장하는 기능을 합니다.
afterLogin 할수가 호울되면 dispatch 을 이용하여 store의 actions 의 afterLogin 함수가 호출됩니다.
const obj2 = { al: { id: 'naya', email: 'verylove@naver.com'} };
const afterLogin =_=> {
store.dispatch('afterLogin', obj2);
dd(store.getters.afterLogin, 'afterLogin')
}
actions 의 호출된 함수(afterLogin) 는 commit 을 이용하여 mutations 의 SET_AFTER_LOGIN 함수를 호출하여
해당 값(val) 을 실제 store 에 저장합니다.
store/index.js
import { createStore } from 'vuex'
export default createStore({
state: {
afterLogin: null,
},
getters: {
afterLogin: state => state.afterLogin,
},
mutations: {
SET_AFTER_LOGIN(state, val) {
state.afterLogin = val;
},
},
actions: {
afterLogin( {commit}, { al }) {
commit('SET_AFTER_LOGIN', al);
},
},
modules: {
}
})
저장된 store 의 값을 보려면 아래와 같이 하면 됩니다.
dd(store.getters.afterLogin, 'afterLogin')
2. watch 사용 방법
store 객체의 afterLogin 에 어떠한 정보가 들어오거나 수정되면 sendTr1() 할수를 호출하고 싶습니다.
이와 같을때 아래와 같이 하면 됩니다.
watch(_=>store.getters.afterLogin, function() {
dd('afterLogin value changes detected');
// afterLogin 받아왔으니 sendTr1() 호출후 nowCrncy 저장
sendTr1();
}, {deep:true} ); // 객체 변경을 감지하기 위해
그러면 sendTr1() 함수가 호출되고 n-test__W1101 이름을 가지는 bus 로 다른 component 에서 불러올수 있습니다.
const sendTr1 =_=>{
dd('sendTr1() start');
const tr = {};
tr.trName = 'W1101';
tr.id = store.getters.afterLogin.id;
/*
1. emitter 버스 보냄
*/
bus.emit('n-test__W1101',tr);
}
W1101.vue
n-test__W1101 의 이름을 가지는 버스를 찾아서 실행합니다.
여기서는 console.log 찍고 nowCrncy 함수를 이용하여 store 저장소의 nowCrncy 저장소에 저장합니다.
bus.on('n-test__W1101', (val) => {
dd(val, 'n-test__W1101');
// nowCrncy 저장소에 저장
const res = { nc: {id:'W6112S01', date:'2023.01.16', time:'11:05:37'} }
const nowCrncy =_=> {
store.dispatch('nowCrncy', res);
dd(store.getters.nowCrncy, 'nowCrncy')
}
nowCrncy();
});
여기서 저장소의 nowCrncy 에 값이 저장되거나 변경되는 watch를 만들어보겠습니다.
watch 는 n-test 파일에서 확인해보겠습니다.
n-test.vue
watch(_=>store.getters.nowCrncy, function() {
dd('nowCrncy value changes detected');
});
실행결과
전체소스
App.vue
<script setup>
import { ref } from 'vue';
import tradingviewVue from './components/tradingview.vue'
import nTestVue from './components/n-test.vue';
import W1101Vue from './components/W1101.vue';
</script>
<template>
<nTestVue ref="nTestVue"></nTestVue>
<W1101Vue ref="W1101Vue"></W1101Vue>
</template>
<style scoped>
</style>
main.js
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import store from './store'
import mitt from 'mitt'
const emitter = mitt();
/*
createApp(App)
.use(store)
.use(mitt)
.mount('#app')
*/
const coforwardUi = createApp(App);
coforwardUi.provide('emitter', emitter)
coforwardUi.use(store);
coforwardUi.mount('#app');
/*
import { createApp, } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import jQuery from 'jquery'
import currencyFormat from './js/currencyFormat'
import { socketWorker,wsObj } from './js/socketWorker'
//Vue App의 구성
var coForwarVueUi=createApp(App);
coForwarVueUi.use(store);
coForwarVueUi.use(router);
coForwarVueUi.use(currencyFormat);
coForwarVueUi.mount('#app');
window.vueUi=coForwarVueUi;
global.$ = jQuery
//소켓워커 초기화 실행
window.coForwardSocket = socketWorker;
// window.coForwardSocket.init();
//==== 테스트 영역 ======//
// '636f466f7277617264'
// let utf8='636f466f727761726420ed959ceab880';
// let euckr='636f466f727761726420c7d1b1db'
// let header=socketWorker.headerInfo('length');
// console.log(header);
//==== 테스트 영역 끝 ======//
//쉐어드워커와 소켓포트를 전역으로 등록
coForwarVueUi.config.globalProperties.socketWorker=socketWorker;
coForwarVueUi.config.globalProperties.wsObj=wsObj;
*/
store/index.js
import { createStore } from 'vuex'
export default createStore({
state: {
afterLogin: null,
nowCrncy: null,
user : null,
},
getters: {
afterLogin: state => state.afterLogin,
nowCrncy: state => state.nowCrncy,
loginStatus: state => !!state.user,
},
mutations: {
SET_AFTER_LOGIN(state, val) {
state.afterLogin = val;
},
SET_NOW_CRNCY(state, val) {
state.nowCrncy = val;
},
SET_USER(state, user) {
state.user = user;
}
},
actions: {
afterLogin( {commit}, { al }) {
commit('SET_AFTER_LOGIN', al);
},
nowCrncy( {commit}, {nc} ) {
commit('SET_NOW_CRNCY', nc);
},
login( {commit}, { user }) {
commit('SET_USER', user);
},
logout({commit}) {
commit('SET_USER', null);
}
},
modules: {
}
})
n-test.vue
<script setup>
import {
ref,
computed,
onMounted,
watch,
inject,
} from 'vue';
import { useStore } from 'vuex';
const store = useStore();
const bus = inject('emitter');
let id = ref('');
const dd = (data, header = false) => {
let now = new Date();
let h = now.getHours();
let m = now.getMinutes();
let s = now.getSeconds();
let ms = now.getMilliseconds();
console.log(`>>>>>: ${h}:${m}:${s} ${ms}`)
if(header) {
console.log(`-------${header}------`);
console.log(data);
}
else console.log(data);
};
const obj = { user: { email: 'john@gmail.com' }};
const login = _ => store.dispatch('login', obj );
const logout = _ => store.dispatch('logout');
const loginStatus = computed(_=>store.getters.loginStatus);
const obj2 = { al: { id: 'naya', email: 'verylove@naver.com'} };
const afterLogin =_=> {
store.dispatch('afterLogin', obj2);
dd(store.getters.afterLogin, 'afterLogin')
}
const sendTr1 =_=>{
dd('sendTr1() start');
const tr = {};
tr.trName = 'W1101';
tr.id = store.getters.afterLogin.id;
/*
1. emitter 버스 보냄
*/
bus.emit('n-test__W1101',tr);
}
watch(_=>store.getters.afterLogin, function() {
dd('afterLogin value changes detected');
// afterLogin 받아왔으니 sendTr1() 호출후 nowCrncy 저장
sendTr1();
});
watch(_=>store.getters.nowCrncy, function() {
dd('nowCrncy value changes detected');
id.value = store.getters.nowCrncy.id;
}, {deep:true}); // 객체의 값 변경을 감지하기 위해
onMounted(_=>{
dd('on Mounted');
afterLogin(); // afterLogin() 함수 호출
});
</script>
<template>
<div>
<h1>n-test.vue</h1>
<button @click="logout" v-if="loginStatus">Logout</button>
<button @click="login" v-else>Login</button>
<pre>loginStatus: {{ loginStatus }}</pre>
<pre>id: {{ id }}</pre>
</div>
</template>
<style>
</style>
W1101.vue
<template>
</template>
<script setup>
import {
ref,
computed,
onMounted,
watch,
inject,
} from 'vue';
import { useStore } from 'vuex';
const store = useStore();
const bus = inject('emitter');
const dd = (data, header = false) => {
if(header) {
console.log(`-------${header}------`);
console.log(data);
}
else console.log(data);
};
bus.on('n-test__W1101', (val) => {
dd(val, 'n-test__W1101');
// nowCrncy 저장소에 저장
const res = { nc: {id:'W6112S01', date:'2023.01.16', time:'11:05:37'} }
const nowCrncy =_=> {
store.dispatch('nowCrncy', res);
dd(store.getters.nowCrncy, 'nowCrncy')
}
nowCrncy();
});
</script>
<style>
</style>
함수가 많아질경우 코드 지저분해질것 같아 정리1
n-test.vue
<script setup>
import {
ref,
computed,
onMounted,
watch,
inject,
} from 'vue';
import { useStore } from 'vuex';
const store = useStore();
const bus = inject('emitter');
const Dt = class {
constructor() {
this._now = new Date();
}
getY() {}
getM() {}
getD() {}
getH() { return this._now.getHours(); }
getM() { return this._now.getMinutes(); }
getS() { return this._now.getSeconds(); }
getMS() { return this._now.getMilliseconds(); }
}
const dd = (data, header = false) => {
const dt = new Dt();
console.log(`>>>>>: ${dt.getH()}:${dt.getM()}:${dt.getS()} ${dt.getMS()}`)
if(header) {
console.log(`-----${header}----`);
console.log(data);
}
else console.log(data);
};
const obj = { user: { email: 'john@gmail.com' }};
const login = _ => store.dispatch('login', obj );
const logout = _ => store.dispatch('logout');
const loginStatus = computed(_=>store.getters.loginStatus);
let id = ref('');
const AfterLogin = class {
constructor(obj) {
this._obj = obj;
}
async fetch(url) {
const res = await fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json',
},
});
return await res.json();
}
setStore() {
store.dispatch('afterLogin', this._obj);
}
getStore() {
id.value = store.getters.afterLogin.id;
return store.getters.afterLogin;
}
}
const sendTr1 =_=>{
dd('sendTr1() start');
const tr = {};
tr.trName = 'W1101';
tr.id = store.getters.afterLogin.id;
/*
1. emitter 버스 보냄
*/
bus.emit('n-test__W1101',tr);
}
const change = _=> {
dd('change')
const res = { nc: {id:'W11zz', date:'2023.01.16', time:'13:05:37'} }
const nowCrncy =_=> {
store.dispatch('nowCrncy', res);
dd(store.getters.nowCrncy, 'nowCrncy 222')
}
nowCrncy();
}
//------- watch start --------------------//
watch(_=>store.getters.afterLogin, _=> {
dd('afterLogin value changes detected');
// afterLogin 받아왔으니 sendTr1() 호출후 nowCrncy 저장
sendTr1();
});
watch(_=>store.getters.nowCrncy, _=> {
const dt = new Dt();
dd('nowCrncy value changes detected');
dd(store.getters.nowCrncy, `nowCrncy_${dt.getM()}:${dt.getS()} ${dt.getMS()}`);
id.value = store.getters.nowCrncy.id;
}, {deep:true});
//--------- process layer start ------------//
const afterLoginProc = async()=>{
const obj = { al: { id: 'naya', email: 'verylove@naver.com'} };
const af = new AfterLogin(obj);
const json = await af.fetch('https://reqbin.com/echo/get/json');
dd(json, 'fetch json 11')
af.setStore();
dd(af.getStore(), 'afterLogin 111');
}
//----------- life cycle start --------//
onMounted(_=>{
dd('on Mounted');
afterLoginProc();
setTimeout(_=>{
change();
},5000)
});
</script>
<template>
<div>
<h1>n-test.vue</h1>
<button @click="logout" v-if="loginStatus">Logout</button>
<button @click="login" v-else>Login</button>
<pre>loginStatus: {{ loginStatus }}</pre>
<pre>id: {{ id }}</pre>
</div>
</template>
<style>
</style>