我应该使用Knockout MVC,而不是Knockout JS吗?

54

另一位用户建议使用Knockout MVC来处理一些AJAX发布问题。 我了解了一些相关信息,发现它是基于Knockout JS封装的。所以我想知道这两者之间真正的区别在哪里?既然有Knockout MVC,是否还需要使用Knockout JS呢?什么时候应该使用其中的一个而不是另一个呢?

12个回答

123

Knockout MVC 是 WebForms 的私生子。它通过控制器操作路由所有视图模型方法,这意味着每个操作都必须在客户端和服务器之间来回传输。我无法理解为什么有人会拿像 Knockout 这样的客户端MVVM框架,并强制让它调用每个函数时都要访问服务器。

此外,在服务器上执行这些方法意味着整个视图模型需要传递到服务器,然后再传回到客户端,对资源非常浪费。

使用 Knockout MVC 意味着牺牲了客户端代码的所有性能优势,只是为了不写 JavaScript。这与 WebForms 做出的同样的权衡相似,但并不明智,而且是一种反模式。

如果 Knockout MVC 明天消失了,网络世界将变得更好。


10
我“推测”这是为了借助C#和ASP.NET这两种我也喜欢的好技术,吸引更擅长它们的人来关注KO的流行。但是,我同意使用KO MVC而不是KO没有什么好理由。KO的主要优点之一是丰富的客户端和低网络聊天。 - John Papa
4
@JohnPapa 在学习 Knockout 之前,我很喜欢 C# 和 ASP (MVC)。在我们的行业中,不愿意学习新技术和新技巧是一种错误的立场,特别是当这会导致您采用效率低下的技术。如果您想要开发网页应用程序,学习 JavaScript 是必须的! - Kyeotic
5
需要翻译的内容:我认为重要的是要记住这些行为有适当的用法。例如,一个具有添加/编辑/保存按钮的单页应用程序需要与服务器通信。在传统的提交方式中,你会发送表单并获得整个渲染的 HTML 返回。但使用 Knockout MVC,则仅需返回 json 而不是整个页面。使用 AJAX 方法则需要自己编写 JS 和控制器代码。所以在这种情况下,Knockout 可以节省您重复编写JS的时间,并比传统方法更高效。就像任何东西一样,它可以被正确地使用或者被滥用。 - AaronLS
3
@Tyrsius,我很高兴找到了这个页面,感谢你提供的信息。我被更轻松的开发体验所吸引,并考虑在我的当前项目中使用KMVC,但不确定是否应该依赖于第三方库而没有更多了解。幸运的是,我的谨慎让我来到了这个页面。你提到的服务器调用使得使用Knockout失去意义,这一点至关重要,并成功地阻止了我使用KMVC(对KMVC开发人员表示敬意)。约翰·帕帕(John Papa)同意你的观点,这是至关重要的决定因素。我将选择纯粹的KO+MVC。 - David Barrows
2
Tyrsius完全错了,也许你从未使用过KnockOutMVC来创建完整的应用程序。需要数据操作(CREATE,UPDATE,DELETE)的应用程序需要服务器端功能才能工作,没有这个是无法生存的。 KnockOutMVC为客户端创建整个模型,处理与服务器的连接,并创建具有绑定客户端使用的视图。所有客户端逻辑都在客户端中保留,无需服务器,也许你误解了它正确的使用方式。 - Diego Mendes
显示剩余24条评论

21

我刚看到这个有一些非常负面的回复的问题。我会快速加上我的两分钱。

我刚刚开始使用 KnockoutJS。由于我正在构建 ASP.NET MVC 应用程序,因此对我来说使用类似 Knockout MVC 的东西似乎很合理。在大多数情况下,这似乎是一个好主意。如果我可以使用我所知道和喜爱的 .Net 功能来完成相同的工作,我就不想花时间编写 javascript 和 <!-- ko --> 注释。

话虽如此……目前 KMVC 有限制。将整个模型发送回服务器是其中之一。因此,我已经开始了自己的 knockout-mvc 分支。目前的更改必须匆忙进行。但是,我现在能够:

  • 创建子上下文(具有完全不同的模型或视图模型组件)
  • 在调用服务器时返回所选部分的模型
  • 期望从调用返回与发送内容不同的模型
  • 在 ajax 调用周围触发事件
  • 支持更多 html5 输入类型
  • 通过标头向服务器传递防伪令牌(用于 ajax 调用)
  • 可能还有我忘记的其他功能

我希望很快就会回来,真正整理我所做的事情。希望作者能将这些更改包含在他的代码中。如果不是,我想我会继续使用自己的分支。无论哪种方式,都有曙光。KMVC 可能需要工作,但我相信这个概念绝对值得做。

