FreeOZ论坛

标题: 发起了一个Javascript开源MVVM框架 [打印本页]

作者: woodheadz    时间: 29-9-2013 23:11
标题: 发起了一个Javascript开源MVVM框架
上周打算在项目中引入MVVM框架,研究了下现在流行的几个框架,感觉要么过于复杂,要么实现方式让人不太舒服。
于是趁周末自己做了一个,结果感觉还不错,有潜力发展成一个很棒的MVVM框架。干脆就放到Github上,打算以MIT协议开源发布。
我把这个框架取名为knot.js. 因为MVVM框架的使用过程最重要的部分就是在数据和UI之间“打结”把它们绑成一堆  :-)

比较目前流行的几个javascript mvvm框架,knot.js的特征是:
1. 注入式,不要求对数据对象做任何改变。你甚至直接可以用来自服务器的JSON对象作为你的model,knot.js会自动建立监控,当数据改变时更新自动UI。而目前的javascript mvvm框架大多要求修改model,甚至要求从指定对象继承来产生model才能以支持双向绑定。

2.超级轻量。目前压缩后的代码核心+扩展不足12k,但已经能实现45k大小的knockout.js的大部分功能,实际上做得更多,比如knot.js提供了非常方便的数据验证支持。

3.简单。knot.js避免在html标记中加入太过于复杂的逻辑,转而提供很方便的javascript扩展模块引入机制。不把用户限制在一堆复杂而功能有限的语法内,让程序和标记做各自最擅长做的事。


下图是一个常见的增删改界面,包括数据录入,修改,删除,各项数据合法性,重复性验证, 以及界面上各个控件的状态控制(enable, visible, 选中状态...)等等。用knot.js不过一点简单的代码就能搞定。
[attach]276549[/attach]

knot.js的标记是这个样子:
[attach]276551[/attach]

代码已经传到github上。今天晚上赶了个网站初稿,暂时放在这儿:http://knotjs.atwebpages.com/.  
如果你对参与这个框架的工作感兴趣,可以直接上github fork一下提出自己的改进意见。对于设计方面的问题可以和我直接交流。

作者: black_zerg    时间: 30-9-2013 09:40
提示: 作者被禁止或删除, 无法发言 Very interesting!
Would you like to share your opinions on MVC, MVP and MVVM?  
Since this is a MVVM framework, would you like to draw a diagram to explain the implementation ?  

'注入式,不要求对数据对象做任何改变。你甚至直接可以用来自服务器的JSON对象作为你的model',
does that mean the view-model is always a dynamic one? how you do data-binding then?
作者: woodheadz    时间: 30-9-2013 11:44
black_zerg 发表于 30-9-2013 09:40
Very interesting!
Would you like to share your opinions on MVC, MVP and MVVM?  
Since this is a M ...


框架一般都有个特点,就是解决的问题越多,框架本身就会越复杂,学习成本越高,适用的情况越少。当然一旦用对了,威力也就越大。就knot.js的定位来说,和knockout.js的定位基本上是一样的,偏轻量,避免涉及太深层次的问题,仅仅关注于数据和UI之间的绑定和同步。

knot.js和其它mvvm理念上最大的一个不同点在于:目前的mvvm框架都有个特点或者说是趋势,就是越来越倾向于把逻辑放在标记中。一些大的框架比如angularjs,甚至还可以在标记里进行数学运算运算。 我认为这是明显的过渡设计。这种做法的确能进一步减少javascript代码量,但减少的其实部分以一种更难看的形式分散出现在标记里。html标记本来就够乱七八糟了,再摆一堆由各种奇葩符号包起来的逻辑进去还真是嫌世界不够乱!  
knot.js 的解决方案就是"converter".  举个例子,比如要显示利润,小于零的时候红色,大于则绿色。
在knockout.js里你要这么做:
  1. <div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }">
  2.    Profit Information
  3. </div>

  4. <script type="text/javascript">
  5.     var viewModel = {
  6.         currentProfit: ko.observable(150000) // Positive value, so initially black
  7.     };
  8.     viewModel.currentProfit(-50); // Causes the DIV's contents to go red
  9. </script>
