ExtJS - How to use Proxy, Model? How are they rela

2019-03-09 12:00发布

I've been trying to learn to work with Models and Stores. But the proxy bit is confusing me a lot. So I'm going to list out my understanding here - please point out the gaps in my understanding.

My understanding

  1. Models are used to represent domain objects.
  2. Models can be created by ModelManager, or by simply using the constructor
  3. Models are saved in Stores
  4. Stores may be in memory stores, or can be server stores. This is configured using Proxy.
  5. Proxy tells the store how to talk to a backing store - be that a JSON array, or a REST resource, or a simply configured URL via ajax.
  6. Stores are responsible for storing models, and Proxies are responsible for controlling/helping with that task.
  7. When a model's values are changed, its dirty flag gets set. It gets automatically cleared when the model is saved. (more in this later)

The part that confuses me

  1. Why is there a proxy config and save method on Model? I understand that models can only be stored on to stores.
  2. Why is the dirty flag not cleared simply when I add a model object to a store?
  3. When I add a model object to a store, why does the model not acquire the proxy configured with that store?
  4. proxy is a static configuration for a Model. Does that mean that we cannot use objects of a particular model with multiple data sources? By extension, does this mean having multiple stores for a single model essentially useless?
  5. When we define a Store, are we defining a class (store-type, if we may call it that), or is it an instance of a store? Reason I ask is when we declare a grid, we simply pass it a store config as store: 'MyApp.store.MyStore' - does the grid instantiate a grid of that type, or is it simply using the store we've already instantiated?

Thanks!

PS: +50 bounty to the person who explains all this :) - will offer bounty after those 48 hours are over..

3条回答
时光不老,我们不散
2楼-- · 2019-03-09 12:15

The docs say:

A Model represents some object that your application manages.

A Store is just a collection of Model instances - usually loaded from a server somewhere.


Models are saved in Stores

Not only. The Models can be used separately (f.i. for populating forms with data. Check out Ext.form.Panel.loadRecord for more info).

Why is there a proxy config and save method on Model? I understand that models can only be stored on to stores.

As I've said, not only.

Why is the dirty flag not cleared simply when I add a model object to a store?

Why should it? The Record becomes clean only when it gets synchronized with the corresponding record on the server side.

When I add a model object to a store, why does the model not acquire the proxy configured with that store?

This is, again, because model can be used without store.

proxy is a static configuration for a Model. Does that mean that we cannot use objects of a particular model with multiple data sources?

We cannot use objects of a particular model but we can use one model definition for multiple store. For example:

Ext.define('MyModel', {
  // ... config
});
var store1 = Ext.create('Ext.data.Store', {
  model: 'MyModel',
  // ... config
  proxy: {
    // ...
    // this proxy will be used when store1.sync() and store1.load() are called
  }
  // ...
});
// ...
var storeN = Ext.create('Ext.data.Store', {
  model: 'MyModel',
  // ... config
  proxy: {
    // ...
    // this proxy will be used when storeN.sync() and storeN.load() are called
  }
  // ...
});

Since store1 and storeN use different proxies, the records, contained by these stores, may be completely different.

When we define a Store, are we defining a class (store-type, if we may call it that), or is it an instance of a store?

Yes, when we define a Store, we are defining a class.

Reason I ask is when we declare a grid, we simply pass it a store config as store: 'MyApp.store.MyStore' - does the grid instantiate a grid of that type, or is it simply using the store we've already instantiated?

There are couple of ways to set store config for grid:

  1. store: existingStore,
  2. store: 'someStoresId',
  3. store: 'MyApp.store.MyStore',

In the first and the second cases existing instances of stores would be used. In the third case newly created instance of 'MyApp.store.MyStore' would be used. So, store: 'MyApp.store.MyStore', is equal to

  var myStore = Ext.create('MyApp.store.MyStore', {});
  // ... 
    // the following - is in a grid's config:
    store: myStore,

UPDATE


When a model is added to store and then the store's sync() is called, why is the model's dirty flag not cleared?

It should be cleared, unless reader, writer and server response are not set up properly. Check out writer example. There is dirty flag being cleared automaticaly on store's sync().


if a model class is not given any proxy at all, why does it track its dirty status?

To let you know if the record was changed since the creation moment.


What is achieved by introducing the concept of Models syncing themselves to the server?

Let's assume you are creating a widget which contains plain set of inputs. The values for this inputs can be loaded from db (this set of inputs represents one row in db table). And when user changes the inputs' values data should be sent to the server. This data can be stored in one record.

So what would you use for this interface: one record or a store with only one record?

Standalone model - is for widgets that represent one row in db table.
Store - is for widgets that represent set of rows in db table.

查看更多
我想做一个坏孩纸
3楼-- · 2019-03-09 12:23

I found it in the documentation of sencha App Architecture Part 2

Use proxies for models:

It is generally good practice to do this as it allows you to load and save instances of this model without needing a store. Also, when multiple stores use this same model, you don’t have to redefine your proxy on each one of them.

Use proxies for stores:

In Ext JS 4, multiple stores can use the same data model, even if the stores will load their data from different sources. In our example, the Station model will be used by the SearchResults and the Stations store, both loading the data from a different location. One returns search results, the other returns the user’s favorite stations. To achieve this, one of our stores will need to override the proxy defined on the model.

查看更多
劫难
4楼-- · 2019-03-09 12:29

I'm coming from ExtJS 2.2 [sic] to 4, and the Model behavior and terminology threw me for a loop too.

The best quick explanation I can find is from this post in the "Countdown to ExtJS 4" series on Sencha's blog. Turns out a Model acts like it does because it's "really" a Record.

The centerpiece of the data package is Ext.data.Model. A Model represents some type of data in an application - for example an e-commerce app might have models for Users, Products and Orders. At its simplest a Model is just a set of fields and their data. Anyone familiar with Ext JS 3 will have used Ext.data.Record, which was the precursor to Ext.data.Model.

Here's the confusing part: A Model is both a model for the data you're using and a single instance of an object following that model. Let's call its two uses "Model qua model" and "Model qua Record".

This is why its load method requires a unique id (full stop). Model qua Record uses that id to create RESTful URLs for retrieving (and saving, etc) a single Record worth of data. The RESTful URL convention is described here and is linked to in this post on Sencha's blog that talks specifically about Model usage.

Here are a few RESTful URLs formed to that standard to get you familiar with the format, which it appears ExtJS' Model does use:

Operate on a Record with id of 1

GET /people/1 <<< That's what's used to retrieve a single record into Model

return the first record with id of 2

DELETE /people/2

destroy the first record with id of 7

POST /people/7?_method=DELETE

Etc etc.

This is also why Models have their own proxies, so that they can run RESTful operations via that URL modified to follow the conventions described in that link. You might pull 100s of records from one URL, which you'd use as your Store's proxy source, but when you want to save what's in the single Model (again, think "Model qua Record" here), you might perform those Record-specific operations through another URL whose backend messes with one record at a time.


So When Do I use Stores?

To store more than one instance of that Model, you'd slap them into a Store. You add lots of Models qua Records into Stores and then access those "Models" to pull data out. So if you have a grid you'll naturally want to have all that data locally, without having to re-query the server for each row's display.

From the first post:

Models are typically used with a Store, which is basically a collection of Model instances.

And, of course, the Stores apparently pull info from Model qua Model here to know what they're carrying.

查看更多
登录 后发表回答