vue
vue copied to clipboard
need a lifecycle hook which could exec when a component be going to destroy, and it happens before next component created
What problem does this feature solve?
1、though this request is because the component we use has side effect,but it brings huge convenience to implement bro component communication, cross level component communication, form data collection and so on. i tryed to remove the side effect of my component in "beforeDestroy" hook before other components which will cause conflict created, That's obviously not going to work due to the order of lifecycle hooks. 2、It is semantically counter-intuitive to have "beforeDestroy" hook called after the next component's "created" hook called. we need another lifecycle to express the semantic. it's easy to make mistakes when use beforeDestory intuitively 3、when we want component to auto use $set to bind data and use $delete to auto unbind data, we can't solve the side effect with current lifecycle hooks. and we can't find another way to achieve that.
What does the proposed API look like?
a new lifecycle hook which could exec when a component be going to destroy, and before next component created.
@yyx990803 尤大大,could this kind of lifecycle hook be possible to add? it really helps a lot
In my opinion, this may be the creation flow function of a component. If you don't want to maintain a global state yourself, Vue.minxin may be able to solve your needs.
function createComponentCreationFlowMixins(Vue: VueConstructor) {
const cleanups: Array<() => void> = []
const pushCleanup = (cleanup: () => void) =>
!cleanups.includes(cleanup) && cleanups.push(cleanup)
Vue.mixin({
beforeCreate() {
// Pass in the effect cleanup function before the component is unmounted
this.$pushCleanup = pushCleanup
},
created() {
while (cleanups.length) cleanups.pop()!()
}
})
}
In my opinion, this may be the creation flow function of a component. If you don't want to maintain a global state yourself,
Vue.minxinmay be able to solve your needs.function createComponentCreationFlowMixins(Vue: VueConstructor) { const cleanups: Array<() => void> = [] const pushCleanup = (cleanup: () => void) => !cleanups.includes(cleanup) && cleanups.push(cleanup) Vue.mixin({ beforeCreate() { // Pass in the effect cleanup function before the component is unmounted this.$pushCleanup = pushCleanup }, created() { while (cleanups.length) cleanups.pop()!() } }) }
This is a good idea to deal the side-effect created by any component. but it can't solve my problem, i'm sorry that i didn't describe the problem specifically. A simple example is as follows:
<template>
<div>
<A v-if="someController" v-bind="value"></A>
<B v-else v-bind="value"></B>
</div>
</template>
<script>
export default {
data() {
return {
someController: true,
value: {} // A or B controll it.
};
}
};
</script>
I will let A or B to handle "value", maybe the typeof A's value is { AValue: '', ...}, and the typeof B's value is { BValue: '', ...}. I want both A and B component could auto format the value type to fit it in "created" hook, and could auto reset the value to initial value{} in "beforeDestroy" hook, which is for avoid conflict between A and B.
this is just a simple example. if I don't use this way i may will use "ref" to invoke A/B's methods to collect form data. when form data has many level, and needs to combine compoents flexibly. it's a very disgusting thing to handle it. The page is as follows:

I know React is encourage Unidirectional Data flow, and change props directly is not encourage in Vue. but it's so convenient to modify data with props' ref, we just need to remember to clean side-effect (reset the data) when a component is destroying.
In my opinion, this may be the creation flow function of a component. If you don't want to maintain a global state yourself,
Vue.minxinmay be able to solve your needs.function createComponentCreationFlowMixins(Vue: VueConstructor) { const cleanups: Array<() => void> = [] const pushCleanup = (cleanup: () => void) => !cleanups.includes(cleanup) && cleanups.push(cleanup) Vue.mixin({ beforeCreate() { // Pass in the effect cleanup function before the component is unmounted this.$pushCleanup = pushCleanup }, created() { while (cleanups.length) cleanups.pop()!() } }) }This is a good idea to deal the side-effect created by any component. but it can't solve my problem, i'm sorry that i didn't describe the problem specifically. A simple example is as follows:
<template> <div> <A v-if="someController" v-bind="value"></A> <B v-else v-bind="value"></B> </div> </template> <script> export default { data() { return { someController: true, value: {} // A or B controll it. }; } }; </script>I will let A or B to handle "value", maybe the typeof A's value is
{ AValue: '', ...}, and the typeof B's value is{ BValue: '', ...}. I want both A and B component could auto format the value type to fit it in "created" hook, and could auto reset the value to initial value{}in "beforeDestroy" hook, which is for avoid conflict between A and B. this is just a simple example. if I don't use this way i may will use "ref" to invoke A/B's methods to collect form data. when form data has many level, and needs to combine compoents flexibly. it's a very disgusting thing to handle it. The page is as follows:
我可不可以这样理解,你想要将当前激活组件内部的值作为主要值,判断这些组件中某个组件是否激活的条件为该组件是否已经创建,我想你既然有变量来控制某个组件的创建状态,为什么不把这个变量用来判断将哪个组件的值作为主要值,自始至终这个功能跟一个组件的生命周期都是无关的
@nooooooom 大概就是这个意思,我其实就是想让组件自己created绑定值, beforeDestroy清空值,其实两个组件控制的值key不一样还行,如果遇到key一样就会冲突了。主要的问题是收集组件里的数据很麻烦,如果组件数据是独立的话。。
如果你不想每个组件都绑一个 key ,并且你的组件都拥有同一个父级的话,根据你的描述,用指令就能完成你的需求了
如果你不想每个组件都绑一个 key ,并且你的组件都拥有同一个父级的话,根据你的描述,用指令就能完成你的需求了
指令执行顺序是 下一个组件created => 当前组件beforeDestroy => 当前组件指令unbind,还是滞后执行unbind,不太明白指令怎么实现。如果说是它来做自动收集数据的话,不太明白咋做到QAQ
我认为数据的流向在这种情况下是没有问题的,即使你不通过 props 来传输,你也会想办法用 provide 或者全局状态来调控,
但是我认为最重要的是尽可能的减少组件中关于 “重置数据” 这段逻辑的引用,因为它不再跟 “组件是用来提供数据” 这个逻辑相关
这是一个来自父组件(或者是数据接受者自己的逻辑),指令或者组件的声明周期钩子回调都可以很好的完成这个任务
如果你不想每个组件都绑一个 key ,并且你的组件都拥有同一个父级的话,根据你的描述,用指令就能完成你的需求了
指令执行顺序是 下一个组件created => 当前组件beforeDestroy => 当前组件指令unbind,还是滞后执行unbind,不太明白指令怎么实现。如果说是它来做自动收集数据的话,不太明白咋做到QAQ
只需要在 unbind 或者 onHook:destroyed 的时候重置数据就可以了
如果你不想每个组件都绑一个 key ,并且你的组件都拥有同一个父级的话,根据你的描述,用指令就能完成你的需求了
指令执行顺序是 下一个组件created => 当前组件beforeDestroy => 当前组件指令unbind,还是滞后执行unbind,不太明白指令怎么实现。如果说是它来做自动收集数据的话,不太明白咋做到QAQ
只需要在
unbind或者 onHook:destroyed 的时候重置数据就可以了
我之前也是这样想的,我实践发现 如果下一个替换进来的组件B也使用到了这个数据,它可能会在created做初始化,那当前组件A指令的unbind和组件钩子beforeDestroy以及destroyed 执行因为迟于组件B的created,所以都会把B初始化的数据给重置了,难受
我认为数据的流向在这种情况下是没有问题的,即使你不通过
props来传输,你也会想办法用provide或者全局状态来调控, 但是我认为最重要的是尽可能的减少组件中关于 “重置数据” 这段逻辑的引用,因为它不再跟 “组件是用来提供数据” 这个逻辑相关这是一个来自父组件(或者是数据接受者自己的逻辑),指令或者组件的声明周期钩子回调都可以很好的完成这个任务
我理解你的意思是让下一个替换进来的组件自己初始化的时候来重置数据吧。这相当于让B组件来清理A组件产生的副作用了,我当时没办法了也是这样想过,可是组件创建的逻辑可能是表单初始化,也可能是联动出现。我无法判断传入的数据是服务器传过来反显的数据还是另一个组件的副作用产生的数据,很难处理
我认为数据的流向在这种情况下是没有问题的,即使你不通过
props来传输,你也会想办法用provide或者全局状态来调控, 但是我认为最重要的是尽可能的减少组件中关于 “重置数据” 这段逻辑的引用,因为它不再跟 “组件是用来提供数据” 这个逻辑相关 这是一个来自父组件(或者是数据接受者自己的逻辑),指令或者组件的声明周期钩子回调都可以很好的完成这个任务我理解你的意思是让下一个替换进来的组件自己初始化的时候来重置数据吧。这相当于让B组件来清理A组件产生的副作用了,我当时没办法了也是这样想过,可是组件创建的逻辑可能是表单初始化,也可能是联动出现。我无法判断传入的数据是服务器传过来反显的数据还是另一个组件的副作用产生的数据,很难处理
简单啊,打个脏数据的标志就行了,如果服务器的数据设置了这个值你就设置标志为 true,然后再每次数据变动的时候把这个标志清掉
你可以先把这个 issuse 转到讨论里面去,因为这跟 Vue 的底层实现无关了
我的建议还是你最好给每个组件一个 key,这样至少组件之间的数据是互不冲突的,我能不能理解为服务器传过来的是 initialValue,然后每个组件创建时都将接收这个数据作为初始,也就是你说的 {}
如果是的话那业务就很好写了,你用这个 key 去一个大对象里面拿这个组件自己维护的数据,如果这个拿到的数据是
undefined,那么你就将服务器的数据抛出去进去,当组件卸载时只需要将自己的数据清除即可