码迷,mamicode.com
首页 > Web开发 > 详细

EmberMVC视图相关分享

时间:2015-07-26 19:23:35      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:

  1. Ember中视图与组件的对比

  2. 创建一个不在视图树中的任意视图,如对话框

  3. 时序:didInsertElement和Em.run区别与各自应用场景



1 Ember中视图与组件的对比 
依据现有经验,结合国外社区的讨论,总结两者的对比:

从最终奥义来讲,视图能实现当前应用内的代码复用,而组件则能实现应用无关的放之任何场景都可用的代码复用


由于两者意图的不同,视图代码会更贴合当前业务需求,但不利于独立成一个日后可用的工具箱部件。而组件则会极大的与当前业务需求解耦出来,它仅提供几个有限的对外接口


视图的上下文是和当前所在路由控制器一致的,也就是共用了一套变量环境,并往往会与外部环境的控制器,消息传递发生交叉
组件的上下文则是与外部上下文独立的(当然,如有必要,组件依赖某些外部变量,还是能通过属性传入的方法来导入)。另外它也不能访问外部环境的控制器。如果需要消息交互,则应该通过一个主操作接口来向外部环境传出消息。


总体来说,很多方面,组件都力图做到内外部的解耦,充分的独立。虽然这么做能极方便的使其成为我们日后可用工具箱的一个部件,但是由于较大的脱离了业务逻辑以及上下环境的隔离,其实现往往需要更多的代码,许多时候,还需要我们处理一些细节来绕过其特性带来的约束。


2 创建一个不在视图树中的任意视图,如对话框 

在Ember应用中,那些通过路由管理,容器视图管理,视图助手管理等等的视图,都是构建在一个完整视图树层级中的,并且能被chrome浏览器中的Ember Ispector拓展检测到的
然而有时候我们可能会需要创建一个不在视图树层级中的视图,某些场景下这往往能带来逻辑实现上的方便
例如一个对话框,官网教程cookbook上对于对话框的实现涉及了outlet插口,路由actions,而且这还是个未集成上效果美观的jQuery对话框插件的初步效果,咋看起来实现上还是略略麻烦,且将UI的操作放进路由里处理不太符合MVC的概念,这种界面上的响应操作我推荐写进视图的actions中
那么讲讲我推荐的做法,首先我们可以看到,一个对话框在应用中往往没有明确的节点位置、视图层级关系,那么我们可以构建一个不在视图树层次中的视图来实现它,同时我们可以手动指定一个控制器给它以提供合适的上下文环境,需要注意的是我们必须传入一个变量容器container给它(否则控制台会报出一个逆反信息)。最后,对于一个无层级的视图,我们需要通过调用视图的append方法将其追加到body节点中:

App.DialogView.create({
	controller: XXXX,
	container: this.container,
}).append();

ok, 当视图插入到body中后,也就是说dialog的主体dom内容已经ready了,接下去我们需要通过一个jQuery对话框插件将其弹出。最后,由于对话框关闭时,仅仅是通过js的方式将其css式隐藏而没有销毁对话框的视图对象,为了避免下次弹出对话框时重复,我们这里需要手动地在对话框关闭时候,将这个对话框视图销毁掉:

App.DialogView.extend = Em.View.extend({
	didInsertElement: function(){
		this._super();

		var self = this;

		this.$().dialog({
			height: 200,
			width: 500,
			draggable: true,
			resizable: false,
			modal: true,
			title: "请选择竞争车系......",
			close: function(event, ui){
				self.destroy();
			},
	}
});

ok,最后还要提醒的是,由于这个对话框是不在视图层级的,所以Ember Ispector中调试时候,我们是观察不到它的,我们需要手动的在console中输出调试信息或者加debug断点来测试它。


3 时序问题:didInsertElement和Em.run的区别与各自应用场景
Ember提供了两套逻辑来对应用生命周期的各个时间点进行管理.


1)通过生命周期钩子对一个视图view的生命周期进行管理.

包括了willInsertElement、didInsertElement、willDestroyElement、willClearRender、becameVisible、becameHidden六个视图层次的生命周期钩子.


2)通过运行时循环对应用的一个事件响应周期进行管理.

包括了sync, actions, routerTransitions, render, afterRender, destroy六个运行时队列

通常的,我们用的较多的分别是didInsertElement钩子与afterRender运行时队列。



在didInsertElement中的操作确保了当前视图及其父视图已经ready,但是不能确保其子视图的ready。
而afterRender运行时队列确保了应用当前所有的运行视图已经ready。


举例一个应用场景,如商品列表页面上有一组筛选项,它的结构是一个大容器视图包含了许多个筛选项视图,我们希望在筛选项都渲染出来后,进行一个初始化操作,将部分筛选项临时收拉起来。


首先我们就发现不能在大容器视图进入didInsertElement钩子即容器视图ready后进行初始化操作,因为此时筛选项作为其子视图还没有ready。那么最后,我们其实可以在大容器视图的didInsertElement钩子中调度一个afterRender运行时队列,这样就确保了大容器及筛选项视图的ready,并进一步的进行初始化操作:

App.FiltersContainerView = Em.View.extend({
		didInsertElement: function(){
			this._super();

			Em.run.afterRender(‘afterRender‘, this, function(){
				#初始化操作,通过调度afterRender队列来等待子筛选项视图的ready
			});
		}
	});


EmberMVC视图相关分享

标签:

原文地址:http://my.oschina.net/u/2400083/blog/483900

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!