复制代码
在knot.js里你这么做:

  1. <div knots="style: { color: *currentProfit =>profitValueToColor}">
  2.    Profit Information
  3. </div>
  4. <script type="text/javascript">
  5. var profitValueToColor={to: function(value):{return value<0?'red':'black‘;}}
  6. </script>
复制代码
knot.js的做法的好处在于首先,你的转换逻辑可以重用,一旦需求发生变化,比如从红色变为绿色那么改一个地方就好。其次这个转换的逻辑复杂程度knot.js没有任何限制,用js代码啥都能做出来,knockout.js限制就很大了。所以knockout.js经常得根据显示的需求在model上创建些属性进行转换。


关于knot.js怎么完成数据双向绑定,说起来神秘,其实是个不值钱的小trick。 knot.js内建了个键=>值列表,每个绑定的数据对象在表中都有一个对应的附加信息,数据更新时的callback就存在这个附加信息上(此外还有数据的验证结果也在上面)。当值发生改变的时候取出callback函数call一遍就完了。现在还有个不大完美的地方就是如果在代码中修改值,需要用Knot.setValue来更改,不能自己直接用object.property的方式,否则界面不会更新。这本来也能解决,让knot在绑定的时候修改数据对象把原来的property替换成Knot监控下property即可。但我对于这点还有疑虑,主要是担心如果用户没有解除绑定就序列化数据到服务器或者worker线程里的话,数据会不会有问题。所以暂时没这么做。
作者: black_zerg    时间: 30-9-2013 12:37
提示: 作者被禁止或删除, 无法发言 "一些大的框架比如angularjs,甚至还可以在标记里进行数学运算运算。 我认为这是明显的过渡设计"
I totally agree with that. Actually I basically against the using of '标记'.

I see you have a lot of great ideas. Still I believe to make a good framework, a solid design on the data flow is essential (a diagram at least).

For example, since you called it a MVVM framework, you might want to explain how you implement these 3 parts, how they work together, what are the base class for each part(if you are using prototypical class) and how to extend them.

Actually I am biased as I am not fond of 2 way data-binding. I think it won't be flexible enough when things get complicated.

I fear some frameworks just make simple things easy and difficult things impossible


作者: woodheadz    时间: 30-9-2013 13:14
black_zerg 发表于 30-9-2013 12:37
"一些大的框架比如angularjs,甚至还可以在标记里进行数学运算运算。 我认为这是明显的过渡设计"
I total ...

不可极端化。
标记里面写太多逻辑不是好做法,但不用标记,以代码来完全控制UI也不是好办法。最好的做法必然是两者间的一个平衡点。我之所以重新设计一个mvvm框架,最重要的原因就是因为不认可其它框架所选取的平衡点。
knot.js里标记的作用被严格限定为“绑定”,也就是做一个代码和UI属性之间的关系定义。 这个定义很明显放在标记端比放在代码段优势大得多也灵活得多。
two-way-binding是必须的,只要有UI录入,你必然不可避免这个逻辑的存在。不用two-way-binding意味着你的代码量会有一堆event handler,那才是设计的灾难。
作者: black_zerg    时间: 30-9-2013 15:00
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 30-9-2013 15:08 编辑

I don't agree. I would prefer HTML is HTML, CSS is CSS and JS takes care of dynamic logics.
The fact that Jquery is so popular has proved that we can create sophisticated apps without fancy data-binding or in-line tags. and in most really life cases, people are quite happy about that.

Let s look at the problem at a higher level, the view is supposed to be isolated from the 'domain logic' or 'binding logic'. I don't see why having ugly tags in html is a good thing. I was never a fan of struts, webwork or JSF, and so happy when I found AJAX makes life so easy. Now I see people are bringing these old clumsy designs to JS world, just makes me sad.

'two-way-binding是必须的,只要有UI录入,你必然不可避免这个逻辑的存在'. That is a good point. I would agree there must be some glue logic to fetch data from server (Model), then populate them to HTML DOM tree(view). In MVC, the logic is in controller; in mvp, it is in presenter; in MVVM, it is supposed in ViewModel. However I would suggest the 'GLUE' logic needs to be inside code as we can't guarantee the fancy background magic always fits the needs. because the 'glue' logic are not always the same.

Still, I am very interested in your project. Maybe you can explain your idea from a high level when you have time.

As I said before, my experience about 2 way data-binding is normally it makes simple things easy and difficult things impossible. And since it is a 'framework', during project development, you can't simple stop using it when the framework doesn't fit the need, doesn't improve productivity or becomes a burden. Then the team will have a long and painful fighting with the framework until everyone is exhausted.
作者: black_zerg    时间: 30-9-2013 15:27
提示: 作者被禁止或删除, 无法发言 Sorry forgot to explain my point, I think a 'lib'  is more useful than 'framework'. for example we can create a 'Form' widget which does 2 way binding to a json object, a 'List' widget works with 'Form' widget and bound to a json Array. something like that would be useful.
I am more interested in creating 'component' rather than 'framework' unless I am certain one way of 'data gluing' is always better than another.
作者: woodheadz    时间: 30-9-2013 15:27
本帖最后由 woodheadz 于 30-9-2013 15:33 编辑
black_zerg 发表于 30-9-2013 15:00
I don't agree. I would prefer HTML is HTML, CSS is CSS and JS takes care of dynamic logics.
The fa ...


其实high level的东西都很简单,我们都了解需要一个你说的glue logic存在,这其实不需要讨论。此外我们也明白系统逻辑之间要尽量降低依赖性,这也是不需要讨论的。

所以关键的问题上是这个逻辑该以什么方式存在。

现在的框架对于这个问题倾向于尽量用标记解决,你倾向于用代码解决,而knot.js,也就是我的观点是在你们二者的中间。

我认为这个glue放在标记里优势是极其明显的,无论是从降低工作量的角度说还是从增加可维护性的角度说都是如此。所以我不同意你的观点。

但其它MVVM框架的观点我也不同意。他们实际上是想完全通过标记来描述数据对象<=>UI 对象之间的关系。这听起来很酷,但实际上数据对象和UI对象之间的关系也是非常复杂的,可能有大量的业务逻辑在里面。而标记本身的纯逻辑描述能力就很弱,你非要用它来描述逻辑那不是吃饱了撑的么。

knot.js就是彻底只解决“glue”这个问题,可以把东西glue到UI组件上,但这个东西不一定直接就是数据。中间你可以粘converter和validator,再把converter,validator粘到数据上。

把knot.js的做法拔高务虚的来说,就是knot.js的世界里 不是只有m=>v, 而是还有 m=>vm=>v。 其它的mvvm框架试图通过标记来完成vm的部分,而knot.js把vm的部分完全放开用javascript实现,把自己的角色单纯化,只负责规划组织的部分 ,然后把自己变成一个好用的“glue”。
作者: woodheadz    时间: 30-9-2013 15:29
black_zerg 发表于 30-9-2013 15:27
Sorry forgot to explain my point, I think a 'lib'  is more useful than 'framework'. for example we c ...

component和framework直接我觉得也是有个平衡点,我不偏向任何一方。所以我不喜欢太过于复杂的框架,但我同时认为框架也有自己不可替代的重要作用。
作者: woodheadz    时间: 30-9-2013 15:31
woodheadz 发表于 30-9-2013 15:27
其实high level的东西都很简单,我们都了解需要一个你说的glue logic存在,这其实不需要讨论。此外我们也 ...

对了,忽然come up了一个knot.js的宣传口号:
Give to code what is code's, and to markup what is markup's.
怎么样? 哈哈
作者: black_zerg    时间: 30-9-2013 15:44
提示: 作者被禁止或删除, 无法发言 Markup in html simply doesn't make sense to me.

A HTML Dom element IS a component it self, it has it's view and model API (same as VM in MVVM).
If required, developer creates a new new component(Class) to wrap a list of elements. So it will be reused in a similar scenario.

'Creating' the component and 'Using' the component are 2 different tasks. Mixing them only make the code looks very confusing.



作者: woodheadz    时间: 30-9-2013 15:57
black_zerg 发表于 30-9-2013 15:44
Markup in html simply doesn't make sense to me.

A HTML Dom element IS a component it self, it has ...

我发现你的想法和我想法的区别可以归结到你前面提出的“component”和framework的问题上。

我猜你可能在潜意识里有这么一个误区,认为component 和framework是两种相互对立的概念。其实不然,这两者之间根本没有任何冲突。
component解决的是具体的问题,framework提出更多是一个解决问题的思路,组织系统的办法,比component宏观。这两者描述的是两个不同层面上的问题。

一定程度上,你说framework是“using component”是正确的,但这里不存在“mix”的问题,因为framework不是component。你愿意自己为每个项目的每个ui组件编写代码当然没问题,但如果你觉得这些重复劳动是无价值的工作,那么为什么不把这些工作丢给framework来解决呢?
作者: woodheadz    时间: 30-9-2013 16:13
black_zerg 发表于 30-9-2013 15:44
Markup in html simply doesn't make sense to me.

A HTML Dom element IS a component it self, it has ...

纯粹从设计哲学上来说说这个问题:
component可以视为是对一个具体问题的具体解决办法的重用包装, 而framework是对一个解决问题的方法论的重用包装。
你为了using component而创建的“component”,一旦做到了重用,那么就是framework。因为你包装的对象不是某个具体的component,而是如何使用component的方法。
作者: black_zerg    时间: 30-9-2013 16:57
提示: 作者被禁止或删除, 无法发言 let me put is in this way:


A component is design to solve a certain problem. It doesn't make sense to create one component to solve all problems.
Because that means you API will be very complicated and become the 'Problem'.

Every time we create a component, we basically make the API simpler to better fit our needs. But at the same time, the system will become less 'powerful' or 'flexible' if you like.
Now the question is: Doesn't it make sense to create a component(Class) for the Whole application (which will be a Framework). My answer is no because I feel the current APIs (HTML, js, css, etc) are necessary because of the variety of my requirement. I am not convinced a subset of these APIs is good enough.
It is like in OOP programming, you need to decide when & when not to create a Class.

for example, what if the new app is not using JSON at all, what if the new app needs some UI component that your data-binding logic doesn't fit?

My suggestion will be, say if you are very interested in data-binding and view-model concept, you just create Widgets(component) to do certain things.

Those framework guys been working on their frameworks for years. I am interested in their presentations and feel they are very smart/passionate. but would not use their frameworks personal because I don't see much value except creating GDP.
Now you think your solution is better and more concise, but when new requirements comes you will have to add more and more logic. Your API will grow fat I am afraid.

作者: black_zerg    时间: 30-9-2013 17:05
提示: 作者被禁止或删除, 无法发言
woodheadz 发表于 30-9-2013 15:57
我发现你的想法和我想法的区别可以归结到你前面提出的“component”和framework的问题上。

我猜你可能 ...

The reason I said that was because I value the quality of a component(Class), once it is created it needs to stable, predictable and has very clear and well designed functions (API).

When working with those frameworks, you have to create a lot of half baked 'components', and you have to use some weird API which is more difficult to understand than the natural DOM.  

作者: woodheadz    时间: 30-9-2013 17:27
本帖最后由 woodheadz 于 30-9-2013 18:38 编辑
black_zerg 发表于 30-9-2013 16:57
let me put is in this way:


大哥,我前面讲了framework不是component。另外framework也不是solve all problems的。
这里面有个度的问题,过犹不及,不足也有不好。 我就是嫌其它的js mvvm framework解决问题的范围过度了,所以才自己又重新做一个出来。

具体到你说的例子,knot.js既然支持json对象,那么当然也能支持普通对象。 knot.js对UI component支持接口很简单,你自己创建一个对新UIcomponet的扩展也只是举手之劳。

就像你用面向对象去写hello world会增加很多不必要的复杂性一样,你用framework去解决简单的小问题也会增加复杂性。 但是随着你系统的的扩大和复杂程度的增加,使用framework带来的好处很容易就能盖过framework增加的复杂性。这就是为什么在中大型项目里或多或少都会采用一些framework的原因。 其实现在的小项目用framework的也很多。

framework应用起来自然是要比单纯使用component要求要高些,所以使用framework失败(带来的坏处比好处多)的例子的确不少。但这不是framework的问题。

技术一直在进步,从过程化到对象化再到组件化和框架化,每一个进步都在增加复杂度,因为每一个进步其实都是提出了新的方法而不是推翻了前面的方法。例如面向对象的程序内部一定也有很多过程化的逻辑,所以面向对象技术必然比过程化技术复杂。
你不能单纯的因为复杂度增加来拒绝一项技术,你要看承受这个增加的复杂度后收益是否值得。我建议你还是可以放开对framework的成见去尝试下吧。
作者: woodheadz    时间: 30-9-2013 17:40
black_zerg 发表于 30-9-2013 17:05
The reason I said that was because I value the quality of a component(Class), once it is created i ...

我理解你对使用framework后带来的这种“不安全”的感觉。 这不是错觉,事实上的确存在。如果系统的需求远远超出了framework的能力,那么会带来很严重的问题。
所以我一向不大喜欢太过于复杂的framework,那样风险会增加。另外在一些特别的场景下,贸然使用framework也是很危险的。
我们公司的产品在我进入公司的时候大量的使用了wpf内置的绑定framework来进行渲染,导致效率很低。我进入公司半年后提出来的重构方案第一个就是移除wpf绑定,自己来写viewmodel层。最后完成后极端情况下效率提高了90多倍。 但这是一个产品项目,另外这个项目里只有核心的渲染部分移自己建立了vm层,其它普通的ui全部还是用的wpf绑定,因为实在是很方便,很好用。

这里面就是一个度的问题。程序员最核心的经验和价值所在,也就在这个度的选择上。
作者: black_zerg    时间: 30-9-2013 19:15
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 30-9-2013 19:19 编辑

Cool, keep up the good work then! I will be following your project. Later I may implement your demo in my way then we can compare. Quite happy to find someone interested in js and innovation
作者: woodheadz    时间: 30-9-2013 19:24
black_zerg 发表于 30-9-2013 19:15
Cool, keep up the good work then! I will be following your project. Later I may implement your demo  ...

  
的确可以用不同的方案实际做做,比较下
作者: woodheadz    时间: 30-9-2013 20:51
black_zerg 发表于 30-9-2013 19:15
Cool, keep up the good work then! I will be following your project. Later I may implement your demo  ...

我刚才很仔细的想了想为什么会有不少人觉得用了framework有点不够安全。
结论是很多framework都是个复杂的大黑盒子,一旦出问题,即便绝大多数时候都是使用的人自己的问题,但要找问题的话跟踪调试的时候到了framework里面就不行了。 framework和component又不一样,component一般只会在运行过程的一端,你只要确保进入component之前没问题或者处理component的事件响应没有问题就OK,而framework往往存在于一次代码运行过程的两端,有时候中间还要占上几段。这样要调试找出问题来就头疼了。

所以呢,我决定为Knot.js增加一个debug模块,让knot.js的内部运行状态白盒化! 这个模块将作为附加模块存在,正式发布的时候可以排除,基本不会增加文件大小
作者: black_zerg    时间: 30-9-2013 22:56
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 30-9-2013 22:59 编辑

just created a simple demo to mimic yours.
http://glue.atwebpages.com/

There is no validation logics yet but you can see the idea. I really don't like the in-line markup thing. That is messing with the view, and very intrusive.  
作者: black_zerg    时间: 30-9-2013 23:09
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 30-9-2013 23:21 编辑
woodheadz 发表于 30-9-2013 20:51
我刚才很仔细的想了想为什么会有不少人觉得用了framework有点不够安全。
结论是很多framework都是个复杂 ...


主要的问题是,使用框架的风险是很大的。如果是库,我今天用了,明天发现不对头我还可以换,而且如果库有问题,一般很容易发现。但整个程序按照框架来建的话,项目做到一半发现这个框架问题很多,或者说文档不行,程序员没搞明白作者思路,代码混乱了,这时候就悲剧了。就像我上面说的,框架都是做简单的东西(或者说在看作者的例子)的时候,觉得狂容易。头疼的时候都是在后来,因为实际项目中什么千奇百怪的要求都有可能出现,而且团队的话,每个人思路和技术背景都不同,多数情况下还是用原生接口保险。就好象大家都说英文并不是说英文多优秀,只不过这玩意通用。
我为什么讨厌html写标记就是因为这玩意不伦不类,又不是规范语言,可能很简洁,但不见得好懂,更不要提调试。 其实代码最后并不是拼简洁,清晰易懂更重要。

用框架还有一个最可恨的地方就是代码逻辑跑动的很厉害,往往一个流程跳跃好几个文件,出了问题难查得很。 若干年前我用struts用得不亦乐乎,后来发现随便干点什么事都得有五六个文件参与。仔细一想早年用jsp的时候一个文件就解决了。开发的时候还没什么,维护系统帮别人改bug的时候就想跳楼了。

我很赞同你的这个加强logging的想法。不过真的要推广框架还是很难的。你做两个很好用的widget我还会更有兴趣。你想想那么多 MXX的框架,都是有团队在嗨哟嗨哟的折腾,实话说我看也就那么回事吧,增加GDP而已,不然大家没的事情干。

不过这个精神我还是很佩服的,这年头有点兴趣的人不多了,都是混日子。
作者: woodheadz    时间: 30-9-2013 23:41
black_zerg 发表于 30-9-2013 22:56
just created a simple demo to mimic yours.
http://glue.atwebpages.com/

嗯。 你这个demo不错。
刚好可以和用了框架的比较下。 你这个demo基本上没有去处理数据验证和控件的状态控制这些烦人的问题。但已经比使用框架的代码量多得多。这里还没包含你凭空写的东西的时候设计代码工作流程和组织代码的成本。这个例子比价简单也许很低,但如果是个更复杂的界面,这个成本也不小。

凭空写的demo的代码量和可阅读性可维护性是完全不能和使用了框架后的来比较的,还有团队里各个成员因为编码风格和喜好不同带来的隐性成本。

程序员都不会太喜欢markup,但如果你要和设计师合作,那就不同了。把你的这个demo放在一个设计师的面前让他去做设计处理,他一定会崩溃的。
作者: woodheadz    时间: 30-9-2013 23:59
本帖最后由 woodheadz 于 1-10-2013 00:06 编辑
black_zerg 发表于 30-9-2013 23:09
主要的问题是,使用框架的风险是很大的。如果是库,我今天用了,明天发现不对头我还可以换,而且如果库 ...


那么多的框架,刚好就说明框架本身很有用,是大家的兴趣热点。
你说的框架的问题我理解。用好框架本身也是个很有技术含量的活儿。但所有的问题最后都归结为你的投入是否值得产出。
其实面向对象技术也是一样的。用不好的人比用得好的人多得多,因此产生了大量的过度设计和丑陋代码。也有人因此认为面向对象不过是花式。 这和你对framwork的观点是一样的,太偏激了。

回到knot.js上来说,我之所以会强调knot.js的注入性,限制Knot.js的范围,就是为了让knot.js在任意时候都能方便的退出。 和java里面那些动不动就涵盖整个程序生命周期的大框架不同,knot.js 对系统的控制极小。你不信可以试试,在我的那个demo的基础上,把初始化用的knot.tie()注释掉,整个Knot.js就从你的系统里消失了。 你会发现你不用修改任何东西就可以直接用你喜欢的方式加入javascript来完成整个功能。 你退出knot.js的成本几乎为0.  
另外Knot.js也能和你的自定义代码共存。你完全可以在knot.js不能帮你解决问题的地方彻底使用自己的代码来完成工作嘛。

你对框架的印象看来还只停留在java里面那些控制欲超强的大框架上。这个世界上的框架可不都是这样的哦

作者: black_zerg    时间: 1-10-2013 00:08
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 1-10-2013 00:28 编辑

我从来没说不可以造framework,我的观点是第一如果没有理论基础,我们很难折腾出比别人好的东西。所以我才再三问你你的基本思路架构是什么,怎么个MVVM法。
MVVM的话,最重要的部分就是ViewModel,因为基本上大部分的胶水逻辑都会在这里。
我的代码是随手刚写的,基本上基于MVC。 因为我很久不做crud了,也没怎么仔细想过这个事情。 但是我还是相信动态的页面逻辑,就用纯JS解决比较好。HTML和CSS去解决布局和静态的。

设计师对我的demo为什么崩溃,你看了源码了么?就是两个div而已。相反的如果都是mashup夹在html里,那才要崩溃。


‘你完全可以在knot.js不能帮你解决问题的地方彻底使用自己的代码来完成工作嘛’ 你看到这句话的问题没有,如果是类库,那么这话就是合理的, 代码也不会太难看也好跟。那如果你做框架,让一个团队以这个为核心开发,那这个就会变成一个很伤人心的事。我以前的一个项目就是所谓databinding,这东西你说他不管用吧,他也管点用,你说他管用他又不全管,总之就是他那套东西,我们也得巴巴的写,然后还有一大段手写代码或者workaround, 一个增删改就是一堆文件,模板还有手写代码,每个人的解决方案可能还各不相同。如果几个实体类有点关系,要在界面上显示这个层叠,就比登天还难。打电话找支持,他说你这个需求不对,不应该这么用。客户要求这样,那我们能说客户要求不对么?简直就是渣。他那个databinding当然更牛b一点,一直要绑到数据库表,改它的流程是极痛苦的。这时候我整天想的就是如果让我写jsp操一下表,我分分钟就解决了

当然了,一个项目大家修修改改做了几年,也不是坏事,要看你怎么看了。但是要说这玩意提高生产力,那就是笑话。

当然每个人看法都是主观的从自己经验出发,我只是觉得这玩意很难搞,也许你能做个更好的或者说起码很适用你的情况的,那还是很有可能的。
作者: woodheadz    时间: 1-10-2013 00:30
black_zerg 发表于 1-10-2013 00:08
我从来没说不可以造framework,我的观点是第一如果没有理论基础,我们很难折腾出比别人好的东西。所以我才再 ...

我当然是看了你的源码才这么说的。

就两个div, 设计师打开你的网页,什么都看不到。他怎么设计?
你的每个录入框在什么地方? 如果他要往上加css怎么办?要调整位置大小怎么办? 你列表中动态创建的的项目,如果他想往里面加一个图形背景该怎么办?
夹在html里的markup丝毫不影响html设计。所有的HTML设计软件都会自动忽略这些不认识的tag,并且原样保存。

我的理论基础前面也和你讲过了,就是把vm里面的胶水部分和业务逻辑分离,把业务逻辑回归代码。 比着现有的js框架,我自然是有突破。你可以拿和我这个框架最接近,同时也非常流行的Knockout.js来比,knot.js的优势是非常明显的。我相信我能折腾出比knockout.js好的东西,实际上我这个用一个周末折腾出来的东西就已经在很多地方比knockout.js好了。

我觉得咱们这个讨论有点往于口舌之争的方向发展了。我们还是不要去讨论什么framework和component, markup和code比较好。这些问题太虚,讨论不出什么结果的。

还是讨论具体的技术问题比较好。

作者: black_zerg    时间: 1-10-2013 00:30
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 1-10-2013 00:32 编辑

其实我们证明各自的观点很简单的,等你的东西做得差不多了,我们来找一个复杂的例子,然后去实现,这样就好比较了。最好是有点用的东西,比如content management system 之类的,我们可以一起做一个开源的来玩玩。
作者: woodheadz    时间: 1-10-2013 00:35
black_zerg 发表于 1-10-2013 00:30
其实我们证明各自的观点很简单的,等你的东西做得差不多了,我们来找一个复杂的例子,然后去实现,这样就好 ...

这个问题不大。我现在在做我们公司的online版本。里面的UI交互会全部采用这个框架,到时候上线了你去看吧。


作者: black_zerg    时间: 1-10-2013 00:42
提示: 作者被禁止或删除, 无法发言 你说的很有道理,回头我来修改我的代码,让流程做到方便设计师。
作者: woodheadz    时间: 1-10-2013 00:42
black_zerg 发表于 1-10-2013 00:08
我从来没说不可以造framework,我的观点是第一如果没有理论基础,我们很难折腾出比别人好的东西。所以我才再 ...

你还是很牛,业界流行了这么多年的框架理念在提高生产力方面可以被你批成笑话。

我没你那个高度的认识,我一向对框架兴趣都不小,我自己负责设计任务的几个大项目里都有各种框架的使用,我觉得效果大多不错。当然也许我做那些项目不过也是笑话而已
作者: black_zerg    时间: 1-10-2013 00:53
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 1-10-2013 00:55 编辑
woodheadz 发表于 1-10-2013 00:42
你还是很牛,业界流行了这么多年的框架理念在提高生产力方面可以被你批成笑话。

我没你那个高度的认识 ...


我说的是我那个项目的框架,开始的时候被认定能提高生产力最后无论因为什么原因就是个大悲剧。
我对databinding是有很深的成见的,你去搜索 databinding evil这样的词你就会发现不光是我这么说。 这些个mvvm的框架搞了有两三年了吧,我反正看来看去都跟以前模板之类的蛮像的,个人不感冒。
每个人应用场景不同有观点很正常,我已经说我根本就很久不做crud了,我也没有什么专职设计师,所以我的观点都是从我的角度看的。可惜我们观点不同,不然也许可以一起做个开源项目什么的。这个是我做的地图控件 http://glue.atwebpages.com/demo/tutorial.html 其实也没什么用,因为已经有现成的了,就是无聊自己做着玩的
作者: woodheadz    时间: 1-10-2013 01:05
black_zerg 发表于 1-10-2013 00:53
我说的是我那个项目的框架,开始的时候被认定能提高生产力最后无论因为什么原因就是个大悲剧。
我对da ...

这个就保持不同吧。

地图我也前也搞过,曾经以google地图为基础做了一个sns游戏,买卖地块,互相打仗,可惜最后失败了,血本无归啊...
作者: black_zerg    时间: 1-10-2013 01:10
提示: 作者被禁止或删除, 无法发言 我现在准备写一个编辑流程图的东西,again, 也没什么用,就是闲的。 其实现在有一个比较有意思的东西是typescript,流水线开发会是个利器。他的首席设计师是很牛的一个。语言我试了一下,第一印象相当好。
作者: woodheadz    时间: 1-10-2013 01:22
black_zerg 发表于 1-10-2013 01:10
我现在准备写一个编辑流程图的东西,again, 也没什么用,就是闲的。 其实现在有一个比较有意思的东西是type ...

anders嘛,这个世界上要是单说编译器和语言设计,他排第二估计没人敢排第一。 typescript 从anders第一次在teched上做typescript介绍的时候(好像是去年?)我就一直在跟进。
作者: black_zerg    时间: 1-10-2013 11:15
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 1-10-2013 11:42 编辑

OK, i updated my demo to suit designers
http://glue.atwebpages.com/
  1. <div id="listDiv">
  2.         <div>[sex].[name] <hr/> age:[age] ,from:[from]</div>
  3. </div>
  4. <div>
  5.     <div id="formDiv">
  6.                 <label>Name<input name='name'/></label>
  7.                 <label>Sex <select name='sex'>
  8.                         <option>male</option>
  9.                         <option>female</option>
  10.                 </select> </label>
  11.                 <label>Age<input name='age'/></label>
  12.                 <label>From<input name='from'/></label>
  13.         </div>
  14.     <button id="btn_new">New</button>
  15.     <button id="btn_delete">Delete</button>
  16. </div>

  17. JS

  18. var form = new Form('formDiv');   
  19.     var list = new List('listDiv', form);
  20.     list.decorator = function (m) {
  21.         m.sex = m.sex=='female'?'Miss':'Mr';
  22.     };
复制代码
Don't you think this way is easier to understand?  I have 2 classes Form and List here, they basically work on top of HTML elements and adding certain behavior.
call me old fashion I just don't get those MVVM frameworks.

You see the point? the List and Form widgets are very much predictable. They are light-weighted and designed with clear functions instead of forcing developers to follow some 'pattern'
They are tools not rules.
作者: woodheadz    时间: 1-10-2013 13:12
black_zerg 发表于 1-10-2013 11:15
OK, i updated my demo to suit designers
http://glue.atwebpages.com/Don't you think this way is easi ...


看来我们的确是生活在两个不同世界的人啊...

我有一次面试招人的时候对一个坚定的认为oo是花架子,只有面向过程才是简洁设计的老程序员说过一句话:如果一个技术或者思想很流行,已经被广泛接受,那么在你还没有在这个技术上取得过成功的使用经验之前,最好不要轻易对这个技术做出是或者否的判断。否则很容易就把自己局限在一个小空间里,无法取得突破。 现在再把这话拿出来,大家共勉吧。


作者: black_zerg    时间: 1-10-2013 13:57
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 1-10-2013 14:05 编辑

I like to discussion technology, since it is what I am really interested in. I don't see argument is a negative thing, I see it is a chance to learn , but you may not agree with that.  Let's use code to prove our opinions.

I got an idea, let us implement TODO MVC respectively  . How about that?  
作者: woodheadz    时间: 1-10-2013 14:23
black_zerg 发表于 1-10-2013 13:57
I like to discussion technology, since it is what I am really interested in. I don't see argument is ...

不用比了。我们是两个世界的人。
我会和人讨论天安门广场上的国旗的红色正不正,但我不会去讨论那个国旗颜色是不是绿色的。我看你还真回头去吧前面的demo改了一道,看来你真心认为你的解决方案更好。

对于js ui前端开发所面临的问题,现在人们的工作方式等信息你似乎了解不多(不然也不会犯那么明显的错误),另外在framework方面你似乎也没有成功的使用经验(所以你也许并不能真正体会到framework思想的优势,也不能真正理解framework的问题)。那么你大可不必这么急迫的想要证明你有比我的解决方案更好的解决办法。
Knot.js参考了wpf,knockout.js,angularjs,emberjs等多个框架,这些框架不知道凝聚了多少人心血。knot.js柔和了设计思想中我认为好的部分,加上了些我自己的微创新。也许你依然不能理解为什么这些绑定框架为什么就能比你的做法好?但在你在js 前端和framework方面获得更多的经验之前,不妨观望下,多了解下,不要着急吧这个?号改成!号吧。

作者: black_zerg    时间: 1-10-2013 14:52
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 1-10-2013 14:59 编辑

look, it seems like you are very interested in me now. -you just keep expressing your opinions about me. Does that really interest you?

I just don't get it. Don't you think it is a interesting thing to discuss and investigate?  to find out which way is better by deep thinking, instead of the reasons like 'they are so popular' .  If you really feel you are right, and I am wrong, can't you explain your idea calmly?

Well, what ever. That is why Chinese can't work together.  
作者: woodheadz    时间: 1-10-2013 15:00
本帖最后由 woodheadz 于 1-10-2013 15:04 编辑
black_zerg 发表于 1-10-2013 14:52
look, it seems like you are very interested in me now. -you just keep talking about me, and your opi ...


正相反,我很早就对你不感兴趣,只不过强打精神陪聊罢了(非要我说这么清楚?)。 我的工作经历涵盖四个国家,n个大小差异巨大的团队,一向以协作能力特强而自豪。我在这个帖子里表现出来的惊人的耐心(我自己都有点吃惊)就是证明。

解释可以让别人同意广场上国旗的红色基本还是正的,只不过晒退了点色而已,但不可能让一个人为那是绿色的人同意那颜色其实是红色。
当然,也许那颜色本来就是绿色。但无论如何,这都只能说明我和那人不是一个世界的。
作者: black_zerg    时间: 1-10-2013 15:21
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 1-10-2013 15:28 编辑

calm down man, that was uncalled for.
So far only me replied your post. Wasn't it a great opportunity for you to advocate your new framework by proving I am wrong?
I apologize if you think my opinions against those M** frameworks are somehow offensive to you. And now I understand that you don't want to have a deep discussion or do some coding comparisons. All good my friend. Don't make it personal. I don't know you dude. we don't work together and I was just killing my time by playing with code, and kind of hoping you can illustrate me why those M** are helpful.
作者: woodheadz    时间: 1-10-2013 15:47
black_zerg 发表于 1-10-2013 15:21
calm down man, that was uncalled for.
So far only me replied your post. Wasn't it a great opportun ...


... 我们双方的demo都在这儿了,明摆着的,这就是最好的prove了,还需要prove其它什么?
你想让我告诉你你什么地方错了,对不起,我已经很努力的尝试过了,我承认这在我的能力范围之外。我甚至不太婉转的提醒你,如果对这行不大了解,不妨先学习学习再来讨论“对”和“错”,“好”和“坏”这么大的问题。 看来这个提醒是没效果。
话都说到这个份上了,你再继续就是胡搅蛮缠了。我们俩一定是生活在不同的星球上的,在freeoz的所有议题上,咱们都保持距离吧。不然都是白费口舌。
作者: escctrl    时间: 1-10-2013 17:54
I am following this very interesting discussions..Continue  please , you are not alone.
作者: woodheadz    时间: 1-10-2013 18:31
本帖最后由 woodheadz 于 1-10-2013 19:36 编辑
escctrl 发表于 1-10-2013 17:54
I am following this very interesting discussions..Continue  please , you are not alone.


The last parts are not a discussion. I was crashed by black_zerg, again. Maybe you can save this discussion.
作者: black_zerg    时间: 1-10-2013 21:15
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 1-10-2013 21:39 编辑

你说话就和跟基督教的人说话一样,上帝就是存在,怎么你说不存在?书上写的,你读了么?大家都说存在,我这么牛的人都说存在了。基督教那些都还很客气,你则不停的人身攻击 “什么?你说不存在?你弱智吧,你回家读几年圣经再来说话”。
我想大家都有十几年的经验了吧,有必要不停的摆弄你的资格么? 什么mXX的框架多了,遇到被比较,被问框架有什么优点的,我所见到都是认认真真谦虚的回答,人家那些真正的大牛,就职google的也没见像你这么狂妄。就你这样还开源呢。   

一开源框架,连个设计理念也说不清楚,基本框架图也没一个,todoMVC是每个框架必然要实现的东西,在你这里也不当回事。土鸡还觉得自己是个战斗机,只能说呵呵呵。我之前都是一直想认真的讨论下技术问题,对你的跳脚行为也没怎么在意,结果你还来劲了。

有兴趣的可以看一下我们两人的demo。算是这楼唯一有点价值的。我的是看了这个帖子 用手写MVC去实现他的功能,他的是基于他自己的所谓MVVM框架 。我是只看到点databinding, 没看出来MVVM里最重要的VM在那里,这位神仙也不屑说明。
我的主要观点是 html里面大量的markup不好, 维护麻烦。 也就是一个个人观点,为此还特地写了代码来证明Markup未见得比code好写,指望能有点有意思的讨论,也不知道这位跳什么脚。大家互相不认识,犯不上没事辱骂对方吧

http://knotjs.atwebpages.com/
http://glue.atwebpages.com/
作者: woodheadz    时间: 1-10-2013 21:46
black_zerg 发表于 1-10-2013 21:15
你说话就和跟基督教的人说话一样,上帝就是存在,怎么你说不存在?书上写的,你读了么?大家都说存在,我这 ...

你冤枉我了。我其实一直回答的都很认真...
虽然我后来发现原来你根本就不熟悉这个领域,不只不熟悉js前端,同时你对重用,架构等方面的知识也很贫乏。我一开始还以为你说的真是component,后来才发现就是个class包装了下的东西,毫无重用性可言。  但我还是很注意自己的发帖,对你保持足够的尊重。
直到你让我看你的修改版demo。 我实在忍不住了,很抱歉。
我在freeoz上和人吵架次数不少,你只怕更多些。我们在绝大多数问题上观点相悖,但也争论过很多次了。我发现在所有和你的争论中,我都几乎无法取得任何进展。争论前后你我的观点都没有任何改变。这是绝无仅有的。其它人争论到最后,要不然就是观点越差越远,要不然就是逐渐贴近。而和你永远都是毫无改变。所以在除了技术以外的地方我都是见你就躲,退避三舍。
没想到技术方面也是一样的结果。你的demo我仔细点评过了。为了让你更能理解我的话,我做个比喻:

我做了口切菜刀来给大家看,让大家点评。我期待收获的答案是别人告诉你刀这儿不好用,那里不好用,或者刀太软,不能干这事,不能干那事。

而你老兄直接上来就说我这刀是没用的,太大,你当年用大刀就切了手了。有用的是你那几口小刀。我承认我这刀不小,也承认很多地方刀小才好用。但我也说了,刀大也有刀大的好处,这好处用好了还很不错。
然后你就亮出你的刀了,component。
拜托,你拿出来的是个木头棒子啊,不是刀子,大哥!component是一个关于重用性的概念,component不是class,那是不同的东西!
我点评了,也提醒你了。最后还告诉你,刀子是银色的,不是那木头色。
然后我以为没事了。


最后你亮出了涂成银色的木头。


抱歉,求求你以后像我躲你一样,也躲着我吧。和你扯皮的功夫真的够我喝一壶了。
作者: woodheadz    时间: 1-10-2013 22:02
本帖最后由 woodheadz 于 1-10-2013 22:04 编辑
woodheadz 发表于 1-10-2013 21:46
你冤枉我了。我其实一直回答的都很认真...
虽然我后来发现原来你根本就不熟悉这个领域,不只不熟悉js前 ...


对了,我为什么管你哪根棒子叫“木头棒子”,而不是铁棒呢,是因为你那个demo明显过度设计了。
不打算重用的东西还花那么多精力去包装,简单的逻辑为了看上去像个mvc而非要拿到个对象里去,面向对象对象不是这么用的啊...  真以为面向对象来了就什么都得放对象里? 你去看看Martin fawler那本关于面向对象设计模式的书,其中最详细的一个例子里,一个对象都没用到。
作者: black_zerg    时间: 2-10-2013 12:22
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 2-10-2013 14:51 编辑

http://glue.atwebpages.com/demo/tutorial.html

My implementation of the map widget (similar to openlayers or leaflet). It's my hobby project for killing time. Have a look and let me know if  woodheadz 's comments really make sense:  '根本就不熟悉这个领域,不只不熟悉js前端,同时你对重用,架构等方面的知识也很贫乏'

woodheadz, If you don't mind, stop criticizing me and give some real opinions OK? for example, can you fancy 'MVVM' framework help build a complicated widgets like that? Oh, right, maybe it was only designed to do the simplest CRUD for your little projects?  Then sorry for asking. well done mate.

http://glue.atwebpages.com/chart/index.html
another demo created this week to try functional inheritance.

作者: woodheadz    时间: 2-10-2013 14:50
本帖最后由 woodheadz 于 2-10-2013 14:54 编辑
black_zerg 发表于 2-10-2013 12:22
http://glue.atwebpages.com/demo/tutorial.html

My implementation of map widget (similar to openlay ...


为什么我觉得无法和你交流?

我你的demo一出来我就在告诉你你demo的问题,代码量大得多(接近我三倍的代码实现了我60%的功能), 可维护性差,还告诉你用你这种做法在团队协作里会有更多的问题,最后顺便指出来你在代码里生成html的做法有多么业余。你demo里最大的两个问题我出于维护你的面子,同时也不想歪楼所以没说:
1.你那不是component。component是面向复用的,你的代码毫无复用性可言。
2.对如此简单的逻辑进行了过度的包装,严重的过度设计。mvc架构能被成功应用的场景只有两个:a.你在使用某种mvc框架,所以你的系统自然是mvc架构的;b.你没使用任何框架,但你的系统表现逻辑十分复杂,所以你自己从头建立了mvc架构。 就这个demo而言,逻辑极其简单,如果你不用框架,那么最好的设计就是简单直白地把功能完成。你那个做法,除了让你的代码看起来像是个“MVC”以外,还能给你带来任何其它好处? 能比简单直白的代码跟容易让人理解?

后来我看你实在是不醒眼,所以这个两个点我也提出来了。

除了做了一个去除动态html的修改版demo(对,这就是那个涂了银色涂料的木头棒子)以外,你对我的这些观点的回应在哪里?  你觉得在你还没搞清楚什么叫component之前你是一个值得与之讨论mvc,mvvm这类更复杂的概念的人吗?

你也许能用js做出复杂的东西来,但不代表你对js前端开发所面临的问题一定就有所了解。你连人们平时是怎样在前端开发过程中使用html都不了解,你还在这儿自称专家要求别人按你的要求讨论前端开发问题?

你自己看看你是怎么参与这贴讨论的:
实话说我看也就那么回事吧,增加GDP而已,不然大家没的事情干

你对别人的不尊重自己不觉得,我对你的尊重和容忍你也视而不见,不把话挑明了你就不懂,挑明了有在这儿抱怨说我不给你real opinions,拜托,我多少的real opinions摆在前面,你除了听懂了“刀子的颜色该是银色”这个最简单的opinion以外,其它的你都忽略了。

这事真怪不得我。你要是进了我的team,我一定会疯掉的。
作者: black_zerg    时间: 2-10-2013 14:56
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 2-10-2013 15:11 编辑

代码量大得多(接近我三倍的代码实现了我60%的功能)

how is that ? how big is your 'framework'?  

'你那不是component'  , Why? it has a clear purpose: to bind a form with a list. So the part in *.js  can be reused as Classes, the part I put in html is the code to use the Classes (List & Form).  The idea is , if there is new requirement that List and Form class are not good enough, I will create new class(widget) by extend them,composite or from scratch. Since HTML is just standard HTML, those widgets will work perfectly well with Jquery etc.  Users can pick the right widget for his requirement instead of bound to a 'fancy' magic box.

Well, if no one else is interested, no point to waste my time here. see u


作者: woodheadz    时间: 2-10-2013 15:11
black_zerg 发表于 2-10-2013 14:56
代码量大得多(接近我三倍的代码实现了我60%的功能)

how is that ? how big is your 'framework'?  


晕死...
“复用”的意思,不是弄出一个东西,可以重复的应用在其它一摸一样的问题上。“复用”的意思,是我弄出一个东西,可以用在这一类的的问题上。
比如demo变成商品信息录入,列表也变成两个有marster,detail关系的列表,你的“复用”还有多少剩下?

然后你居然拿你一个ui界面的代码和我一个framework的代码量比,天哪,我还要被你crash多少遍?

天雷滚滚啊... 你真干了十多年的程序员?
作者: black_zerg    时间: 2-10-2013 15:21
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 2-10-2013 15:47 编辑

天雷滚滚啊... woodheadz你真干了十多年的程序员?
天雷滚滚啊... woodheadz你真干了十多年的程序员?
天雷滚滚啊... woodheadz你真干了十多年的程序员?
天雷滚滚啊... woodheadz你真干了十多年的程序员?
天雷滚滚啊... woodheadz你真干了十多年的程序员?
天雷滚滚啊... woodheadz你真干了十多年的程序员?

Don't argue like a girl man. When you have a complicated demo I would like to accept your challenge.

something like this http://glue.atwebpages.com/demo/basic.html



作者: woodheadz    时间: 2-10-2013 15:28
black_zerg 发表于 2-10-2013 15:21
天雷滚滚啊... woodheadz你真干了十多年的程序员?
天雷滚滚啊... woodheadz你真干了十多年的程序员?
天 ...

if you insist on playing this kind of naughty show in public space, please stay out of my thread,
作者: black_zerg    时间: 2-10-2013 15:45
提示: 作者被禁止或删除, 无法发言
woodheadz 发表于 2-10-2013 15:28
if you insist on playing this kind of naughty show in public space, please stay out of my thread,

Just show you how silly your argument is.  What? don't feel comfortable when other people say that to you? Then don't start. I have plenty of free time play with you.
作者: escctrl    时间: 2-10-2013 16:55
The topic is getting more interesting!
作者: coredump    时间: 2-10-2013 17:32
很久不上论坛了,不过看到这么个有意思的讨论还是忍不住想来掺和几句。

首先大赞木头猫的热情和干劲,有技术的人很多,有热情的人也有很多,又有技术还有热情,同时愿意坐下来写点东西无偿分享的人真的很少很少。不过根据做了几年开源项目得来的粗浅经验来看,一旦决定做开源公开了自己的作品,就一定要彻底开放自己的心态,程序员一定程度上类似于作家,不过只有做开源的程序员才更像一个真正的作家,这时候,你就会迎来四面发放的评价,或欣赏,或鼓励,不过不管什么项目,即便牛至Linux, GTK, Qt这样的,遇到更多的评价就是批评。对品味的批评,对细节的批评,对理念的批评,不一而足,如果你只活在这些批评里,很可能很快就会自我放弃。

所以,想干好开源项目,就要有一颗坚强的心脏和足够厚的脸皮,然后还得有足够开放的心胸。 因为你的项目的批评者,往往是你最忠实的用户, 比如木头猫这个项目,我好多天前就知道了,但是一直真的用心去看,更没去写点demo体验一下,对细节的观摩和理解也比black_zerg相去甚远。 想想看,往往最保守批评嘲讽的技术却最成功: C++, Java, Linux, OOP.... 对于这一点,C++的作者一句话说得好:世界上只有两种编程语言,一种是人人都在抱怨的,另一种是没有人用的。所以,如果我做的一个JS项目收获到了像Hibernate, Spring, Struts, NodeJS, jQuery那么多的潮水般的抨击,我睡觉时都会乐醒。

~~~以上务虚吹水,连鸡汤都算不上,只能算鸡精,下面就具体的几个技术表达下我的肤浅观点~~~

1. MVVM
http://en.wikipedia.org/wiki/Model_View_ViewModel

其实这个名词我才知道,以前只知道MVC, MV, 一开始还以为MV居然还搞出虚拟机了  不知道可以,不学习就可耻了,赶紧上维基补课,想一起补课请自觉的点上面的链接。看完词条我学到了:

1. 顺便知道了还有MVP, MVB的存在,他们本质上都是关于Model和View的分离以及互相通讯的,叫法和侧重点不同
2. MVVM是一种关于架构方面的模式,主要用于基于事件驱动的GUI编程领域
3. 一开始用在.NET平台的WPF/SilverLight上,用一坨坨.net语言和XAML界面描述语言来具体体现
4. 分三个部分: Model, View和ViewModel

关于M和V,大家都一样, 剩下的M和V如何交互的地方大家都在做文章。
MVC : C = Controller, 负责处理从V过来的交互输入(数据和事件),还负责从M过来的数据更新,此外还负责应用逻辑,所以这个C最难写,现实中往往就把C和M或者C和V混在一起,或者人格分裂,M和V一人一半,这样MVC就悲剧的退化了。
Controller有时候也叫Delegate, 比如在Qt里。

MVVM = MVB: B = VM = Binder = ViewModel, 这个是MVVM的另一种叫法,这个让人理解起来更为清晰一点。

这个Binder (ViewModel)和Controller做的事情其实差不多,和Controller的最大区别就是Controller既依赖于Model,又依赖于View, 本身还有应用逻辑, 这会让Controller的测试很难搞,所以便于分离测试是出发点之一。

另一个考虑就是,从实践上来看,C最容易和V搞基,傻傻分不清楚,这很容易让代码退化,让V变成C,然后前端射鸡虱就不答应了,你们程序猿这么折腾这可让臣妾如何射鸡啊..... 所以Binder的一个目的就是尽量干净,彻底,绝情地从V里去掉尽可能多的C。不过鉴于实现V的那一坨可选的语言里,从语言本身可是都能够写出C的,君不见程序猿茶余饭后最喜闻乐见的娱乐活动就是用XML实现if-else-for, 让CSS支持逻辑控制,最不济,只要爷高兴,爷就能把一个ERP系统的完整代码塞在一个div的tag......

为了遏制射鸡师不断攀升的自杀率,微软挤出XAML,说咱不能在这玩意里写code,一句也不行,"理论上", 这就阻断了C和V搞基的可能,和M暗送秋波只能通过Binder,互相放电也行,反正Binder不直也不弯,就是个双工的传声筒。 (当然我不看好XAML,因为XAML就是XML,而程序猿早就知道怎么蹂躏XML了...).

抄来MVVM的具体实践指南: (http://stackoverflow.com/questio ... etween-mvc-and-mvvm)
1. Views display a certain shape of data. They have no idea where the data comes from.
2. ViewModels hold a certain shape of data and commands, they do not know where the data, or code, comes from or how it is displayed.
3. Models hold the actual data (various context, store or other methods)
4. Controllers listen for, and publish, events. Controllers provide the logic that controls what data is seen and where. Controllers provide the command code to the ViewModel so that the ViewModel is actually reusable.
所以,在MVVM里,Controller还是存在滴,只不过干的事情少了一些,和V之间插了个无性别倾向的第三者:邦德 Binder。正应了软件界的一句谚语:关于软件开发的任何难题都可以通过增加一个中间层来解决。

有趣的,维基上列的对MVVM的批评(或者忠告),来自于MVVM概念的创造者,主要包括:
1. 对简单小巧的UI而言太over-kill
2. 对复杂大型的应用而言,抽象和泛化View又太困难
3. 对data-binding而言,如果实现的不够好,可能会导致内存消耗大量增加 (我觉得对CPU的负担也是个必须考虑的部分)
~~~~~~~~~~~~~~~~~
关于data binding

比较文艺的说法是data binding属于reactive programming的范畴。关于这个话题,我不太同意黑虫的观点,不过比较赞同他对javascript和HTML上做data binding的吐槽。这是因为,reactive programming本身是个很优美很理想的东西, 但是现在大部分编程语言是不直接支持reactive programming的,所以就必须用比较ugly的方式来实现, 比如通过HTML的tag。关于这方面,我觉得QML支持reactive programming比较好 (当然是因为我比较深入弄过一段时间QML), 算是接近native支持reactive programming了。 如果有一天HTML和JS规范本身能够引入data binding语义,那么世界会美好很多。

往往技术的演化就是这样, 大家先做梦,如果TMD有个X功能就好了, 然后大家去实践, 通过A, B, C, D的E,F, G, I加上某些magic,就能实现或逼近X的功能或理念,咱然后大家就觉得这些具体实现都太TMD恶心了,那么X还是远远的,可望不可即,可远观不可亵玩矣,就像程序猿隔壁的女神一样,理想的丰满总是不敌现实的骨感, 然后终于有一天,X被从基因的层面找到了的理论依据和实现方法,于是大家的理想就完美实现了,可以继续梦想下一个X'.

作者: woodheadz    时间: 2-10-2013 18:34
coredump 发表于 2-10-2013 17:32
很久不上论坛了,不过看到这么个有意思的讨论还是忍不住想来掺和几句。

首先大赞木头猫的热情和干劲,有 ...

谢谢老丐捧场。
我发这个贴之前我其实是有一点心理准备的,我等着有人拿knot.js和angular.js,ember.js,knockout.js这些前辈比,找出knot.js的不足,质疑knot.js改进的意义。也等着有人直接告诉我我要干那啥啥啥,你这干不了。甚至也想到有人可能直接从我的源码里揪出这样那样的问题。
没想到最后出现这样的结果,实在是没想到。看来是我修养还不够,连续几个干雷下来就崩溃了。以后加强锻炼,争取脸皮加厚三寸。

虽然没用过,但我看过下QML的相关资料。的确QML的描述方式更容易阅读和编辑,也更便于表达。HTML有历史负担,放弃这种markup的方式只怕是不可能了。
一个比较值得去做的对比是QML和XAML。我不知道XAML是不是anders负责设计的,但我想anders在其中肯定扮演了重要的角色。 anders当年做的delphi的ui描述部分使用的是有点类似QML这种非markup语言的方式(当然没这么强),而WPF却转向了xml为基础,中间的原因我想是不是因为XML有完整的命名空间,定义描述语言(DTD,XSD)的存在?  定义描述语言也就算了,命名空间在XAML里面是非常重要的。不知道QML有没有命名空间的概念?

作者: woodheadz    时间: 2-10-2013 18:55
coredump 发表于 2-10-2013 17:32
很久不上论坛了,不过看到这么个有意思的讨论还是忍不住想来掺和几句。

首先大赞木头猫的热情和干劲,有 ...

说说knot.js的定位.

作为一个WPF程序员,我实在是讨厌现在这些js绑定框架的做法。该代码干的事,非要放到丑陋的tag里面。最后的结果一是限制大,框架不支持你就没招;二是无关逻辑被迫分散到整个html文档中。
另外让我不能接受的是这些框架都要求在model定义方面遵循他们的规范。这意味着如果我用个框架用到一半觉得不好了,撤出的成本就会变高。我觉得以javascript的动态特性,完全没必要这样。

于是才有的knot.js.  

我一开始考虑过吧knot.js的定义不是放在html的属性里,而是我自己定一个标签,用更容易写的类json(类qml)方式写在标签里,再把标签插入到html元素中间。但尝试了下觉得不方便,markup中间混一对json定义阅读效果也不见得好。于是就做成就是现在这个结果。

knot.js没什么革命性的理念,就是一堆在前人基础上的微创新。但我觉得还是挺值得做这么个东西的。你不知道我终于把knockoutjs从我们的项目里踢掉删除了那些眼中钉的时候有多开心。
这两天加了个binding状态监视器,调试的时候狂好用,我觉得稍作习惯,binding带来的调试上的困难基本上可以通过这个监视器消除。这让我对knot更有信心了

等knot.js基本通过我们这个项目的考验,我就打算去开源社区好好推广下。

我先发到freeoz,是想freeoz毕竟熟人多些,不妨在没成熟的时候发过来先收集下意见。请大家不吝赐教。
作者: coredump    时间: 2-10-2013 19:21
QML最初的原型也是用的XML, 后来放弃了。 XML不是human readable的语言。 QML有namespace的概念。
作者: coredump    时间: 2-10-2013 19:25
黑虫的很多观点也是很有价值的,面对批评不能点菜,我要具体的意见,别来宏观的,切,给你吐槽就不错了,还挑食怎么行,大家都知道挑食会营养不良的。
作者: woodheadz    时间: 2-10-2013 19:29
coredump 发表于 2-10-2013 17:32
很久不上论坛了,不过看到这么个有意思的讨论还是忍不住想来掺和几句。

首先大赞木头猫的热情和干劲,有 ...

从mvvm的角度来看现在的这些js mvvm框架,在m端和v都没啥太本质的区别。 关键就在对“vm”的看法上。

knotjs以外js框架倾向于把vm整个作为框架的职责,这样就必然要求在配置中提供足够灵活的语法来描述vm的工作逻辑。

knot.js基本是沿用WPF的哲学,逻辑都是代码的责任,标记干的事,就是把逻辑粘合。所以knot.js的vm完全是面对开放和与代码的整合设计的。这种方式我觉得要灵活得多也简单得多。实际做下来,因为js的动态特性,knot.js比wpf的绑定要容易使用很多。

knot.js里的controller,和你发的链接里skackoverflow上的次高票观点是一致的。knot.js实际上直接用vm替换了controller.
我把user input看作成两类,一类是直接的命令,比如按钮,菜单等;一类是间接的事件,例如文字改变,选择改变等等。
knot.js不处理第一类命令。这类命令由用户直接根据命令结果操作数据即可,因为这类命令在发动的时候意图非常明确,状态非常单纯。如果要在这方面完成重用,一个附加command模式就已经足够了,knot.js不该去处理这个问题。
第二类命令常常会跟随有非常复杂的后续状态变化,而这些状态的变化逻辑绝大多数在描述绑定的时候就已经完成描述了。所以由框架处理是最好。

我回头好好看看那个贴里提到的“ Sculpture code-gen framework ”,看看他们把controller从vm独立出来的动机是什么。没准又能学到些新想法。
作者: woodheadz    时间: 2-10-2013 19:31
woodheadz 发表于 2-10-2013 19:29
从mvvm的角度来看现在的这些js mvvm框架,在m端和v都没啥太本质的区别。 关键就在对“vm”的看法上。

...

郁闷,貌似Sculpture code-gen framework 已经被取消了
作者: woodheadz    时间: 2-10-2013 19:35
coredump 发表于 2-10-2013 19:25
黑虫的很多观点也是很有价值的,面对批评不能点菜,我要具体的意见,别来宏观的,切,给你吐槽就不错了,还 ...


其实我一开始也没点菜...   我还是老老实实的从宏观上解释了knotjs的变化了啊...
唉,算了,不聊这事了
作者: woodheadz    时间: 2-10-2013 19:44
本帖最后由 woodheadz 于 2-10-2013 19:47 编辑
coredump 发表于 2-10-2013 19:21
QML最初的原型也是用的XML, 后来放弃了。 XML不是human readable的语言。 QML有namespace的概念。


忽然想到,你说做这么个东西出来有没有价值:

做一个类似css的东西,把界面的绑定逻辑独立放在一个文件中,用类似qml的模式去描述,使用和css一样的selector和html页面元素关联。

----------------
再想想,觉得对于网页js应用而言,这么做可能太过于重型了
作者: coredump    时间: 2-10-2013 20:17
woodheadz 发表于 2-10-2013 19:44
忽然想到,你说做这么个东西出来有没有价值:

做一个类似css的东西,把界面的绑定逻辑独立放在一个文 ...

我觉得这个思路是蛮有意思的,HTML最有价值的核心就是DOM模型,除此之外的会统统逐渐分离,本来也没有CSS,Opera的工程师觉得这样啰哩啰唆的到处color, font, size太不好了,于是把这些单独拿出来弄了个CSS出来,Javascript更是无心插柳弄出来的玩意,如果现有CSS出来,Netscape可能就没动力弄Javascript了。 而且不管CSS还是JS都和HTML标准没关系,他们在一起成为整个Web Platform (http://www.webplatform.org/) 生态系统的组成部分。现在的整个Web架构基本上还只是大体上实现了View部分的规范化,Model或者数据层的API才刚刚起步,Model和View的交互离规范化还很远,现在就只能在JS上做文章hack。
作者: woodheadz    时间: 2-10-2013 20:31
coredump 发表于 2-10-2013 20:17
我觉得这个思路是蛮有意思的,HTML最有价值的核心就是DOM模型,除此之外的会统统逐渐分离,本来也没有CSS ...


我刚才又想了下,想法又有点改变。
之前觉得重型是因为老想着放在单独的文件里,其实不一定是这样,像css一样直接放在html文件里也没啥。 我会拥着个思路重新做一个knot.js试试

这个算是今天最大的收获了,哈哈,thx
作者: woodheadz    时间: 2-10-2013 20:36
本帖最后由 woodheadz 于 2-10-2013 20:41 编辑
coredump 发表于 2-10-2013 20:17
我觉得这个思路是蛮有意思的,HTML最有价值的核心就是DOM模型,除此之外的会统统逐渐分离,本来也没有CSS ...


QML对逻辑是怎么处理的? 允许在QML中内嵌写逻辑吗?  还是采用和WPF类似的做法?
--------------
用js的动态特性,应该容易把逻辑镶嵌到定义里。但我还有点不确定该不该这么做。
作者: coredump    时间: 2-10-2013 20:43
reactive programming对于Javascript来说就像OOP对于C的样子,实现起来肯定是doable的,而且不止一种思路,但是总归会有隔靴瘙痒之感,最终的出路肯定有或者JS语言扩充规范,或者有新的语言来实现,而且reactive programming总体上来说更适合用函数式语言来做(因为CSP,call cc对于函数式语言更加自然,而reactive programming在实现层面必然是一些callbacks),除了QML外,有一个elm (elm-lang.org)函数式语言号称FRP (Functional Reactive Programming), 刚才在github上一顿搜,发现也有人用Javascript来做FRP的实践, 比如这个(https://github.com/baconjs/bacon.js)。
作者: coredump    时间: 2-10-2013 20:50
woodheadz 发表于 2-10-2013 20:36
QML对逻辑是怎么处理的? 允许在QML中内嵌写逻辑吗?  还是采用和WPF类似的做法?
--------------
用 ...

QML和JS是完全mix的,任何binding都可以用JS表达式,这点和XAML正好相反,当然这也有缺点,很容易让View和逻辑混在一起,需要通过编程规范来约束,比如:

  1. import QtQuick 2.0

  2. Rectangle {
  3.    id: rect
  4.    width: 400  //bind to contant
  5.    height: width / 2   //js expression, height always binds to width/2
  6.    color: getColor()  //bind to js function

  7.    function getColor () {
  8.        //js code
  9.        return "red";
  10.    }
  11. }
复制代码

作者: woodheadz    时间: 2-10-2013 21:05
coredump 发表于 2-10-2013 20:43
reactive programming对于Javascript来说就像OOP对于C的样子,实现起来肯定是doable的,而且不止一种思路, ...

我不大喜欢这个思路。
markup/json/qml这类描述方式的一个优势就是在描述静态关系时特别方便,比在代码里描述舒服多了。用来描述UI和数据以及逻辑块之间的关系刚刚好。 我觉得bacon走到另一个极端上了。
-----------------------
我现在的整个思路是这样,现在knot.js提供的东西,相当于镶嵌在htmltag中的style样式,我在这个基础上增加一个我称为"cbs"的东西(Cascading Binding Sheets),可以独立于html tag定义数据绑定关系。
即便是在目前的技术限制下,这方面我觉得还是有很大的想象空间的。你觉得如何?

作者: coredump    时间: 2-10-2013 21:07
又找到一个http://www.reactjs.com/
作者: coredump    时间: 2-10-2013 21:08
woodheadz 发表于 2-10-2013 21:05
我不大喜欢这个思路。
markup/json/qml这类描述方式的一个优势就是在描述静态关系时特别方便,比在代码里 ...

嗯,值得探索一下,很有意思
作者: coredump    时间: 2-10-2013 21:12
https://github.com/reactivemanifesto/reactivemanifesto
http://redmonk.com/jgovernor/201 ... usiness-is-reactive
作者: woodheadz    时间: 2-10-2013 21:14
coredump 发表于 2-10-2013 20:50
QML和JS是完全mix的,任何binding都可以用JS表达式,这点和XAML正好相反,当然这也有缺点,很容易让View和 ...

嗯。我觉得用编程规范解决这个问题要好些。
我不大喜欢限制太多的框架,没必要这么不相信使用者嘛 更何况在某些情况直接嵌入javascript可能简洁很多。

===============
thanks, 我觉得我好像又欠你一顿酒了。上次的还没兑现呢
作者: black_zerg    时间: 2-10-2013 21:20
提示: 作者被禁止或删除, 无法发言 本帖最后由 black_zerg 于 2-10-2013 21:37 编辑

这类CRUD数据库的网页都不是什么火箭科技,说老实话,有点经验的怎么写都能成功。所以最重要是团队合作和维护上,逻辑必须predictable。大家都按一个规矩写,就完了。追求代码最短没有意义。就好象英文通用,大家都说英文,跟英文是不是最简洁没冗余没什么关系。

reactive programming 我能看到的好处就是缩短代码,不然到处函数好像很恶心。 但是直觉上我就觉得这个让编程难度增加很多,容易有副作用。 a = b + a , 就变成了 类似
a = function(){ b() + c()}, 然后每次 a(); 这不是更晕么。反正我是想不过来

如果说到js应用框架,认真地说我觉得对于CRUD的话,老backbone大概是在功能和平衡上做的最好的。databing的话,
初看到了觉得挺稀奇的,但总有界面复杂了之后很不靠谱的感觉,就像老丐说的,Javascript 就没有reactive programming 支持,怎么做都是模拟。 那程序员就只能认了,自己写逻辑。现在为了绑定事件什么的,都是一堆getter setter 或者watcher之类的,反正看着也都有些别扭的。

我刚写了个例子(尝试做binding) http://glue.atwebpages.com/clip.html ,感觉还是只能自己玩玩,真用还是用backbone保险。

作者: woodheadz    时间: 2-10-2013 21:36
coredump 发表于 2-10-2013 21:12
https://github.com/reactivemanifesto/reactivemanifesto
http://redmonk.com/jgovernor/2013/09/26/why ...

如果把Reactive programming这个思想放大点,不要局限在具体语言上,那么绑定实际上就算是reactive programming的实现。但具体到在语言级建立reactive programming,我觉得可能意义不大。
有两个原因:

首先,他在数据之间建立的联系并没有任何限制,这有点类似于当年的goto语句,太过于强大以至于很容易出现产生的破坏性远远大于利益的情况。所以这个思路直接用于建立复杂逻辑模型我是不大看好的。

其次,虽然这个思想天然就可以用来描述UI和数据之间的绑定情况,但用代码去做这样的描述始终不够直观。

作者: coredump    时间: 2-10-2013 21:44
black_zerg 发表于 2-10-2013 21:20
这类CRUD数据库的网页都不是什么火箭科技,说老实话,有点经验的怎么写都能成功。所以最重要是团队合作和维 ...

reactive programming 我能看到的好处就是缩短代码,不然到处函数好像很恶心。 但是直觉上我就觉得这个让编程难度增加很多,容易有副作用。 a = b + a , 就变成了 类似
a = function(){ b() + c()}, 然后每次 a(); 这不是更晕么。反正我是想不过来


如果支持RP,赋值和binding就必须有区分,在QML中, binding 是用:, =还是赋值语意。
reactive最适合的领域是高度实时交互的UI和其它事件来源密集,依赖复杂的应用领域,比如Game, 大数据处理之类的地方。这个和OOP有点类似,OOP最成功的领域也是GUI。

这里有个paper: http://conal.net/fran/tutorial.htm
作者: coredump    时间: 2-10-2013 21:59
black_zerg 发表于 2-10-2013 21:20
这类CRUD数据库的网页都不是什么火箭科技,说老实话,有点经验的怎么写都能成功。所以最重要是团队合作和维 ...
这类CRUD数据库的网页都不是什么火箭科技

话说整个软件开发界就没有什么rocket sience的东西,别说rocket,连那点勉强够sience的基础部分也都被发掘殆尽了, 最后一个改进的排序算法 (library sort http://en.wikipedia.org/wiki/Library_sort )是2004年发现,经常被做为栗子被大家用各种姿势举着来让人震惊居然这么晚还能在这么基础的领域有所发现。

剩下的全部都是工程实践,不管是Linux Kernel还是Google集群,新语言,新数据库,新的开发哲学,统统都是在实践过程中对基础理论的应用和微调,所以面对现实,做一个IT农场的码农是幸福的,做一个计算机科学家是痛苦的。

CRUD虽然基础得很,可是一个ORM整个软件开发界死啃了这么多年也没什么像样的东西出来,只好说这玩意本身就是evil的,然后发现OOP也evil了,SQL也evil了,搞IT的,虽然不是搞科学,可是科学精神那是一点都不缺的,得有足够的自我否定精神和大胆假设,小心求证,不断实践的热情。

虽然已经很久没人发明出钢琴了,可是能弹一首好曲子还是很让人赞叹的,编程上也类似。
作者: coredump    时间: 2-10-2013 22:14
black_zerg 发表于 2-10-2013 21:20
这类CRUD数据库的网页都不是什么火箭科技,说老实话,有点经验的怎么写都能成功。所以最重要是团队合作和维 ...

backbone的实现就的确挺不错的。
作者: woodheadz    时间: 2-10-2013 22:31
本帖最后由 woodheadz 于 2-10-2013 22:39 编辑
coredump 发表于 2-10-2013 22:14
backbone的实现就的确挺不错的。


在我现在做的NovaMind html5版本中就有一个和backbone很像的数据底层。为系统的数据层提供事件(包括自动生成的datachange)和序列化支持。和backbone不同的是我的底层序列化的结果是xml,因为NovaMind的数据文件格式基于XML。
javascript没有元数据,所以这个部分的实现无论我的数据底层和backbone都没办法做得像C#里的那么优雅。很期待anders在typescript里也创建类似的东西,到时候就很爽了。

但我觉得backbone这类的东西离UI还是远了点,把UI的繁琐工作拿出来交给一个前端框架还是很有必要的。


作者: woodheadz    时间: 2-10-2013 23:09
coredump 发表于 2-10-2013 20:50
QML和JS是完全mix的,任何binding都可以用JS表达式,这点和XAML正好相反,当然这也有缺点,很容易让View和 ...

还有个关于QML的问题请教一下:QML支持数据验证不? 怎么支持的?
作者: woodheadz    时间: 3-10-2013 00:21
本帖最后由 woodheadz 于 3-10-2013 00:24 编辑
coredump 发表于 2-10-2013 19:25
黑虫的很多观点也是很有价值的,面对批评不能点菜,我要具体的意见,别来宏观的,切,给你吐槽就不错了,还 ...


刚才好好想了下,又把帖子从头到尾看了一遍,我这次发火了,这是我的不对。
我只觉得黑虫的态度言语让我很不舒服,但实际上可能是我的那句“让设计师奔溃”先让他不舒服的。

看来我身上的确是有一点要不得的精英主义思想,另外也情绪和判断力也太容易受自己对人的成见影响了。

在此郑重向 @black_zerg 道歉,这次是我错了,请你原谅。收回"stay away from my thread",欢迎你在我的帖子里发言。

以后继续努力,以老丐的签名“言者所在意,得意而忘言”为目标,提高自己。 顺便谢谢 @coredump 提醒。
作者: coredump    时间: 3-10-2013 07:07
woodheadz 发表于 2-10-2013 23:09
还有个关于QML的问题请教一下:QML支持数据验证不? 怎么支持的?

TextInput专门有个validator的属性,内置IntValidator, DoubleValidator和RegExpValidator
在此基础上可以添加自定义的validator,比如DateValidator之类

http://qt-project.org/doc/qt-4.8/texthandling.html
http://qt-project.org/forums/viewthread/18044


作者: coredump    时间: 3-10-2013 11:06
woodheadz 发表于 3-10-2013 00:21
刚才好好想了下,又把帖子从头到尾看了一遍,我这次发火了,这是我的不对。
我只觉得黑虫的态度言语让 ...
以后继续努力,以老丐的签名“言者所在意,得意而忘言”为目标,提高自己。

还借我签名用,三顿饭钱了
作者: woodheadz    时间: 3-10-2013 11:38
coredump 发表于 3-10-2013 11:06
还借我签名用,三顿饭钱了


作者: black_zerg    时间: 3-10-2013 14:07
提示: 作者被禁止或删除, 无法发言 my new demo for '2 way binding'
http://glue.atwebpages.com/clip/Clip.html
作者: woodheadz    时间: 3-10-2013 15:28
刚才改了改,现在knot.js支持也cbs的形式嵌入配置了。感觉还不错
cbs语法基本和css差不多,在selector方面在css selector的基础上增加了一个新的,
例如: #dataList>div span [0]
最后的这个"[0]"表示选择结果中的第一个。 这和css selector的nth-child不一样,这表示是在选择结果集中德顺序。
现在还没开始支持函数,我仔细考虑和尝试了下,还是暂时不打算直接支持在cbs内部嵌入函数了。增加很多复杂性但得到的好处实在有限。
但我打算支持在 cbs script block中用js加入converter,validator的定义,这样比直接应用在javascript的好处是knot.js可以控制这些对象变量的命名空间,防止污染global scope. 当然用户还是可以像原来那样直接引用js中德对象

使用cbs的一个巨大的好处就是cbs使用和css一样的selector,意味着你很少需要为cbs而修改你的html。这直接把knotjs的“注入式”从代码级提升到了html级。现在使用knots.js的话要退出成本基本为0了。以前你还得清理下html中没用的tag,现在直接删掉cbs block就结了。

下面是使用cbs重新定义后的example html部分。代码部分和原来比基本没有变动。
  1. <script type="text/cbs">
  2.         body{
  3.             knotDataContext:/model
  4.         }

  5.         #dataList{
  6.             foreach:*list;
  7.             @itemCreated:onItemCreated;
  8.         }

  9.         #dataList>div{
  10.             class:*isSelected=>boolToClassConverter;
  11.         }

  12.         #dataList>div span [0]{
  13.             text:*sex=>sexToTitle
  14.         }
  15.         #spanName{
  16.             text:*name
  17.         }
  18.         #spanAge{
  19.             text:*age
  20.         }
  21.         #spanFrom{
  22.             text:*from
  23.         }


  24.         #editArea input[type="text"] [0]{
  25.             value:*selected.name =!mustNotNull & duplicatedName;
  26.             disabled:*selected=>enableControl
  27.         }
  28.         #editArea .errorMessage [0]{
  29.             style:{
  30.                 display:!selected.name=>visibleControl
  31.                 };
  32.             text:!selected.name
  33.         }

  34.         #editArea input[type="text"] [1]{
  35.             value:*selected.age =!mustNotNull & checkInteger&ageRange;
  36.             disabled:*selected=>enableControl
  37.         }
  38.         #editArea .errorMessage [1]{
  39.             style:
  40.                 {
  41.                     display:!selected.age=>visibleControl
  42.                 };
  43.             text:!selected.age
  44.         }

  45.         #editArea select [0]{
  46.             selected:*selected.sex;
  47.             disabled:*selected=>enableControl
  48.         }
  49.         #editArea select [1]{
  50.             selected:*selected.from;
  51.             disabled:*selected=>enableControl;
  52.             foreach:/countries
  53.         }

  54.         #selectFromOptionTemplate{
  55.             text:--self
  56.         }

  57.         #buttonRemove{
  58.             disabled:*selected=>enableControl
  59.         }
  60.     </script>


  61. <body onload="onLoad();">
  62. <h2>Knot.js Example</h2>
  63. <div>
  64.     <div id="dataList">
  65.         <div>
  66.             <span id="spanTitle"> </span><span id="spanName"></span>
  67.             <hr/>
  68.             Age:<span id="spanAge"></span>,
  69.             From:<span id="spanFrom"></span>
  70.         </div>
  71.     </div>
  72.     <div id="editArea">
  73.         <div>
  74.             <div class="fieldTitle">Name:</div>
  75.             <input type="text"/>
  76.             <span class="errorMessage"></span>
  77.         </div>
  78.         <div>
  79.             <div class="fieldTitle">Age:</div>
  80.             <input type="text"/>
  81.             <span class="errorMessage"></span>
  82.         </div>
  83.         <div>
  84.             <div class="fieldTitle">Sex:</div>
  85.             <select>
  86.                 <option>Male</option>
  87.                 <option>Female</option>
  88.             </select>
  89.         </div>
  90.         <div>
  91.             <div class="fieldTitle">From:</div>
  92.             <select>
  93.                 <option id="selectFromOptionTemplate"></option>
  94.             </select>
  95.         </div>

  96.         <p>
  97.             <button onclick="onNew();">New</button>

  98.             <button id="buttonRemove" onclick="onRemove()">Delete</button>
  99.         </p>
  100.     </div>
  101. </div>
  102. </body>
