Using Backbone without jQuery

Adam Krebs edited this page Jun 15, 2015 · 12 revisions

With the latest changes from #3003, Backbone is now even further decoupled from jQuery. You can use your favorite non-jQuery DOM manipulation library with Backbone.View, or even forgo a DOM manipulation library entirely in favor of native methods. Backbone.View now exposes a hooks that allow a View "adapter" to easily overwrite a few key Backbone.View methods that Backbone needs to operate, and leaves the rest of the public interface mostly the same.

For most users, the changes should be minimal. If you like using jQuery please by all means continue using it. If you're interested in using something other than jQuery with your project, take a look at Backbone.D3View for D3-backed Views, and Backbone.NativeView for going full native. You can also use a server-side DOM library like jsdom or cheerio for server-side rendering as in this gist example.

View Hooks:

There are 8 total overridable methods:

  • $ for view-scoped element lookup. Takes a string selector and returns an array-like object (i.e. an object with a numeric length property, like an NodeList, an Array, or a jQuery context) for easy iteration. See Backbone.View and Backbone.NativeView implementations.
  • _createElement creates an element given a tagName. Useful for out-of-browser DOM creation (for instance server-side rendering). Backbone.View and Backbone.NativeView use the same method.
  • _removeElement to remove the view's element from the DOM. Backbone.View and Backbone.NativeView.
  • delegate to add a single event listener to the view's this.el property, with the benefit of easy bookkeeping for later event removal. Backbone.View and Backbone.NativeView.
  • undelegate to remove a single event listener, the inverse of delegate. The selector and listener arguments are optional. Backbone.View and Backbone.NativeView.
  • undelegateEvents to remove all events added by delegate. Backbone.View and Backbone.NativeView.
  • _setElement sets the view's this.el property from a string of HTML, a string selector, or a string element. Backbone.View and Backbone.NativeView.
  • _setAttributes applies a hash of attributes to the element. Backbone.View and Backbone.NativeView.

Ajax methods:

A number of drop-in replacements for Backbone.ajax provide feature parity with jQuery.ajax without jQuery. A native implementation is available as Backbone.NativeAjax.

For Plugin Authors:

Since we can no longer rely on the existence of the jQuery-friendly interface of view.$el.on to be present on all Views, Backbone.View exposes two new hooks for event delegation, view.delegate and view.undelegate. It also requires that the return value from view.$ be an array-like object (a 0-indexed element list with a numeric length property, like an Array, a NodeList, or a jQuery context). You should iterate over the return value of view.$ with Underscore methods like _.each and _.map and use native element methods on the results:

_.each(view.$('.title'), function(el) {
  el.classList.add('active');
});

Build tools

By default Backbone attempts to load $ for you. Either off the window object if global, through define if AMD, and require if CommonJS. If you use jQuery in your app this should work seamlessly.

Without jQuery

If you don't want jQuery and you're using a build tool like browserify or webpack to build your bundle, you must tell it to exclude or ignore the import.

For browserify, pass the exclude option to the command line (or set the argument in your configuration).

$ browserify app.js --exclude jquery

For Webpack, add the IgnorePlugin and turn off Webpack's AMD detection in webpack.config.js with imports-loader.

{
    module: {
        loaders: [
            { test: /backbone\.js$/, loader: 'imports?define=>false' }
        ]
    },
    plugins: [
        new webpack.IgnorePlugin(/^jquery$/)
    ]
}

With a different DOM library:

Set the Backbone.$ property to support Ender, Zepto or your favorite DOM library.

To change the DOM library to Zepto with Browserify, first install aliasify.

npm install --save aliasify

Add an "aliasify" section to the application's package.json:

{
    "browserify" {
        "transform": ["aliasify"]
    },
    "aliasify": {
        "aliases": {
            "jquery": "zepto"
        }
    }
}

... and call the browserify executable with an extra flag:

browserify entry.js --global-transform aliasify -o out.js

... or if your app uses the browserify node API (example):

browserify(['./index.js'])
  .transform(aliasify, {global: true})
  .bundle()
  .pipe(fs.createWriteStream(__dirname + '/out.js'));

Using WebPack, the resolve.alias configuration option can be used:

{
    context: __dirname + "/app",
    entry: "./entry",
    output: {
        path: __dirname + "/dist",
        filename: "bundle.js"
    }
    resolve: {
        alias: {
            "jquery": "zepto"
        }
    }
}