1. 程式人生 > >HTML中的資料繫結(Data Binding)

HTML中的資料繫結(Data Binding)

有沒想過在javascript中使用recordset?原來在客戶端操作資料也可以這樣簡單,定義一個數據源,將資料繫結在各種tag上,實現應用程式般的效果,酷斃了!(首先申明一點,文章的內容全部來自msdn,不過用我自己的話總結而已。)

先看看這樣兩個例子:
http://msdn.microsoft.com/workshop/samples/author/databind/dbevts.htm
http://msdn.microsoft.com/workshop/samples/author/databind/dbupdate.htm
不得不又一次佩服微軟。

這個是DataBinding的架構:

架構


當然實現資料繫結有下面幾步:

第一步,定義資料來源
從IE4.0起,就支援下面四種資料來源:

Tabular Data Control (TDC)

TDC提供了一個簡單的訪問帶有格式的文字資料的方法,一般是csv檔案。
下面是一個簡單的示例:

<OBJECT CLASSID="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83"
    ID=dsoComposer WIDTH=0 HEIGHT=0>
    <PARAM NAME="DataURL" VALUE="composer.csv">
</OBJECT>

Remote Data Service (RDS)

遠端資料服務,直接訪問遠端伺服器端的資料,Internet Explorer 4.0. RDS 通過OLE-DB 或 Open Database Connectivity (ODBC)來實現。

示例:

<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
    ID=dsoComposer HEIGHT=0 WIDTH=0>
    <PARAM NAME="Server"  VALUE="http://musicserver">
    <PARAM NAME="Connect" VALUE="dsn=music;uid=guest;pwd=">
    <PARAM NAME="SQL"     VALUE="select compsr_name from composer">
</OBJECT>

不過感覺有點安全性的問題,因為客戶端能看到這段程式碼。

XML Data Source

XML就不多說了,在IE4.0中這樣使用:
<APPLET
    CODE="com.ms.xml.dso.XMLDSO.class"
    ID="xmldso"
    WIDTH="0"
    HEIGHT="0"
    MAYSCRIPT="true">
    <PARAM NAME="URL" VALUE="composer.xml">
</APPLET>

Internet Explorer 5以上可以這樣:

<!--[if gte IE 5]>
<XML ID="xml1">
<topic-info>
    <page-type>reference</page-type>
    <member-type>property</member-type>
    <persistent-name>ACCESSKEY</persistent-name>
    <runtime-name readable="1" writeable="1">accessKey</runtime-name>
    <abstract>Sets or retrieves the accelerator key for the object.</abstract>
</topic-info>
</XML>
<![endif]-->

另外IE還提供了一個XML資料島的概念:XML Data Islands.

MSHTML Data Source

html資料頁示例:
<H1 ID=COMPSR_FIRST>Hector</H1>
<MARQUEE ID=COMPSR_LAST>Berlioz</MARQUEE>
<DIV ID=COMPSR_BIRTH>1803</DIV>
<H2 ID=COMPSR_FIRST>Modest</H2>
<H3 ID=COMPSR_LAST>Moussorgsky</H3>
<BUTTON ID=COMPSR_BIRTH>1839</BUTTON>
<TEXTAREA ID=COMPSR_FIRST>Franz</TEXTAREA>
<XMP ID=COMPSR_LAST>Liszt</XMP>
<SPAN ID=COMPSR_BIRTH>1811</SPAN>

一旦定義可以這樣訪問:

<OBJECT ID=htmlComposer DATA="compdata.htm" HEIGHT=0 WIDTH=0>
</OBJECT>

.第二步:繫結資料到HTML元素上
一般都是通過tag中的datasrc和datafld實現繫結的。例如:
<INPUT TYPE=TEXTBOX DATASRC="#dsoComposers" DATAFLD="compsr_last">

<TABLE DATASRC=#dsoComposer>
<TR>
<TD><DIV DATAFLD=compsr_first></DIV></TD>
</TR>
</TABLE>
這個是繫結表格的示例:
http://msdn.microsoft.com/workshop/samples/author/databind/dbtable.htm

其中資料來源:
<OBJECT id="tdcComposers" CLASSID="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83">
 <PARAM NAME="DataURL" VALUE="http://msdn.microsoft.com/workshop/samples/author/databind/composer.csv">         
 <PARAM NAME="UseHeader" VALUE="True">
 <PARAM NAME="TextQualifier" VALUE="'">