复制代码

作者: coredump    时间: 3-10-2013 16:10
两位真是爱动手的好同学啊,就我抄着手光说不练 team里如果都是你们这样的淫才就享福了。
@woodheadz 现在的实现就漂亮多了, 你可以顺便看看Mozilla的XBL: http://www-archive.mozilla.org/projects/xbl/xbl2.html 找点灵感或者教训, XBL目前正在被W3C标准化中, 不过是用XML实现的,不如CSS风格来得简练。
作者: woodheadz    时间: 3-10-2013 16:17
coredump 发表于 3-10-2013 16:10
两位真是爱动手的好同学啊,就我抄着手光说不练 team里如果都是你们这样的淫才就享福了。
@woodheadz 现 ...

现在的实现是看起来舒服,但做的时候需要多费点功夫,你得通过selector找到element才能明白绑定的对象。这对于用户而言也是一个成本。

把绑定信息从html tag里提到cbs里的综合效果还是不能与把style提到css里的综合效果比。主要原因是css应用的时候selector的覆盖范围往往是成片覆盖,而cbs实用时多数时候一个cbs只会对应一个element。 这也是我为什么在css selector的基础上增加了个索引的缘故。

不过我觉得多花的这个成本还是值得的,我正在把公司项目里之前做的绑定配置一个个全部提出来
作者: woodheadz    时间: 3-10-2013 16:36
coredump 发表于 3-10-2013 16:10
两位真是爱动手的好同学啊,就我抄着手光说不练 team里如果都是你们这样的淫才就享福了。
@woodheadz 现 ...

