ساخت یک گرید با HTML

شنبه 3 مرداد 1394

این مقاله مقدمه ای است بر ایجاد یک گرید تقریبا پیشرفته قابل توسعه با HTML5 که از ابتدا تا انتها با جزییات کامل به آن می پردازیم. برخلاف آنچه که اغلب افراد فکر می کنند اصلا کار سختی نیست.

ساخت یک  گرید با HTML

مقدمه

در این مقاله دستورکار ایجاد یک grid HTML5 از ابتدا تا انتها را مرور خواهیم کرد. تکنیکی را بررسی می کنیم که بدنه گرید با متغیرهایی که به هنگام تقاضا قرار داده می شوند ، ساخته می شود. مزیت نوشتن یک گرید برای خودتان این است که کنترل کافی بر قابلیت های گرید خود خواهید داشت. اگر به امکانات جدیدی نیاز داشته باشید و یا تغییری موردنیاز باشد با توجه به تجربه چند سال اخیر این اطمینان را می دهم که در مدت زمان چند ساعت یا یک روز به آسانی انجام خواهد شد.

lightGrid

ایده مقاله

ایده ساخت کنترل هایی برای خودتان، به یک موضوع رقابتی تبدیل شده است. به ویژه گریدی که در این دسته بندی به عنوان افت های کنترلی پیچیده شناخته می شوند.

درحالیکه درست است که خرید یک گرید آماده، در عمل امکانات زیاد و راضی کننده ای در اختیار شما قرار خواهد داد اما در ازای هزینه ای که می پردازید. اما تجربه ثابت کرده اگر شما چیزی نیاز داشته باشید که در گرید تهیه شده، فراهم نشده باشد، شما با مشکل مواجه خواهید شد. درسته، می توان سورس کدی گرفت و آن را توسعه داد اما همیشه به این آسانی نیست. همچنین با انتشار نسخه های جدید یا به روز رسانی توسط تولیدکننده نیاز به مدیریت خواهد داشت.

اشتباه نکنید،خرید یک گرید حاضر و آماده مزیت هایی دارد، می تواند به سرعت اجرا شود و با کامپوننت های دیگر به خوبی سازگار باشد (اگرچه احتمالا با محصولات همان تولید کننده). بنابراین اگر سازگاری چیزی باشد که شما به دنبال آن هستید، خرید یک گرید برای شما مناسب خواهد بود.

اگرچه، همانطور که در این مقاله ثابت خواهم کرد، نوشتن گریدی برای خودتان درواقع به سختی که شما فکر می کنید نیست. واضح ترین و مهم ترین دلیل اینکه، شما دقیقا همان چیزی که را نیاز دارید به دست خواهید آورد، اگر مشکلی داشته باشید می توانید آن را سریعتر پیدا کرده و اشکال را رفع کنید نسبت به  زمان زیادی که باید بعد از انتشار هر نسخه جدید در انجمن ها و قسمت سوال های متداول (FAQ) سایت مربوط به تولیدکننده صرف کنید.

ویژگی های Grid

gridای که خواهیم ساخت، ویژگی های زیر را خواهد داشت:

- امکان تغییر سایز ستون

- امکان تغییر ترتیب ستون

- مرتب سازی

- صفحه بندی

- ستون های انعطاف پذیر - ستونی که تمام فضای خالی گرید را پر می کند. (سایز این ستون را تغییر دهید تا این قابلیت غیرفعال شود، با یک کلیک روی تغییردهنده سایز به سادگی می توانید دوباره آن را فعال کنید)

- واحدهای پولی و ارزی

و نقصی که دارد:

فیلترها - اگرچه در حال حاضر می توان اطلاعات داده شده به گرید را محدود کرد.

اولین گرید خود را بسازید

