DoneJS StealJS jQuery++ FuncUnit DocumentJS
4.3.0
5.0.0 3.13.1 2.3.35
  • About
  • Guides
  • API Docs
  • Community
  • Contributing
  • Bitovi
    • Bitovi.com
    • Blog
    • Design
    • Development
    • Training
    • Open Source
    • About
    • Contact Us
  • About
  • Guides
  • API Docs
  • Community
  • Contributing
  • GitHub
  • Twitter
  • Chat
  • Forum
  • News
Bitovi

CanJS

  • npm package badge
  • Star
  • Edit on GitHub

CanJS is a client-side JavaScript framework used to build rich web interfaces. It provides state-management, templates, custom elements, and a whole bunch more.

CanJS makes it easy to to do the common stuff, while helping you build the impossible.

Why is our logo a tortoise? Read the short fable The Hare & the Tortoise by Aesop to find out.

Easy to do the common stuff

CanJS starts with a familiar object-oriented approach to making custom elements. Let's say you want to create a counter widget like the following: (click the button):

You want this widget to appear wherever you add <my-counter></my-counter> to the page.

All you need to do is import can-component and define the <my-counter> element by extending can-component with:

  • A tag for the name of the custom element for which you want to define.
  • A view that provides the HTML content of the custom element. The can-stache view supports live binding, event bindings, and two-way bindings.
  • A ViewModel that defines the methods and stateful properties available to the view.
import Component from "can-component";

Component.extend({
    tag: "my-counter",
    view: `
        Count: <span>{{count}}</span>
        <button on:click='increment()'>+1</button>
    `,
    ViewModel: {
        count: {default: 0},
        increment() {
            this.count++;
        }
    }
});
Play with this example in a JS Bin



Convinced already? Get started with one of the tutorials below:

Learn more

  • Technology Overview
or

Start from scratch

  • Setting Up CanJS
or

Build a demo app

  • Chat Guide

Build the impossible

For over 10 years, CanJS has been used to build production applications for almost every use case — from massive online stores, to small mobile apps. To help you build whatever comes your way, CanJS helps you:

  • become an expert quickly,
  • solve difficult problems, and
  • maintain your app over years.

Become an expert quickly

Learning a new framework is hard. Your needs and experiences don't fit a one-size-fits-all solution. Our long list of guides are organized in a skill tree as follows, so you level up faster by taking the guide that meets your needs.

We add a new guide every 6 weeks. Let us know what you want to learn next!

Solve difficult problems

CanJS has been used to build everything so it's both flexible and has a wide variety of extensions and plugins that solve all sorts of problems.

Flexible Programming Styles

Manage state in the way that fits your needs best. For example, you can use imperative object oriented programming and scale up to Functional Reactive Programming with streams.

// Imperative
DefineMap.extend({
  name: "string",
  nameChangeCount: {default: 0},
  updateName(name){
    this.name = name;
    this.nameChangeCount++;
  }
});




// Imperative setter
DefineMap.extend({
  name: {
    set(name) {
      this.nameChangeCount++;
      return name;
    }
  },
  nameChangeCount: {default: 0}
});



// Declarative light-weight streams
DefineMap.extend({
    name: "string",
    nameChangeCount: {
        value({listenTo, resolve}) {
            let count = resolve(0);
            listenTo("name", () => {
                resolve(++count);
            });
        }
    }
})
// Declarative Kefir streaming properties
DefineMap.extend({
    name: "string",
    nameChangeCount: {
        stream(){
            return this.stream(".name").scan((prev) => {
                return prev+1;
            },0)
        }
    }
})
// Solo Kefir streams
const name = Kefir.emitterProperty();

const nameChangeCount = name.scan(function(prev){
    return prev+1;
},0);






Extensions and Plugins

CanJS has many extensions and plugins that go beyond state management and templates:

  • Hashchange and pushstate routing
  • A service & data modeling layer that has plugins for:
    • real-time
    • minimizing requests
    • caching and fall-through-caching
    • relationships
    • Streaming NSJSON fetch responses
  • Service simulation
  • Validation
  • React integration
  • Memory safe declarative event binding

There are also extensions to state management:

  • Proxy-based observables
  • debugging tools

And to views:

  • Converters that simplify two-way bindings
  • Routing helpers for the view

If you need even more 🔥, checkout CanJS's parent framework, , which adds:

  • iOS, Andriod, and desktop builds
  • Server-side rendering (Isomorphic / UniversalJS)
  • Progressive loading
  • Continuous Integration (Testing)
  • Continuous Deployment
  • Code generators

Flexible Pieces

If you can't find what you need, you can build it! CanJS has all of its inner workings exposed and documented. Integrating other technology (like React and Kefir streams) and non-DOM APIs (like Google Map and Canvas) straightforward.

Useful low-level APIs:

  • can-reflect - This is the Lodash of CanJS. It lets you perform operations and read information on data. But unlike Lodash, can-reflect is able to work with any data type. For example, you can assign all key-values from a DefineMap to a Map:
    const meDefineMap = new DefineMap({name: "Justin"});
    const meMap = canReflect.assign( new Map(), meDefineMap );
    meMap.get("name") //-> "Justin"
    
  • diff-array & diff-object - Diff objects and arrays.
  • can-dom-events - Listen to DOM events, including custom events, using event delegation.
  • can-dom-mutate - MutationObserver polyfill.
  • can-ajax - jQuery-like XHR helper.
  • can-globals - Feature detection and storage of environmental globals.
  • can-key-tree - Tree datatype.
  • can-string - String helpers.

Useful integration APIs:

  • can-symbol - Decorate objects with symbols to make them work with can-reflect.
  • can-dom-events - Create custom events.
  • can-queues - Schedule tasks to run in a particular order.
  • can-observation-recorder - Track when observables are read.

Maintain your app over years

CanJS is dedicated to supporting you and your application long term. As technology progresses and tastes change, your code evolves too so you aren't left maintaining 💩.

We've kept folks releasing for 10 years by:

  • Avoiding breaking changes for as long as possible by maintaining CanJS in independent repositories.
  • Experimenting with changes (like can-observe) before promoting them as the way to build new applications.
  • Making the upgrade process as easy as possible with deprecation warnings, migration guides, and codemods (scipts that rewrite your code for you).
  • Focusing on what matters to users with a survey every six weeks.
  • Being supported by Bitovi, whose bottom line is open source, not a side-project.

Missing Something?

Is there an itch that CanJS doesn’t scratch? Let us know on Gitter chat or the forums. We like contributions of all sorts. Read the Contributing guide for more details.

Love Something?

Let us know by giving us a star on GitHub and following on Twitter. If there’s a particular package you like, make sure to star that too. Check out the Evangelism Guide on how to help spread the word!

CanJS is part of DoneJS. Created and maintained by the core DoneJS team and Bitovi. Currently 4.3.0.

On this page

Get help

  • Chat with us
  • File an issue
  • Ask questions
  • Read latest news