Loading...

Sử dụng Sammy.js làm singlepage

Mô tả

Hướng dẫn cách sử dụng Sammy.js để tạo ứng dụng single-page, giúp quản lý route và nội dung động mà không cần tải lại trang.

The Skinny

sammy.js is a tiny client-side framework for building web applications.

It features:

  • Small footprint (16K)

  • Hash-routing (via HTML5 pushState by default)

  • Plugins like crazy

This guide will take you through:

  • What does sammy.js solve?

  • What does sammy.js leave up to the developer?

  • Why sammy.js instead of other frameworks?

  • How do sammy’s plugins work?

  • What are some more advanced techniques for using sammy.js?

What is sammy.js?

sammy.js is a lightweight solution for a client-side web framework.

At its core, sammy.js is mostly a routing framework. It allows you to attach callbacks to specific routes.

var Application = Sammy( function( )
{
  this.get( '#/', function( )
  {
    alert( "Check out the home page!" );
  } );
} );

After that, sammy.js comes bundled with almost 20 plugins that you can include and use to handle everything from client-side persistence to templating to analytics.

What doesn’t sammy.js do?

Unlike backbone.js, there is no model/service layer included with sammy.js. This means that you can either roll your own, or if you’re RESTful, use something pre-built like js-model.

Comparison to backbone.js

sammy.js and backbone.js do overlap in their routing functionality so I don’t recommend using both libraries together in the same project.

You might want sammy.js if…

  • your application looks more like a site with pages.

  • you have a backend service that isn’t exactly RESTful.

You might want backbone.js if…

  • your application looks more like google docs.

  • you have a backend service that is entirely RESTful.

Let’s see some code!

Here’s a bare-bones sammy.js app with two routes:

var Application = Sammy( function( )
{
  this.get( '#/home', function( )
  {
    alert( "Check out the home page!" );
  } );
  
  this.get( '#/shop', function( )
  {
    alert( "Check out the shop page!" );
  } );
} );

This app has two routes, #/home and #/shop. If the browser’s hash changes to either of these routes, the corresponding callback will be invoked.

When you’re ready to kick off your app, call Application.run( );. You can also pass in the default route like Application.run( '#/home' );.

Rendering your pages

These route callbacks are great places to render our content into the page.

var Application = Sammy( function( )
{
  this.get( '#/home', function( )
  {
    $( '#content' ).text( "Check out the home page!" );
  } );
  
  this.get( '#/shop', function( )
  {
    $( '#content' ).text( "Check out the shop page!" );
  } );
} );

But if our content is any more complicated than that, we should switch to using a templating plugin!

Templating plugins

sammy.js comes with plugins for mustache.jsjquery-tmplEJShaml-js, and pure.

If you don’t like any of those, or maybe you’re just a purist, sammy.js also provides a templating plugin in the style of John Resig’s original JavaScript templates.

To use it, you’ll first need to include the Sammy.Template plugin in your page. Next, you have to tell your sammy app to use it:

var Application = Sammy( function( )
{
  this.use( 'Template' );
  
  this.get( '#/home', function( )
  {
    $( '#content' ).text( "Check out the home page!" );
  } );
  
  this.get( '#/shop', function( )
  {
    $( '#content' ).text( "Check out the shop page!" );
  } );
} );

Next, we can write a couple templates:

<!-- home.template -->
<h1>The Home Page</h1>
<p>Hey there, internet surfer!</p>
<!-- shop.template -->
<h1>The Online Shop</h1>
<ul>
    <li>Our first product</li>
    <li>Our second product</li>
</ul>
var Application = Sammy( function( )
{
  this.use( 'Template' );
  
  this.get( '#/home', function( )
  {
    this.partial( 'home.template' );
  } );
  
  this.get( '#/shop', function( )
  {
    this.partial( 'shop.template' );
  } );
} );

sammy.js will actually load in your templates for you and render them in the context of the app.

Route segments

Sometimes our routes have important information in them. sammy.js lets us use named segments to match these routes. Let’s add a new route for a product in the shop:

var Application = Sammy( function( )
{
  this.use( 'Template' );
  
  this.get( '#/home', function( )
  {
    this.partial( 'home.template' );
  } );
  
  this.get( '#/shop', function( )
  {
    this.partial( 'shop.template' );
  } );
  
  this.get( '#/shop/:product', function( cxt )
  {
    alert( cxt.params.product );
  } );
} );

Now, if we go to #/shop/trampolines, the value of cxt.params.product will be “trampolines”.