شما یک المنت DOM دارید که می خواهید گرید به آن اضافه کنید. ابتدا مجموعه ای از ستون ها را برای نمایش داده هایی که می خواهید نشان دهید، تعریف کنید. colDef تعیین می کندکه گرید شما چیست، کجاست و اطلاعات را به چه شکلی نشان دهد. دقت کنید که اطلاعات بیشتری می تواند مشخص شود اما اگر colDef متناظر یافت نشود، واضح است که نمایش داده نخواهد شد. همچنین یک سری CurrencyInfo Object تعریف خواهیم کرد(اختیاری) تا گرید ما راهی برای پیدا کردن نمادهای (واحدهای پول و ارز) currency برای فیلدهایی که ممکن است به آن نیاز داشته باشند، در اختیار داشته باشد.

کد زیر در قسمت client Code جایی که شما گرید را ساخته و مدیریت می کنید تعریف می شود:

// one-off, define some currencies for the CurrencyManager so it can return symbols for the grid
__cm.setCurrencyInfo(new __cm.CurrencyInfo("GBP", "British Pound", "£", "GBP", ""));
__cm.setCurrencyInfo(new __cm.CurrencyInfo("USD", "US Dollar", "$", "USD", ""));
__cm.setCurrencyInfo(new __cm.CurrencyInfo("EUR", "Euro", "€", "EUR", ""));

// define the column definitions for the grid
this._coldefs = [];
this._coldefs.push(new __gc.ColDefinition("code", "Code", 100, "", "", "", "asc"));
this._coldefs.push(new __gc.ColDefinition("fullname", "Fullname", -1));     
this._coldefs.push(new __gc.ColDefinition("county", "County", 110, "", "", "", "", "", true));
this._coldefs.push(new __gc.ColDefinition("currency", "Currency", 90, "", "", "center"));
this._coldefs.push(new __gc.ColDefinition("valuation", "Valuation", 110, "number", "0,0.00", "right", "", "currency"));
this._coldefs.push(new __gc.ColDefinition("price", "Price", 110, "number", "0,0.00", "right", "", "currency"));
this._coldefs.push(new __gc.ColDefinition("myimage", "Img", 50, "image", "", "center"));
this._coldefs.push(new __gc.ColDefinition("created", "Created", 150, "date", "", "center"));

با هم یک نگاه دقیق تر به سطر 'price' می اندازیم. این سطر colDefinition را برای ویژگی سطرهای داده مشخصی که 'price' نام دارد، تعریف می کند. در این مورد ما مشخص کردیم که بالای ستون عنوان 'price' را نمایش دهد، عرضی معادل 110 پیکسل داشته باشد و با استفاده از numeral.js نوع داده "عددی" آن با این فرمت "0,0.0" نمایش داده شود. اگر نوع داده شما "date" بود برای فرمت نمایش آن باید moment.js را فراخوانی می کردید. همچنین این ستون باید راست چین باشد و برای نماد currency خود، به فیلد داده ای 'Currency' مراجعه کند. تعبیه ستون currency، باعث می شود که گرید معادل نماد currency را جستجو کرده و نمایش دهد.

درحال حاضر، ما مجموعه ای از ColDefinition داریم که از بین المنت های DOM خود پیدا کرده و در گرید جای دادیم، یک GridController بسازید و از بدنه گرید بخواهید تا آن را برای شما بسازد. ( طبق آنچه که در Code Snippet زیر نشان داده شده است)

گرید ما کاملا ساخته شد و آماده پذیرش داده هایی است که ما به عنوان نمونه به آن تحویل خواهیم داد. (به همراه ColDefs)

توجه داشته باشید که در این مثال، آرایه ColDefs را به همراه داده هایش بعد از ساخت گرید تهیه کردیم. این به این معناست که شما می توانید در هر زمانی داده های مختلف را تا زمانی که با مجموعه ای از ColDefs متناظر باشد به گرید بفرسیتد.

// find the element we will place the grid in
var $grid = $('.mygrid');

// create a grid controller
this._gc = new __gc.GridController();
this._gc.createGrid($grid);

// create some sample data
var data = __data.generateSampleData(rowcount);

// simply pass on the data (and their definitions) to the grid
this._gc.setData(data, this._coldefs).done(function () {
    ...
});