在cbs里使用扫射也还是很爽  
比如以前我界面上好几个控件都有单独针对是否有当前选择项而进行的disable绑定,需要每个控件单独配置。现在就简单了,一个cbs搞定:
  1. .disableWhenNoSelection{
  2.             disabled:*selected=>enableControl;
  3.         }
复制代码

作者: woodheadz    时间: 6-10-2013 00:48
今天有得空加了点工。
itemtemplate现在支持引用,所以可以实现递归模版,也就是说支持和树状结构的数据进行绑定了。
除了引用外,itemtemplate还支持回掉函数,也就是彻底由用户自行创建,这个在需求很变态(比如要求一个列表中的项目根据数据类型不同采用不同模版之类的)的时候特别管用。

增加了新的扩展“action”,基本上就是从knot.js提供UI事件支持,和普通UI事件的区别是knotjs在事件发生时会往事件handler里传递当前的data context。本来不打算加这个支持害怕不必要的增加系统复杂度,后来想了想,有这个东西的确还是能方便很多。

knot.js已经接近完成了,接下来还打算增加异步validator和独立的cbs文件的支持,之后,我认为就可以做第一次发布了。  新增这些东西后Knot.js压缩后尺寸依然极小,不过14k.

做了个新的包含树状结构,master-detail结构的demo在这里, 按ctl+alt+k可以呼出调试窗口,实时监控绑定状态。:
http://knotjs.atwebpages.com/example/treeExample.html

