视图层
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
视图为事件作出相应,如点击,拖拉,滚动,并在dom的内容改变时及时更新。
视图层级通常通过评估一个hbs模板而创建,当评估模板时子视图被添加进来,当子视图的模板被评估时,他们的子视图又被添加进来,直到整个层级被创建出来。
即使没有显式的在hbs模板中创建子视图,emberjs内部也会使用视图系统来更新绑定的值,比如,每个hbs表达式{{value}}会创建一个幕后的视图,知道在绑定的值改变时及时更新。
你也会在应用运行时使用ember.ContainerView动态的改变视图层级,而不是模板驱动,一个容器视图暴露了一组可以手动管理的子视图实例。
视图和模板串联工作为用户提供一个梦寐以求的强健的系统,最后用户应该从复杂的东西中分离出来,比如渲染和事件传播,应用开发者应该能一次性的描述他们的ui,例如一串的hbs标签,然后继续其应用而无需关心ui是否保持更新。
视图层级解决了什么问题?
子视图:
在一个典型的客户端应用中,视图可以代表dom中互相嵌套的元素,这个问题的最简单的解决方案,分离表示每个dom元素的视图对象,特定的引用可以帮助视图对象跟踪那些概念上嵌套在其中的视图。
这有一个简单的例子,表示一个主要的应用视图,有一个容器在其中,并且各个独立的元素嵌套在容器中。
看上去,这个系统工作的很好,但是想象一下,我们想要在八点打开应用而不是九点,在这个方案中,我们需要重新渲染app view ,因为开发者需要为子视图建立一个参考在特定的基础上,重新渲染的方案有很多的问题。
为了重新渲染应用视图,应用视图必须手动的重新渲染子视图,并将子视图插入应用视图的元素中去。
如果实现的完美的话,这个进程会工作的好,但是,这是依赖于一个完美的,特定的视图层级的实现,如果其中一个视图没有精确的实现,整个重新渲染就失败了。
为了避免这些问题,ember的视图层级有了子视图的概念。
当应用视图重新渲染,ember为重新渲染和插入子视图作出响应,而不是应用的代码,这也意味着ember可以为你执行任何一个内存管理,比如清理观察器和绑定。
这不仅消除了相当多的引用代码,而且他尽可能的消除了没有实现的那么完美的视图层级在重新渲染时出现的意想不到的错误的情况。
事件委派
过去,web开发者添加事件监听到每一个元素为了知道用户什么时候与它交互,比如,你可能有一个<div>元素,你注册一个函数当用户点击它时触发。
当然,有大量交互元素的时候,这个方法不是一个解决的办法,比如,想象一个<ul>中有100个<li>,每个<li>中有一个删除按钮,全部的按钮的行为是一样的,那么,他会被低效
率的创建100个事件监听。
为了解决这个问题,开发者发现一个技术叫做事件委托,你可以为包含的元素注册一个监听,使用event.target辨认用户点击的的那个元素,而不是为每个元素注册监听。
实现这个有一点狡猾,因为有一些事件不会冒泡,比如,focus,blur,change,幸运的是,jquery已经完全解决了这个问题,用jquery的on可以解决全部的本地浏览器事件。
其他的js框架解决这个问题通常有两种方法,第一,他们让你用你自己最简单的方法去实现,创建一个分离的视图为每个元素,当你创建好了视图,他建立一个事件监听器在视图元素上,如果你有一串500个元素的列表,你应该创建500个视图并且为每个加上监听器。
第二种方法,框架建立事件委托在视图层级上,当创建一个视图,你可以提供给一系列的事件委托并且一个方法被唤醒只有当事件发生的时,这只需要识别接收到点击事件方法的上下文,如列表中哪个元素被点击。
现在面临一个很不舒服的选择:为每个元素创建视图则损失了事件委托的利益,创建一个单独的视图则必须保存一堆dom中的js对象。
为了解决这个问题,ember使用jquery将所有事件委派给应用的根元素,通常是文档的body,当事件发生时,ember识别出最近的视图并调用其事件处理方法,这就意味着,你可以创建一个视图去装js的上下文,并且得到事件委派的好处。
另外,因为ember只注册一个事件为整个ember应用,创建新视图从不需要建立事件监听,使重新渲染更加高效并且更少错误。
当一个视图有子视图时,也意味着不需要手动解除重新渲染过程替换的视图的委托。
渲染管道
大多数的web应用用一种特定的模板语言来标记他们的用户界面接口,比如,emberjs,我们用hbs模板语言,自动的更新值当其中的值改变的时候。
虽然显示模板的过程对于开发者来说是自动的,但实际上这个过程包含了从原始模板到最终,用户见到的dom表示一系列必备的步骤。
下面是一个ember的近似的生命周期:
1. 模板编辑
应用的模板通过网络加载或作为字符串的表格的一部分应用加载,当应用下载后,他发送模板的字符串到hbs被编译成为一个函数,一旦编译完成,模板函数被保存,并且可以在每次需要重新渲染的时候被重复使用在复杂的视图中。
当模板预先编译好在服务器的时候,这一步将被省略,这种情况下模板不作为初始的可读的模板字符串被传输,而是编译后的代码。
因为ember负责了模板的编译,因此不需要为确保编译后的模板的可重用做一些附加的工作2. 字符串连接
一个视图启用了append或appendto时,视图的渲染过程被唤醒,唤醒append或appendto 相当于将视图的渲染和插入加入计划中,这个允许在渲染前处理其他的应用中的延迟逻辑,如绑定同步。
开始渲染时,ember创建一个renderbuffer,视图可以将其内容追加到其中,渲染过程中,一个视图可以创建和渲染子视图,这时父视图创建一个renderbuffer并赋给子视图,这个新创建的renderbuffer和父的renderbuffer相连。
Ember在渲染每个视图前进行同步绑定,通过渲染视图前的同步绑定,ember确保不会渲染那些已经过期需要的立即替换的数据
当主视图渲染完,整个渲染过程创建了一个与缓存树关联的视图树(视图层级),通过遍历缓存树,将其转换为字符串,就可以得到插入到dom中的字符串。