Compile Jade to React JavaScript
npm install react-jade
If you are using browserify, just write a file that looks like the following, then use react-jade as a transform. It will then inline the result of calling jade.compileFile automatically.
varReact=require('react');varjade=require('react-jade');vartemplate=jade.compileFile(__dirname+'/template.jade');React.render(template({local: 'values'}),document.getElementById('container'));browserify index.js --transform react-jade > bundle.js
If you are not using browserify, you could manually compile the jade to some client file. e.g.
varfs=require('fs');varjade=require('react-jade');fs.writeFileSync(__dirname+'/template.js','var template = '+jade.compileFileClient(__dirname+'/template.jade'));Then on your html page:
<divid="container"></div><scriptsrc="http://fb.me/react-0.12.2.js"></script><scriptsrc="template.js"></script><script>React.render(template({local: 'values'}),document.getElementById('container'));</script>You can also use react-jade to render templates on the server side via React.renderToString. This is especially useful for building isomorphic applications (i.e. applications that run the same on the server side and client side).
varfs=require('fs');varReact=require('react');varjade=require('react-jade');vartemplate=jade.compileFile(__dirname+'/template.jade');varhtml=React.renderToString(template({local: 'values'}));fs.writeFileSync(__dirname+'/template.html',html);If you are using ES6 server side, or the browserify transform client side (even without any other ES6 support), you can use Tagged Literals to embed your jade code directly within your JavaScript components:
varTodoList=React.createClass({render: jade`ul each item in this.props.items li= item`});varTodoApp=React.createClass({getInitialState: function(){return{items: [],text: ''};},onChange: function(e){this.setState({text: e.target.value});},handleSubmit: function(e){e.preventDefault();varnextItems=this.state.items.concat([this.state.text]);varnextText='';this.setState({items: nextItems,text: nextText});},render: jade`h3 TODOTodoList(items=this.state.items)form(onSubmit=this.handleSubmit) input(onChange=this.onChange value=this.state.text) button= 'Add #' + (this.state.items.length + 1)`.locals({TodoList: TodoList})});React.render(TodoApp(),mountNode);varjade=require('react-jade');Acts as a browserify transform to inline calls to jade.compileFile. The source code looks something like:
functionbrowserify(options){functiontransform(file){returnnewTransformStream();//stream to do the transform implemented here}if(typeofoptions==='string'){varfile=options;options=arguments[2]||{};returntransform(file);}else{returntransform;}}Compile a jade file into a function that takes locals and returns a React DOM node.
Compile a jade file into the source code for a function that takes locals and returns a React DOM node. The result requires either a global 'React' variable, or the ability to require 'React' as a CommonJS module.
Same as jade.compileFile except you pass an inline jade string instead of a filename. You should set options.filename manually.
Same as jade.compileFileClient except you pass an inline jade string instead of a filename. You should set options.filename manually.
You can set default locals values via the template.locals api. e.g.
varReact=require('react');varjade=require('react-jade');vartemplate=jade.compileFile(__dirname+'/template.jade').locals({title: 'React Jade'});React.render(template({local: 'values'}),document.getElementById('container'));React Jade has a few bonus features, that are not part of Jade.
In react, you add event listeners by setting attributes, e.g. onClick. For example:
button(onClick=clicked) Click Me!varfn=jade.compileFile('template.jade');React.render(fn({clicked: function(){alert('clicked');}),container);Often, you may want to partially apply a function, e.g.
input(value=view.textonChange=view.setProperty.bind(view, 'text'))functionView(){}View.prototype.setProperty=function(name,e){this[name]=e.target.value;render();};varview=newView();functionrender(){React.renderComponent(fn({view: view}),container);}Because you so often want that .bind syntax, and it gets pretty long and cumbersome to write, react-jade lets you omit it:
input(value=view.textonChange=view.setProperty('text'))This is then automatically re-written to do the .bind for you.
In keeping with React, the style attribute should be an object, not a string. e.g.
div(style={background:'blue'})The valueLink property supports two way binding to this.state.name by default. e.g.
input(valueLink=this.state.name)is eqivalent to:
input(valueLink={value:this.state.name,requestChange:function(v){ this.setState({name:v})}.bind(this)})This makes building simple forms where each input should use a property of the state very easy.
Although a lot of jade just works, there are still some features that have yet to be implemented. Here is a list of known missing features, in order of priority for adding them. Pull requests welcome:
- mixins
- attribute extension/merging (via
&attributes) - case/when
- using each to iterate over keys of an object (rather than over items in an array)
- interpolation
- attribute interpollation
- special handling of data-attributes
- outputting unescaped html results in an extra wrapper div and doesn't work for attributes
MIT