这个demo里面的treeview完全是由Knot.js绑定到一组div上创建而成的,包括tree的展开收缩状态,全部可以由绑定来实现。关键是这个实现同时还非常简单直观。

html:
  1. <body onload="onLoad();">
  2. <h2>Knot.js Example</h2>
  3. <div>
  4.     <div id="treeArea">
  5.         <div>Group</div>
  6.         <input id="textCategoryTitle" class="disableWhenNoCategorySelected"/>
  7.         <div id="treeView">
  8.             <div id="treeItem">
  9.                 <div><button>+</button><span></span></div>
  10.                 <div></div>
  11.             </div>
  12.         </div>
  13.         <div>
  14.             <button onclick="addCategory()" class="disableWhenNoCategorySelected">+</button>
  15.             <button onclick="removeCategory()" class="disableWhenNoCategorySelected">-</button></div>
  16.     </div>
  17.     <div id="peopleListArea">
  18.         <div>People</div>
  19.         <div id="peopleList">
  20.             <div>
  21.                 <span id="spanTitle"> </span><span id="spanName"></span>
  22.                 <hr/>
  23.                 Age:<span id="spanAge"></span>,
  24.                 From:<span id="spanFrom"></span>
  25.             </div>
  26.         </div>
  27.     </div>
  28.     <div id="editArea">
  29.         <div>
  30.             <div class="fieldTitle">Name:</div>
  31.             <input class="disableWhenNoSelection" type="text"/>
  32.             <span class="errorMessage"></span>
  33.         </div>
  34.         <div>
  35.             <div class="fieldTitle">Age:</div>
  36.             <input class="disableWhenNoSelection" type="text"/>
  37.             <span class="errorMessage"></span>
  38.         </div>
  39.         <div>
  40.             <div class="fieldTitle">Sex:</div>
  41.             <select class="disableWhenNoSelection">
  42.                 <option>Male</option>
  43.                 <option>Female</option>
  44.             </select>
  45.         </div>
  46.         <div>
  47.             <div class="fieldTitle">From:</div>
  48.             <select class="disableWhenNoSelection">
  49.                 <option id="selectFromOptionTemplate"></option>
  50.             </select>
  51.         </div>

  52.         <p>
  53.             <button class="disableWhenNoCategorySelected" onclick="onNewPeople();">New</button>

  54.             <button class="disableWhenNoSelection" onclick="onRemovePeople()">Delete</button>
  55.         </p>
  56.     </div>
  57. </div>
  58. </body>
