sodajs
Version:
Light weight but powerful template engine for JavaScript.
445 lines (317 loc) • 9.23 kB
Markdown
# sodajs
超好用的指令模板引擎
## 特性
* 超小体积(gzip之后只有4K)
* 支持dom指令系统
* 良好的兼容性,兼容ie8及现代浏览器,兼容node环境
* 避免输出的xss漏洞
* 高性能dom渲染引擎
* 与AngularJS指令兼容
* 自定义指令和前缀
## 安装
### npm
``` js
npm install --save sodajs
```
### CDN
* [https://unpkg.com/sodajs@0.4.10/dist/soda.min.js](https://unpkg.com/sodajs@0.4.10/dist/soda.min.js)
* [https://unpkg.com/sodajs@0.4.10/dist/soda.js](https://unpkg.com/sodajs@0.4.10/dist/soda.js)
* [https://unpkg.com/sodajs@0.4.10/dist/soda.node.min.js](https://unpkg.com/sodajs@0.4.10/dist/soda.node.min.js)
* [https://unpkg.com/sodajs@0.4.10/dist/soda.node.js](https://unpkg.com/sodajs@0.4.10/dist/soda.node.js)
## 使用
### soda & soda.node的不同
| version | soda | soda.node |
| ------------ | ------------ | ------------ |
| Mordern Browsers | ✓| ✓|
| Mobile Browsers | ✓ | ✓ |
| ie | ≥8 | ≥9|
| node | ✗ | ✓|
| dom解析引擎| 原生| 自带nodeWindow引擎|
提示: ie 8兼容需要自行引入es5-shim 或es5-sham 和console-polyfill
查看这里的ie8的兼容测试
* [ie8 browser test](http://alloyteam.github.io/sodajs/test/soda-browser.html)
### 浏览器端
* script标签
```html
<script src="https://unpkg.com/sodajs@0.4.10/dist/soda.min.js"></script>
```
* 使用webpack
```javascript
import soda from "sodajs"
```
### Node端
```js
let soda = require('sodajs/node');
```
低版本node可以使用dist版本
```js
let soda = require('sodajs/dist/soda.node')
```
## API
### 输出
#### 简单输出
```js
var tpl = '<div>{{name}}</div>';
document.body.innerHTML = soda(tpl,{ name : 'soda' })
```
➜ [示例](http://alloyteam.github.io/sodajs/pg/rd.html?type=simple)
#### 安全的链式输出
```js
var data = {
name: 'soda',
info: {
version: '2.0'
}
}
soda("{{info.version}}", data);
// result => "2.0"
soda("{{info.foo.foo1}}", data)
// result => "" without errors
soda("{{info['name']}}", data)
// result => "2.0"
```
#### 表达式
```js
var data = {}
soda("{{1 + 2}}", data);
// result => 2
soda("{{true ? 'soda' : 'foo'}}", data)
// result => "soda"
soda("{{1 < 3 && 'soda'}}", data)
// result => "soda"
```
➜ [示例](http://alloyteam.github.io/sodajs/pg/rd.html?type=expression)
#### 复杂的表达式
```js
var data = {
list: [
{list: [{'title': '<>aa</h1>'}, {'title': 'bb'}], name: 0, show: 1},
{list: [{'title': 0 }, {'title': 'bb'}], name: 'b'}
]
};
soda('{{list[list[0].show === 1 ? list[0].name : 1].list[0].title}}', data)
// result => '<>aa</h1>'
```
### 指令
#### if
``` js
var data = { name : 'soda',show: true };
soda(` <div soda-if="show">Hello, {{name}}</div>
<div soda-if="!show">I\'m hidden!</div>`,
data
)
// result => <div>Hello, soda</div>
```
➜ [示例](http://alloyteam.github.io/sodajs/pg/rd.html?type=if)
### repeat
> soda-repeat="item in array"
> soda-repeat="item in object"
> soda-repeat="item in array by index"
> soda-repeat="item in object by key"
> soda-repeat="(index, value) in array"
> soda-repeat="(key, value) in object"
默认的下标是$index
``` js
var tpl = '\
<ul>\
<li soda-repeat="item in list" soda-if="item.show">\
{{item.name}}\
{{$index}}\
</li>\
</ul>'
var data = {
list: [
{name: "Hello" ,show: true},
{name: "sodajs" ,show: true},
{name: "AlloyTeam"}
]
};
document.body.innerHTML = soda(tpl, data);
```
➜ [示例](http://alloyteam.github.io/sodajs/pg/rd.html?type=repeat)
### filter
> soda.filter(String filterName, Function func(input, args...))
> {{input|filte1:args1:args2...|filter2:args...}}
example:
``` js
soda.filter('shortTitle', function(input, length){
return (input || '').substr(0, length);
});
var tpl = '\
<ul soda-repeat="item in list">\
<li class="title">\
{{item.title|shortTitle:10}}\
</li>\
</ul>'
document.body.innerHTML = soda(tpl,{ list : [
{title:'short'},
{title:'i am too long!'}
] })
```
➜ [示例](http://alloyteam.github.io/sodajs/pg/rd.html?type=filter)
### html
输出原始的html,不做完全转换
```js
var tpl = '<div soda-html="html"></div>'
document.body.innerHTML = soda(tpl,{ html : '<span style="color:red;">test soda-html</span>' })
```
➜ [html example](http://alloyteam.github.io/sodajs/pg/rd.html?type=html)
### replace
用html替换当前结点
```js
var tpl = '<div soda-replace="html"></div>'
document.body.innerHTML = soda(tpl,{ html : '<span style="color:red;">test soda-html</span>' })
```
➜ [replace example](http://alloyteam.github.io/sodajs/pg/rd.html?type=replace)
div will be replaced with given html
div会被html替换
#### include
嵌套模板
soda-include="tmplateName:arg1:arg2:..."
和soda.discribe一起使用
```js
var data = {
name: "soda"
};
// define sub template named tmpl1
soda.discribe('tmpl1', `<h1>{{name}}</h1>`);
// use template tmpl1 by soda-include
soda(`<span soda-include="tmpl1">1</span>`, data);
// result => <h1>dorsy</h1>
// set compile false not to compile sub template
soda.discribe('tmpl1', `<h1>{{name}}</h1>`, {
compile: false
});
// show origin template
soda(`<span soda-include="tmpl1">1</span>`, data);
// result => <h1>{{name}}</h1>
soda.discribe('tmpl2', function(path){
return `<h1>{{name}}_${path}</h1>`;
});
soda(`<span soda-include="list3:sub{{'path' + 1}}">1</span>`, data);
// result => <h1>soda_subpath1</h1>
// In node env
soda.discribe('tmplNode', function(path){
return fs.readFileSync(path, 'utf-8');
});
soda(`<span soda-include="tmplNode:view.html">1</span>`, data);
// result => view.html Tmplate
```
### 其他
#### soda-class
> soda-class="currItem === 'list1' ? 'active' : ''"
#### soda-src
> soda-src="hello{{index}}.png"
#### soda-style
> soda-style="style"
data example:
```js
var data = { style : { width : '100px', height : '100px' } };
```
#### soda-*
> soda-rx="{{rx}}%"
## 自定义
### soda.prefix
改变指令的前缀,默认的前缀是soda-
``` js
soda.prefix('v:')
var tpl = '\
<ul>\
<li v:repeat="item in list" v:if="item.show">\
{{item.name}}\
</li>\
</ul>'
var data = {
list: [
{name: "Hello" ,show: true},
{name: "sodajs" ,show: true},
{name: "AlloyTeam"}
]
};
document.body.innerHTML = soda(tpl, data);
```
### soda.directive
自定义指令
#### es 2015写法
```js
soda.directive('name', {
priority: 8,
// how to compile el
link({ scope, el, parseSodaExpression, expression, getValue, compileNode, document }) {
}
});
```
* scope: 当前的scope数据
* el: 当前节点
* expression: 指令的表达式原始字符串
* getValue: 从data链式获取值
```js
getValue({a: {b: 1}}, "a.b"); // ===> 1
```
* parseSodaExpression: 解析soda表达式
```js
parseSodaExpression('{{1 + 2 + a}}', {a: 1}); // ===> 4
```
* compileNode: 继续编译节点
* document: 使用document参数而不是使用window.document, 这样可以在node环境下去用
#### 示例
```js
soda.directive('mydirective', {
priority: 8,
link({ scope, el, parseSodaExpression, expression, getValue, compileNode, document }) {
var value = parseSodaExpression(expression);
if(value){
var textNode = document.createTextNode(value);
el.appendChild(textNode);
}
}
}
soda(`
<div soda-mydirective="add one tips: {{tips}}"></div>
`, {
tips: 'tips'
});
// result ==> <div>add one tips: tips</div>
```
### soda.setDocument
自定义node端的dom解析引擎
soda.node版本的默认dom解析引擎是nodeWindow,你可以用这个方法替换为jsdom等
```js
var document = require('document');
var soda = require('soda');
soda.setDocument(document);
// ... run
```
## 贡献代码
### 开发
git clone
``` shell
git clone git://github.com/AlloyTeam/sodajs.git
```
安装依赖
``` shell
npm install
```
然后执行npm start
``` shell
npm start
```
执行run build构建代码
``` shell
npm run build
```
### 自动化测试
soda使用mocha来做自动化测试
测试单元在test目录
``` shell
npm run test
```
#### 在线测试页面
* [soda-mocha](http://alloyteam.github.io/sodajs/test/soda-mocha.html)
* [soda.node-mocha](http://alloyteam.github.io/sodajs/test/soda.node-mocha.html)
* [ie8 browser test](http://alloyteam.github.io/sodajs/test/soda-browser.html)
## 使用项目
兴趣部落, QQ群, 群活动
## 协议
[MIT](http://opensource.org/licenses/MIT)
Copyright (c) 2015-present, AlloyTeam