我肯定认为

如果 Knockout MVC 明天消失了,网络会变得更好。

有点过于苛刻了。

编辑:

我正在查看评论并再次查看原始问题。在这样做之后,我认为我的答案应该再加一点:

首先,原始问题是“我是否有理由使用 Knockout MVC 而不是 Knockout JS?”为了回答/澄清这个问题(也许我只是太挑剔了):Knockout MVC 是一个框架,旨在使将 KnockoutJS 集成到您的 ASP.NET MVC 应用程序中更容易。它主要通过使用熟悉的强类型构造生成 KnockoutJS 标记来实现这一点。它并不是 KnockoutJS 的替代品。一定要使用 KnockoutJS 。问题实际上是是否要同时使用 Knockout MVC。

话虽如此,作为开发人员,选择何时使用可用工具的各种方面仍然取决于您自己。如果您想通过向服务器执行完整请求来处理某个功能方面,请执行该操作。如果您想执行 ajax 请求以检索/更新数据,请执行该操作。如果您想完全在客户端执行功能,则请执行该操作。

使用 Knockout MVC 不会阻止您充分利用 KnockoutJS。使用 Knockout MVC 不会阻止您编写其他 JavaScript 代码,以处理尽可能多的客户端功能。仅因为 Knockout MVC 为您提供了一种生成向服务器的 ajax 回调的快捷方式,就不意味着您必须使用它们。虽然,如果应用程序持久存储数据,那么它必须在某个时候调用 home。

与仅使用 Apache 提供静态 HTML 和脚本文件相比,使用 ASP.NET MVC 构建应用程序后端有其优点。Knockout MVC 允许您继续利用这些同样的好处来辅助 KnockoutJS 的集成。


7
我认为“我不想花时间编写JavaScript”既是KMVC存在的原因,也是它最大的缺陷。当你试图避免使用JavaScript时,你与Web进行斗争。 - Kyeotic
2
@Tyrsius,我必须不同意你的看法。我并不是试图避免使用JavaScript。我只是想避免手动编写JavaScript,而可以使用工具来代替我完成这项工作。这也是我首先会使用KnockoutJS的原因。我本来可以自己编写这些功能,但既然已经有了一个完整的工具集,为什么还要费力去做呢?同样地,为什么要在我的文件中手动编写JavaScript(至少是基本部分),当我可以让KMVC为我完成呢?结果页面应该没有任何区别,只是开发工作量不同而已。 - Nigel Whatling
1
除了结果页面上的差异,您的答案已经解决了这个问题:KMVC需要服务器做任何事情。而普通的KnockoutJs应用程序则不需要。这不仅是开发工作量的差异,也是性能上的差异。 - Kyeotic
我认为你在假设最坏的情况。如果正确使用,KMVC 应该是一种辅助生成 Knockout 绑定等工具。性能优势仍然存在。当然,Web 应用程序仍然需要依赖服务器来至少执行初始页面生成……就像任何基于 Web 的应用程序一样。 - Nigel Whatling
1
除非它们仍然存在。一旦视图模型函数去服务器执行其逻辑,就像KMVC中的任何视图模型函数或“computed”可观察对象一样,性能优势就已经丧失了。Knockout会在客户端完成这个过程,而KMVC需要一个服务器请求。无论如何,KMVC都要为不编写JavaScript而交换性能和响应能力。 - Kyeotic
显示剩余2条评论

13

我认为Tyrsius的回答有点太消极了。Knockout MVC仍处于早期开发阶段,但从我所看到的来看,它具有一些优势,比如与Webforms相比减轻了服务器负担。可见性依赖完全在客户端处理,仅在使用函数时才会调用服务器。当使用复杂数据结构时,有时仍需要通过服务器进行处理,因此使用Knockout MVC可能是节省大量自己编写Ajax处理的好方法。

确实,它总是发送整个模型来回传输,这会带来一些额外开销,而不是自行构建。但我不会完全排除它的可能性。特别是当未来有了针对复杂验证的适当客户端处理时。


6
那么你对这个框架最好的评价就是它将来会变得更好吗? - Kyeotic

11

我在搜索有关knockout mvc的信息时发现了这篇文章。虽然我同意浪费网络带宽是不好的,但是这行代码还是让我很心动:

@{
  var ko = Html.CreateKnockoutContext();
 }

这是一种整洁简洁的方式,用于生成 knockout 视图模型。有人只使用 knockout MVC 的这个特性而没有将所有逻辑移到服务器端吗?


