【问题标题】:CanJS - Control CommunicationCanJS - 控制通信
【发布时间】:2013-04-23 12:58:40
【问题描述】:

我现在正在学习CanJS,所以想尝试一个非常基础的小demo。该演示是您将拥有不同类型的移动充值计划,这些计划显示在顶部(单选按钮),通过选择每个计划,相应的价格选项将显示在底部的表格中。

对于这个演示,我创建了两个 Model , 2 Control 和 2 Template 文件,我的问题是两个控件如何相互通信?标准方式是什么?

现在我通过它的实例直接调用控制方法,但我不确定这是否是正确的做法。另外请解释一下Can.Route。

输出 http://jsfiddle.net/sabhab1/2mxfT/10/

数据

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));
        });
    }
});**

查看

<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>

主调用

new CategoryControl("#categoriesView");     

【问题讨论】:

    标签: model-view-controller canjs canjs-control


    【解决方案1】:

    有几种方法可以做到这一点。

    1。直接调用方法

    这就是你正在做的,不一定是错的。为了让事情更灵活一点,您可以在初始化 CategoryControl 时传递 RechargeAmountControl 的类或实例,而不是直接使用它。

    2。 DOM 事件

    这里涉及到更多面向事件的架构。如果您通常想通知其他控件,您可以触发任何类型的事件并让他们监听它。像这样:http://jsfiddle.net/2mxfT/11/

    ' rechargeAmountUpdated': function(element, event, id){
        var el = this.element;
        console.log(arguments);
        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));
        });
    }
    

    3。可观察的

    另一个选择是使用 Observables 来维护共享状态。这是专注于数据并让实时绑定完成所有其他工作的好方法。为了让事情更灵活,应该在 Control 初始化期间传递状态对象(参见http://jsfiddle.net/2mxfT/12/):

    var state = new can.Observe();
    
    new RechargeAmountControl("#rechnageAmountView", {
        state: state
    }); 
    new CategoryControl("#categoriesView", {
        state: state
    });
    
    state.attr('rechargeId', 1);
    

    然后你可以像这样监听 RechargeAmountControl 中的属性变化:

    '{state} rechargeId': function(Construct, event, id){}
    

    每当您更新状态观察时,都会调用此处理程序。

    这也是can.route 的用武之地。基本上 can.route 是一个将其状态保存在位置哈希中的 Observe。在上面的例子中像#!&amp;rechargeId=1(除非你初始化一个特定的路由像can.route(':rechargeId'))。如果位置哈希发生变化,Observe 将被更新,反之亦然。

    【讨论】:

    • 你太棒了,我会选择选项 3。请问最后一个问题,Can.Route 的真正用途是什么?我刚刚从 Adob​​e Flex 迁移到 JS 框架。还有CanJS的教程除了提供什么网站,付费的也可以。
    • 我更新了我的答案。基本上 can.route 只是一个将其状态持久化到窗口位置哈希的 Observe。
    • 非常感谢达夫!现在是我学习模型列表的时候了。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多