复制代码
cbs
  1. <script type="text/cbs">
  2.     body{
  3.         knotDataContext:/model
  4.     }

  5.     #treeView{
  6.         foreach:*categories =>treeItem;
  7.     }
  8.     #treeItem>div:first-child{
  9.         class:*isSelected=>boolToClassConverter;
  10.         @click: onTreeItemClicked;
  11.     }
  12.     #treeItem>div:first-child span{
  13.         text:*title
  14.     }

  15.     #treeItem>div:last-child{
  16.         foreach: *children =>treeItem;
  17.         style-display: *isExpanded =>visibleControl
  18.     }

  19.     #treeItem button {
  20.         text: *isExpanded =>boolToExpandSymbol;
  21.         style-opacity: *children.length =>boolToOpacity;
  22.         disabled: *children.length =>enableControl;
  23.         @click: onExpandButtonClicked
  24.     }

  25.     .disableWhenNoCategorySelected{
  26.         disabled: */model.selectedCategory=>enableControl;
  27.     }

  28.     #textCategoryTitle{
  29.         value: */model.selectedCategory.title =!mustNotNull;
  30.     }


  31.     #peopleList{
  32.         foreach:*selectedCategory.peopleList;
  33.     }

  34.     #peopleList>div{
  35.         class:*isSelected=>boolToClassConverter;
  36.         @click:onPeopleClicked
  37.     }

  38.     #peopleList>div span [0]{
  39.         text:*sex=>sexToTitle
  40.     }
  41.     #spanName{
  42.         text:*name
  43.     }
  44.     #spanAge{
  45.         text:*age
  46.     }
  47.     #spanFrom{
  48.         text:*from
  49.     }


  50.     #editArea input[type="text"] [0]{
  51.         value:*selectedPeople.name =!mustNotNull & duplicatedName;
  52.     }
  53.     #editArea .errorMessage [0]{
  54.         style:{
  55.             display:!selectedPeople.name=>visibleControl
  56.         };
  57.         text:!selectedPeople.name
  58.     }

  59.     #editArea input[type="text"] [1]{
  60.         value:*selectedPeople.age =!mustNotNull & checkInteger&ageRange;
  61.     }
  62.     #editArea .errorMessage [1]{
  63.         style:
  64.         {
  65.             display:!selectedPeople.age=>visibleControl
  66.         };
  67.         text:!selectedPeople.age
  68.     }

  69.     #editArea select [0]{
  70.         selected:*selectedPeople.sex;
  71.     }
  72.     #editArea select [1]{
  73.         selected:*selectedPeople.from;
  74.         foreach:/countries
  75.     }

  76.     .disableWhenNoSelection{
  77.         disabled:*/model.selectedPeople=>enableControl;
  78.     }

  79.     #selectFromOptionTemplate{
  80.         text:--self
  81.     }

  82. </script>
