Vuex를 사용하는 글로벌 이벤트 버스 - 항상 가입자에게 알림
나는 Vue에서 꽤 오랫동안 글로벌 이벤트 버스를 이용하고 있다.const bus = new Vue()
그러나 구독 폐기는 장황하게 될 수 있다.
구성 요소의 이벤트에 가입한다고 가정해 봅시다.
mounted() {
bus.$on('some.event', callback)
}
콜백을 계속 추적해서 적절히 처리해야 할 것이다.beforeDestroy
. 글로벌 믹스인을 사용하면 어느 정도 간소화할 수 있지만, 지금 사용하고 있기 때문에<keep-alive>
, 나는 다음에서 만들어진 구독을 구별해야 한다.mounted
그리고activated
콜백
그래서 나는 Vuex에게 이것을 관리할 수 있는 기회를 주겠다고 생각했다. 왜냐하면 관찰자들은 틀에 의해 처분되기 때문이다.나는 아래에서 그 제안을 생각해 냈다.
객체나 배열이 공개되는 한 잘 작동하는 것 같다.원시 데이터는 외부 물체에 포장되어 있음에도 불구하고 반응성을 유발하지 않는 것 같다.{ data: 123 }
가입자에게 알리는 것에 대한 대안을 찾고 있어.지금까지 내가 본 것은 내부적인 것뿐이다.notify
사용하기에 매우 안전하지 않은 방법.
eventstore.js
import Vue from 'vue'
const state = {
events: {}
}
const actions = {
publish({commit}, payload) {
commit('publish_event', payload)
}
}
const mutations = {
publish_event(state, payload) {
if(!state.events[payload.key]) {
Vue.set(state.events, payload.key, { data: payload.data })
} else {
state.events[payload.key] = { data: payload.data }
}
}
}
const getters = {
events: state => state.events
}
export default {
state,
actions,
mutations,
getters
}
글로벌믹신js
methods: {
publish(key, data) {
this.$store.dispatch('publish', { key, data })
}
}
일부의 구성 요소부에를 하다
function mapEventGetters(eventKeys) {
return _.reduce(eventKeys, (result, current) => {
result[current] = function() {
return _.get(this, `$store.getters.events.${current}.data`)
}
return result
}, {})
}
computed: {
...mapEventGetters(['foo_bar'])
},
watch: {
'foo_bar'(value) {
console.log(`foo_bar changed to ${value}`)
}
}
딥카피(예: 딥카피)를 사용할 수 있음JSON.parse(JSON.stringify())
데이터가 반응하는지 확인하기 위해
const mutations = {
publish_event(state, payload) {
if(!state.events[payload.key]) {
state.events[payload.key] = { data: payload.data }
} else {
state.events[payload.key] = Object.assign({}, state.events[payload.key], { data: payload.data })
}
state.events = JSON.parse(JSON.stringify(state.events))
}
}
위의 구성 요소에서foo_bar
감시 하에Vue Watcher는 구성 요소 데이터로만 작업(원하는 데이터)data
,computed
, 또는vuex
).
다음과 같이 데이터를 재정의할 수 있음componentData
아래와 같이사용할 수 있다mapGetters
더 짧은 구문의 경우:
<script>
import { mapGetters } from 'vuex'
export default {
...mapGetters(['events']),
computed: {
componentData () {
const eventKeys = ['foo_bar']
return _.reduce(eventKeys, (result, current) => {
result[current] = function() {
return _.get(this, `events.${current}.data`)
}
return result
}, {})
}
},
watch: {
componentData: function (newVal, oldVal) {
...
}
}
}
</script>
이 API는 Vuex의 핵심 개념인 Vuex의 데이터 흐름을 깨뜨릴 것이다.고객들은 Vuex의 모든 곳에서 매장 상태를 변이하거나 읽을 수 있을 것이다.
솔직히 이런 방법은 Vuex에서 실행될 필요가 없다. 왜냐하면 그것은 단지 이벤트 방출자일 뿐이기 때문이다.동작에 이벤트 이미터(아마 빈 Vue 인스턴스)를 사용할 것을 제안한다.
export const emitter = new Vue()
export default {
// ...
actions: {
// should be called when the store is initialized
// to observe events
observe({ dispatch, commit }) {
emitter.$on('some-event', () => {
commit('someEvent')
})
emitter.$on('other-event', () => {
dispatch('otherEvent')
})
},
// notify some event in action
notify({ state }) {
emitter.$emit('notify', state.someValue)
}
}
}
그것은 내가 Github에서 검색할 때 내 문제를 한 번 해결한다.맷이 도와줄게고마워!!
호출Vue.set
객체에서 관측자/반응도를 객체 내부의 데이터에 추가하지 않는다.이를 위해서는 부가적인 Vue가 필요하다.세트
Vue.set(state.events, payload.key, {})
Vue.set(state.events[payload.key], 'data', payload.data)
또한 이 기능을 유틸리티 함수에 포함시킬 수 있으며, 이 함수를 사용하여 데이터를 재귀적으로 설정할 수 있으며,Vue.set
이 두 가지 상황에서 모두 반응성이 발생했는지 알려주시겠습니까?
먼저 외부 객체로 불필요한 랩핑을 제거하고 원하는 이벤트 키와 이 키에 대한 데이터를 사용하여 페이로드를 단순 키/값 객체로 전송하십시오.
{
someKey: 123
}
두 번째로 일부 중첩 데이터를 전송하십시오.
{
someKey: {
nested: 'Value'
}
}
그러나 이 전에 돌연변이 코드를 다음과 같이 변경하십시오.
const mutations = {
publish_event(state, payload) {
// Instead of the previous code, just "patch"
// the state.events with the payload content.
state.events = { ...state.events, ...payload }
}
}
또한 데이터는 더 이상 "데이터" 속성에 중첩되지 않으므로 mapEventGetters 기능을 향상시키는 것도 잊지 마십시오.
PS: 하지만 개인적으로 나는 왜 특정한 게터들과 함께 Vuex를 사용하지 않는지 이해할 수 없다. 왜냐하면 그것은 원초적인 유형과 반응성을 유발하기 때문이다.
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
const state = {
events: {}
}
const actions = {
publish({commit}, payload) {
commit('publish_event', payload)
}
}
const mutations = {
publish_event(state, payload) {
state.events = { ...state.events, ...payload }
}
}
const getters = {
fooBar: state => state.events.fooBar || ''
}
Vue.use(Vuex)
export default new Vuex.Store({
state,
actions,
mutations,
getters
})
main.js.
import Vue from 'vue'
import App from '@/App'
import store from '@/store'
new Vue({
store,
render: h => h(App)
}).$mount('main')
어떤 구성 요소
<template>
<span>{{ fooBar }}</span>
</template>
import { mapGetters, mapActions } from 'vuex'
export default {
name: 'SomeComponent',
computed: {
...mapGetters(['fooBar'])
},
methods: {
...mapActions(['publish'])
},
created () {
setTimeout(() => {
publish({
fooBar: 123
})
}, 3000)
}
}
참조URL: https://stackoverflow.com/questions/53597963/global-event-bus-using-vuex-always-notify-subscribers
'programing' 카테고리의 다른 글
c_str 함수의 용도는 무엇인가? (0) | 2022.05.15 |
---|---|
MVC 프로젝트에서 MapState가 Vue3와 함께 Vuex4를 찾을 수 없음 (0) | 2022.05.15 |
Vue.js 2에서 이벤트 버스를 사용하여 사용자 지정 이벤트로 데이터를 전달하는 방법 (0) | 2022.05.15 |
LocalDate를 문자열로 포맷하는 방법? (0) | 2022.05.14 |
Linux/unix에 WinAPI의 MAX_PATH와 동등한 것이 있는가? (0) | 2022.05.14 |