June 23, 2011 David Kaneda
The process of building a complex web application has evolved a lot over the past few years, largely thanks to the ever-evolving browser landscape. Many server-side and native application development paradigms — including MVC, layout systems, and data stores — are moving to frontend web technology like JavaScript. This article will take a brief, high-level, look at data stores, and how they can be used to reduce your development time and future-proof your applications.
For demonstration purposes, we will look at the Twitter homepage, which relaunched a few months ago as a single page application. To be clear, Twitter does not use Sencha frameworks — I am simply using their user interface as a study in development process. We could just as easily look at a variety of other single-page applications like Facebook or Grooveshark.
Let’s take a quick look at the Twitter homepage when you’re logged in:
Note that any action a user takes on this screen does not load a new web page but rather fires JavaScript and updates the page dynamically. For this example, we will be looking at one interaction in particular: Clicking “Follow” under the “Who To Follow” list.
For Twitter to properly and dynamically update when a user clicks “Follow,” a lot of things need to happen, and very quickly. First, the link we just clicked needs to change from “Follow” to “Unfollow” list. We will also need to bump up the user’s follower count, and then add the newly followed user into the “Following” list.
In traditional web page development, if we were using a basic DOMmanipulation library such as jQuery, this would be quite a tedious task and involve things like:
- Figuring out who the user is choosing to follow, probably by traversing up the DOM tree from the follow button.
- Selecting the follower count ($(’#followercount’)), increasing the number by one, then replacing the text in the element.
- Pulling the user’s avatar out of the “Who To Follow” row, and adding it to the front of the “Following” list. Additionally, we would have to remove the last avatar in that list so as not to change the layout.
This is not ideal for a few reasons. First, this would all be custom code in the click handler of the Follow button. If we were to add any additional functionality or UI to the application that involved one’s follower list, we would have to remember to come back and update this code, so our app continued to function properly. Additionally, we would have to duplicate the code in reverse to handle links in the app which “Unfollow.” Lastly, we would have to manually optimize this code by caching selectors, where appropriate. Together, all of this means code that is error-prone and difficult to debug.
There’s a Better Way
Now, let’s look at the same example but introduce the concept of a data store. For those who are unfamiliar, a data store is an abstract representation of a collection of records, almost like a database. In this example, our data store will be the user’s “Following” list. Please note that this is pseudo-code, loosely based on the Ext JS API, but it’s concepts can be used anywhere (there is a similar API for Sencha Touch, for example).
var followingStore = Ext.create('Ext.data.Store', { model: 'User' });
Now, we can take that data store and “bind” relevent elements on the page to it. This means they will listen for changes to the data store itself and update themselves, when necessary.
To create the list of avatars that the user is following, for example, we could do something like this:
// Create the following list (pseudo-code) var followingList = new Ext.DataView({ store: followingStore, tpl: '', collectData: function(){ var data = this.callParent(arguments); return Ext.Array.slice(data, 0, 5); } });
Here, we’ve created a “DataView,” which is a component that loops through items in a data store and creates DOM elements for each one. We pass in our
followingStore
, give each item a template, and then use the collectData
function to make sure we’re always only showing the 6 most recently followed users. This collectData
function will automatically fire anytime thefollowingStore
is updated, so we never have to worry about this part of the page being out of sync.
Similarly, we can create the view which shows the numeric count of people the user is following:
// Create the following count display (psuedo-code) var followingCountCmp = Ext.create('Ext.Component', { tpl: 'Following {followCount}' }); followingStore.on('datachange', function() { followingCountCmp.update({ followCount: followingStore.getCount() }); });
With this, we’ve created a basic component,
followingCountCmp
, which uses a template to show some text about how many people the user is following. We then bind a callback to the datachange
event on the data store which updates the component. The datachange
event will fire whenever a new user is followed or unfollowed, so again, we don’t have to worry about this follower count breaking in the future.
With these components established, our logic for when the user clicks “Follow” is much simpler. Instead of going through and manually updating DOM elements throughout the page, we can simply call something like the following code, and all of the components will update automatically.
followingStore.add(newUserToFollow);
Now, as we begin to develop “Unfollow” buttons and other functionality around a user’s following list, we can be confident that we don’t have to revisit the code we have already written. Ultimately, this creates code that is more future-proof and accessible to new developers working on our project.
댓글 없음:
댓글 쓰기