3
我很想看到对此的回应,因为我发现自己在客户端重复了很多我已经在服务器端编写过的代码。 - IronicMuffin
7
我发现一种不需要使用KnockoutMVC的方法,只需使用Knockout Mapping即可:var myViewModel = ko.mapping.fromJS([将MVC模型返回为JSON]);。这种方法不需要使用AJAX。 - Lasse Espeholt
我已经停止使用Knockout转向AngularJS了,但还是感谢你分享这个 :) - Sam

8
Knockout.js的优美之处在于,你可以仅通过将JSON传来传去来为你的应用服务,无需推送整个视图,这样服务器就不必费力生成HTML。但是,将其放回到服务器上似乎非常违反直觉!如果你对此感兴趣,最好使用razor语法来完成你的绑定。我的建议是使用knockout.js来进行绑定,以便在客户端而不是服务器上进行绑定,如果这是你追求的目标。如果你想要在服务器上数据绑定你的视图,请使用razor。

2
@jimtollan 看起来使用 KO-JS 你需要在客户端和服务器端分别编写 ViewModel,这似乎不太明智。KO-MVC 似乎解决了这个问题,但我没有意识到它带来了一系列其他问题。 - dotnetN00b
1
@dotnetN00b,这是真的。在某些情况下,Knockout映射插件可以解决此问题,但在其他情况下,您可能需要编写两个视图模型。问题是,您的C#视图模型不应该具有相同的功能,只需使用props即可。任何客户端操作都将在您的KO视图模型中进行,而任何服务器操作(如果有)都将在C#中进行。作为交换,您可以保持快速,高效的客户端视图和一致的数据。 - Kyeotic
@dotnetN00b,并不是总是这样的。在大多数情况下,我发现 ViewModel 只在 JavaScript 中定义,因为控制器操作只会发送基于领域模型的 JSON,而不是单独的视图模型。 - OnResolve
@Tyrsius 我一直在使用KO来构建单页应用程序,因此我会推送一个单独的、通常非常简洁的视图。其余的工作是通过相互传递JSON进行通信完成的。对于非单页应用程序,我想你可能两者都有--我的评论只是让他知道这并不总是情况 :) - OnResolve
@Tyrsius 好的,我的视图模型(服务器端)只是模型。我有其他处理业务逻辑的类(也在服务器端)。 - dotnetN00b
显示剩余3条评论

6
我也看到了许多使用Knockout MVC库的好例子。我很难将KnockoutJS集成到我们的MVC Web应用程序中,这正是例如@ChinaHelloWorld指出的原因。以下是我发现它非常有用的一些情况。
1. 强类型绑定 我喜欢漂亮的强类型HTML helper方法,但在设置KnockoutJS时变得完全无用和杂乱。我能做的最好的事情就是手动附加我的绑定属性到带有辅助方法的额外参数上,但我仍然需要在那里使用魔术字符串。我喜欢Knockout MVC提供的helper,用于创建具有强类型、基于C#表达式的绑定的输入和其他元素。但是,我想在此提到,我错过了生成的字段的名称属性,所以我需要进行微调。
2. 强类型绑定语法(有点) 使用纯字符串绑定时,总有可能拼写错误,或者不知道要应用的正确绑定格式。使用Knockout MVC和VS IntelliSense的流畅API可以轻松应用正确的绑定。
3.(几乎)自动从计算的C#属性转换为计算的绑定 只需应用小的[Computed]属性,Knockout MVC即可生成正确的KnockoutJS语法中的相应绑定表达式。我认为这个非常有用。
4.无视图模型代码重复 在传统方式中,我需要在C#代码中拥有视图模型类,然后在JS中(几乎)相同的视图模型代码(带有可观察对象)。对我来说,那真是令人沮丧。当我看到Knockout MVC中使用的技术时,我非常高兴。但是,我需要微调它,以便能够将其与真正复杂的视图模型(嵌套视图模型、集合等)一起使用,并且能够扩展映射的Knockout视图模型,例如任何所需的自定义JS方法或计算可观察对象。
所以,这里至少有四个非常好的要点。至于viewModel往返:没有人告诉我们必须使用Knockout MVC的服务器端处理机制。如果没有一些真正需要在服务器上处理的复杂业务逻辑,我也不会使用它。但是,在大多数情况下,Knockout MVC只是为了简化MVC Views和KnockoutJS的绑定和设置过程。因此,我不太理解上面的不良意见。我认为撰写这些意见的人没有花费精力学习Knockout MVC的基本概念。你绝对不应该使用Knockout MVC代替KnockoutJS,而是在KnockoutJS之外使用。无论如何,在任何情况下,理解Javascript和至少了解KnockoutJS的基础知识仍然是必要的。
我希望作者继续开发Knockout MVC,因为除了这些好点外,还有一些功能和改进,可以使它变得更加强大。