</OBJECT>
繫結的table
<TABLE datasrc=#tdcComposers>
<THEAD><TR STYLE="font-weight:bold">
   <TD>First</TD><TD>Last</TD><TD>Birth</TD><TD>Death</TD><TD>Origin</TD>
   </TR></THEAD>
<TBODY>
<TR>
   <TD><DIV datafld="compsr_first"></DIV></TD>
   <TD><DIV datafld="compsr_last"></DIV></TD>
   <TD><DIV datafld="compsr_birth"></DIV></TD>
   <TD><DIV datafld="compsr_death"></DIV></TD>
   <TD><DIV datafld="origin"></DIV></TD>
</TR>
</TBODY>
</TABLE>
這就是效果了:

First Last Birth Death Origin
Hector Berlioz 1803 1869 France
Modest Moussorgsky 1839 1881 Russia
Franz Liszt 1811 1886 France
Antonio Vivaldi 1678 1741 Italy
Johann Sebastian Bach 1685 1750 Germany
Ludwig van Beethoven 1770 1827 Germany
Wolfgang Amadeus Mozart 1756 1791 Austria
Joseph Haydn 1732 1809 Germany
Claude Debussy 1862 1918 France


第三步:資料的動態新增,刪除等等(物件模型)
當然繫結可以是動態的:
在script中:
span1.dataSrc = "#dsoComposer";
span1.dataFld = "compsr_first";

html是這樣的:
<SPAN DATASRC="#dsoComposer" DATAFLD="compsr_first"></SPAN>

而且可以訪問資料來源的ado:
var oRecordSet = dsoComposer.recordset;
自然就有oRecordSet .MoveNext等等。

如:
<INPUT ID=cmdNavFirst TYPE=BUTTON VALUE="<<"
    onclick="tdcComposers.recordset.MoveFirst()">
<INPUT ID=cmdNavPrev TYPE=BUTTON VALUE=" < "
    onclick="tdcComposers.recordset.MovePrevious();
    if (tdcComposers.recordset.BOF)
        tdcComposers.recordset.MoveFirst();">
<INPUT ID=cmdNavNext TYPE=BUTTON VALUE=" > "
    onclick="tdcComposers.recordset.MoveNext();
        if (tdcComposers.recordset.EOF)
            tdcComposers.recordset.MoveLast();">
<INPUT ID=cmdNavLast TYPE=BUTTON VALUE=">>"
    onclick="tdcComposers.recordset.MoveLast()">

還可以這樣用:
<SCRIPT Language="VBScript">
For Each objFld in rsAttendees.Fields
    document.write("The field name is " & objFld.Name & "<BR>")
    document.write("The field value is " & objFld.Value & "<BR>")
Next
</SCRIPT>

新增刪除記錄就是:oRecordSet.AddNew()以及oRecordSet.Delete()。

第三步:響應各種資料事件(事件模型)
如何在資料更改後做出相應的處理?
msdn中提供的方法是這樣的:
<SCRIPT FOR=cboSort(資料來源名) EVENT=onchange(事件名)>
    ……
</SCRIPT>
這些是事件名列表:

Event Bubbles Cancelable Applies to Introduced In Internet Explorer Version
onbeforeupdate True True bound elements 4.0
onafterupdate True False bound elements 4.0
onrowenter True False DSO 4.0
onrowexit True True DSO 4.0
onbeforeunload False False window 4.0
ondataavailable True False DSO 4.0
ondatasetcomplete True False DSO 4.0
ondatasetchanged True False DSO 4.0
onerrorupdate True True bound elements 4.0
onreadystatechange True False DSO 4.0
oncellchange True False DSO 5.0
onrowsinserted True False DSO 5.0
onrowsdelete True False DSO 5.0

怎麼樣?
我覺得http://msdn.microsoft.com/workshop/samples/author/databind/dbevts.htm算是一個應用比較綜合的例子了,好好研究一下,必有收穫。

網上有不少利用資料繫結實現分頁的示例,其實資料繫結還可以做更多的事情吧?應該在rich client裡面有非常大的應用,例如製作非常複雜的datagrid。

現在想進一步搞清楚的是如何簡便實現與伺服器端的同步,因為客戶端的資料繫結是對伺服器端沒有影響的(你可以從伺服器端生成資料來源,但是在客戶端的操作不會自動返回伺服器),msdn上說RDS可以,但是這種方法太笨拙了吧,又不安全。