Vue 고급 - newlife-js/Wiki GitHub Wiki
※ 함수 내 this == (브라우저 this / 객체 인스턴스의 this) / 비동기 this
함수 내 this는 해당 함수가 포함된 브라우저나 객체 인스턴스의 this와 같고,
비동기 호출 내부의 this는 객체 내에 있더라도 비동기 객체를 가리킨다.
단, 화살표 함수를 사용하면, 비동기 내부의 this도 객체의 인스턴스를 가리키게 된다.
※ Vuex에서는 action에서 바로 state를 변경하지 못하고, mutations을 거쳐야 가능하다.
action에서 mutations로 데이터를 넘길 때는 context 키워드를 사용한다.
export const store = new Vuex.Store({
state: {
new: [],
},
mutations: {
SET_NEWS(state, news) {
state.news = news;
}
},
actions: {
FETCH_NEWS(context) {
fetchNewsList()
.then((response) => context.commit('SET_NEWS', response.data))
.catch((error) => console.log(error));
},
}
})
<router-link>
태그 사용
@router
{
path: '/user/:id',
component: UserView,
}
@NewsView.vue
<router-link v-bind:to="`/user/${item.user}`">{{ item.user }}</router-link>
:id에 들어가는 값들은
this.$route.params.id와 같이 접근할 수 있음.
:variable을 여러개 사용할 수도 있음.
<div v-html="fetchedItem.content"/>
event emit을 받아서 뿌려주는 vue 객체
@bus.js
import Vue from 'vue';
export const bus = new Vue();
@App.vue
created() {
bus.$on('start:spinner', this.startSpinner);
bus.$on('end:spinner', this.endSpinner);
},
beforeDestroy() {
bus.$off('start:spinner', this.startSpinner);
bus.$off('end:spinner', this.endSpinner);
}
@NewsView.vue
created() {
bus.$emit('start:spinner');
this.$store.dispatch('FETCH_NEWS')
.then(() => {
console.log('fetched');
bus.$emit('end:spinner');
})
.catch(error => console.log(error));
}
** ※ 왜인지 모르겠지만 WEBPACK 어쩌구 하면서 동작이 안됨. **
_utils_bus_js__WEBPACK_IMPORTED_MODULE_7___default.a.$emit is not a function
참고자료
@main.js
Vue.prototype.$bus = new Vue();
를 new Vue 위에 등록해주고,
bus대신에 this.$bus를 사용해야 한다...
왜일까...
router 객체에서는 this.$bus가 안되어서... 다른 방법을 시도해보니,
bus 객체를 const로 바꿔주면 또 되네
컴포넌트 로직을 재사용하기 위한 기술
router에 넘겨주는 component를 render해서 return하는 함수를 구현
@views/CreateListView.js
import ListView from './ListView.vue';
export default function createListView(name) {
return {
name: name,
created() {
this.$bus.$emit('start:spinner');
this.$store.dispatch('FETCH_LIST', this.$route.name)
.then(() => {
console.log('fetched');
this.$bus.$emit('end:spinner');
})
.catch(error => console.log(error));
},
render(createElement) {
return createElement(ListView);
}
}
}
@routes/index.js
{
path: '/news',
name: 'news',
component: createListView('NewsView'),
},
{
path: '/ask',
name: 'ask',
component: createListView('AskView'),
},
{
path: '/jobs',
name: 'jobs',
component: createListView('JobsView'),
},
※ 단점: 컴포넌트의 깊이가 깊어지면서 통신이 불편해짐...
여러 컴포넌트 간에 공통으로 사용하고 있는 로직, 기능들을 재사용하는 방법
new Vue({
mixins: [someMixin]
})
- 컴포넌트 라이프 사이클 훅 vuejs API 문서
- created : 컴포넌트가 생성되자마자 호출되는 로직
- 라우터 내비게이션 가드 강의자료
- 특정 URL로 접근하기 전의 동작을 정의하는 속성
to: 목표 url
from: 이전 url
next를 해줘야 routing 페이지로 넘어감
@routers/index.js
{
path: '/news',
name: 'news',
component: createListView('NewsView'),
beforeEnter: (to, from, next) => {
next();
}
},
기존의 비동기 처리 방식에 비해 직관적인 코딩 가능
promise의 .then().catch() 구문을 안 쓸 수 있음
예외처리는 try{ } catch {error} 로 대신함
async fuction fetchData()({
try{
var user = await getUserList(); // promise를 return하는 함수에만 await 사용할 수 있음.
} catch (error) {
console.log(error);
}
}
모든 컴포넌트에 공통으로 적용하고 싶은 기능을 포함시키는 것
컴포넌트마다 동일 library를 import할 필요가 없도록 함
@main.js
Vue.use(플러그인);
@plugin.js
import chart from 'chart.js';
export default {
install(Vue){
Vue.prototype.$_Chart = Chart;
}
}
props와 $emit 사용
화면별 component customize
상위 컴포넌트에서 props 대신 v-model로 데이터를 내려보냄
하위 컴포넌트에서는 props로 'value'를 내려받고, $emit으로 'input'을 올려보낸다.
표현하지 않는 컴포넌트(데이터 제공만 하는..)
** ※ render function **
render : function(createElement) { // createElement -> h : hyper script를 뜻함
return createElement(App);
}
@fetchedData.vue
render() {
// 하위 컴포넌트에서 상위컴포넌트로 올린다 $scopedSlots
// slot -> v-slot // $scopedSlots.default -> $slots.default
return this.$scopedSlots.default({
response: this.response,
loading: this.loading,
});
},
@App.vue
<fetch-data url="https://jsonplaceholder.typicode.com/users/1">
<!-- ... response, loading 을 가져올수 있다-->
<div v-slot="{response, loading}">
<div v-if="!loading">
<p>{{response.name}}</p>
<p>{{response.email}}</p>
</div>
<div v-if="loading">
loading...
</div>
</div>
</fetch-data>