Model view controller CanJS-控制通信
我现在正在学习CanJS,所以我想尝试一个非常基本的小演示。演示内容是,您将在顶部(单选按钮)显示不同类型的移动充值计划,通过选择每个计划,相应的价格选项将显示在底部的表格中 对于这个演示,我创建了两个模型、两个控件和两个模板文件,我的问题是两个控件如何相互通信?标准方式是什么 现在,我通过实例直接调用控件方法,但我不确定这样做是否正确。另外,请解释Can.Route 输出 数据Model view controller CanJS-控制通信,model-view-controller,canjs,canjs-control,Model View Controller,Canjs,Canjs Control,我现在正在学习CanJS,所以我想尝试一个非常基本的小演示。演示内容是,您将在顶部(单选按钮)显示不同类型的移动充值计划,通过选择每个计划,相应的价格选项将显示在底部的表格中 对于这个演示,我创建了两个模型、两个控件和两个模板文件,我的问题是两个控件如何相互通信?标准方式是什么 现在,我通过实例直接调用控件方法,但我不确定这样做是否正确。另外,请解释Can.Route 输出 数据 var CATEGORIES = [{id: 1 , name: "2G Internet Recharge"},
var CATEGORIES = [{id: 1 , name: "2G Internet Recharge"},
{id: 2 , name: "3G Internet Recharge"},
{id: 3 , name: "full talktime Recharge"},
{id: 4 , name: "Validity and talktime Recharge"},
{id: 5 , name: "National and international roaming"}];
var RECHARGEAMOUNTS =[{
id: 1 ,
values : [{amount: "Rs. 100" , benefit:"300 MB" ,validity:"30"},
{amount: "Rs. 200" , benefit:"1 GB" ,validity:"30"}]
},
{
id: 2 ,
values : [{amount: "Rs. 10" , benefit:"300 MB" ,validity:"30"},
{amount: "Rs. 99" , benefit:"100 GB" ,validity:"90"}]
},
{
id: 3 ,
values : [{amount: "Rs. 80" , benefit:"1 GB" ,validity:"50"},
{amount: "Rs. 99" , benefit:"100 GB" ,validity:"50"}]
},
{
id: 4 ,
values : [{amount: "Rs. 55" , benefit:"30 MB" ,validity:"10"},
{amount: "Rs. 200" , benefit:"1 GB" ,validity:"30"},
{amount: "Rs. 99" , benefit:"100 GB" ,validity:"90"}]
},
{
id: 5 ,
values : [{amount: "Rs. 880" , benefit:"100 MB" ,validity:"90"},
{amount: "Rs. 550" , benefit:"2 GB" ,validity:"30"},
{amount: "Rs. 1000" , benefit:"4 GB" ,validity:"90"},
{amount: "Rs. 1550" , benefit:"10 GB" ,validity:"90"}]
}
];
型号
//Model Category
CategoryModel = can.Model({
findAll : function(){
return $.Deferred().resolve(CATEGORIES);
}
},{});
//Model Category
ReachargeAmountModel = can.Model({
findAll : function(){
return $.Deferred().resolve(RECHARGEAMOUNTS);
},
findOne : function(params){
return $.Deferred().resolve(RECHARGEAMOUNTS[(+params.id)-1]);
}
},{});
**// Can Control
var CategoryControl = can.Control({
// called when a new Todos() is created
init: function (element, options) {
// get all todos and render them with
// a template in the element's html
var el = this.element;
CategoryModel.findAll({}, function (values) {
el.html(can.view('categoriesEJS', values))
});
this.options.rchAmtCtrl = new RechargeAmountControl("#rechnageAmountView");
},
'input click' : function( el, ev ) {
var id = el.data('category').attr('id');
console.log(id);
this.options.rchAmtCtrl.update(id);
}
});
// Can Control
var RechargeAmountControl = can.Control({
// called when a new Todos() is created
init: function (element, options) {
// get all todos and render them with
// a template in the element's html
this.update(1);//this.update(id,this.element);
},
update : function(id){
var el = this.element;
ReachargeAmountModel.findOne({id: id}, function( rechargeAmount ){
// print out the todo name
//console.log(rechargeAmount.values[id].attr('benefit'));
el.html(can.view('RechnageAmountEJS', rechargeAmount.values));
});
}
});**
new CategoryControl("#categoriesView");
控制
//Model Category
CategoryModel = can.Model({
findAll : function(){
return $.Deferred().resolve(CATEGORIES);
}
},{});
//Model Category
ReachargeAmountModel = can.Model({
findAll : function(){
return $.Deferred().resolve(RECHARGEAMOUNTS);
},
findOne : function(params){
return $.Deferred().resolve(RECHARGEAMOUNTS[(+params.id)-1]);
}
},{});
**// Can Control
var CategoryControl = can.Control({
// called when a new Todos() is created
init: function (element, options) {
// get all todos and render them with
// a template in the element's html
var el = this.element;
CategoryModel.findAll({}, function (values) {
el.html(can.view('categoriesEJS', values))
});
this.options.rchAmtCtrl = new RechargeAmountControl("#rechnageAmountView");
},
'input click' : function( el, ev ) {
var id = el.data('category').attr('id');
console.log(id);
this.options.rchAmtCtrl.update(id);
}
});
// Can Control
var RechargeAmountControl = can.Control({
// called when a new Todos() is created
init: function (element, options) {
// get all todos and render them with
// a template in the element's html
this.update(1);//this.update(id,this.element);
},
update : function(id){
var el = this.element;
ReachargeAmountModel.findOne({id: id}, function( rechargeAmount ){
// print out the todo name
//console.log(rechargeAmount.values[id].attr('benefit'));
el.html(can.view('RechnageAmountEJS', rechargeAmount.values));
});
}
});**
new CategoryControl("#categoriesView");
查看
<form id='categoriesView'></form>
</p>
<table id='rechnageAmountView'></table>
<script type='text/ejs' id='RechnageAmountEJS'>
<tr>
<th>Recharge Amount</th>
<th>Benefits</th>
<th>Validity(Days)</th>
</tr>
<% this.each(function( rechargeAmount ) { %>
<tr>
<td>
<%= rechargeAmount.attr( 'amount' ) %>
</td>
<td>
<%= rechargeAmount.attr( 'benefit' ) %>
</td>
<td>
<%= rechargeAmount.attr( 'validity' ) %>
</td>
</tr>
<% }) %>
</script>
<script type='text/ejs' id='categoriesEJS'>
<% this.each(function( category ) { %>
<input type="radio"
name="category"
<%= category.attr('id') == 1 ? 'checked' : '' %>
value=<%= category.attr( 'name' ) %>
<%= (el) -> el.data('category',category) %>>
<%= category.attr( 'name' ) %>
</input>
<% }) %>
</script>
有几种方法可以做到这一点 1.直接调用方法 这就是你正在做的,并不一定是错的。为了使事情更加灵活,您可以在初始化
CategoryControl
时传递recoveriamountcontrol
的类或实例,而不是直接使用它
2.DOM事件
这里,我们将进一步讨论面向事件的体系结构。如果您通常想要通知其他控件,您可以触发任何类型的事件并让它们侦听它。大概是这样的:
3.可观测
另一种选择是使用可观察对象来维护共享状态。这是一种关注数据并让实时绑定完成所有其他工作的好方法。为了使事情更加灵活,应该在控件初始化期间传递state对象(请参阅):
然后您可以只听RechareAmountControl中的属性更改,如下所示:
'{state} rechargeId': function(Construct, event, id){}
无论何时更新状态,都将调用此处理程序
这也是
can.route
的用武之地。基本上,can.route是一个将其状态保存在位置散列中的观察。在上面的例子中,比如#&rechargeId=1
(除非您初始化特定的路由,如can.route(“:rechargeId”)
)。如果位置散列发生变化,观察将被更新,反之亦然。你太棒了,我会选择选项3。我可以问你最后一个问题吗,Can.Route的真正用途是什么?我刚刚从Adobe Flex迁移到JS框架。另外,除了提供什么网站,还有什么关于CanJS的教程,付费的也可以。我更新了我的答案。基本上,can.route只是一个将其状态持续到窗口位置散列的观察。非常感谢Daff!现在是我学习模型列表的时候了。再次感谢。