Why I don't like KnockoutJS
A few times I've ruffled a few features by making the statement that I am not a fan of KnockoutJS.
Let me start by clarifying a few things:
- I think the concept of KnockoutJS is a good one
- It's nothing against Steve Sanderson, to have come up with it in the first place is impressive
- This is my opinion and I will still recommend that others try it and form their own opinions.
Ok so on to backing up my statement and let me start by showing you why I am not a fan:
<button data-bind="click: registerClick, enable: !hasClickedTooManyTimes()">Click me</button>
Can't see it? I'll remove some of the 'guff':
data-bind="click: registerClick, enable: !hasClickedTooManyTimes()"
Right there, the data-bind="..." is what I don't like, the fact that I'm embedding potentially large amounts of JavaScript in my HTML.
So ultimately what it comes down to is that I have an issue with the binding syntax that is used with KnockoutJS. Now I (think) understand why it is like this, KnockoutJS has a lot of relationships with the WPF/ Sliverlight binding idea (and MVVM obviously) so it makes sense to people coming from those backgrounds. Me, I'm not a WPF/ Silverlight developer, never have been (I did try my hand at WPF but just didn't get very far...).
Why does it bother me?
You may be asking yourself that if the problem I have is with the syntax and not concept then where's the real issue, heck it's only a small part of it.
And this is where it gets into the "don't take my word, use it yourself" part of the post. I'm a web purest and I believe there should be a strict separation between your UI and your functionality, even in the client aspect. This means that your HTML file should only contain HTML and your JavaScript file is where the client 'brain' resides.
Having been around ASP.Net for a while (and particularly Web Forms) the idea of obtrusive JavaScript is something that you grow up with. You're use to seeing in-line event handlers, JavaScript tacked at the bottom of the page, etc. This is a smell, your HTML file is no longer responsible for what HTML is, a mark-up language, it's starting to try and become self aware, to intrinsically know that when I click a button some JavaScript has to be fired, that kind of stuff.
This is smarts that I don't want my HTML to have.
In the web we've also seen a shift on this in recent years away from have JavaScript in HTML, and even within Microsoft we've seen them acknowledge this with the jQuery unobtrusive validation plugin which was released with MVC3.
The shift has seen us using HTML to describe the intention. Using the jQuery unobtrusive validation as an example we use the data-validate-* attributes to describe our validation rules, and then we use JavaScript to convey those rules into a functional concept.
This results in a clean separation between HTML and JavaScript with HTML going back to just describing intention and JavaScript taking those intentions and running with it.
Conclusion
This post has basically outlined my primary grievance with KnockoutJS. As stated, I don't have a problem with the concept of it, the idea of two-way binding is quite nice but what's required to achieve that is where the issue lies.
Comments
José F. Romaniello
There should not be complex javascript code in the data-binding side.
In the other hand when you talk about separation between UI and HTML (or templates), I feel that when I am not using knockoutjs I have to use a lot of jquery selectors in the functionaly, so I don't have a simple javascript binding in the html, but i have a complex html selection in the "functionality" side. This means that my -templates- are very independent from my functionality but the functionality itself is very tied to the templates.
What do you think about this?
(I am a js beginner)
Gustavo
I see your point, however when you do this:
$("#some-id").click(function(e){e.preventDef....(); viewModel.clickedMe();}); //wire up in javascript.
What you have right there is html as a placeholder which makes no sense without the javascript that tights the knots, and javascript is doing two very different things, having your model logic mixed with dom manipulation. Your rendering logic is separated in two parts instead of one.
HTML is not what it used to be. Using knockout.js you can have your domain model in javascript, and your rendering logic in html/templates. Now the rendering logic is in only one part.
Elijah Manor
Knockout appears very powerful and I would guess it appeals greatly to the Silverlight and WPF crowd since they are more familiar with the whole MVVM approach.
I have some of the same concerns as you've mentioned (about mixing concerns). I'm not a Knockout user, but I've heard there are ways to wire it up without putting code in the attributes, but it seems most examples I see are combining the two.
Brandon Satrum has actually extended it somewhat here... http://userinexperience.com/?p=689
Kenneth Solberg
I've been using KO for some time now and really like it. I prefer clean javascript over clean markup in web applications where you'd typically use KO. Recently our design team dropped a complete html rewrite of an app and all we had to do was to copy the databinding attributes over, without even touching the underlying javascript layer - saved us a lot of time!
jim
Unobtrusive KnockOut.js might solve your problem: http://joel.net/unobtrusive-data-binding-for-knockout-js
Kenneth Solberg
FYI - some of your dislikes regarding mixed concerns has been addressed in 1.3 and a beta was released earlier today. Check it out at link text
Gareth Evans
What if the bindings worked like this:
$knockoutJs.databind("body > ul > li > a", "click: registerClick, enable: !hasClickedTooManyTimes()");
Soo, combine a CSS selector with the data-bind attribute?
I've been playing around with KO and while I tend to agree with you on the mix of HTML+JS, the power of the observable seems pretty good
Gareth
Asti
You couldn't possibly have got it more wrong.
What you want is the logic of the views to reside within the views, and the business logic to be part of your code.
It's a more higher level separation than HTML/CSS and JS. MVVM is a clean separation between UI/Models.
$("#searchText") <- referring to UI from within business logic.
-_-
Asti
You couldn't possibly have got it more wrong.
What you want is the logic of the views to reside within the views, and the business logic to be part of your code.
It's a more higher level separation than HTML/CSS and JS. MVVM is a clean separation between UI/Models.
$("#searchText") <- referring to UI from within business logic. = (eventual) FAIL -_-