天天看點

JQuery模闆 :(七)JsRender中的轉換器

一、什麼是轉換器?

       在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" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  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" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  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" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  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" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  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>