一、什么是转换器?
在JsRender中,转换器是一种方便的处理数据或者是格式化数据的快捷方式,也是一种评估表达式的结果的是重要方式。例如:
{{html:movie.description}} - 对数据进行Html的encode
{{url:getTheFilePath()}} - 对URL进行encode {{daymonth:invoice.date}} - 对日期进行格式化
在JsRender中,可以使用HTML-encode,attribute-encode,URL-encode.当然也可以注册自定义的converters(转换器)。
如果使用JsViews,还可以使用具有双向数据绑定功能的converters,这包括convert和convertBack(反转换器),其中每一个负责一个方向。
二、开始使用转换器。
1. 注册转换器:$.views.converters(name, converterFn)
使用转换器:{{converterName: someExpression}}
简单例子:将输入内容转化为大写的转换器:
$.views.converters("upper", function(val) { return val.toUpperCase(); }); {{upper: "upper case: " + nickname}}
实用自定义转换器的例子:
<!DOCTYPE html>
<html>
<head>
<link href="http://www.jsviews.com/samples/resources/css/samples.css" rel="stylesheet"/>
<script src="../jquery/jquery-2.0.3.js"></script>
<script src="../jsrender/jsrender.js"></script>
</head>
<body>
<div id="person"></div>
<script id="personTemplate" type="text/x-jsrender">
{{:name}}<br/>
Upper case nickname: {{upper:nickname}}<br/>
{{upper: "this will be upper case too"}}
</script>
<script>
$.views.converters("upper", function(val) {
return val.toUpperCase();
});
var person = {name: "JoshWang", nickname: "Jack"};
var html = $("#personTemplate").render(person);
$("#person").html(html);
</script>
</body>
</html>
2. 在converter 的function中可以使用常用的参数和属性:
<!DOCTYPE html>
<html>
<head>
<link href="http://www.jsviews.com/samples/resources/css/samples.css" rel="stylesheet"/>
<script src="../jquery/jquery-2.0.3.js"></script>
<script src="../jsrender/jsrender.js"></script>
</head>
<body>
<div id="person"></div>
<script id="personTemplate" type="text/x-jsrender">
<label>Normal:</label> {{full:first last}}<br/>
<label>Reverse:</label> {{full:first last format="reverse"}}<br/>
</script>
<script>
$.views.converters("full", function(first, last) {
var format = this.tagCtx.props.format;
return format === "reverse" ? last.toUpperCase() + " " + first : first + " " + last;
});
var person = {first: "Josh", last: "Wang"};
var html = $("#personTemplate").render(person);
$("#person").html(html);
</script>
</body>
</html>
其中:this.tagCtx.props.xxx用于访问该标签上的xxx属性,另外如果需要访问整个对象,可以使用:this.tagCtx.view.data
3. $.views.converters(namedConverters) :用于注册多个转换器
$.views.converters({ upper: function(val) {...}, lower: function(val) {...} });
4. $.views.converters(namedConverters[, parentTemplate]):如果传入的converters不是在全局注册的,那么该方法会为所指定的parentTemplate注册私有的转换器资源,即传入的转换器将会被注册成为parentTemplate的私有资源。
$.views.converters({ upper: function(val) {...}, lower: function(val) {...} }, parentTemplate);
有用的实例:
实例1. 双向绑定和转换器的结合使用。
<!DOCTYPE html>
<html>
<head>
<link href="../css/samples.css" rel="stylesheet"/>
<script src="../jquery/jquery-2.0.3.js"></script>
<script src="../jsviews/jsviews.js"></script>
</head>
<body>
<table class="three">
<thead><tr><th>Data</th><th>DayOff</th><th>Choose day off</th></tr></thead>
<tbody id="linked"></tbody>
</table>
<div><em>To edit, enter part of the name, or the number, or click here:</em>
<button id="changeDay">Change day</button></div>
<script id="linkedTmpl" type="text/x-jsrender">
<tr>
<td data-link="dayOff"></td>
<td data-link="{intToDay:dayOff}"></td>
<td><input data-link="{intToDay:dayOff:dayToInt} title{:dayOff}" /></td>
</tr>
</script>
<script>
var days = [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ],
myWeek = {
dayOff: 1
};
$.views.converters({
dayToInt: function(val) {
var dayOff = parseInt(val);
if (isNaN(dayOff)) {
for (var i = 0; i < 7; i++) {
if ( days[ i ].toLowerCase().slice(0, val.length) === val.toLowerCase()) {
dayOff = i;
break;
}
}
}
if (isNaN(dayOff)) {
dayOff = val;
} else {
this.linkCtx.elem.value = days[dayOff]; // Set the text box value to the Day Off name
}
return dayOff;
},
intToDay: function( val ) {
return days[ val ] || val;
}
});
// Observable property change
$( "#changeDay" ).on( "click", function() {
var dayOff = myWeek.dayOff;
$.observable( myWeek ).setProperty( "dayOff", dayOff < 6 ? dayOff + 1 : 0);
});
var myTmpl = $.templates("#linkedTmpl")
myTmpl.link( "#linked", myWeek );
</script>
</body>
</html>
代码解读:
A、使用转换器来渲染标签:
1)HTML encoding,没有使用自定义的转换器
<td>{{>dayOff}}</td>
2) 渲染数据并转换成显示名:
<td>{{intToDay:dayOff}}</td>
B、使用具有数据绑定功能的converter和convertBack
1)动态绑定到数据,没有转换器:
<td data-link="dayOff"></td>
2) 动态绑定到数据,并通过转换器转换显示名子:
<td data-link="{intToDay:dayOff}"></td>
3)双向的数据绑定将会在数据格式(integer)和显示的名字(text)之间做convert和convertBack,也将会使用tooltip来显示数据的值。
<td><input data-link="{intToDay:dayOff:dayToInt} title{:dayOff}" /></td>
实例2:使用转换器绑定到表单元素:
<!DOCTYPE html>
<html>
<head>
<link href="../css/samples.css" rel="stylesheet"/>
<script src="../jquery/jquery-2.0.3.js"></script>
<script src="../jsviews/jsviews.js"></script>
</head>
<body>
<div id="amountPickers">
<div class="box">
<div class="subhead">Using convert and 'convert back'
functions with integer-to-string conversion:</div>
<em>— Binding to form elements, but keeping the
'amount' data as type 'number'</em><br><br>
<b>Choose amount:</b><br><br>
<input data-link="{intToStr:amount:strToInt}"><br><br>
<b>Choose amount:</b><br><br>
<input name="intVal" value="0" data-link="{intToStr:amount:strToInt}" type="radio">
0<br>
<input name="intVal" value="1" data-link="{intToStr:amount:strToInt}" type="radio">
1<br>
<input name="intVal" value="2" data-link="{intToStr:amount:strToInt}" type="radio">
2<br>
<input name="intVal" value="3" data-link="{intToStr:amount:strToInt}" type="radio">
3<br>
<input name="intVal" value="4" data-link="{intToStr:amount:strToInt}" type="radio">
4<br>
<input name="intVal" value="5" data-link="{intToStr:amount:strToInt}" type="radio">
5<br>
<input name="intVal" value="6" data-link="{intToStr:amount:strToInt}" type="radio">
6<br>
<input name="intVal" value="7" data-link="{intToStr:amount:strToInt}" type="radio">
7<br><br>
<b>Choose amount:</b><br><br>
<select data-link="{intToStr:amount:strToInt}">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
</select>
</div>
<div class="box">
<div class="subhead">Convert and 'convert back'
functions using bit-masks on the integer data value:</div>
<b>Choose amount:</b><br><br>
<input data-link="{getBit:amount bit=0 :setBit}" type="checkbox"> bit 0<br>
<input data-link="{getBit:amount bit=1 :setBit}" type="checkbox"> bit 1<br>
<input data-link="{getBit:amount bit=2 :setBit}" type="checkbox"> bit 2<br>
</div>
<b>Amount: <div class="box subhead" data-link="amount"></div></b>
</div>
<script>
$.views.converters({
setBit: function (value) {
// "Convert Back": If checked, set this bit on the data,
// or if unchecked, unset this bit on the data
var mask = 1 << this.tagCtx.props.bit,
// Shift first bit, 0, 1 or 2 bits to the left, to create a mask
dataValue = this.linkCtx.data[this.linkCtx.fn.paths[0]];
// Take the current data value
return value ? (dataValue | mask) : (dataValue & ~mask);
// Use the mask to set or unset that bit on the data, and return the modified value
},
getBit: function (value) {
// "Convert": Get the bit from the data, and check or uncheck the checkbox
return (value >> this.tagCtx.props.bit & 1) === 1;
// Shift 0, 1 or 2 bits to the right, and see if the first bit is set.
},
intToStr: function (value) {
return "" + value;
},
strToInt: function (value) {
return parseInt(value);
}
});
var data = { amount: 3 };
$( "#amountPickers" ).link( true, data );
</script>
</body>
</html>
代码解读:注册了不同的convert和convertBack 转换器,然后使用下面的方式将form中的元素和数据进行了绑定:
<input data-link="{intToStr:amount:strToInt}"> <input type="radio" name="intVal" value="0" data-link="{intToStr:amount:strToInt}"> <select data-link="{intToStr:amount:strToInt}"> <option>0</option> ... </select> <input type="checkbox" data-link="{getBit:amount bit=1 :setBit}"> bit 1<br>