react-templates/README.md

139 lines
5.0 KiB
Markdown
Raw Normal View History

2014-11-15 23:32:40 +01:00
# react-templates
2014-11-10 11:47:49 +01:00
Light weight templates for react. Reasons that we love it:
* No runtime libraries. No magic. Just simple pre-compilation to a clear code
* Super easy to write panels. By panels we mean components that have a lot of HTML code and non-reusable logic
* Very good separation of presentation and logic. Almost no HTML within the component file
* Declerative coding for presentation. HTML that you write and inspect look similar
* Easy syntax. Similar to HTML. All IDEs recognize this format
2014-11-15 23:32:40 +01:00
## How does it work
2014-11-16 00:25:09 +01:00
React templates compiles a *.rt file (react template - extended HTML format) into a javascript file. Currently, this file supports requirejs format, that will return a function. This function, when applied, will return a virtual react DOM (based on React.DOM elements and user custom components). A common use case would be that a React component would require a JS file generated by a template, and then call `func.apply(this)`, causing the template to have the component as its context.
2014-11-15 23:32:40 +01:00
###### Basic concepts for react templates:
* Any valid HTML is a template (and comments)
2014-11-15 23:32:40 +01:00
* {} to identify JS expression
* rt-if
* rt-repeat
* rt-scope
* rt-class
* style
* event handlers
* doctype rt, require dependencies, and calling other components
2014-11-15 23:32:40 +01:00
###### Why not use JSX?
Some love jsx, some don't. We don't. Well, not that we don't like it, but it seems to fit only components with very little html inside, which could be done by creating elements in code. Also, we like to separate code and html. It just feels right.
## Any valid HTML is a template
Writing any html is a valid template. This does not apply to event handlers ("on" methods). See the section about event handlers
## {} to identify JS expression
In html attributes and text, you can replace context by a javascript expression. You do this by wrapping it in {}. If this is inside an attribute, it still needs to be wrapped by quotes. In text, you can just use it.
Sample:
```
<a href="{this.state.linkRef}">{this.state.linkText}</a>
```
Compiled:
```
define([
'react',
'lodash'
], function (React, _) {
'use strict';
return function () {
return React.DOM.a({ 'href': this.state.linkRef }, this.state.linkText);
};
});
```
2014-11-15 23:46:27 +01:00
*Note: within the special **"rt-"** directives, simple strings don't make sense, as all those directives apply on some execution context. Therefore, in these directives, there won't be a need to add the {} to identify execution context*
## rt-if
This gives you the ability to add conditions to a sub-tree of html. If the condition is evaluated to true, the subree will be returned, otherwise, it will not be calculated. It is implemented by a trinary expression
Sample:
```
<div rt-if="this.state.resultCode === 200">Success!</div>
```
Complied:
```
define([
'react',
'lodash'
], function (React, _) {
'use strict';
return function () {
return this.state.resultCode === 200 ? React.DOM.div({}, 'Success!') : null;
};
});
```
2014-11-16 00:25:09 +01:00
## rt-repeat
Repeats a node with its subtree for each item in an array. This is implemented by creating a method that is passed to a map method as a callback. It creates a real context for the iterated variable. It will create an item*Index* variable to represent the index of the item. If the definition is "myNum in this.getMyNumbers()", than there will be 2 variables in the scope: myNum and myNumIndex
2014-11-15 23:46:27 +01:00
Sample:
```
2014-11-16 00:25:09 +01:00
<div rt-repeat="myNum in this.getMyNumbers()">{myNumIndex}. myNum</div>
2014-11-15 23:46:27 +01:00
```
Complied:
```
2014-11-16 00:25:09 +01:00
define([
'react',
'lodash'
], function (React, _) {
'use strict';
function repeatMyNum1(myNum, myNumIndex) {
return React.DOM.div({}, myNumIndex + '. myNum');
}
return function () {
return _.map(this.getMyNumbers(), repeatMyNum1.bind(this));
};
});
```
## rt-scope
This directive creates a new javascript scope. It actually creates a new method for this scope, and calls it with its current context. The syntax is `rt-scope="expr1 as var1; expr2 as var2`. This gives a convenience method to shorten stuff up in a scope and make the code more readable. It also helps to execute an expression only once in a scope instead of every chunk that needs it.
2014-11-15 23:46:27 +01:00
2014-11-16 00:25:09 +01:00
Sample:
```
<div rt-repeat="rpt in array">
<div rt-scope="')' as separator; rpt.val as val">{rptIndex}{separator} {val}</div>
<div>'rpt' exists here, but not 'separator' and 'val'</div>
</div>
```
Complied:
```
define([
'react',
'lodash'
], function (React, _) {
'use strict';
function scopeSeparatorVal1(rpt, rptIndex, separator, val) {
return React.DOM.div({}, rptIndex + separator + ' ' + val);
}
function repeatRpt2(rpt, rptIndex) {
return React.DOM.div({}, scopeSeparatorVal1.apply(this, [
rpt,
rptIndex,
')',
rpt.val
]), React.DOM.div({}, '\'rpt\' exists here, but not \'separator\' and \'val\''));
}
return function () {
return _.map(array, repeatRpt2.bind(this));
};
});
2014-11-15 23:46:27 +01:00
```
## section
Section text
Sample:
```
```
Complied:
```
```