Filters

sammy.js also lets us put beforeafter, and around filters on our routes.

before filters let us attach behavior to before any route is run. If the callback provided returns false, the route will not be run.

var Application = Sammy( function( )
{
  this.before( function( )
  {
    if( !user.isAllowedToSeeThisPage )
    {
      return false;
    }
  } );
} );

after filters are not so much filters because they occur after the route has already been run, but they can be good for cleaning up the app if you need to.

var Application = Sammy( function( )
{
  this.after( function( )
  {
    this.log( 'route completed!' );
  } );
} );

around filters are perhaps the most helpful of all of the sammy.js filters as they are capable of altering routing behavior based on asynchronous criteria.

Consider the case where we have a user that logs into our site, and in doing so gets a session, but we don’t want to make them log in before viewing every page. We can wrap all of our routes in an around filter that checks for the user’s session before allowing them to continue.

var Application = Sammy( function( )
{
  var current_user; // undefined to start
  
  this.around( function( callback )
  {
    // check for the user's session
    if( !current_user )
    {
      // user is not logged in, sign them in somehow!
      $.get( '/session', function( user )
      {
        // we store the user's session
        current_user = user;
        
        // and now they may proceed
        callback( );
      } );
    }
    else
    {
      // user is logged in, carry on
      callback( );
    }
  } );
} );

Caching plugins

sammy.js comes with a number of plugins for client-side caching.

All of the different types are under the Sammy.Store namespace. The different types are:

  • Sammy.Store.Cookie: Store client data in a traditional cookie.

  • Sammy.Store.Data: Store client data on a DOM node. (will not persist across page views)

  • Sammy.Store.LocalStorage: Store client data in HTML5 LocalStorage.

  • Sammy.Store.Memory: Store client data in-memory. (will not persist across page views)

  • Sammy.Store.SessionStorage: Store client data in HTML SessionStorage. (will persist across page views but not after the browser is closed)

Each Sammy.Store can be used straight up, or they can be mixed into your sammy app with the Sammy.Storage plugin.

Forms

By default, sammy.js will also bind a route to each one of your forms. This can be confusing at first, but there are actually quite graceful ways to handle it in your app.

Let’s say, for example, you’ve got a simple form on a Rails app, so you’re also using Rails UJS.

If your form is set to post to /orders, your sammy app will actually intercept that route and log a 404 warning.

The first thing to do would be to set up the route that sammy expects. Forms POST, not GET, so we can use that verb in our app too:

var Application = Sammy( function( )
{
  this.post( '/orders', function( cxt )
  {
    alert( "form tried to post!" );
  } );
} );

We don’t actually want to stop the form from posting, nor do we want to manually post the form. We’d rather let Rails UJS work its magic behind the scenes, but we still want to handle the result in our sammy route.

The cxt parameter is a Sammy.EventContext, which has a lot of information about the route being hit. For form POSTs, this includes the form element that triggered the route.

Using cxt.target, we can attach a one-off handler for the Rails UJS success and keep everything in our route handler:

var Application = Sammy( function( )
{
  this.post( '/orders', function( cxt )
  {
    $( cxt.target ).one( 'ajax:success', function( event, response )
    {
      if( response.success )
      {
        cxt.redirect( '#/success' );
      }
      else
      {
        alert( "There were errors with your form submission" );
      }
    } );
  } );
} );

Video liên quan

Khám Phá Lập Trình C# Nâng Cao – Từ Kiến Thức Đến Ứng Dụng Thực Tế

1 tháng trước • 12/05/2025

ập trình C# không chỉ dừng lại ở những cú pháp cơ bản. Khi bạn đã nắm vững nền tảng, việc tiếp cận các khái niệm nâng cao sẽ mở ra cánh cửa đến với những ứng dụng phức tạp và hiệu quả hơn. Bài viết này sẽ giúp bạn khám phá các kỹ thuật lập trình C# nâng cao và cung cấp tài nguyên học tập hữu ích.
Sử dụng Sammy.js làm singlepage

10 tháng trước • 15/08/2024

Hướng dẫn cách sử dụng Sammy.js để tạo ứng dụng single-page, giúp quản lý route và nội dung động mà không cần tải lại trang.
Sử dụng Mimap.js để làm sơ đồ

1 năm trước • 01/01/2024

Hướng dẫn cách tích hợp Mimap.js vào ứng dụng để tạo sơ đồ trực quan, hỗ trợ quản lý và trình bày ý tưởng hiệu quả.