关于第四点:如果你在客户端有一个好的映射/合并技术,那么你不需要复制你的viewModel。因此,在这里,我只有一些在服务器上不需要设置的Model属性,这样我就不需要在两个方面都创建它们。 - David Freire
1
@DavidFreire 在不太复杂的应用程序中,这是正确的,但是在构建真正复杂的应用程序时,最终我总是希望已经声明了那些可观察对象。例如,如果我想创建一个基于其他可观察对象的计算属性,那么我必须将它们声明出来,不能即兴映射它们。实际上,在过去的一年中,我已经放弃了 Knockout MVC 并使用了自己的服务器端帮助程序,并且我已经创建了一个“工具”,将我的 C# 模型转换为 TypeScript。这种技术整体效果非常好。如果有时间,我会在某个地方公开这个工具。 - Zoltán Tamási
你是完全正确的,如果在视图中使用计算观察器,这确实是一个问题,但对于更简单的情况,它可以工作。 - David Freire
@ZoltánTamási,你有没有发布过你提到的那个工具? - kayess
@kayess 如果你指的是C#转TS的“转换器”,我还没有发布它,虽然我仍然想发布,但不幸的是,我没有计划这样做,因为这需要相当多的工作量,而我在这些年里真的很少有空闲时间。我将其用作我们内部框架的一部分。不过,互联网上有几个类似的选项。 - Zoltán Tamási

6
更多地说,knockout.js非常擅长于客户端数据的展示、删除、插入和更新,以及客户端数据计算。如果真正的业务逻辑如此简单,我们就可以直接应用knockout.js。
但事实上,业务逻辑并不总是像那样简单。例如,当客户端在视图中插入一个新记录时,系统可能需要检查用户的身份验证,根据某些业务逻辑或公式为新创建的对象设置默认值等等...总之,这些都应该在服务器端进行,并基于数据库数据进行检查逻辑。
开发人员可以将所有所需的业务逻辑转换为knockout.js视图模型内的JavaScript方法。但是这种方式违反了集中处理业务逻辑的规则。
这种设计的维护将成为噩梦。
总之,框架选择真正取决于业务要求。有时,性能并不是首要考虑因素。

4
在 .Net MVC 模式中,视图模型已通过标记“@model yourmodel”明确地标记在每个视图/局部视图中,这可以引导开发人员了解此视图中将要执行的操作。
当使用 Knockout.js MVVM 模式时,您可能不会看到任何 .Net 视图模型,除了视图中的"data-bind"标签。这将使视图和控制器解耦,并且对于团队中的新开发人员而言,跟踪逻辑变得困难。
我相信 KnockoutMVC 可以解决这些问题,并节省大量的 JavaScript 代码,这会使系统难以维护和理解。
由于 KnockoutMVC 仍然应用服务器端视图模型设计,因此易于跟踪和维护,因为它是 C# 代码。
对于业务项目,经理应始终关注易于开发、易于维护、易于升级、易于理解和快速交付以赚取利润。
牺牲一点性能,使其简单,客户端和服务器端的一致性应该是一个关键点。JavaScript 是一个很大的维护问题。
将整个视图模型发送回服务器端真的很重要吗?如果是,我们可以将大型模型拆分为几个小模型。

基于非常痛苦的经验,我非常赞同并认为非常出色。 - Terry Delahunt

2

如果您不使用由komvc生成的函数,仍然可以保持性能。正如Nigel所说,初始页面生成仍然必须由服务器生成。您始终可以添加用户脚本并在客户端创建函数,这些函数不需要返回到服务器。这是一种为开发人员提供生产力的工具。与Web表单的性能比较肯定是夸大其词的。各位,这确实是一个有助于您满足截止日期的工具。


1
我会支持knockoutjs,尽管与knockout MVC相比,它的编写可能有些复杂,但在可重用性方面获得的好处是巨大的。客户端代码也可以与其他技术协同工作。
除了安全方面的考虑,我个人认为knockout js是一种让asp.net MVC变得复杂的方式,应该像纯RESTful应用程序(如asp.net webapi)一样使用它(knockout js)。

什么安全角度? - Homer
如果你在使用客户端来管理隐藏/显示和其他通常在knockout示例中完成的功能,通常需要向客户端发送更多的信息。 - pilavdzice
从我的角度来看,安全性是非常重要的。你可以参考这个例子:http://stackoverflow.com/questions/19375173/mvc-4-web-api-security - Govin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接