而第二种方法是,框架在视图层内置了事件委派机制。当创建一个视图时,可以提供一个需要委派的事件列表,及一个在事件发生时会被调用的方法。这样只需要识别接收到点击事件方法的上下文(例如列表中哪个元素被点击)。
现在面临一个让人感觉不爽的选择:是放弃事件委派的好处,为每一个元素创建一个视图,还是为所有元素创建一个视图,但保存一堆DOM中的Javascript对象呢?
为了解决这个问题,Ember使用jQuery将所有事件委派给应用的根元素(通常是文档的body)。当一个事件发生时,Ember识别出能够处理该事件的最近的视图,并调用其事件处理方法。这就意味着可以创建视图来保持Javascript上下文,并能享受使用事件委派的好处。
另外,因为Ember在整个Ember应用中只注册了一个事件,这样创建新视图时不需要设置事件器,这样不仅使重新渲染高效,而且不易出错。当一个视图有子视图时,也不需要手动解除重新渲染过程替换的视图的委托。
大部分Web应用使用一种特定的模板语言标记来指定其用户界面。对于Ember.js,采用Handlebars模板语言来编写模板,当模板中使用的值发生改变的时候可以自动更新。
虽然显示模板的过程对于开发者来说是自动的,但是实际上这个过程包含了从原始模板到最终的、用户见到的DOM表示一系列必备的步骤。
下面是一个Ember视图近似的生命周期:

应用的模板通常是以字符串形式通过网络加载,或者随着应用加载的过程一同加载。当应用加载时,应用将模板字符串发送给Handlebars,将其编译成一个函数。一旦编译完成,这个模板函数就被保存起来,并且可以被多个视图每次需要重新渲染的时候重复使用。
如果模板在服务端进行预编译,那么这个步骤也可以在应用中省略。在这样的情况下,模板不在作为初始的、可读的模板字符串被传输,而是编译后的代码。
因为Ember负责了模板编译,因此不需要为确保编译后的模板可重用而做一些附加的工作。
当应用调用视图的append或者appendTo方法时,启动了视图的渲染过程。调用append或者appendTo相当于将视图渲染和插入操作排入了计划中。这样允许在渲染前处理其他的应用中的延迟逻辑(如绑定同步)。
在开始渲染过程时,Ember创建了一个RenderBuffer,视图可以将其内容追加到其中。在渲染的过程中,一个视图可以创建和渲染子视图。这时父视图创建一个RenderBuffer并赋给子视图,这个新创建的RenderBuffer与父的RenderBuffer相连。
Ember在渲染每个视图前进行绑定同步。通过在渲染视图前同步绑定,Ember确保不会渲染那些已经过期需要立刻替换的数据。
当主视图完成渲染时,整个渲染过程创建了一个与缓存树关联的视图树(视图层级)。通过遍历缓存树,将其转换为字符串,就得到了可以插入到DOM中的字符串。
下面是一个简单的示例:

除了子视图之外(字符串或其他RenderBuffer),一个RenderBuffer还封装了元素的标签名、id、类、样式和其他属性。这使得渲染过程中可以修改这些属性(比如样式),哪怕在其子字符串被渲染后。由于这些属性都通过绑定来控制(例如使用bind-attr),因此整个过程非常稳定且透明。
在渲染过程的最后阶段,根视图向RenderBuffer请求它的元素。这时RenderBuffer将完整的字符串使用jQuery转换成一个元素。根视图将这个元素赋给它的element属性,将其放置到DOM中正确的位置(appendTo指定的位置,如果应用使用append则是应用的根元素)。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-22614-2.html
和男朋友走在街上