...

دقت کنید که فراخوانی setData یک jQuary برمی گرداند که بعد از اینکه ایجاد گرید کامل شد، فراخواننده خود را مطلع می سازد.

کد

کدهای خیلی زیادی با جزییات کامل برای توصیف کد گرید وجود دارند. بنابراین من در این مقاله اصول اساسی را بحث خواهم کرد و به قسمت هایی از کد که کلیدی هستند، نگاه دقیق تری خواهم داشت. پیشنهاد می کنم برای فهم عمیق تر فایل فشرده را کپی کنید و یا آن را در github چک کنید.

توجه داشته باشید که من با پیش زمینه و سابقه #C این مقاله را نوشتم و این باعث می شود که من در تفکر شی گرای خود باقی بمانم و به آسانی از کلاس های دیگر استفاده کنم و یا رابط کاربری پیاده سازی کنم و از نوع ایمنی و... دیگر توسعه دهندگان خوب استفاده کنم.

همانطور که گفته شد، سورس کد کامل را می توانید در Github ببینید. درصورت مورد استقبال قرار گرفتن این مقاله، گرید را ویرایش و بهینه خواهم کرد.

ساختمان گرید

ایده کد ساخت یک نمونه از این گرید، این است که در "کد" ساخته شود و با استفاده از تابع 'createGridStructure' به div موردنظر تزریق شود. این تابع یک رشته در کد می سازد که به المنت DOM تبدیل می شود (با استفاده از jQuary) و سپس به المنت موردنظر تزریق می شود.

سرنخ و دسترسی به قسمت های $header و $datarows بعد از اینکه این قسمت ها  پر شدند به دست می آید. دوباره، ابتدا در کد و سپس به هرکدام از متغیرها تزریق می شوند. (به ترتیب header ساخته می شود و بعد datarow).

GridSkeletion

گرید مبتنی بر سه نوع اطلاعات است، actual data (داده واقعی)، آرایه تعریف ستون ها که ستون هایی که این داده ها را نمایش می دهد توصیف می کند و المنت DOM موردنظر که ما گرید کامل شده را به آن تزریق می کنیم.

تعریف ستون مشخص می کند که: هر ستونی از چه داده های سطری استفاده می کند، فرمت عنوان، هم ترازی آن (راست چین، وسط چین، چپ چین)، نوع آن (string, number, date, image etc) و غیره.

بررسی اجمالی کلاس های اصلی مورداستفاده برای ساخت گرید در شکل زیر نشان داده شده است:

gridComponent

DataEngine.ts

یک شی از DataEngine ساخته می شود تا کنترل عملکرد گرید را از پیاده سازی داده های آن جدا کند. وظیفه DataEngin نگه داری داده هایی اصلی و مدیریت مجموعه ای از داده های از پیش آماده شده است که زمانی که کنترلر سطرها را می سازد، توسط کنترلر فراخوانی می شود. این کلاس می تواند بعدها توسعه پیدا کند و شامل ویژگی های جدیدی چون فیلترها، گروه بندی و یا ویرایش داده نیز باشند.

GridController.ts

این GridController.ts روی تمام HTML هایی تمرکز می کند که قرار است از ابتدا به یک المنت مشخص DOM تزریق شود. به این معنی که این سطرها روی re-sorting و column-reorder دوباره ساخته می شوند. در Column-resize تمام خانه هایی که تحت تاثیر تغییر قرار می گیرند، در کد تنظیم و تعدیل می شوند بنابراین سریعتر است. ایجاد دوباره همه سطرها آخر دنیا نیست، ساخت 1000 سطر هنوز زیر 0 ثانیه انجام می شود.

CurrencyMananger.ts

زمانی که ColDefinition یک فیلد جستجوی currency شناسایی می کند، CurrencyMananger با مقدار آن فیلد حاضر می شود مثل 'USD' و نماد $ را برمی گرداند و سپس به عنوان قسمتی از فرمت نمایش خانه موردنظر استفاده می شود.

