Redux/Flux(使用 ReactJS)和动画
Redux/Flux (with ReactJS) and animation
我正在学习 React+Redux,但我不了解制作动画的正确方法。让我们举例说明:
例如,我有一个列表,我想在点击时删除项目。如果我那里没有动画效果,那就超级简单了:点击时发送 REMOVE_ITEM
动作,reducer 从商店中删除该项目并做出反应重新渲染 html.
让我们添加一个点击删除订单项的动画。所以,当用户点击一个项目时,我想 运行 删除行项目的奇特效果...... 如何? 我可以想出几种方法来实现它:
1) 单击我发送 REMOVE_ITEM
操作,然后 reducer 在 Store 中将一个项目标记为 goingToBeDeleted
,然后反应使用 class 的 .fancy-dissolve-animation
渲染该元素我 运行 一个计时器来调度第二个动作 REMOVE_ITEM_COMPLETED
。我不喜欢这个想法,因为还不清楚如何在这里添加 JS 动画(例如,使用 TweenMax
)并且我 运行 一个 JS 计时器在 CSS 动画时重新渲染结束。听起来不太好。
2) 我以 ~30ms 的间隔发送 ITEM_REMOVE_PROGRESS
动作,存储有一些 "value" 代表动画的当前状态。我也不喜欢它,因为它需要我为 ~2 秒的动画复制商店 ~120 次(比如,我想要流畅的 60 fps 动画),这简直是浪费内存。
3) 制作动画并仅在动画完成后发送 REMOVE_ITEM
。这是我能想到的最合适的方式,但我仍然希望在用户执行操作后立即更改商店中的内容。例如,动画可能需要几秒钟以上的时间,并且 REMOVE_ITEM
可能会与后端同步 - 没有理由等待动画完成才能进行后端 API 调用。
感谢阅读 – 有什么建议吗?
即时动作在保存状态的 redux 中是有问题的,所以如果我们发送动作并且它会改变商店然后商店中的这种变化在下一个状态中可用,所以我们可能会出现动画一遍又一遍地显示的情况,因为在存储这样的参数已设置。
我对 redux 即时操作的解决方案是添加一些 id,例如(操作示例代码):
{
type:"SOME_ANIMATION",
id: new Date().getTime() //we get timestamp of animation init
}
接下来在运行动画的组件中保存最后一个动画 ID,如果匹配则不执行动画。例如,我使用组件状态(组件代码):
componentDidUpdate (){
if (this.lastAnimationId===this.props.animation.id)
return; //the same animation id so do not do anything
//here setState or do animation because it is new one
this.lastAnimationId=this.props.animation.id; //here set new id of last abnimation
}
谢谢 id 我们只能有一个没有反转状态的动作。超时后的反向动作可能会导致问题,因为如果其他动作(与组件连接)将在反向动作之前发送,则动画可以再次开始。
我提出的方法的缺点是动画数据存在于状态中,但也存在为我们提供有关它的信息的动画 ID。所以我们可以说 store 保存了最后调度的动画。
React 在 ReactCSSTransitionGroup 助手 class 中有一个很好的解决这个问题的方法(参见 https://facebook.github.io/react/docs/animation.html)。有了这个选项,React 会为你处理它,通过保持 child 的 DOM 状态,就像它在上次渲染时一样。您只需将项目包装在 ReactCSSTransitionGroupobject 中。这会跟踪它的 children,当它在移除 child 的情况下呈现时,而不是在没有 child 的情况下呈现,它会在 child 的情况下呈现,但会添加一个CSS class 到 child(您可以使用它来触发 CSS 动画,或者为了简单起见,您可以只使用 CSS 过渡)。然后,在超时后(配置为传递给 ReactCSSTransitionGroup 的 prop),它将再次 re-render,并从 DOM.[=11= 中删除 child ]
要使用 ReactCSSTransitionGroup,您需要 npm install react-addons-css-transition-group,然后 require/import 'react-addons-css-transition-group'。动画文档提供了更详细的信息。
要记住一件事 - 确保 children 具有唯一且不变的密钥。仅使用索引作为键会使它的行为不正确。
我正在学习 React+Redux,但我不了解制作动画的正确方法。让我们举例说明:
例如,我有一个列表,我想在点击时删除项目。如果我那里没有动画效果,那就超级简单了:点击时发送 REMOVE_ITEM
动作,reducer 从商店中删除该项目并做出反应重新渲染 html.
让我们添加一个点击删除订单项的动画。所以,当用户点击一个项目时,我想 运行 删除行项目的奇特效果...... 如何? 我可以想出几种方法来实现它:
1) 单击我发送 REMOVE_ITEM
操作,然后 reducer 在 Store 中将一个项目标记为 goingToBeDeleted
,然后反应使用 class 的 .fancy-dissolve-animation
渲染该元素我 运行 一个计时器来调度第二个动作 REMOVE_ITEM_COMPLETED
。我不喜欢这个想法,因为还不清楚如何在这里添加 JS 动画(例如,使用 TweenMax
)并且我 运行 一个 JS 计时器在 CSS 动画时重新渲染结束。听起来不太好。
2) 我以 ~30ms 的间隔发送 ITEM_REMOVE_PROGRESS
动作,存储有一些 "value" 代表动画的当前状态。我也不喜欢它,因为它需要我为 ~2 秒的动画复制商店 ~120 次(比如,我想要流畅的 60 fps 动画),这简直是浪费内存。
3) 制作动画并仅在动画完成后发送 REMOVE_ITEM
。这是我能想到的最合适的方式,但我仍然希望在用户执行操作后立即更改商店中的内容。例如,动画可能需要几秒钟以上的时间,并且 REMOVE_ITEM
可能会与后端同步 - 没有理由等待动画完成才能进行后端 API 调用。
感谢阅读 – 有什么建议吗?
即时动作在保存状态的 redux 中是有问题的,所以如果我们发送动作并且它会改变商店然后商店中的这种变化在下一个状态中可用,所以我们可能会出现动画一遍又一遍地显示的情况,因为在存储这样的参数已设置。
我对 redux 即时操作的解决方案是添加一些 id,例如(操作示例代码):
{
type:"SOME_ANIMATION",
id: new Date().getTime() //we get timestamp of animation init
}
接下来在运行动画的组件中保存最后一个动画 ID,如果匹配则不执行动画。例如,我使用组件状态(组件代码):
componentDidUpdate (){
if (this.lastAnimationId===this.props.animation.id)
return; //the same animation id so do not do anything
//here setState or do animation because it is new one
this.lastAnimationId=this.props.animation.id; //here set new id of last abnimation
}
谢谢 id 我们只能有一个没有反转状态的动作。超时后的反向动作可能会导致问题,因为如果其他动作(与组件连接)将在反向动作之前发送,则动画可以再次开始。
我提出的方法的缺点是动画数据存在于状态中,但也存在为我们提供有关它的信息的动画 ID。所以我们可以说 store 保存了最后调度的动画。
React 在 ReactCSSTransitionGroup 助手 class 中有一个很好的解决这个问题的方法(参见 https://facebook.github.io/react/docs/animation.html)。有了这个选项,React 会为你处理它,通过保持 child 的 DOM 状态,就像它在上次渲染时一样。您只需将项目包装在 ReactCSSTransitionGroupobject 中。这会跟踪它的 children,当它在移除 child 的情况下呈现时,而不是在没有 child 的情况下呈现,它会在 child 的情况下呈现,但会添加一个CSS class 到 child(您可以使用它来触发 CSS 动画,或者为了简单起见,您可以只使用 CSS 过渡)。然后,在超时后(配置为传递给 ReactCSSTransitionGroup 的 prop),它将再次 re-render,并从 DOM.[=11= 中删除 child ]
要使用 ReactCSSTransitionGroup,您需要 npm install react-addons-css-transition-group,然后 require/import 'react-addons-css-transition-group'。动画文档提供了更详细的信息。
要记住一件事 - 确保 children 具有唯一且不变的密钥。仅使用索引作为键会使它的行为不正确。