ng-ng repeat index出来的数据怎么实现手风琴效果?

后使用快捷导航没有帐号?
有没有必要把机器学习算法自己实现一遍?
查看: 20928|
评论: 0|原作者: 紫杉|来自: 数据家cdo.ren
摘要: 我觉得很多人都有这个疑问吧。机器学习好高大上,多么牛逼的东西,光是看公式就已经眼花缭乱了,总觉得自己该全部去实现一遍,有的时候太懒,有的时候觉得能力不够。道理虽然明白——任何事情自己亲手做一做还是更好 ...
我觉得很多人都有这个疑问吧。机器学习好高大上,多么牛逼的东西,光是看公式就已经眼花缭乱了,总觉得自己该全部去实现一遍,有的时候太懒,有的时候觉得能力不够。道理虽然明白——任何事情自己亲手做一做还是更好的,但机器学习已经有了大量的库了,SVM-Light,R里面的glm()方程,自己实现一遍,最后又不敢用(因为不知道算法究竟是否正确),或者不能用(一是速度赶不上大神写的库那么快,二是精度没有专业库那么高),耗时耗力的写了一堆后究竟有什么用?这里很多答案都提供了一些解释,但我想从另一个角度来聊聊这个问题。我在1年半前(本科阶段)就开始接触计算心理学和机器学习方面的研究,在NAACL(自然语言处理排名第三的论坛)上发表了一篇文章,用的计算机教授写的算法库,跑的是经过AdaGrad优化的向量支持机(SVM)算法。在这种论坛发文章,你是必须去做海报展示的,站在自己的大幅海报面前傻傻的待4个小时,我的两位教授(一位是认知语言学教授,一位是计算机教授)都在那里。我的位置不太好,在最边缘的角落里,本来以为就可以赢得一份清净,Philip Resnik走了过来。直到那一刹那之前,我一直不知道他是谁。但经过教授介绍后,他是马里兰大学的机器学习和自然语言处理教授,在这个领域混了多年,在Google Schoar上的论文引用数高达12,853。他走过来的第一句话是:“假设我一点也不懂数学,告诉我你这篇论文做的是什么。”我解释后,看到我的计算机教授走了过来和Resnik聊天,Resnik问我的教授:“你用的是不是hinge loss(辛基损失函数)?”我的教授说:“是。但不是全局优化,所以我没有叫这玩意SVM……”(我凭回忆打出来的,可能不完全精确)。当时我站在一旁觉得这他们能这样大聊特聊数学,甚至是向量支持机(我当时认为这是最厉害的算法——除以外),简直是太厉害了,我一点也听不懂他们在讲什么。直到现在,我才明白所谓的“辛基损失函数(Hinge loss)”其实就是Max(a,b)函数,就是比较 a 和 b 谁大谁小,然后选大的那个。这玩意究竟有什么难理解的?为什么要那么高大上?你让一个五岁的小孩,问他:“有一堆红球,一堆绿球,哪一堆的球更多啊?”这个小孩都能告诉你正确答案。当然这说的有点偏题了。后来我非常幸运的考上了研究生,才终于开始了对“高档”算法的学习。第一个学期被Christopher Manning(克里斯多夫·曼宁)的CS224N自然语言处理虐了一番,这个学期开始上Andrej Karpathy(安杰·卡帕西)的神经网络(CS231N),该君是李菲菲教授(音译,Fei-Fei Li)的爱徒,在推特上有14.9K关注者,我越看他那张方块脸,越觉得他长得像贾斯丁·汀布莱克(Justin Timberlake)。这里有篇他的新闻报道:Karpathy打败了Google的超级人工智能,但也许再没有下次了 (/archives/3179.html)我其实也是自控能力很差的人,在上安杰·卡帕西的课之前,也从没有萌生过自己去写机器学习算法的想法。原因在文章开头有提过:1. 我的代码运行速度肯定赶不上经过多次迭代的专业库的运行速度;2. 我咋知道我的代码写的就是对的呢??我直到现在都这样认为:不考虑对方的环境和条件,知识与技能,就一味要求对方把机器学习算法都实现一遍,估计是最无理取闹的行为了吧。前天晚上,我跟另一个研究生Jason Freeman(杰森·弗里曼)聊天,他在微软的西雅图总部工作了4年,在目前越来越有名的TypeScript团队工作了3年(TypeScript是静态的JavaScript语言,正在国内和国外开始流行)——他告诉我他和安德斯·海尔斯伯格(Anders Hejlsberg)一起工作,他还经常顶撞安德斯。我的第一反应是:“他是谁……”(安德斯·海尔斯伯格是Delphi和C#之父,但我不熟悉这两门语言,所以不会崇拜他——小广告:Scala是我目前最喜欢的语言)。我和杰森讨论的是3月份开始究竟要不要选吴恩达(Andrew Ng)的机器学习课(CS229)。我持的立场是我可能不打算上那门课,因为我已经看过大部分他的视频了,还读了他讲义的一部分(这里是讲义链接: CS 229: Machine Learning (Course handouts) )http://cs229.stanford.edu/materials.html &因为我已经确定以后要做神经网络方面的研究,所以觉得他课上的一些其他内容比如特征降维(PCA),对我而言用处不大,我只需要会用就行了。我不仅用过特征降维,还用过更好的降维可视化(tSNE算法)。这玩意和我的领域不搭,为什么我要浪费时间去学?杰森的论点是,如果我学了它们的理论(甚至把它们实现一遍),就能更好的应用它们。我说:你把直觉(intuition)当什么了?在我看来,对算法进行“直观”上的了解,就已经很足够了。什么是向量支持机?就是拿一个平面去分隔一堆点。更术语一点的解释不外乎是拿一个超平面(Hyperplane)在高维空间里去分割。什么是特征降维?就是看如何把高维度的点阵降到两三个维度。什么是alpha值?就是看这个算法学得有多快。什么是正则化(regularization)?就是别让你的算法过度拟合数据(当然L1,L2等等都有区别,但这些区别都很简单,L1让你关注某个值,L2让你利用所有的值)。为什么我谈这么多关于理论的问题?在我看来,学习机器学习的算法的进度是这样的:应用 -》理论 -》实现。就跟教小孩折射一样,你先让他看看筷子在水中如何弯折(应用),再告诉他光的折射原因(理论),再让他自己用其他物体来试试(实现)。实现,是这个漫长学习过程的最后一步。一开始就来谈实现,实在是很神奇的事情。让我准确论述一下我的观点:如果你是学界精英,那么去学习那些你将要使用的算法的理论,最后再自己尝试着实现他们,是很有必要的,除非你是只做应用(比如社会科学,心理学,商学等等)。如果是普通的程序员/工程师,不需要强迫自己去实现这些算法。没人会给你一个小奖章,大公司招这类员工的时候,也是更看重学历,而不是看“哦,我把‘所有’的机器学习算法都实现了一遍”。最后送上一点我觉得实现机器学习算法最好的路径:最好用Python和Numpy库。这两样宝具会让你非常轻松。安杰·卡帕西(Andrej)推荐用ipython notebook(现在改名叫Jupyter了),来可视化数据,以及实验算法。昨天有一个下午茶会,我们系举办的,也邀请了安杰,我跑去凑热闹,跟安杰谈到了这个问题,他说就算是大公司做研究,也是这种路径,先从ipython notebook开始(这点让我很惊讶)。机器学习算法最难的部分其实不是写出来,而是高效率的实现,让你的算法跑快一点。其中一个技巧叫做“矢量化”(Vectorization)。矢量化就是说,能做矩阵操作就矩阵操作,最好连一个外循环都不写。这是我写的Softmax算法的测评:(在500个样本上跑的)naive loss: 2. computed in 0.255952svectorized loss: 2. computed in 0.004148s第一个是用普通的Python和循环写出来的,第二个是用矢量化操作写出来的,可以看到64倍速度的提升——侧面也可以看到Python有多垃圾(慢)。这个是SVM(支持向量机)算法的测评:(同样500个样本)Naive loss: 9. computed in 0.136226sVectorized loss: 9. computed in 0.005909s这次的速度提升没有那么明显,但也是26倍的提速。但我只想说:矢量化真是很难的事情。数学家随便就写公式,也不考虑考虑可怜的计算机科学孩子们。原初的公式几十分钟就搞定,矢量化要一两个小时的冥思苦想。最后,对于那些读懂了理论,实在是闲得无聊,或者想要进军更高级的学术界的同志们,这里是安杰·卡帕西课代码的链接:http://cs231n.github.io/如果你不属于这个类别,就不要瞎掺合啦,用用别人的库又怎么了?骇客精神(Hacker Code)中一条就是:“不要重复劳动,有库就要用库,不然就是对库写作者的不尊重。”最近这篇文章被学姐前辈Danqi Chen看到了。。所以我稍微补充几句,免得被大牛们看到后笑话。。- ___ - || Danqi前辈是清华姚班的高材生,Chris Manning的博士,在224N课上是首席助教,然后被我缠着问了好多次问题……这篇文章有点接近“反智”文章的边缘,大意是实用主义至上,自己实现的必要性不大。这个观点还是有很多争议的,比如目前有一个答案就“实名”反对这个答案。机器学习是一个交叉学科,作为学生而言,从不同的部门学到的机器学习,必然是不一样的。在统计学部门学到的机器学习,和在计算机部门学的机器学习,肯定是两个样。我秋天的时候跟一位概率教授上了一节课,当我告诉他斯坦福计算机入门概率课要介绍MLE(最大拟然估值)和蒙特拉罗模拟(Monte Carlo Simulation)的时候,他沉重的摇摇头,说这么早就介绍这样深刻的概念,是很不应该的,在他的部门,要第三年的学生才接触这样的知识,因为直到那时,学生才有足够的知识框架去理解这些知识。我写这篇文章是有一定的原因的。我认识一些国内的大学同学,都异常优秀,他们努力的程度是我一辈子都比不上的,他们中一部分人因为运气不好(高考),不幸去了一些相对不是那么优异的大学,但是他们用努力弥补这个缺陷,对数学和各种学科展开攻克,很多人的阅读量和数学解题技巧也是我不能企及的。还有一部分人,是处于业界转型边缘,本来已是成熟的程序员,或者数据分析师,但是想要进一步提升自己,亦或是转型。我把这两类人定做这篇回答的目标受众。我希望为他们写一篇回答,不让他们走我走过的弯路,不受太多的误导。开复先生(李开复)最近说深度学习急缺人才。我非常的不赞同。深度学习领域是处于半饱和状态的,实际上就业情况就是一堆熠熠生辉(Scintillating)的博士们在学术界待腻了,想要去赚点钱玩玩,就跑去业界晃一圈的状况。这和大部分人的就业状况根本是不搭边的。深度学习,以及理论机器学习,除非是平台很高,起点很高,是很难得到广泛认可的。我最近刚买了一本书:这本书很详细的在讲Lasso Loss(L1),写SVM的部分也非常不错,很神奇的是,三位作者,两位是斯坦福统计学系的,一位是伯克利的。如果我能读完这本书,会上来改进一下这个答案的。最近我想提一提答案末尾写的,关于“实现”的问题。我过去几周一直在写我自己的Theano库(是的,放着牛逼的Lasagne不用,非要自己手写),终于把CNN写完后,现在在写RNN的部分。当我已经花费这么多的时间,然后意识到,我的代码暂时还只能在CPU上跑,因为我暂时还没有用Theano的CUDA库,又意识到,仅仅几周后,我的两门春季课已经开始教TensorFlow了,于是觉得自己是个傻子。所以我自己都陷入了我回答中所写的那个陷阱:实现之后却不能使用,但又不愿意放弃自己的代码,于是只有投入更多的时间去改代码,而不是去理解数学。愿与各位共勉。欢迎加入本站公开兴趣群高性能计算群兴趣范围包括:并行计算,GPU计算,CUDA,MPI,OpenMP等各种流行计算框架,超级计算机,超级计算在气象,军事,航空,汽车设计,科学探索,生物,医药等各个领域里的应用QQ群:
刚表态过的朋友 ()
上一篇:下一篇:966,690 十月 独立访问用户
语言 & 开发
架构 & 设计
文化 & 方法
您目前处于:
深入浅出React(一):React的设计哲学 - 简单之美
深入浅出React(一):React的设计哲学 - 简单之美
ArchSummit全球架构师峰会(北京站)-03日举办,
相关厂商内容
相关赞助商
为中小微企业提供!
上个月React发布了最新的0.13版,并提供了对ES6的支持。在新版本中,一个小小的改变是React取消了函数的自动绑定,也就是说,以前可以这样去绑定一个事件:
&button onClick={this.handleSubmit}&Submit&/button&
而在以ES6语法定义的组件中,必须写为:
&button onClick={this.handleSubmit.bind(this)}&Submit&/button&
了解前端开发和JavaScript的同学都知道,做事件绑定时我们需要通过bind(或类似函数)来实现一个闭包以让事件处理函数自带上下文信息,这是由JavaScript语言特性决定的。而在0.13版本之前,React会自动在初始化时对组件的每一个方法做一次这样的绑定,类似于this.func = this.func.bind(this),这样在JSX的事件绑定中就可以直接写为onClick={this.handleSubmit}。
表面上看自动绑定给开发带来了便利,而Facebook却这破坏了JavaScript的语言习惯,其背后的神奇(Magic)逻辑或许会给初学者带来困惑,甚至开发者如果从React再转到其它库也可能会无所适从。基于同样的理由,React还取消了对mixin的支持,基于ES6的React组件不再能够以mixin的形式进行代码复用或者扩展。尽管这带来了很大不便,但Facebook认为mixin增加了代码的不可预测性,无法直观的去理解。关于mixin的思考,还可以参考。
以简单直观、符合习惯的(idiomatic)方式去编程,让代码更容易被理解,从而易于维护和不断演进。这正是React的设计哲学。
编写可预测,符合习惯的代码
所谓可预测(predictable),即容易理解的代码。在年初的React开发者大会上,React项目经理Tom Occhino进一步阐述React诞生的,在演讲中提到,React最大的价值究竟是什么?是高性能虚拟DOM、服务器端Render、封装过的事件机制、还是完善的错误提示信息?尽管每一点都足以重要。但他指出,其实React最有价值的是声明式的,直观的编程方式。
软件工程向来不提倡用高深莫测的技巧去编程,相反,如何写出可理解可维护的代码才是质量和效率的关键。试想,一个月之后你回头看你写的代码,是否一眼就明白某个变量,某个if判断的含义;一个新加入的同事想去增加一个小小的新功能或是修复某个Bug,他是否对自己的代码有足够的信心不引入任何副作用?随着功能的增加,代码很容易变得越来越复杂,这些问题也将越来越严重,最终导致一份难以维护的代码。而React号称,新同事甚至在加入的第一天就能开始开发新功能。
那么React是如何做的呢?
使用JSX直观的定义用户界面
JSX是React的核心组成部分,它使用XML标记的方式去直接声明界面,界面组件之间可以互相嵌套。但是JSX给人的第一印象却是相当&丑陋&。当下面这样的例子被第一次展示的时候,甚至很多人称之为&巨大的退步(Huge Step Backwards)&:
var React = require(&React&);
var message =
&div class=&hello& onClick={someFunc}&
&span&Hello World&/span&
React.renderComponent(message, document.body);
将HTML直接嵌入到JavaScript代码中看上去确实是一件足够疯狂的事情。人们花了多年时间总结出的界面和业务逻辑相互分离的&最佳实践&就这么被彻底打破。那么React为何要如此另类?
模板出现的初衷是让非开发人员也能对界面做一定的修改。但这个初衷在当前Web程序里已完全不适用,每个模板背后的代码逻辑严重依赖模板中的内容和DOM结构,两者是紧密耦合的。即使做到文件位置的分离,实际上两者还是一体的,并且为了两者之间的协作而不得不引入很多机制和概念。以的首页示例代码为例:
&ul class=&unstyled&&
&li ng-repeat=&todo in todoList.todos&&
&input type=&checkbox& ng-model=&todo.done&&
&span class=&done-{{todo.done}}&&{{todo.text}}&/span&
尽管我们很容易看懂这一小段模板的含义,但你却无法开始写这样的代码,因为你需要学习这一整套语法。比如说,你得知道有ng-repeat这样的标记的准确含义,其中的&todo in todoList.todos&看上去是repeat语法的一部分,或许还有其它语法存在;可以看到有{{todo.text}}这样的数据绑定,那么如果要对这段文本格式化(加一个formatter)该怎么做;另外,ng-model背后又需要什么样的数据结构?
现在来看React怎么写这段逻辑:
render: function () {
var lis = this.todoList.todos.map(function (todo) {
&input type=&checkbox& checked={todo.done}&
&span className=&done-{todo.done}&&{todo.text}&/span&
&ul class=&unstyled&&
可以看到,JSX中除了另类的HTML标记之外,并没有引入其它任何新的概念(事实上HTML标记也可以)。Angular中的repeat在这里被一个简单的数组方法map所替代。在这里你可以利用熟悉的JavaScript语法去定义界面,在你的思维过程中其实已经不需要存在模板的概念,需要考虑的仅仅是如何用代码构建整个界面。这种自然而直观的方式直接降低了React的学习门槛并且让代码更容易理解。
简化的组件模型:所谓组件,其实就是状态机器
组件并不是一个新的概念,它意味着某个独立功能或界面的封装,达到复用、或是业务逻辑分离的目的。而React却:
所谓组件,就是状态机器
React将用户界面看做简单的状态机器。当组件处于某个状态时,那么就输出这个状态对应的界面。通过这种方式,就很容易去保证界面的一致性。
在React中,你简单的去更新某个组件的状态,然后输出基于新状态的整个界面。React负责以最高效的方式去比较两个界面并更新DOM树。
这种组件模型简化了我们思考的方式:对组件的管理就是对状态的管理。不同于其它框架模型,React组件很少需要暴露组件方法和外部交互。例如,某个组件有只读和编辑两个状态。一般的思路可能是提供beginEditing()和endEditing()这样的方法来实现切换;而在React中,需要做的是setState({editing: true/false})。在组件的输出逻辑中负责正确展现当前状态。这种方式,你不需要考虑beginEditing和endEditing中应该怎样更新UI,而只需要考虑在某个状态下,UI是怎样的。显然后者更加自然和直观。
组件是React中构建用户界面的基本单位。它们和外界的交互除了状态(state)之外,还有就是属性(props)。事实上,状态更多的是一个组件内部去自己维护,而属性则由外部在初始化这个组件时传递进来(一般是组件需要管理的数据)。React认为属性应该是只读的,一旦赋值过去后就不应该变化。关于状态和属性的使用在后续文章中还会深入探讨。
每一次界面变化都是整体刷新
数据模型驱动UI界面的两层编程模型从概念角度看上去是直观的,而在实际开发中却困难重重。一个数据模型的变化可能导致分散在界面多个角落的UI同时发生变化。界面越复杂,这种数据和界面的一致性越难维护。在Facebook内部他们称之为&Cascading Updates&,即层叠式更新,意味着UI界面之间会有一种互相依赖的关系。开发者为了维护这种依赖更新,有时不得不触发大范围的界面刷新,而其中很多并不真的需要。React的初衷之一就是,既然整体刷新一定能解决层叠更新的问题,那我们为什么不索性就每次都这么做呢?让框架自身去解决哪些局部UI需要更新的问题。这听上去非常有挑战,但React却做到了,实现途径就是通过虚拟DOM(Virtual DOM)。
关于虚拟DOM的原理我在去年底的有过比较详细的介绍,这里不再重复。简而言之就是,UI界面是一棵DOM树,对应的我们创建一个全局唯一的数据模型,每次数据模型有任何变化,都将整个数据模型应用到UI DOM树上,由React来负责去更新需要更新的界面部分。事实证明,这种方式不但简化了开发逻辑并且极大的提高了性能。
以这种思路出发,我们在考虑不断变化的UI界面时,仅仅需要整体考虑UI的构成。编程模型的简化带来的是代码的精简和易于理解,也即React不断提到的可预测(Predictable)的代码,代码的功能一目了然易于理解。Tom Occhino在2015 React开发者大会上也了React在Facebook内部的应用案例,随着新功能被不断的添加到系统中,开发进度非但没有变慢,甚至越来越快。
单向数据流动:Flux
既然已经有了组件机制去定义界面,那么还需要一定的机制来定义组件之间,以及组件和数据模型之间如何通信。为此,Facebook提出了Flux框架用于管理数据流。Flux是一个相当宽松的概念框架,同样符合React简单直观的原则。不同于其它大多数MVC框架的双向数据绑定,Flux提倡的是单向数据流动,即永远只有从模型到视图的数据流动。
Flux引入了Dispatcher和Action的概念:Dispatcher是一个全局的分发器负责接收Action,而Store可以在Dispatcher上监听到Action并做出相应的操作。简单的理解可以认为类似于全局的消息发布订阅模型。Action可以来自于用户的某个界面操作,比如点击提交按钮;也可以来自服务器端的某个数据更新。当数据模型发生变化时,就触发刷新整个界面。
Flux的定义非常宽松,除了Facebook之外,社区中还出现了很多Flux的不同实现,各有特点,比较流行的包括, , 等等。
让数据模型也变简单:Immutability
Immutability含义是只读数据,React提倡使用只读数据来建立数据模型。这又是一个听上去相当疯狂的机制:所有数据都是只读的,如果需要修改它,那么你只能产生一份包含新的修改的数据。假设有如下数据:
var employee = {
name: &John&,
如果要修改年龄,那么你需要产生一份新的数据:
var updated = {
name: employee.name,
这样,原来的employee对象并没有发生任何变化,相反,产生了一个新的updated对象,体现了年龄发生了变化。这时候需要把新的updated对象应用到界面组件上来进行界面的更新。
只读数据并不是Facebook的全新发明,而是起源于Clojure, Scala, Haskell等函数式编程语言。只读的数据可以让代码更加的安全和易于维护,你不再需要担心数据在某个角落被某段神奇的代码所修改;也就不必再为了找到修改的地方而苦苦调试。而结合React,只读数据能够让React的组件仅仅通过比较对象引用是否相等来决定自身是否要重新Render。这在复杂的界面上可以极大的提高性能。
针对只读数据,Facebook开发了一整套框架,将只读数据的概念引入JavaScript,并且在github开源。如果不希望一开始就引入这样一个较大的框架,React还提供了一个工具类插件,帮助管理和操作只读数据:。
React思想的衍生:React Native, React Canvas等等
在前几天的Facebook F8开发者大会上,终于众望所归的发布,它将React的思想延伸到了原生移动开发。它的口号是&Learn Once, Write Anywhere&,有React开发经验的开发人员将可以无缝的进行React Native开发。无论是组件化的思想,调试工具,动态代码加载等React具有的强大特性都可以应用在React Native。相信这会对以后的移动开发布局产生重要影响。
React对UI层进行了完美的抽象,写Web界面时甚至能够做到完全的去DOM化:开发者可以无需进行任何DOM操作。因此,这也让对UI层进行整体替换成为了可能。React Native正是将浏览器基于DOM的UI层换成了iOS或者Android的原生控件。而Flipboard则将UI层换成了Canvas。
是Flipboard出品的一套前端框架,所有的界面元素都通过Canvas来绘制,infoQ之前也有文章对其进行了介绍。Flipboard追求极致的性能和用户体验,因此对浏览器的缓慢DOM操作深恶痛绝,不惜大刀阔斧彻底舍弃了DOM,而完全用Canvas实现了整套UI控件。有兴趣的同学不妨一试。
React并不是突然从哪里蹦出来,而是为了解决前端开发中的痛点而生。以简单为原则设计也决定了React具有极其平缓的学习曲线,开发者可以快速上手并应用到实际项目中。本文总结分析了其相关技术背后的设计思想,希望通过这个角度能让大家对React有一个总体的认识,从而在React的实际项目开发中,遵循简单直观的原则,进行高效率高质量的产品开发。
React官方网站:
React博客:
React入门:
颠覆式前端UI框架:React:
Immutable.js:
React Native:
Flux框架对比:
React开发者大会网站:
React在Slack上的聊天社区:
感谢对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至。也欢迎大家通过新浪微博(,),微信(微信号:)关注我们,并与我们的编辑和其他读者朋友交流。
Author Contacted
告诉我们您的想法
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
Re: 关于&严谨&
Li Hannibal
Re: 关于&严谨&
Re: 关于&严谨&
从React到Domcom
lang taiji
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
赞助商链接
InfoQ每周精要
通过个性化定制的新闻邮件、RSS Feeds和InfoQ业界邮件通知,保持您对感兴趣的社区内容的时刻关注。
架构 & 设计
文化 & 方法
<及所有内容,版权所有 &#169;
C4Media Inc.
服务器由 提供, 我们最信赖的ISP伙伴。
北京创新网媒广告有限公司
京ICP备号-7
注意:如果要修改您的邮箱,我们将会发送确认邮件到您原来的邮箱。
使用现有的公司名称
修改公司名称为:
公司性质:
使用现有的公司性质
修改公司性质为:
使用现有的公司规模
修改公司规模为:
使用现在的国家
使用现在的省份
Subscribe to our newsletter?
Subscribe to our industry email notices?
我们发现您在使用ad blocker。
我们理解您使用ad blocker的初衷,但为了保证InfoQ能够继续以免费方式为您服务,我们需要您的支持。InfoQ绝不会在未经您许可的情况下将您的数据提供给第三方。我们仅将其用于向读者发送相关广告内容。请您将InfoQ添加至白名单,感谢您的理解与支持。angular-1.3 之ng-model-options指令 - 推酷
angular-1.3 之ng-model-options指令
ng-model-options是angular-1.3新出的一个指令,这篇文章就来介绍这个指令的用法.
ng-model-options允许我们控制ng-model何时进行同步. 比如:1.当某个确定的事件被触发的时候 2.在指定的防抖动延迟时间之后,这样视图值就会在指定的时间之后被同步到模型.
为了了解它到底是什么意思,我们从一个最简单的ng-model指令创建的input元素双向数据绑定的栗子开始看起:
&input type=&text& ng-model=&name&&
&p&Hello {{name}}!&/p&
点击查看效果:
这是我们都很熟悉的,在angular-1.2版本就可以实现的ng-model双向绑定.
可以看到,它是实时同步更新的,input中每输入一个字,它就立刻同步到数据模型,这是因为,每次输入input,都会触发一个input的事件,然后angular就会执行的$digest循环,直到模型稳定下来.我们不用手动设置任何事件监听来同步更新视图和模型,这样很赞,这就是angular的目的.
然而,由于每次键盘按下,都会触发$digest循环,所以当你在输入input内容的时候,angular不得不处理所有绑定在scope上的watch监听,所以,它执行的效率就取决于你在scope上绑定了多少watch监听,以及这些监听的回调函数是怎样的,这个代价是十分昂贵的.
所以,如果我们能够自己控制$digest的触发,比如当用户停止输入300毫秒后触发,又或者是当input元素失去焦点的时候再触发,那不是更好么?&于是,angular-1.3的ng-model-options就为我们做了这件事.
一. 通过 updataOn 指定同步ng-model的时间
ng-model-options 提供了一系列的选项去控制ng-model的更新.
通过updateOn参数,我们可以定义input触发$digest的事件.举个栗子,我们希望当input失去焦点的时候更新模型,我们只需要按照如下的配置来实现:
type=&text&
ng-model=&name&
ng-model-options=&{ updateOn: 'blur' }&/&
&p&Hello {{name}}!&/p&
在eg-0.0的基础上,我们添加了
ng-model-options=&{ updateOn: 'blur' }& 这样一个指令.它
告诉angular, 它应该在input触发了onblur事件的时候再更新ng-model,而不是每次按下键盘就立即更新model. 点击查看效果:(maybe需要墙~~~)
如果我们想要保留默认的更新模型事件,另外再给它添加其它触发$digest的事件,我们可以使用一个特殊的事件:default. 可以通过空格分隔的字符串来给它添加多个事件. 下面这段代码能够在输入的时候同步更新模型,并且当input失去焦点的时候,也更新模型.
type=&text&
ng-model=&name&
ng-model-options=&{ updateOn: 'default blur' }&/&
&p&Hello {{name}}!&/p&
点击查看效果:(maybe需要墙~~~)
(效果其实不太看不出来的...因为虽然blur的时候它在同步,但是其实输入的时候已经同步完了)
好了,现在我们知道指定更新model的事件是怎么做的了. 接下来让我们看看怎么指定更新的延迟时间.
二. 通过 debounce 延迟模型更新
我们可以通过ng-model-options来延迟模型的更新,以此来降低当用户和模型交互时触发的$digest循环的次数. 这不仅减少了$digest循环的次数,同时也是处理异步数据模型时提升用户体验度的一个好方法.
想象有这样一个元素: input[type=&search&] & ,每当用户正在输入的时候,数据模型就会更新,并且用最新的字段向后台提交请求.这样是没错的.然而,我们很可能并不想让用户每次按键的时候就立刻更新模型,而是希望当用户输入完了一段有意义的搜索字段以后才更新模型. 在这种情况下,我们正适合使用ng-model-options的 debounce参数. debounce定义了模型更新的延迟毫秒数(需要是整数). 比如刚才提到的这种情况,我们希望当用户停止输入1000毫秒以后再更新模型,(停止输入1000毫秒差不多应该就是输入完了一段有意义的内容了吧).我们可以像下面这样,定义debounce参数的值为1000:
&input type=&search& ng-model=&searchQuery& ng-model-options=&{debounce:1000}&&
&p&Search results for: {{searchQuery}}&/p&
现在,当输入搜索内容的时候,会有1秒的延迟.&点击查看效果:(maybe需要墙~~~)
我们还可以做更多的配置: 为指定的事件指定延迟时间. 为不同的事件指定不同的延时,可以通过给debounce属性定义一个json对象来实现: 属性名代表事件名,属性值代表延迟时间.如果某个事件不需要延迟,那么它的属性值就是0.
下面这个栗子实现了这样的模型: 当用户在input里输入的时候,延迟1000毫秒更新模型,但是当input元素失去焦点的时候,立刻更新模型:
&input type=&search& ng-model=&searchQuery& ng-model-options=&{updateOn:'default blur',debounce:{default:1000,blur:0}}&&
&p&Search results for: {{searchQuery}}&/p&
点击查看效果:(maybe需要墙~~~)
三. 通过 $rollbackViewValue方法 同步模型和视图
由于我们通过ng-model-options来控制了模型的更新时间,所有,在很多时候,模型和视图就会出现不同步的情况. 举个栗子,我们配置ng-model-options,让input在失去焦点的时候同步数据模型,当用户正在输入内容时,数据模型没有发生更新,所以input的value指向的是模型里真实的值(但是视图上看到的是用户输入的值)
假设在这种情境下,你希望在数据模型更新前把视图上的值回滚到它真实的值.这时,angular提供了一个叫做$rollbackViewValue的方法来为我们同步数据模型到视图. 这个方法会把数据模型的值返回给视图,同时取消所有的将要发生的延迟同步更新事件.
为了解释这个方法,我写了两个demo来感受一下:
&div class=&container& ng-controller=&Rollback&&
&form role=&form& name=&myForm2& ng-model-options=&{ updateOn: 'blur' }&&
&div class=&form-group&&
&label&执行了 $rollbackViewValue() 方法&/label&
&input name=&myInput1& ng-model=&myValue1& class=&form-control& ng-keydown=&resetWithRollback($event)&&
&blockquote&
&footer&myValue1: &{{ myValue1 }}&&/footer&
&/blockquote&
&div class=&form-group&&
&label&没有执行了 $rollbackViewValue() 方法&/label&
&input name=&myInput2& ng-model=&myValue2& class=&form-control& ng-keydown=&resetWithoutRollback($event)&&
&blockquote&
&footer&myValue2: &{{ myValue2 }}&&/footer&
&/blockquote&
app.controller('Rollback',function($scope){
$scope.resetWithRollback = function(e){
if(e.keyCode == 27) {
$scope.myForm2.myInput1.$rollbackViewValue();
$scope.resetWithoutRollback = function(e){
if(e.keyCode == 27){
angular.noop()
点击查看效果:(maybe需要墙~~~)
按照下图所示的顺序操作:
myValue1使用了$rollbackViewValue()方法,可以回滚文本域里的值和数据模型同步,但是myValue2是不能的.
看一遍这个demo,也就知道了$rollbackViewValue()方法的意思和作用了.
*需要特别注意的一点是, 在使用了ng-model-options这种情况下,如果直接修改模型值,有时可能让视图同步,有时却不能 ,什么意思,看这个栗子:
html部分同eg-3.0.
app.controller('Rollback',function($scope){
$scope.resetWithRollback = function(e){
if(e.keyCode == 27) {
$scope.myValue1 = '';
//使用了$rollbackViewValue,总是可以同步视图,清空myValue1值
$scope.myForm2.myInput1.$rollbackViewValue();
$scope.resetWithoutRollback = function(e){
if(e.keyCode == 27){
//并不是每次都可以成功的同步的,有时可以,有时不可以.
$scope.myValue2 = ''
点击查看运行效果:(maybe需要墙~~~)
在eg-3.0的基础上,我们做了一个小修改,就是按Esc的时候,不是直接回滚视图值到当前的数据模型,而是先设置数据模型为空,然后再回滚视图值.而myValue2,直接设置数据模型为空,不使用回滚.
在demo里多试几次就会发现,在这种情况下,在myValue2的input里按Esc,有时可以同步视图值为空,有时则不能.
所以,在用了ng-model-opitons的时候,如果在模型没有被视图同步之前需要让视图被模型同步,不能简单通过设置模型,必须使用$rollbackViewValue()方法.
(要墙哦~~~)
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 ng repeat 嵌套 的文章

 

随机推荐