/ div >
Toptal, LLC版权所有
< / div >< / div >< / div >\n\n\n如果这看起来很眼熟,那是因为安伯.js使用 车把 模板,它有一个非常简单的语法和帮助,但不允许重要的逻辑(如.g.(条件条件中的ORing或ding项).
\n\n在上面的模板中, 我们遍历模型(前面通过到包含所有艺术家的数组的路由设置)并遍历其中的每个项目, 我们呈现一个链接,将我们带到 艺术家.歌曲
那个艺术家的路线. 该链接包含艺术家名称. 的 #每一个
车把中的helper将其内部的作用域更改为当前项,因此 {{名称}}
总是提到目前正在迭代的美工的名字吗.
上面的代码片段中还有一个有趣的地方: {{插座}}
,它指定模板中可以呈现内容的位置. 当嵌套路由时, 模板为外层, 首先呈现资源路由, 接着是内线, 将其模板内容呈现到 {{插座}}
由外部路由定义. 这就是这里发生的事情.
按照惯例,所有路由都把自己的内容呈现到同名的模板中. 以上, data-template-name
属性为 艺术家
这意味着它会被渲染为外部路线, 艺术家
. 它为右面板的内容指定了一个出口,内部路由将进入该出口。 艺术家.指数
渲染其内容:
\n
\n\n总之,一条路线(艺术家
)在左侧栏中呈现其内容,其模型是艺术家列表. 另一条路线, 艺术家.指数
控件提供的槽中呈现它自己的内容 艺术家
template. 它可以获取一些数据作为模型,但这里我们只想显示静态文本, 所以我们不需要.
接下来,我们希望能够创造艺术家,而不仅仅是看一个无聊的列表.
\n\n当我展示的时候 艺术家
模板,渲染艺术家列表,我骗了一点. 我把上面的部分剪掉,把重点放在重要的部分上. 现在,我把它加回去:
\n
\n\n我们使用烬助手, input
,使用type text来呈现简单的文本输入. 在里面,我们 绑定 的文本输入值 新名称
备份此模板的控制器的属性, 艺术家Controller
. 的后果, 当输入的值属性发生变化时(换句话说, 当用户在其中输入文本时 新名称
属性将保持同步.
我们也知道 create艺术家
操作应该在按钮被点击时被触发. 最后,我们将按钮的禁用属性绑定到 禁用
控制器的属性. 那么控制器是什么样的呢?
应用程序.artstscontroller = 灰烬.数组Controller.扩展({\n 新名称:”,\n 禁用:function() {\n 回归灰烬.isEmpty(这.(新名称));\n }.属性(新名称)\n});\n
\n\n新名称
在开始时设置为空,这意味着文本输入将是空的. (还记得我说过的绑定吗? 试着改变 新名称
然后把它作为文本反射到输入框中.)
禁用
是这样实现的,当输入框中没有文本时,它将返回 真正的
因此按钮将被禁用. 的 .财产
最后的调用使它成为一个“计算属性”,烬蛋糕的另一个美味的切片.
计算属性 依赖于其他属性的属性本身是“正常的”或可计算的吗. 灰烬会缓存这些属性的值,直到其中一个相关属性发生变化. 然后重新计算计算属性的值并再次缓存它.
\n\n下面是上述过程的可视化表示. 总而言之:当用户输入艺术家的名字时 新名称
属性更新,然后是 禁用
属性,最后将艺术家的名字添加到列表中.
想想看. 借助绑定和计算属性,我们可以将(模型)数据建立为 真理的单一来源. 以上, 新艺术家名称的更改会触发控制器属性的更改, 进而触发禁用属性的更改. 当用户开始输入新艺术家的名字时,按钮就会被启用,就像变魔术一样.
\n\n系统越大,我们从“单一真相来源”原则中获得的杠杆作用就越大. 它使我们的代码保持整洁和健壮,并且使我们的属性定义更具声明性.
\n\n其他一些框架也强调将模型数据作为事实的单一来源,但要么没有灰烬做得那么好,要么没有做得那么彻底. 例如,角有双向绑定——但没有计算属性. It can “emulate” 计算 properties through simple functions; the problem here is that it has no way of knowing when to refresh a “计算 财产” 和 thus resorts to dirty checking 和, 反过来, 导致性能损失, 尤其是在大型应用程序中.
\n\n如果您想了解更多有关该主题的信息,我建议您阅读 恶魔鳟鱼的博客 对于较短的版本或 这个Quora问题 为了让双方核心开发者参与更长的讨论.
\n\n让我们回去看看 create艺术家
动作是在它被触发后创建的(在按下按钮之后):
应用程序.艺术家路线 = 灰烬.路线.扩展({\n ...\n 行动:{\n create艺术家:函数(){\n Var name = 这.get(控制器).(新名称);\n\n 灰烬.$.ajax (http://localhost: 9393 /艺术家,{\n 类型:“文章”,\n 数据类型:json,\n 数据:{name: name},\n 背景:这个,\n 成功:function(data) {\n var artist = 应用程序.艺术家.createRecord(数据);\n 这.梅尔('艺术家').推Object(艺术家);\n 这.get(控制器).集(新名称,”);\n 这.transitionTo(“艺术家.歌”,艺术家);\n },\n 错误:function() {\n alert('未能保存艺术家');\n }\n });\n }\n }\n});\n
\n\n操作处理程序需要包装在 行动
对象,可以在路由、控制器或视图上定义. 我选择在这里的路由中定义它,因为动作的结果并不局限于控制器,而是, “全球”.
这里没有什么特别的. 后端通知我们保存操作成功完成后, 我们做三件事, 在顺序:
\n\n新名称
绑定,使我们不必直接操作DOM.艺术家.歌曲
),将新创建的艺术家作为这条路线的模型. transitionTo
在内部路线之间移动的方式. ( 链接到
Helper通过用户操作来完成这个任务.)我们可以通过点击艺术家的名字来显示艺术家的歌曲. 我们也让艺术家进来,他将成为新路线的模特. 如果模型对象就这样被传入,则 模型
路由的钩子将不会被调用,因为不需要解析模型.
这里的活动路径是 艺术家.歌曲
因此控制器和模板将是 艺术家SongsController
和 艺术家/歌曲
分别. 我们已经看到了模板是如何被渲染到 艺术家
模板,这样我们就可以只关注手头的模板:
\n
\n\n请注意,我删除了创建新歌的代码,因为它与创建新艺术家的代码完全相同.
\n\n的 歌曲
属性根据服务器返回的数据在所有艺术家对象中设置. 这一过程的确切机制并没有引起科学家的兴趣\n当前讨论. 现在,我们知道每首歌都有一个标题和评分就足够了.
标题直接显示在模板中,评级由星星表示 StarRating
视图. 我们来看看.
歌曲的评分在1到5之间,并通过视图显示给用户, 应用程序.StarRating
. 视图可以访问它们的上下文(在本例中是歌曲)和它们的控制器. 这意味着他们可以读取和修改它的属性. 这与另一个烬构建块形成对比, 组件, 它们是孤立的, 可重用的控件,只能访问传递给它们的内容. (我们也可以在这个例子中使用星级评价组件.)
让我们看看视图如何显示星星的数量,并在用户点击其中一个星星时设置歌曲的评级:
\n\n应用程序.StarRating =灰烬.视图.扩展({\n 一会:“评级-panel”,\n templateName:“星级”,\n\n 评级:灰烬.计算.别名(“上下文.评级”),\n 完整的Stars:灰烬.计算.别名(“评级”),\n numStars:灰烬.计算.别名(“maxRating”),\n\n *: function() {\n Var评级= [];\n var 完整的Stars = 这.starRange(1,这.(“完整的Stars”),“满”);\n var emptyStars = 这.starRange(这.get('完整的Stars') + 1,这.(“numStars”),“空”);\n 数组.原型.推.应用(评级,完整的Stars);\n 数组.原型.推.应用(评级,emptyStars);\n 返回评级;\n }.产权(“完整的Stars”、“numStars”),\n\n starRange:函数(start, end, type) {\n var 星星Data = [];\n for (i = start; i <= end; i++) {\n 星星Data.Push ({评级: i, 完整的: type === '完整的'});\n };\n 返回星星Data;\n },\n (...)\n});\n
\n\n评级
, 完整的Stars
和 numStars
我们之前讨论过的计算属性是 禁用
的性质 艺术家Controller
. 上面,我使用了一个所谓的计算属性宏,其中大约有十几个是在灰烬中定义的. 它们使典型的计算属性更简洁,更不容易出错(编写)。. 我设置 评级
是对上下文的评价(因此也是对歌曲的评价),而我定义了 完整的Stars
和 numStars
属性,以便它们在星级评定小部件的上下文中更好地阅读.
的 星星
方法是主要的吸引力. 它返回一个星号数据数组,其中每个项目都包含一个 评级
属性(从1到5)和标志(完整的
)来表示星星是否满了. 这使得在模板中遍历它们变得非常简单:
\n
\n\n这段代码包含几个注意事项:
\n\n每一个
Helper指定它\n通过前缀使用视图属性(而不是控制器上的属性)\n带有的属性名 视图
.class
属性\n分配的混合动态类和静态类. 任何以a为前缀的 :
变成了一个\n静态类,而 全部:glyphicon-star: glyphicon-star-empty
符号就像\nJavaScript中的三元运算符:如果完整的属性为真,\nthe first class should be assigned; if 不, the second.setRating
action应该被触发——但是灰烬会在视图中查找它, 不是路由或控制器, 就像创造一个新的艺术家一样.因此,在视图上定义了操作:
\n\n应用程序.StarRating =灰烬.视图.扩展({\n (...)\n 行动:{\n setRating: function() {\n var newRating = $(事件.目标).数据(“评级”);\n 这.设置(“评级”,newRating);\n }\n }\n});\n
\n\n我们从 评级
属性,然后将其设置为 评级
为了这首歌. 请注意,新评级不会在后端持久化. 基于我们创造美工的方式,实现这一功能并不是一件难事,它留给有动机的读者作为练习.
我们已经品尝了前面提到的余烬蛋糕的几种成分:
\n\n很漂亮,不是吗?
\n\n关于烬的内容远远超过我在这篇文章中所能描述的. 如果你想看一个关于我如何构建上述应用程序的更先进版本和/或了解更多关于灰烬的视频系列, 你可以 加入我的邮件列表 每周获得文章或提示.
\n\n我希望我已经激起了你对烬的更多了解.js和你远远超出了我在这篇文章中使用的示例应用程序. 当你继续了解烬.请务必看一下我们的 关于灰烬 Data的文章,以学习如何使用灰烬 - Data库. 玩得开心!
\n\n