Sencha Touch MVC — recommended ways of passing dat

2020-02-28 04:14发布

问题:

I'm using Sencha Touch for a mobile app and am using the MVC functionality in it. I like Sencha quite a bit but I'm having a little trouble when it comes to passing data from one 'screen' to the next using the controller.

There's a "record" property associated with a number of the Sencha widgets --indicating the currently selected record in an Ext.list for instance-- and for some reason I can't quite get there as to how to pass something like that from an Ext.Panel to another one.

For instance, I have an Ext.Panel with data in it from an Ext.Store, including an address. I have another Ext.Panel that will show a map. I need to pass this address to the map's panel, but am not sure how. Here's what I'm trying from the first panel:

                listeners: {
                'tap': function () {
                    Ext.dispatch({
                        controller: app.controllers.establishments,
                        action: 'showMap',
                        id: record.getId(),
                        data: record.data
                    });
                }

I'm floundering a bit as you can see, trying to use both an 'id' and 'data' config option in the controller in an attempt to get data to the map panel, by any means necessary.

I don't necessarily need a answer for this specific problem, but if you had suggestions on how to do this in general-- basically, best practices for passing data from one screen to the next.

If it helps, I'm basing my app's structure on a nice MVC tutorial by Mr. Pearce at Sencha:

http://www.sencha.com/learn/Tutorial:A_Sencha_Touch_MVC_application_with_PhoneGap

Thanks much!

回答1:

I think you're on the right track with Ext.Dispatch. The parameters you add in the Dispatch options object are passed to the action method on the controller.

E.g.

showMap: function(options){ 
               var id = options.id; 
               //load data based on the id and pass it to your map
               ...
         }

I also think you should set the historyUrl on the Dispatch options object so that if they refresh the page the id will still get sent to the controller action.



回答2:

I am not too familiar with this MVC pattern but I have a lot of experience with ExtJS and in my opinion the best way for components to communicate is with events. In your example you would create an event on the Panel like 'addAddress' and the Map would listen for that event. And when the address was set in the panel you would call.

this.addEvent('addAddress');

this.fireEvent('addAddress', this, address);

and the map would have a listener like

onAddress: function(panel, address) {
   // do something with the address
}

and in your top level app you would add the listener.

app.mon(panel, 'addAddress', map.onAddress, this);

Typically it's best for your components together this way so that the Panel isn't dependent on the Map and vice-versa



回答3:

A better solution might be restructure your MVC to eliminate the need to pass records around different views. For example, making different view component share the same store, whose reference is made accessible from anywhere needed.

Usually I'd put the reference of stores used across different views in locations such as App.controllers.data nor directly under App (which is really just part of controller anyway).



回答4:

Answering a very old question, I suppose with the current versions of Sencha touch (2.2+) we have an alternate method, which I kind of prefer. Here it is for your evaluation.

Alternative is to use the routes feature of the controllers.

NOTE: Ext.Dispatch is deprecated in Sencha Touch 2.2, if you still want to use the dispatch method you need get the controller and call the method on it as explained here. How to pass data among the screens in sencha touch2.0?

First you define the routes a controller is interested in.

Ext.define('My.controller.Profile', {
extend: 'Ext.app.Controller'
,config: {
    routes: {
        'products/:id': 'showProduct'
    }
}
,showProduct: function(id) {
    console.log('Load and Show product... ' + id);
}

});

Next you create a link which has a url of this format as the href:

<a href="#products/1234">View Product</a>

Clicking the link will invoke the Product controllers showProduct method with id set to 1234.

Or if you wish to do this programmatically you could write:

location.hash = "products/1234";

which will have the same effect.

I think this is kind of clean, loosely coupled and has less dependency of framework internals. Open for ideas. :)