最近,我一直在研究有关Facebook JavaScript库React.js的功能和使用方法。当其差异说话的JavaScript的世界往往是两种编程风格的休息declarative
和imperative
被mentionned。
两者有什么区别?
Answers:
声明式的样式(如react所具有的样式)允许您通过说“它看起来像这样”来控制应用程序中的流程和状态。命令式风格可以解决这个问题,并允许您通过说“这是您应该做的”来控制应用程序。
声明式的好处是您不会陷入表示状态的实现细节中。您要委派保持应用程序视图一致的组织组成部分,因此您只需要担心状态。
想象您有一个管家,他是一个框架的隐喻。而且你想做晚饭。在当务之急,您会逐步告诉他们如何做饭。您必须提供以下说明:
Go to the kitchen
Open fridge
Remove chicken from fridge
...
Bring food to the table
在声明性世界中,您只需描述您想要的内容
I want dinner with chicken.
如果您的管家不知道怎么做鸡,那么您就不能以声明式的方式进行操作。就像Backbone不知道如何变异自己来完成某项任务一样,您也不能仅仅告诉它去完成该任务。React之所以具有声明性,是因为它“知道如何做鸡肉”。与Backbone相比,后者只知道如何与厨房交互。
能够描述状态可以大大减少bug的表面积,这是一个好处。另一方面,由于委派或抽象化了实现状态的方式,因此事情发生的灵活性可能较低。
想象一个简单的UI组件,例如“ Like”按钮。当您点击它时,如果它先前是灰色的,它将变成蓝色,如果它先前是蓝色的,则变成灰色。
这样做的必要方法是:
if( user.likes() ) {
if( hasBlue() ) {
removeBlue();
addGrey();
} else {
removeGrey();
addBlue();
}
}
基本上,您必须检查屏幕上当前显示的内容,并处理将其重绘为当前状态所需的所有更改,包括撤消先前状态的更改。您可以想象在现实情况下这可能有多么复杂。
相反,声明性方法将是:
if( this.state.liked ) {
return <blueLike />;
} else {
return <greyLike />;
}
因为声明式方法将关注点分开,所以它的这一部分仅需要处理UI在单独状态下的外观,因此更容易理解。
这是一个很好的类比:
*紧急命令:从停车场北出口出来,左拐。在I-15州际公路上向南行驶,直到到达Bangerter Highway出口。就像您要去宜家一样,在出口处右转。一直走并在第一个路口右转。继续穿过下一盏灯,然后左下。我的房子是#298。
声明性答复:我的地址是犹他州德拉珀84020,西不可变胡同298
https://tylermcginnis.com/imperative-vs-declarative-programming/
最好将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更新虚拟元素。
当务之急是在现实生活中进入啤酒酒吧,并向酒保提供以下说明:
-从架子上拿杯
-将玻璃杯放在草稿的前面
-拉下把手直到玻璃杯装满
-把玻璃杯递给我。
相反,在声明性世界中,您只会说:“请啤酒。”
要求啤酒的声明式方法假定调酒师知道如何为某人服务,这是声明式编程工作方式的重要方面。
在声明式编程中,开发人员仅描述他们想要实现的目标,因此无需列出使之工作的所有步骤。
React提供了一种声明式方法,这一事实使它易于使用,因此,生成的代码很简单,这通常导致更少的错误和更多的可维护性。
由于React遵循声明性范式,因此无需告诉它如何与DOM交互;您只需声明要在屏幕上看到的内容,然后React为您完成工作。
声明式编程是一种编程范例……它表示计算的逻辑而不描述其控制流程。
命令式编程是一种编程范式,它使用更改程序状态的语句。
参考链接:-https: //codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2
我以一个类比开始:我有两辆车,在我的两辆车中,我希望车内的温度为正常的室温〜72°F。在第一辆(较旧的)汽车中,有两个用于控制温度的旋钮(一个用于控制温度的旋钮和一个用于控制气流的旋钮)。天气太热时,我必须调节第一个旋钮以降低温度,并可能改变气流),反之亦然。这是当务之急!我必须自己控制旋钮。在我的第二辆(较新的)汽车中,我可以设置/声明温度。这意味着我不必费力调节旋钮即可调节温度,因为我知道汽车声明/将其设置为72°F,并且汽车将必须完成该状态。
React是相同的,您声明标记/模板和stat,然后React进行必要的工作以保持DOM与您的应用程序同步。
<button onClick={activateTeleporter}>Activate Teleporter</button>
无需使用.addEventListener()
事件处理程序,而是声明所需的内容。单击该按钮后,它将运行该activateTeleporter
功能。
Imperative programming: telling the "machine" how to do something, and as a result what you want to happen will happen. Declarative programming: telling the "machine"1 what you would like to happen, and let the computer figure out how to do it.