تمام خانه های گرید یک سطر، با استفاده از flex-boxes کنار هم قرار می گیرند. چند کلاس مفید CSS را کنار هم و با نام flex-boxes قرار داده ام که در جاهای بسیاری که چندین div درون یک parent div دارم و یکی از این div ها نیاز دارد که هر فضای خالی در دسترسی را پر کند، استفاده می کنم.

مثال پایین را بررسی کنید. یک parent div وجود دارد (که می تواند ارتفاع زیادی داشته باشد) که شامل دو div با ارتفاع ثابت در بالا و یکی در پایین است و من می خواهم قسمت باقیمانده را پر کنم. تمام کاری که باید انجام بدهم این است که parent class را به 'flex-parent-col' ست کنم و یکی از فرزندان کلاس را داشته باشم و آن را به 'flex-child' ست کنم، همین. یک 'flex-parent-row' برای سطر متناظر وجود دارد.

FlexParentClass

همچنین grid-row روی این ساختار ساخته می شود. خود سطر با یک کلاس از 'flex-parent-row' ساخته می شود و یکی از فرزندان آن، کلاسش را به منظور پر کردن فضای خالی دردسترس به 'flex-child' ست می کند.

GridController.ts

تمام کدهای نمونه ای که در ادامه آمده، درون GridController.ts نگه داری می شود.

کد زیر ایجاد ساختار اصلی گرید را نشان می دهد. این کد رشته ای می سازد که سپس به یک المنت DOM تبدیل می شود و سپس به متغیر مربوطه تزریق می شود.

private createGridStructure(showBorder: boolean): string {
    var s: string = "";

    // --------------------
    // define the grid structure
    // --------------------
    var s: string = "";

    s += "<div class='bs-grid flex-parent-col " + (showBorder ? "border" : "") + "' >";

    s += "  <div class='spinner' style='display: none'}> <div> <i class='fa fa-spinner fa-spin fa-3x'></i> </div> </div>"

    s += "  <div class='header-containment'> </div>"

    s += "  <div class='header' >"
    s += "      <div class='resize-marker' title='resize this column or double-click to make it the flex-column'> </div>"
    s += "      <div class='insert-marker'>";
    s += "          <i class='down fa fa-caret-down fa-2x'></i>";
    s += "      </div>";
    s += "      <div class='header-template' style='position: relative'> </div>"
    s += "  </div>";

    s += "  <div class='data-scrollable flex-child flex-scrollable' >";
    s += "      <div class='data'> </div>";
    s += "      <div class='full-resize-marker'> </div>"
    s += "  </div> "

    s += "  " + this.createPager();

    s += "</div>";

    return s;
}

private createPager(): string {
    var s: string = "";

    s += "      <div class='pager'>"

    s += "          <button type='button' class='btnFirstPage pager-button'> <i class='fa fa-step-backward' title='First page'></i> </button> ";
    s += "          <button type='button' class='btnPrevPage pager-button'> <i class='fa fa-caret-left fa-lg' title='Previous page'></i> </button> ";
    s += "          <span class='pager-text' style='margin: 0px 4px 0px 4px'></span>";
    s += "          <button type='button' class='btnNextPage pager-button'> <i class='fa fa-caret-right fa-lg' title='Next page'></i> </button> ";
    s += "          <button type='button' class='btnLastPage pager-button'> <i class='fa fa-step-forward' title='Last page'></i> </button> ";

    s += "          <span style='margin: 0px 2px 0px 20px'>page size: </span>";
    s += "          <select class=page-size title='Number of rows per page'></select>";

    return s;
}

و به این صورت فراخوانی می شود:

...

// create a grid string
var grid = this.createGridStructure(showBorder);

// create a DOM grid 
this.$grid = $(grid);

// add this grid to the given dom element
this.$grid.appendTo($el);