复制代码
javascript 代码。绝大多数都是极为简单的逻辑,复杂部分基本上都由绑定解决掉了。
  1. var model = {
  2.         categories:[
  3.             {title:"test", children:[], peopleList:[], isExpanded:true, parent:model}
  4.         ],
  5.         selectedCategory:null,
  6.         selectedPeople:null};

  7.     //here is everything start
  8.     function onLoad() {

  9.         //tie a knot! done!!
  10.         Knot.tie();

  11.         //when validating fails, set focus to the failed element.
  12.         Knot.registerOnValidatingError(function (msg, node) {
  13.             setTimeout(function () {
  14.                 if (node.focus)
  15.                     node.focus();
  16.             }, 1);
  17.         });
  18.     }

  19.     function deselectTreeData(data, children){
  20.         for (var i = 0; i < children.length; i++) {
  21.             if (children[i] != data) {
  22.                 Knot.setValue(children[i], "isSelected", false);
  23.             }
  24.             if(children[i].children){
  25.                 deselectTreeData(data, children[i].children);
  26.             }
  27.         }
  28.     }

  29.     function onExpandButtonClicked(){
  30.         Knot.setValue(this, "isExpanded", !this.isExpanded)
  31.     }
  32.     function onTreeItemClicked(){
  33.         Knot.setValue(this, "isSelected", true);
  34.         Knot.setValue(model, "selectedCategory", this);
  35.         if(this.peopleList.length>0)
  36.             selectPeople(this.peopleList[0]);
  37.         else
  38.             Knot.setValue(model, "selectedPeople");
  39.         deselectTreeData(this, model.categories);
  40.     }

  41.     function addCategory(){
  42.         if(!validate())
  43.             return;
  44.         var cate = model.selectedCategory;
  45.         if(!cate)
  46.             cate = model;
  47.         var newCate = {title: "new", isExpanded:true, peopleList:[], parent:model.selectedCategory};
  48.         if(!cate.children)
  49.             Knot.setValue(cate, "children", []);
  50.         Knot.addToArray(cate.children, newCate);
  51.     }

  52.     function removeCategory(){
  53.         if(!model.selectedCategory)
  54.             return;

  55.         Knot.removeFromArray(model.selectedCategory.parent.children, model.selectedCategory);
  56.         Knot.setValue(model.selectedCategory, null);
  57.         Knot.setValue(model.selectedPeople, null);
  58.     }

  59.     //call this function to validate all data. it is called when model.selected is changed.
  60.     function validate() {
  61.         var errMessage = Knot.validate(document.body);
  62.         if (errMessage) {
  63.             alert(errMessage);
  64.             return false;
  65.         }
  66.         return true;
  67.     }
  68.     //event handler of "new" button
  69.     function onNewPeople() {
  70.         if (!validate())
  71.             return;
  72.         //set default sex to "Male"
  73.         var n = {sex:"Male"};
  74.         //call Knot.addToArray, so that UI will refresh automatically
  75.         Knot.addToArray(model.selectedCategory.peopleList, n);
  76.         selectPeople(n);
  77.     }

  78.     //event handler of "remove" button
  79.     function onRemovePeople() {
  80.         if (model.selectedPeople) {
  81.             var index = model.selectedCategory.peopleList.indexOf(model.selectedPeople);
  82.             Knot.removeFromArray(model.selectedCategory.peopleList, model.selectedPeople);
  83.             if (model.selectedCategory.peopleList.length > 0) {
  84.                 selectPeople(model.selectedCategory.peopleList[Math.min(model.selectedCategory.peopleList.length - 1, index)], true);
  85.             }
  86.             else {
  87.                 //Use Knot.setValue to update data, so the UI will refresh
  88.                 Knot.setValue(model, "selectedPeople", null);
  89.             }
  90.         }
  91.     }

  92.     //set the data to current selected data.
  93.     //setting "model.selected" to update the edit controls, setting "isSelected" to update css on peopleList items
  94.     function selectPeople(data, ignoreValidating) {
  95.         if (!ignoreValidating && !validate())
  96.             return;
  97.         Knot.setValue(data, "isSelected", true);
  98.         Knot.setValue(model, "selectedPeople", data);

  99.         for (var i = 0; i < model.selectedCategory.peopleList.length; i++) {
  100.             if (model.selectedCategory.peopleList[i] != data) {
  101.                 Knot.setValue(model.selectedCategory.peopleList[i], "isSelected", false);
  102.             }
  103.         }
  104.     }

  105.     function onPeopleClicked() {
  106.         selectPeople(this);
  107.     }

  108.     //these converters are used to change the values on data to anything you want them on html. You can create your own, it is super easy!
  109.     //they are associate to Knot by "=>" mark in html
  110.     var boolToClassConverter = Knot.Converters.createBoolToValue("selected", "unselected");
  111.     var enableControl = Knot.Converters.createBoolToValue(false, true);
  112.     var visibleControl = Knot.Converters.createBoolToValue("", "none");

  113.     //these validators are used to validate the inputted value. the last one(duplicatedName) is used to check whether these's another one
  114.     //with the same name. You can see how simple it is.
  115.     var mustNotNull = Knot.Validators.createNotNull("Must not be null!");
  116.     var checkInteger = Knot.Validators.createInteger("Must be integer");
  117.     var ageRange = Knot.Validators.createValueRange(0, 150, "Must in 0~150!");
  118.     var sexToTitle = Knot.Converters.createKeysToValues(["Male", "Female"], ["Mr.", "Miss."]);
  119.     var duplicatedName = function (value, data) {
  120.         for (var i = 0; i < model.selectedCategory.peopleList.length; i++) {
  121.             if (model.selectedCategory.peopleList[i] == data)
  122.                 continue;
  123.             if (model.selectedCategory.peopleList[i].name == value) {
  124.                 return value + " already exists!";
  125.             }
  126.         }
  127.     }

  128.     var boolToExpandSymbol = Knot.Converters.createBoolToValue("-", "+");
  129.     var boolToOpacity = Knot.Converters.createBoolToValue(1, 0);

  130.     //options for the "From" select
  131.     var countries = ["USA", "Japan", "China", "Australia"];
