基於jquery的表格動態創建,自動綁定,自動獲取值


最近剛加入GUT項目,學習了很多其他同事寫的代碼,感覺受益匪淺。

在GUT項目中,經常會碰到這樣一個問題:動態生成表格,包括從數據庫中讀取數據,並綁定在表格中,以及從在頁面上通過jQuery新增刪除表格。如下所示:

 

在實現過程中,開發人員經常采用如下方式來實現:

1)          在前台,通過js生成表格行的html字符串,然后通過jquery的after方法加到表格底部。

2)          在后台,讀取數據庫,然后生成表格的html字符串,然后傳遞給前台渲染

3)          這樣做的好處,主要是可以實現無刷新的操作表格的效果

這種實現方式存在如下些問題(當然,個人意見,僅作技術交流^_^):

1)          代碼重復。前台寫了一遍表格創建的js,后台又寫了一遍

2)          字符串拼接。后台創建時,會大量使用字符串的拼接來實現表格的htnl字符串,不僅影響效率,而且不容易debug。比如少了個引號等,不容易找出來。(關於效率問題,因為字符串在.net中是恆定的,所以如果做很多次字符串的拼接,將造成資料的浪費和效率地下)

3)          綁定表格數據與獲取表格數據要寫很多代碼,假設表格有10列字段,就要寫關於這10列的數據怎么獲取,以及怎么綁定會表格中的。

4)          開發人員經常在.aspx頁面中寫數據庫的訪問操作,這樣也不符合MVC分離關注點的精神。如果項目換成別的數據庫,比如oracle(按照項目的數據量來看,未來不排除換數據庫的可能性),那么屆時開發人員將需要滿項目中數據庫相關的語句來修改。

--------------------------------------分割線------------------------------------------

如前所述,可以從如下幾個思路來思考:

1)          能否只在頁面上編寫一些js腳本,來創造表格,而在后台只是提供要創建表格數據即可。也就是說后台獲取數據,然后交給前台去調用js函數創建表格。這樣就可以避免前后台都寫兩次的問題了。而且也不會在后台用大量的字符串拼接來創建表格的html字符串。

2)          能否換種方式,不要通過字符串拼接的方式來創建表格?比如jquery.html()?

3)          能否提供一種統一的創建表格,綁定表格,獲取表格數據的方法呢?以免每次都要寫那么多代碼來創建表格。

基於上述思路,我開發了一個demo,實現了用較少的代碼動態創建表格,綁定表格數據,獲取表格數據,並保存到數據庫中。而且代碼是可以復用的。

--------------------------------------分割線------------------------------------------

前期准備:

1)          創建數據庫test,添加表person

 

2)          創建Entities層,DAL層,BLL層

 

Entities層(通過T4模板自動生成)

using System;

using MyBasicLib;

using MyBasicLib.Data.ORMLiteNew;

namespace ATMB.DCMS.Entities

{

    /// <summary>

    ///

    /// </summary>

  [Serializable]

    [Table(TableName="person" ,KeyName="ID")]

    public partial class person:BaseTable

    {

      /// <summary>

        ///

        /// </summary>

        public person()

        {

        }

      #region Public Properties

      /// <summary>

        ///

        /// </summary> 

        public  override  String ID

        {

            set ; get ;

        }

      /// <summary>

        ///

        /// </summary> 

        public  String name

        {

            set ; get ;

        }

      /// <summary>

        ///

        /// </summary> 

        public  String age

        {

            set ; get ;

        }

      /// <summary>

        ///

        /// </summary> 

        public  String sex

        {

            set ; get ;

        }

      /// <summary>

        ///

        /// </summary> 

        public  String location

        {

            set ; get ;

        }

 

      #endregion

  }

}

DAL層,實現了新增,批量新增,刪除,獲取所有數據的幾個簡單的方法

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using ATMB.DCMS.Entities;

using MyBasicLib.Data.ORMLiteNew;

 

namespace DAL

{

    public class PersonDA

    {

        public void Add(person p)

        {

            using (var dc = new DataContext())

            {

                dc.Insert(p);

                dc.SubmitChanges();

            }

        }

 

        public void Add(List<person> ds)

        {

            using (var dc = new DataContext())

            {

                foreach(var p in ds)

                {

                    dc.Insert(p);

                }

                dc.SubmitChanges();

            }

        }

 

        public void Delete()

        {

            using (var dc = new DataContext())

            {

                dc.Delete<person>(p => !SqlMethods.IsNull(p.ID));

                dc.SubmitChanges();

            }

        }

 

        public List<person> GetList()

        {

            using (var dc = new DataContext())

            {

                return dc.GetTable<person>().ToList();

            }

        }

 

    }      

}

BLL層

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using ATMB.DCMS.Entities;

using DAL;

 

namespace BLL

{

    public class PersonBLL

    {

        PersonDA da;

 

        public PersonBLL()

        {

            da = new PersonDA();

        }

 

        public void Add(List<person> ds)

        {

            da.Delete();

            da.Add(ds);

        }

 

        public List<person> GetList()

        {

            return da.GetList();

        }

           

    }

}

備注:數據庫底層訪問使用Linq,換成oledb等其他方式只要修改DAL層就可以了。

3)          通過js實現表格的動態創建

第一步:定義表格

 

這里有幾個地方要注意下:

第一:頁面上添加的表格中,我添加了兩個tr,一個是顯示出來的tr,帶有“新增”的圖標。另一個是隱藏的,用來作為新增的行的模板。這樣,不容易出錯,而且避免通過字符串來創建。

第二:顯示的tr中,設置了一個叫”TargetTR”的class,這個是用來搜索表格的所有行的,后面會用到。

第三,每個td中,新增了一個tag屬性,與數據庫表的實際字段對應,用來自動獲取和綁定表格數據。

第四,tr模板的每個input的id(或者其他需要替換的屬性)都定義為XXX_x,_x后綴是用來替換的。比如新增了一個tr,序號為3,便要替換tr中每個input的_x后綴為_3。諸如此類。

第二步:實現新增和刪除表格行的js方法

 

ChangeAttr實現如下:

 

changeAttr主要是實現替換input的帶_x結尾的屬性為具體的序號。

以上實現了在頁面上對表格行的新增和刪除。通過模板的定義,我們無需在js寫新增的tr的html字符串。這樣可以最大可能的減少錯誤發生的可能性。因為字符串的可讀性比較差,debug比較難。

接下來,要實現后台獲取表格數據,然后通過上述的幾個js腳本動態生成表格。

首先介紹下實現的思路

 

第一步,看下.ashx中的實現

 

 

Ashx中的實現很簡單,就是根據前台的請求,進行相應的操作,然后返回結果(json)給前台

第二步:前台通過ajax訪問.ashx,獲取表格數據

 

 

Success時,會以json的格式返回表格的數據(比如person的集合),然后前台會解析這個json數據,並創建表格出來。

 

BindTable的實現很簡單,首先看下共有多少條數據,然后多次調用add_tr方法,添加tr。(因為第一個tr是默認存在的,所以只要調用json.length-1次)

接下來便是該功能的核心了,綁定表格的數據。這里只需要調用一個函數就可以了bindTableValue,其實現如下

 

這個函數可以實現任意表格的數據綁定。完全可以復用。當然還存在些缺陷。本文最后會作以說明。

以上遍實現了從數據庫獲取值,然后動態繪制表格的過程。整個過程沒有針對特定的表格來實現,所以代碼是可以復用的。這個實現過程還有個好處是:分離關注點。對於表現層(前台,web層),只關心於根據數據來做相應的展現,而不關心數據是怎么來的(來自於sql,還是oracle?采用何種方式)。而BLL層負責根據用戶的請求返回數據。關注於業務邏輯的處理。這樣的實現方式,不會在前台寫任何的sql語句。代碼看起來比較簡潔。

最后,實現將修改后的表格數據保存回數據庫中。這就比較簡單了

 

當點擊保存時,調用save方法。Save方法中的核心是第一句:

 

getTableValue的實現為:

 

這樣,開發人員同樣不用寫任何代碼,便可以實現數據對象的自動獲取。該代碼是可以復用的。

--------------------------------------分割線------------------------------------------

總結:

  1. 上文以可復用,可擴展,分離關注點的方式實現了表格的動態繪制,數據的自動綁定和自動獲取。而且用戶的代碼量相較以往減少了非常多。
  2. 自動綁定和獲取的方法還存在些不足,因為當前版本的實現只是基於string類型的。未考慮datetime,bool,int等類型。但是根據分離關注點的原則(或者依賴倒置原則),我們同樣可以將該部分邏輯分離出來,交給專門處理數據類型的類來處理。然后保持原有的邏輯不變。下來我會繼續改進。
  3. 該方法同樣適用於表單數據的保存和綁定.
  4. 心得體會:Less Code, Less Copy, More ReUseable, More Flexiable and More OO。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM