最近,我一直在研究 Facebook JavaScript 库 React.js 的功能和使用方法。当其差异说话的JavaScript的世界往往是两种编程风格的休息declarative
和imperative
被mentionned。
两者有什么区别?
最近,我一直在研究 Facebook JavaScript 库 React.js 的功能和使用方法。当其差异说话的JavaScript的世界往往是两种编程风格的休息declarative
和imperative
被mentionned。
两者有什么区别?
声明式风格,就像 react 一样,允许你通过说“它应该看起来像这样”来控制应用程序中的流和状态。命令式风格扭转了这一局面,并允许您通过说“这是您应该做的”来控制您的应用程序。
声明式的好处是您不会陷入表示状态的实现细节中。您正在委派保持应用程序视图一致的组织组件,因此您只需要担心状态。
想象一下你有一个管家,他是一个框架的隐喻。你想做晚餐。在一个命令式的世界里,你会一步一步地告诉他们如何做晚餐。您必须提供以下说明:
Go to the kitchen
Open fridge
Remove chicken from fridge
...
Bring food to the table
在一个声明式的世界里,你只需描述你想要的
I want dinner with chicken.
如果您的管家不知道如何制作鸡肉,那么您就不能以声明式的方式运作。就像如果 Backbone 不知道如何通过变异来完成某项任务一样,你不能只是告诉它来完成那个任务。例如,React 能够是声明性的,因为它“知道如何制作鸡肉”。与只知道如何与厨房接口的Backbone相比。
能够描述状态显着减少了错误的表面积,这是一个好处。另一方面,您可能在事情如何发生方面缺乏灵活性,因为您正在委托或抽象出您实现状态的方式。
想象一个简单的 UI 组件,例如“喜欢”按钮。当你点击它时,如果它以前是灰色的,它会变成蓝色,如果它以前是蓝色的,它会变成灰色。
这样做的必要方法是:
if( user.likes() ) {
if( hasBlue() ) {
removeBlue();
addGrey();
} else {
removeGrey();
addBlue();
}
}
基本上,您必须检查当前屏幕上的内容并处理使用当前状态重绘它所需的所有更改,包括撤消先前状态的更改。您可以想象这在现实世界中会有多复杂。
相比之下,声明式方法将是:
if( this.state.liked ) {
return <blueLike />;
} else {
return <greyLike />;
}
因为声明式方法将关注点分开,所以这部分只需要处理 UI 在特定状态下的外观,因此更容易理解。
最好比较 React(声明式)和 JQuery(命令式)以向您展示差异。
在 React 中,你只需要在方法中描述你的 UI 的最终状态render()
,而不必担心如何从之前的 UI 状态转换到新的 UI 状态。例如,
render() {
const { price, volume } = this.state;
const totalPrice = price * volume;
return (
<div>
<Label value={price} className={price > 100 ? 'expensive' : 'cheap'} ... />
<Label value={volume} className={volume > 1000 ? 'high' : 'low'} ... />
<Label value={totalPrice} ... />
...
</div>
)
}
另一方面,JQuery 要求您强制转换 UI 状态,例如,选择标签元素并更新它们的文本和 CSS:
updatePrice(price) {
$("#price-label").val(price);
$("#price-label").toggleClass('expansive', price > 100);
$("#price-label").toggleClass('cheap', price < 100);
// also remember to update UI depending on price
updateTotalPrice();
...
}
updateVolume(volume) {
$("#volume-label").val(volume);
$("#volume-label").toggleClass('high', volume > 1000);
$("#volume-label").toggleClass('low', volume < 1000);
// also remember to update UI depending on volume
updateTotalPrice();
...
}
updateTotalPrice() {
const totalPrice = price * volume;
$("#total-price-label").val(totalPrice);
...
}
在现实世界的场景中,将会有更多的 UI 元素需要更新,加上它们的属性(例如,CSS 样式和事件监听器)等。如果您使用 JQuery 强制执行此操作,它将变得复杂和乏味;很容易忘记更新 UI 的某些部分,或者忘记删除旧的事件处理程序(导致内存泄漏或处理程序多次触发)等。这就是错误发生的地方,即 UI 状态和模型状态超出同步。
React 的声明式方法永远不会发生状态不同步的情况,因为我们只需要更新模型状态,而 React 负责保持 UI 和模型状态同步。
您还可以阅读我对编程中声明式范式和命令式范式的区别是什么的回答?.
PS:从上面的jQuery例子,你可能会想,如果我们把所有的DOM操作放在一个updateAll()
方法中,每次当我们的模型状态发生变化时都调用它,UI永远不会不同步。你是对的,这正是 React 所做的,唯一的区别是 jQueryupdateAll()
会导致许多不必要的 DOM 操作,但 React 只会使用其Virtual DOM Diffing Algorithm更新更改的 DOM 元素。
这是一个很好的比喻:
*紧急响应:出停车场北口左转。沿 I-15 向南行驶,直至到达 Bangerter 高速公路出口。从出口右转,就像你要去宜家一样。直行并在第一个红绿灯处右转。继续通过下一个灯,然后左转。我的房子是#298。
声明性回复:我的地址是 298 West Immutable Alley, Draper Utah 84020*
https://tylermcginnis.com/imperative-vs-declarative-programming/
命令式代码指示 JavaScript 如何执行每个步骤。使用声明式代码,我们告诉 JavaScript 我们想要做什么,并让 JavaScript 负责执行这些步骤。
React 是声明式的,因为我们编写了我们想要的代码,而 React 负责获取我们声明的代码并执行所有 JavaScript/DOM 步骤以使我们达到我们想要的结果。