复制代码

作者: smnox    时间: 25-10-2013 13:03
不明觉厉
作者: caoglish    时间: 21-12-2013 22:09
本帖最后由 caoglish 于 21-12-2013 23:57 编辑

不明觉厉,idea 非常不错

不说技术实现吧,一个第三方框架的选用原则至少3条:
1.项目有保证有长期稳定维护
2.保证一定量使用者
3.详细的使用文档和使用教程
3.有个社区来做解答资源

如果是技术方面的原则是:
1.有大量的demo
2.有测试方法
3.代码本身有完全的测试代码

要去使用只有一个人维护的库或者是framework,是在是要很大勇气的。除非是计划如果不好用,自己扩充了。

楼主要推广自己的framework,要好好在文档上面下功夫,还有demo可以在todoMVC做的好一点的todo demo,另外一定要写unit testing。并且提供详细的测试方法。




作者: woodheadz    时间: 22-12-2013 22:56
caoglish 发表于 21-12-2013 23:09
不明觉厉,idea 非常不错

不说技术实现吧,一个第三方框架的选用原则至少3条:

嗯。最近被其他的事扯住脱不开身。这个东西也先放下了。等过了年再回来继续。
作者: ubuntuhk    时间: 8-7-2014 14:02
顶一个,重新关注这个帖子




欢迎光临 FreeOZ论坛 (https://www.freeoz.org/ibbs/) Powered by Discuz! X3.2