Vue 라이프 사이클 리스너를 동적으로 추가하는 방법
vue 컴포넌트가 파괴되었을 때 호출할 수 있어야 하는 특정 함수는 있지만 이벤트가 생성되기 전에 반드시 무엇인지 알 수는 없습니다.
vue 라이프 사이클 이벤트에 청취자를 동적으로 추가하는 방법이 있습니까?
달성하려고 하는 것:
...methods: {
logOnDestroy(txt) {
this.$on('beforeDestroy', () => {
console.log(txt)
}
}
}
그러나 그것은 현재 호출되지 않았다.런타임에 청취자를 컴포넌트 라이프 사이클이벤트에 프로그램적으로 바인드하는 다른 방법이 있습니까?
좀 더 간단하게 할 수 없냐고 물으실 수도 있습니다.
Vue.js 컴포넌트 훅을 이벤트로 하면 다음과 같은 구문을 찾을 수 있습니다.
this.$once('hook:beforeDestroy', () => {
으로 역동적으로 '동적'으로 .logOnDestroy()
앱인 Vue CLI의 HelloWorld의 메서드,
데모
Vue.component('helloworld', {
template: '<h1>{{ msg }}</h1>',
name: 'helloworld',
props: { msg: String },
mounted() {
this.logOnDestroy('Goodbye HelloWorld')
},
methods: {
logOnDestroy(txt) {
this.$once('hook:beforeDestroy', () => {
console.log(txt)
})
}
}
});
new Vue({
el: '#app',
data: {
showHello: true
},
mounted() {
setTimeout(() => {
this.showHello = false
}, 3000)
}
});
Vue.config.productionTip = false
Vue.config.devtools = false
<script src="https://unpkg.com/vue"></script>
<div id="app">
<img alt="Vue logo" src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/277px-Vue.js_Logo_2.svg.png" style="height: 50px;">
<helloworld v-if="showHello" msg="Welcome to Your Vue.js App"/>
</div>
은 에 저장됩니다.this.$options
않은 ).대응하는 어레이에 푸시 하는 것으로, 핸들러를 추가할 수 있습니다(핸들러가 설정되어 있지 않은 경우는, 우선 어레이를 작성할 필요가 있습니다).
new Vue({
el: '#app',
created() {
if (!this.$options.mounted) {
this.$options.mounted = [];
}
this.$options.mounted.push(() => {
console.log('mounted')
});
this.$options.mounted.push(() => {
console.log('also mounted')
});
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
<div></div>
</div>
고객님의 경우:
methods: {
logOnDestroy(txt) {
if (!this.$options.beforeDestroy) {
this.$options.beforeDestroy = [];
}
this.$options.beforeDestroy.push(() => {
console.log(txt)
});
}
}
2019년 1월 - 이 질문에 대한 답변에 대한 경고 - 이 코드를 사용하여 동적 청취자를 추가할 때 미묘한 문제가 발견되었습니다.
this.$options.beforeDestroy.push(() => {
console.log(txt)
});
정적인 합니다.beforeDestroy
정의되어 있습니다.은 "Direct " (입니다.$options
.
, 스태틱을 beforeDestroy
은 「」, 「」의 입니다.$options.__proto__
이는 컴포넌트의 여러 인스턴스가 이전 인스턴스의 다이내믹핸들러를 상속받는 것을 의미합니다(실제로 위의 코드는 연속 인스턴스 작성에 사용되는 템플릿을 변경합니다).
이게 얼마나 현실적인 문제인지 잘 모르겠어요.앱을 탐색할수록 핸들러 배열이 커지기 때문에 상태가 좋지 않습니다(예: 매번 페이지 전환에 새로운 기능이 추가됨).
은 이 핸들러를 입니다.injectHook
핫모듈 입니다(Vue는 해 주십시오).index.js
"Vue" (Vue CLI 3을 하고 있습니다.[ Vue CLI 3 ]를 선택합니다.
function injectHook(options, name, hook) {
var existing = options[name]
options[name] = existing
? Array.isArray(existing) ? existing.concat(hook) : [existing, hook]
: [hook]
}
...
injectHook(this.$options, 'beforeDestroy', myHandler)
여기서 발생하는 것은 새로운 어레이가 인스턴스 상에 생성되고 이 인스턴스에는 모든 핸들러가 포함됩니다.__proto__
것 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , .되지 않은)되므로, 에 있는 .__proto__
핸들러 어레이
한 가지 간단한 해결책은 컴포넌트 내부에 추가하는 모든 다이내믹핸들러를 간단하게 추적하는 것입니다.
Vue.component('foo', {
template: '<div>foo component</div>',
data() {
return {
beforeDestroyHandlers: []
}
},
created() {
this.beforeDestroyHandlers.push(() => {
console.log('new handler called');
});
},
beforeDestroy() {
this.beforeDestroyHandlers.forEach(handler => handler());
}
});
new Vue({
el: '#app',
data: {
includeComponent: false
}
});
<script src="https://unpkg.com/vue"></script>
<div id="app">
<button v-on:click="includeComponent = true">Add component</button>
<button v-on:click="includeComponent = false">Destroy component</button>
<foo v-if="includeComponent"></foo>
</div>
Eric99의 답변은 유익하지만, 같은 목표를 달성하기 위해 Vue의 내부를 만지작거리는 것보다 더 쉬운 것이 있다고 생각합니다.즉, 컴포넌트에 이벤트를 사용하는 것입니다.읽기 쉽고 쓰기에도 짧습니다.
Vue.component('foo', {
methods {
logOnDestroy (txt) {
this.$on('beforeDestroy', () => {
console.log(txt)
})
}
},
beforeDestroy () {
this.$emit('beforeDestroy');
}
});
질문하실 수 있습니다.전화해야 하나요?this.$off()
메모리 누설을 방지하기 위해 이벤트를 내보낸 후?정답은 "아니오"입니다.Vue는 자동으로 이 작업을 수행하므로 위의 코드는 괜찮습니다.
Eric99의 답변은 훌륭하지만 다음과 같은 컴포넌트 내 내비게이션 가드에는 적합하지 않습니다.beforeRouteLeave
,beforeRouteUpdate
,beforeRouteEnter
- VueRouter에 의해 유지된다(및 해당 컴포넌트 컴파일 시 수집).Vue-Router가 컴포넌트의 컨스트럭터를 캐시하여 실제 컴포넌트 인스턴스 대신 사용한다는 사실로 인해 우리의 삶은 더욱 어려워졌습니다.
이 문제를 해결하기 위해 VueRouter의 내부를 조사해야 했지만 다음 코드를 생각해냈습니다._Ctor
캐시된 컨스트럭터입니다.그것만 사용해도 충분한지 확인하지 않았기 때문에 안전을 위해 컴포넌트 정의와 컨스트럭터를 모두 사용합니다.
const routeComponent = this.$route.component;
injectHook([
routeComponent,
routeComponent._Ctor && routeComponent._Ctor[0]
? routeComponent._Ctor[0].options
: null
], 'beforeRouteLeave', this.hookFunction);
function injectHook(routeComponentInstance, hookName, hookFunction)
{
(Array.isArray(routeComponentInstance)
? routeComponentInstance
: [routeComponentInstance]
).forEach(instance =>
{
if (instance)
{
const existing = instance[hookName];
if (existing && Array.isArray(existing))
{
const index = existing.findIndex(item => item === hookFunction);
if (index < 0) return;
}
instance[hookName] = existing
? Array.isArray(existing) ? existing.concat(hookFunction) : [existing, hookFunction]
: [hookFunction];
}
});
}
function removeHook(routeComponentInstance, hookName, hookFunction)
{
(Array.isArray(routeComponentInstance)
? routeComponentInstance
: [routeComponentInstance]
).forEach(instance =>
{
if (instance)
{
const existing = instance[hookName];
if (existing && Array.isArray(existing))
{
const index = existing.findIndex(item => item === hookFunction);
if (index !== -1) existing.splice(index, 1);
}
}
});
}
언급URL : https://stackoverflow.com/questions/48931936/how-to-add-vue-lifecycle-listener-dynamically
'programing' 카테고리의 다른 글
Vuex: 알 수 없는 변환 유형: 드롭다운 상태 (0) | 2022.06.12 |
---|---|
C는 C++의 서브셋이 아닐까요? (0) | 2022.06.12 |
사용자 편집 가능한 Vue 템플릿 (0) | 2022.06.12 |
java.util.stream에서 목록 가져오기Java 8에서의 스트림 (0) | 2022.06.12 |
밀리초를 "hh:mm:ss" 형식으로 변환하는 방법 (0) | 2022.06.12 |