15 How jQuery fits into large projects

8585 ワード

This chapter covers
  • Improving selectors for better performance
  • Organizing your code in modules
  • Loading modules with RequireJS
  • Managing dependencies with Bower
  • Creating SPAs with Backbone.js

  • 15.1 Improving the performance of your selectors
    15.1.1 Avoiding the Universal selector
    $('form :checkbox');
    $('form input:checkbox');
    
    $('input:checkbox', 'form'); v
    
    $('form > *');
    
    $('form').children(); v
    

    15.1.2 Improving the Class selector
    var $elements = $('p.description'); v
    

    15.1.3 Don't abuse the context parameter
    var $element = $('#test', 'div');
    
    var $element = $('#test'); v
    

    15.1.4 Optimizing filters
    $('p:visible');
    
    $('p').filter(':visible'); v
    
    $(':reset');
    $('[type="reset"]'); 
    
    $('input[type="reset"]'); v
    
    $('#my-list li').slice(0,2); v
    
    $('#my-list li:lt(2)');
    
    $('input[placeholder!="Name"]');
    
    $('input').not('[placeholder="Name"]'); v
    

    15.1.5 Don't overspecify selectors
    var $value = $('.revenue span.value'); v
    
    var $value = $('table.revenue .value');
    
    var $values = $('table.revenue tr td span.value');
    
    var $values = $('.revenue span.value'); v
    

    15.2 Organizing your code into modules
    15.2.1 The object literals pattern
    var myService = {
      foo: function() {},
      bar: function() {},
      baz: function() {},
      obj: {},
      anotherObj: {}
    }
    
    var myService = {
      foo: function() {},
      payment: {
        obj: {},
        bar: function() {}
      },
      basket: {
        anotherObj: {},
        baz: function() {}
      }
    };
    
    myService.basket.baz();
    

    15.2.2 The Module pattern
    var myFirstModule = (function() {
     return {
     foo: function() {},
     bar: function () {},
     obj: {}
     }
    })();
    
    var myFirstModule = (function() {
     var count = 0;
     function doSomethingPrivate() {};
     return {
     obj: {},
     foo: function() { count++; },
     bar: function () { doSomethingPrivate(); }
     }
    })();
    
    
    window.myService = (function(oldMyService) {
     oldMyService.basket = {
     baz: function() {},
     anotherObj: {}
     };
     return oldMyService;
    })(window.myService || {});
    

    15.3 Loading modules with RequireJS
    15.3.1 Getting started with RequireJS
    define([[id, ] dependencies,] factory) Parameters id (String) dependencies (Array) factory (Object|Function) Returns undefined
    define(['Person'], function(Person) {
     function Car() {
     this.getOwner = function() {
     return 'The owner is ' + Person.name;
     };
     }
     return Car;
    });
    
    require(['Car'], function(Car) {
     var car = new Car();
     alert(car.getOwner());
    });
    

    15.3.2 Using RequireJS with jQuery
    define(['jquery'], function($) {
      $.fn.jqia = function() {
        //Plugin code here...
      }
    });
    

    15.4 Managing dependencies with Bower
    15.4.1 Getting started with Bower
    15.4.2 Searching a package
    15.4.3 Installing,updating, and deleting packages
    15.5 Creating single-page applications with Backbone.js
    15.5.1 Why use an MV* framework?
    15.5.2 Starting with Backbone.js
    MODEL
    var todo = Backbone.Model.extend({
      position: 1,
      title: '',
      done: false
    });
    

    COLLECTION
    var todoList = Backbone.Collection.extend({
      model: todo
    });
    

    VIEW
    var TodoView = Backbone.View.extend({
      render: function() {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
      }
    });
    
    var TodoView = Backbone.View.extend({
      tagName: 'li',
      className; 'todo',
      template: _.template($('#todo-template').html())
    });
    

    ROUTER
    var TodoRouter = Backbone.Router.extend({
     routes: {
     "todo/:id": "getTodo",
     "search/:string": "searchTodo"
     },
     getTodo: function(id) {
     // Your code here
     },
    
     searchTodo(string) {
     // Your code here
     }
    });
    

    15.5.3 Creating a Todos manage application using Backbone.js
    CREATING THE HTML
    INSTALLING BACKBONE.JS
    THE TODO MODEL
    app.Todo = Backbone.Model.extend({
     defaults: {
     position: 1,
     title: '',
     done: false
     },
     initialize: function() {
     this
     .on('invalid', function(model, error) {
     console.log(error);
     })
     .on('add', function(model, error) {
     console.log(
     'Todo with title "' + model.get('title') + '" added.'
     );
     })
     .on('remove', function(model, error) {
     console.log(
     'Todo with title "' + model.get('title') + '" deleted.'
     );
     })
     .on('change', function(model, error) {
     console.log(
     'Todo with title "' + model.get('title') + '" updated.'
     );
     });
     },
     validate: function(attributes) {
     if(!attributes.title) {
     return 'Title is required and cannot be empty';
     }
     if(
     attributes.position === undefined ||
     parseInt(attributes.position, 10) < 1
     ) {
     return 'Position must be positive';
     }
     }
    });
    

    THE TODOS COLLECTION
    app.todoList = new (Backbone.Collection.extend({
     model: app.Todo,
     localStorage: new Backbone.LocalStorage('todo-list'),
     comparator: 'position',
     initialize: function() {
     this.on('add remove', this.collectionChanged);
     },
     collectionChanged: function(todo) {
     if (todo.isValid()) {
     this.each(function(element, index) {
     element.save({
     position: index + 1
     });
     });
     this.sort();
     }
     }
    }));
    

    THE TODO VIEWS
    app.TodoView = Backbone.View.extend({
     tagName: 'li',
     className: 'todo',
     template: _.template($('#todo-template').html()),
     events: {
     'blur .todo-position': 'updateTodo',
     'change .todo-done': 'updateTodo',
     'keypress .todo-title': 'updateOnEnter',
     'click .todo-delete': 'deleteTodo'
     },
     initialize: function() {
     this.listenTo(this.model, 'change', this.render);
     this.listenTo(this.model, 'destroy', this.remove);
     },
     deleteTodo: function() {
     this.model.destroy();
     },
     updateTodo: function() {
     this.model.save({
     title: $.trim(this.$title.text()),
     position: parseInt(this.$position.text(), 10),
     done: this.$done.is(':checked')
     });
     },
     updateOnEnter: function(event) {
     if (event.which === 13) {
     this.updateTodo();
     }
     },
     render: function() {
     this.$el.html(this.template(this.model.toJSON()));
     this.$title = this.$('.todo-title');
     this.$position = this.$('.todo-position');
     this.$done = this.$('.todo-done');
     return this;
     }
    });
    

    THE APPLICATION VIEW
    app.appView = Backbone.View.extend({
     el: '#todo-sheet',
     events: {
     'click #new-todo-save': 'createTodo'
     },
     initialize: function() {
     this.$input = this.$('#new-todo');
     this.$list = this.$('ul.todos');
     this.listenTo(app.todoList, 'reset sort destroy', this.showTodos);
     this.listenTo(app.todoList, 'invalid', this.showError);
     app.todoList.fetch();
     },
     createTodo: function() {
     app.todoList.create(
     {
     title: this.$input.val().trim()
     },
     {
     at: 0,
     validate: true
     }
     );
     this.$input.val('');
     },
     showError: function(collection, error, model) {
     this
     .$('.error-message')
     .finish()
     .html(error)
     .fadeIn('slow')
     .delay(2000)
     .fadeOut('slow');
     },
     showTodo: function(todo) {
     if (todo.isValid()) {
     var view = new app.TodoView({ model: todo });
     this.$list.prepend(view.render().el);
     }
     },
     showTodos: function() {
     this.$list.empty();
     var todos = app.todoList.sortBy(function(element) {
     return -1 * parseInt(element.get('position'), 10);
     });
     for(var i = 0; i < todos.length; i++) {
     this.showTodo(todos[i]);
     }
     }
    });
    

    15.6 Summary
    selecting elements RequireJS Bower Backbone.js
    15.7 The end
    We also wish you health and happiness, and may all your bugs be easily solvable!