// get a handle to some important data parts
this.$header = $('.header-template', this.$grid);
this.$datarows = $('.data', this.$grid);
this.$pager = $('.pager', this.$grid);
this.$resizemarker = $('.resize-marker', this.$grid);
this.$resizeline = $('.full-resize-marker', this.$grid);
this.$insertmarker = $('.insert-marker', this.$grid);
this.$sgloading = $('.spinner', this.$grid);
this.$datascrollable = $('.data-scrollable', this.$grid);

...

بنابراین در ابتدا 'createGridStructure' را فراخوانی می کنیم که چیدمان کلی گرید را به صورت یک رشته برمی گرداند. سپس این رشته را به یک المنت jQuery DOM تبدیل می کنیم و آن را به یک المنت مشخص DOM گسترش می دهیم.

گرید ما ساختاری دارد و این ساختار در شاخه client DOM قرار می گیرد.

سپس می رسیم به دستگیره ها روی بعضی المنت های مهم مثل header, the data-area, resizemarker و المنت های مختلف دیگر که ما می خواهیم کنترل کنیم.

بخاطر داشته باشید که در این نقطه، ما فقط هنوز بدنه بیرونی را داریم، بنابراین به ساختن قسمت های Header و Rows می پردازیم.

ایجاد Header و Datarows همان الگوی بدنه گرید را دنبال می کند. در ابتدا ما یک رشته برای نمایش کامل Header (یا datarows) می سازیم سپس المنت های واقعی DOM را بیرون آن می سازیم و آنها را به متغیرها تزریق می کنیم. (به ترتیب $header و $datarows)

نگاهی دقیق تر داشته باشیم به ساختار کد این header:

private createHeader(): string {

    var self = this;
    var headerTemplate: string = "<div class='row-header flex-parent-row' > ";

    $.each(this.colDefinitions, function (index, coldef: ColDefinition) {

        // define the css classes we apply to each header column
        var cssclasses: string = "cell-header cell-right-column ";
        cssclasses += coldef.classAlign + " ";
        if (coldef.isFlexCol) cssclasses += "stretchable ";
            
        // get and lowercase the colName allowing us to get hold of the appropriate column when taking actions like sorting, resizing etc.
        var colName = coldef.colName.toLowerCase();
        var hitem: string = "";
        hitem += "<div class='" + cssclasses + "' data-sgcol='" + colName + "' style='width: " + coldef.width + "px;'>";
        hitem += "<span>" + coldef.colHeader + "</span>";
        hitem += "<span class='" + self.getSortSymbol(coldef) + "'></span>";
        if (coldef.isFlexCol) 
            hitem += "<i class='pull-right fa fa-arrows-h' style='background-color: transparent; color: rgb(201, 201, 208);' title='this column is flexible sized'></i>";
        hitem += "</div>";
        headerTemplate += hitem;

    });
    headerTemplate += "</div>";
    return headerTemplate;
}

و به این صورت فراخوانی می شود:

// create the header (string and DOM and append to placeholder)
var header = self.createHeader();

$(header).appendTo(self.$header);

و به این صورت ما یک header داریم!

و به همین صورت پیاده سازی actual data rows:

private createRows(): string {
    var self = this;
    var s = "";

    for (var i = 0; i < self.dataEngine.baseDataPrepared.length; i++) {
        var dataItem: any = self.dataEngine.baseDataPrepared[i];

        // start row definition
        s += "      <div class='row flex-parent-row' data-pkvalue='" + dataItem.pkvalue + "' >";

        // step through each ColDefinition
        self.colDefinitions.forEach(function (coldef: ColDefinition) {

            // retrieve the actual raw cell value
            var myvalue = dataItem[coldef.colName];

            // check if any custom formatting is required
            myvalue = self.getFormattedValue(myvalue, dataItem, coldef);

            // ask the client to fill in any generic styling properties
            var styleProp: CellStyleProperies = self.cbStyling(coldef, dataItem);

            // start Cell definition
            s += "<div class='cell cell-right-column " + (coldef.isFlexCol ? "stretchable" : "") + " " + coldef.classAlign + "' ";
            s += "data-sgcol='" + coldef.colName + "' style='width: " + coldef.width + "px; ";

            // if a cell backcolour was given then apply it
            if (styleProp.cellBackColour) 
                s += " background-color: " + styleProp.cellBackColour + "; ";

            // if a cell forecolour was given then apply it
            if (styleProp.cellForeColour) 
                s += " color: " + styleProp.cellForeColour + "; ";

            s += "'>";  

            // check if this cell is merged with an image and we were given an image
            if (coldef.mergeWithImage && styleProp.imgName) 
                s += "<div class='merged-image " + coldef.colAlign + "' style='background-color: " + styleProp.imgBackColour + "; color: " + styleProp.imgForeColour + ";'> <i class='fa " + styleProp.imgName + "' > </i> </div>"

            // if this is an image colum then just show the image
            if (coldef.colType == "image") {
                var faImage = styleProp.imgName;  
                if (faImage.length == 0) faImage = myvalue;         // if no return value was given then use the actual data
                s += "<i class='fa " + faImage + "'\"></i>";
            }
            else
                // simply write out the actual cell value
                s += myvalue;

            s += " </div>"      // end cell definition

        });
        s += "      </div>";    // end row definition
    }

    return s;
}

و دوباره به این صورت فراخوانی می شود:

// create all rows (string and DOM and append to placeholder)

var rows = self.createRows();

$(rows).appendTo(self.$datarows);

چند نکته اینجا باید توجه کنیم. اول، ما از طریق دیتا آیتم واقعی (از پیش تعریف شده) تکرار می کنیم و برای هر دیتا آیتم از طریق آرایه ColDefinitions تکرار می کنیم که به ما اطلاعات کافی برای تعریف هر Cell را می دهد.

زمانی که می خواهیم یک Cell از grid را تعریف کنیم، ابتدا مقدار سطر را از طریق یک formatter وارد می کنیم که مقدار فرمت شده را برمی گرداند و سپس با تخصیص کلاس های مناسب آن را دیزاین می کنیم.

طراحی cell

برای اینکه به کاربر امکان طراحی سفارشی هر Cell را بدهیم، چک می کنیم که آیا تابع طراحی سفارشی مشخص شده است یا خیر؟ اگر بله، بنابراین آن را با ColDef جاری فراخوانی می کنیم و actual datarow امکان تصمیم گیری درباره اینکه تمام داده های قابل دسترسی را در دست داشته باشد یا خیر را به کاربر می دهد.

ایده این کار این است که برای هر Cell، کاربر یک CellStyleProperties object می سازد که می تواند زمان تعریف Cell توسط GridController استفاده شود. ویژگی هایی که می توانند تنظیم شوند شامل رنگ پس زمینه و پیش زمینه، عکس ها و غیره است.

برای اینکه ببینیم طراحی سفارشی هر Cell چطور کار می کند، نگاهی به کد زیر می اندازیم (که در کلاس Client code تعریف شده)

this._gc.cbStyling = function (coldef: __gc.ColDefinition, item: any) {

    // define a new CellStyleProperties object we will return
    var styleProp: __gc.CellStyleProperies = new __gc.CellStyleProperies();

    // now check which column is being checked and set any style properties appropriately 
    if (coldef.colName == "county") {
        if (item["county"] == "Kent" && Math.floor(item["price"]) % 2 == 0)
            styleProp.cellBackColour = "rgb(178, 232, 178)";
        if (Math.floor(item["price"]) % 4 == 0) 
            styleProp.imgBackColour = "rgb(255, 196, 8)";
        if (item["county"] == "Sussex")
            styleProp.imgForeColour = "red";
    }

    // image
    if (coldef.colName == "myimage") {
        if (item["price"] < 250)
            styleProp.imgName = "fa-floppy-o";
        else if (item["price"] < 500)
            styleProp.imgName = "fa-warning";
    }

    ...
    ...

    return styleProp;
};

این تابع برای هر Cell فراخوانی می شود چرا که آنها ساخته شده اند که بیشترین امکان سفارشی سازی را به ما بدهند.

Grid Images

شاید متوجه شده باشید که روشی که من برای گرفتن image در گرید ترجیح می دهم، استفاده از font-awesome images می باشد.

چون این ها با طراحی المنت ها به وسیله کلاس های خاصی کار می کنند که برای گریدهای ساخته شده در کد ایده آل هستند.

کوتاه درباره کنترل رویداد

بعد از اینکه ما بدنه گرید را ساختیم و به متغیرهای آن دست پیدا کردیم، دستگیره ها را به بعضی از آنها الحاق می کنیم.

این ها شامل کنترل کننده های کلیک روی دکمه های جهت یابی، کلیک سطر و دابل کلیک و بسیاری چیزهای دیگر است.

پیش از این ذکر شد که کنترل کننده رخدادها به صورت 'one-off' (تنها یکبار ساخته شدن) متصل شده اند چرا که بدنه گرید دوباره ساخته نمی شود. اما grid-header متفاوت است و به طور متناوب ساخته می شود. بنابراین کدی که به یک  jQuery-ui با قابلیت drag & drop و تعاملی الحاق می شود، این امکان را به ما می دهد که ستون هایی را که در تابع جداگانه قرار گرفته اند حرکت دهیم و این تابع هر بار که header ساخته می شود، فراخوانی می گردد.

انتخاب یک سطر

برای پشتیبانی انتخاب یک سطر، DataEngine تضمین می کند که یک property به نام 'pkvalue' به هر سطر تولید شده الحاق می شود. این مقدار یکتا توسط صفت داده ای به نام 'data-pkvalue' در هر سطر DOM قرار می گیرد که وقتی یک سطر jQuary را کلیک کند بتوان به آسانی تشخیص داد، کدام سطر بود و کلاس 'Selected' به المنت سطر اضافه شود.

Ajax

در این مقاله، گرید تمام داده هایی که از ابتدا توسط DataEngine نگه داری و کنترل می شوند را دریافت می کند. اگرچه جاوا اسکریپت با نگه داری و پردازش مقادیر بزرگ داده سازگار به نظر می رسد اما به طور واضح چیزی برای توقف شما در توسعه DataEngine و call back به سرور برای داده های صفحه بندی شده وجود ندارد. تنها مطمئن باشید که از <JQueryPromise<T به عنوان نوع شیء بازگشتی از فراخوانی 'Refresh' به موتور استفاده می کنید و کد خود را بر اساس این تنظیم کنید.

کلام آخر

امیدوارم این مقاله به شما نشان داده باشد که ساختن گرید مختص خودتان، کار غیر ممکنی نیست. توسط یک گرید در حالت عادی خودش، اضافه کردن عملکرد بیشتر کار سختی نیست. اگر استقبال کافی از این مطلب وجود داشته باشد، گرید را با عملکردهایی  مانند فیلترینگ، فرمول نویسی ستون ها و شاید فراخوانی های Ajax بهینه خواهم کرد.

من برای کارفرمای خودم گرید مشابهی ساخته ام که ویژگی های بسیار دیگری دارد که از  knockout bindings برای بسیاری از ویژگی ها و توابع مانند قراردادن محتوا، عرض، ترتیب خانه ها و به روزرسانی های پویای داده و غیره استفاده می کند.

بخش های مورد علاقه

در ابتدا، من در شک و تردید بودم که چه چیزی می توانم به مرورگر یا جاوا اسکریپت اضافه کنم که بارها فراخوانی شود و دستکاری های روی DOM را در زمان کم انجام دهد، اما کافی است که بگویم که جاوا اسکریپت و کامپایلر/بهینه سازها توانایی بسیار بالایی برای کنترل این مسئله دارند. این موضوع اعتبار بسیاری به کامپایلرها و بهینه سازهای جاوا اسکریپت می دهد.

 

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان
  • HTML
  • 2k بازدید
  • 6 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید