H Təlim layihələrində sadə js şablon mühərriki yazırıq. H Qaralamalarda sadə js şablon mühərriki yazırıq





İndi js proqramlarında şablonlar üçün yalnız iki variant görürəm - çərçivəyə daxil edilmiş şablon mühərrikləri və jQuery əriştələri (sonuncu ən çox yayılmışdır) inanıram ki, bu, çoxlarının şablon mühərriklərinin necə işlədiyini başa düşməməsi ilə əlaqədardır. hamısı (mən onların daxili xüsusiyyətləri haqqında danışıram, funksiya haqqında deyil) .
Bu yazıda mən sizə müntəzəm ifadələr əsasında sadə, lakin güclü şablon mühərriki necə edəcəyinizi göstərəcəyəm.

Ancaq mövzuda olmayanlar üçün bunun nə olduğu və bizə nə verəcəyi haqqında bir az.

Şablonlama mühərriki (vebdə) yekun html səhifələrini yaratmaq üçün html şablonlarından istifadə etməyə imkan verən proqramdır. Şablon mühərriklərindən istifadənin əsas məqsədi verilənlərin təqdimatını icra olunan koddan ayırmaqdır. Tez-tez bu, proqramçı və layout dizaynerinin paralel işləməsinin mümkünlüyünü təmin etmək üçün lazımdır. Şablonlama mühərriklərinin istifadəsi çox vaxt kodun oxunmasını yaxşılaşdırır və bütün layihə bir şəxs tərəfindən həyata keçirildikdə görünüş dəyişir.

Beləliklə, biz şablonları 1 keçiddə göstərmək və məntiqdən ayrı bir görünüşə sahib olmaq istəyirik. Adətən şablon mühərrikləri oxşar interfeysə malikdir.
template.Run("şablon url", ( VarName:"VarValue" ));
Aşağıda ətraflı şərhləri olan kod (nə və niyə)


Və test.tpl-də sadəcə yazın
((var.VarName))

Ümid edirəm ki, indi daha az jquery əriştəsi olacaq)

Lazım ola biləcəyiniz bir neçə hal var şablon mühərriki haqqında JavaScript, onların arasında həm müştəridə, həm də JavaScript mühitlərindən istifadə edildiyi təqdirdə serverdə məzmun yaratmaq ehtiyacı, məsələn NodeJS və ya kərgədan. Dərhal deməliyəm ki, mən özüm üçün sadədən ekzotik olanlara qədər mövcud şablon mühərriklərin çoxunu nəzərdən keçirdim. Ən çox sadə olanlarla maraqlanırdım, lakin şablonlarda mürəkkəb məntiqdən istifadə etməyə imkan verirdim və EJS onlardan biri oldu. Ancaq bu şey istədiyimdən bir qədər fərqli yazılmışdı, bir tərəfdən həddindən artıq çox şey var idi, digər tərəfdən əsas funksionallıq çox mürəkkəb idi. Mən onun şablonlarını tərtib etməyi və göstərməyi çox asanlaşdırmaq üçün bir fürsət gördüm.

EJS tətbiqi

Nə edir şablon mühərriki: götürmək nümunədata, qaytarır məzmun nümunəsi emal yolu ilə əldə edilir şablon bu spesifikliyə əsaslanır məlumat nümunəsi.

Nə vaxt EJS mahiyyəti sadədir: şablonun bir hissəsi olaraq, göstərilən məzmunu quraşdırılmış hissələrlə birləşdirə bilərik. JavaScript, skript fayllarına bənzəyir PHP HTML ilə kod birləşdirir. Kodda həm qlobal dəyişənlər, həm də çağırılan zaman rendererə ötürməyə diqqət yetirdiyimiz dəyişənlər görünür. Orada tez-tez istifadə olunan strukturların, məsələn, keçid etiketlərinin və ya şəkillərin formalaşmasını asanlaşdıran sözdə köməkçi funksiyaları da görə bilərsiniz.

Kod etiketdə çərçivəyə salınmışdır <% ваш код для исполнения %> və ya etiketdə <%= ваша переменная для вывода %> .

Bunun necə görünə biləcəyi budur:

<%if(content){%> <% if (title) { %>

<%=title%>

<% } %>
<%= content %>
<%}%>

Konstruksiyaları qəsdən müxtəlif üslublarda yazdım ki, boşluqların olması önəmli deyil. Şablondan istifadə edərək çıxış yaradarkən, şablonumuzun içindəki kodun işlədiyi dəyişənlər kimi çıxış edən xassələri olan obyektə keçirik. Məsələ ondadır ki, JavaScript-in özündə məntiqi konstruksiyaların köməyi ilə siz əldə olunan məzmunun görünüşünü çevik şəkildə dəyişə bilərsiniz. Alternativ olaraq kimi etiketlərdən istifadə edə bilərsiniz [% %] şablon DOM ağacına daxil edildikdən sonra göstərilməlidirsə. İstifadə nümunələrimə görə, mən bunu çox faydalı hesab etmədim.

EJS təkmilləşdirilməsi

Orijinal şablon mühərrikində, fayllardan şablon yükləmək üçün əlavə funksionallıq məni qane etmədi, prinsipcə ehtiyac duymadım, çünki o, yalnız müştəri tərəfində deyil, server mühitlərində istifadə edilməli idi. Kompilyatorun özünün mürəkkəbliyi məni də xoşagəlməz bir şəkildə təəccübləndirdi, çünki kod məntiqinin mürəkkəbliyinə görə yerli zənglərdən istifadə etməyi üstün tuturam. Bu səbəblərdən sonra sıfırdan bir kompilyator yazmağa qərar verdim ki, bundan sonra danışacağıq.

Mənbə şablonlarının təhlili

Kompilyasiya həmişə əvvəlcədən müəyyən edilmiş qaydalara uyğun olaraq mənbə materialının təhlilindən başlayır. Bizim qaydalar dəstimiz xüsusi teqlərdəki məzmunu başqa hər şeydən fərqləndirməkdən ibarətdir. Fərdi teqlərimizin strukturuna baxsaq, onları sadə müntəzəm ifadə ilə bütövlükdə çəkmək asandır. Unutmayın ki, faktiki koddan əlavə, içəridəki kodla nə edəcəyimizi başa düşmək üçün açılış etiketini çıxartmalıyıq. RegExp necə görünəcək:

/(?:\n\s*)?(<%[=]?)((?:[^%]|[%][^>])+)%>/gm

Beləliklə, biz burada nə edirik:

  • (?:\n\s*)?- əgər varsa, yeni sətri və bütün boşluqları kod etiketinə çıxarın. Təbii ki, bunu etmək heç lazım deyildi, amma biz estetikayaq, ona görə də yaradılan məzmunda çoxlu boş sətirlərin görünməsinin qarşısını alacağıq. dəqiqləşdirici ?: alt modelin əvvəlində onun məzmununun tutulmaması, sadəcə atlanması deməkdir.
  • (<%[=]?) - açılış etiketinin özünü tutun. Bu dəfə biz açılış teqinin bütün alt modelini çəkirik, sonra kodu yaradan zaman bizə lazım olacaq.
  • [^%]|[%][^>] - kodumuz olmayan hər hansı simvoldur % , və ya simvol % , simvolun ardınca gəlmir > .
  • (?:[^%]|[%][^>])+ - kodumuz - bu ardıcıllıqlar bir dəfədən çox ola bilər, lakin tutulmamalıdır.
  • ((?:[^%]|[%][^>])+) - kodumuz - və biz bütün ardıcıllığı çəkirik.
  • %> - bağlanış etiketi tutulmayıb.
  • gm- qlobal tam mətnin (çox sətirli) emalını aktivləşdirin.

Gördüyünüz kimi, hər şey olduqca mənasızdır, bu müntəzəm ifadə ilə nə edəcəyinizi anlamaq qalır. Və burada çox faydalı bir üsul bizə kömək edəcəkdir String.split, müəyyən edilmiş ayırıcıdan istifadə edərək sətri parçalayan, nəticədə yaranan alt sətirlərin massivini qaytarır. Bu metodun özəlliyi ondan ibarətdir ki, o, ayırıcı kimi müntəzəm ifadə qəbul edə bilir və əgər orada tutulan alt modellər varsa, onlara uyğun gələn alt sətirlər də adi qaydada yaranan massivə düşəcək. Bu, bizə şablon tərtibçisinin yerli optimallaşdırılması ideyasını verir: biz sətri müntəzəm ifadə ilə bölürük, daxili məzmun və kod dəqiqləşdiricilərinin ardıcıllığını bu kodun parçaları ilə əldə edirik, onda sadəcə emal etmək kifayətdir. yaranan massiv.

İcra edilə bilən kodun yaradılması

İndi bizim təhlil edilmiş şablonumuz var, yəni biz onu tam xətti olaraq icra edilə bilən JavaScript koduna necə çevirəcəyimizi artıq təsəvvür edə bilərik. Bizə lazım olan yalnız bir funksiya əldə etməkdir, ona zəng edərək məzmunu orijinal şablona uyğun olaraq düzgün şəkildə formalaşdıracağıq. Beləliklə, şablondan məzmun parçaları olduğu kimi daxil edilməli, dəyişənlərin yerinə onların dəyərləri daxil edilməli və kod icra edilməlidir.

Bunu aşağıdakı sadə şəkildə təşkil edək:

  • biz funksiyanı eval çağırmaq üçün uyğun sətir kimi formalaşdıracağıq
  • funksiyanın gövdəsində müəyyən nəticə dəyişəninə məzmun hissələrinin ardıcıl əlavə edilməsini təşkil edirik
  • adi JS kodunu olduğu kimi yapışdırın

Bununla belə, aşağıdakı problemləri həll etməliyik:

  • icra edilə bilən şablon funksiyasının gövdəsinə dəyişənlərin və köməkçi funksiyaların ötürülməsi
  • nəticə dəyişəninin şablonda istifadə olunan dəyişənlərlə üst-üstə düşməməsi üçün təşkili

Birinci problemin həlli

Birinci problemi həll etmək üçün tikintidən istifadə etmək ən asandır ilə. Bəli, bu, tərtibatçılar arasında qızğın müzakirələrin əbədi mövzusu və w3c standartlaşdırıcılarının baş ağrısıdır, məhz JSLINT kimi təsdiqləyicilərin və Closure Compiler kimi tərtibçilərin nifrət etdiyi şeydir. Bu konstruksiya onu obyekti yerli dəyişənlər üçün görünmə təbəqəsi kimi təqdim etmək kimi düşünməyin ən sadə yoludur, yəni obyektin xassələrinə normal dəyişənlər kimi adla daxil ola bilərsiniz, yəni obyektin adını nöqtə ilə qeyd etmədən, burada nə kimi görünür:

Var obj = ( foo: "Bu foo.", bar: 42 ); with(obj)( foo += "Və bar " + bar; )

Dəyərləri oxuyarkən hər şey olduqca sadədir, yazarkən o qədər də mənasız deyil, xüsusən də iç içə konstruksiyalardan istifadə edərkən ilə, lakin şablonlarda biz əsasən dəyərləri oxumalıyıq, ona görə də başqa qoltuqağacı yaratmaq əvəzinə yerli yanaşmadan istifadə etmək daha doğrudur. Dəqiq desək, yerli dəyişənlərin iki qarşılıqlı iç-içə görünmə səviyyəsi əslində yaradılır: biri obyektdən, digəri with body daxilində, yəni orada lokal dəyişənlər yaradanda onlar orijinal obyektə daxil olmurlar.

İkinci problemin həlli

Şablon göstərmə funksiyasında məzmun hissələrini necə toplayacağımızı anlamaq qalır. Ağla gələ biləcək ilk şey sadəcə olaraq funksiyanın gövdəsində nadir görülən bir adla lokal dəyişən yaratmaq və icra zamanı ona lazım olan hər şeyi əlavə etməkdir. Açığını deyim ki, başlanğıcda bunu etmək istədim, əgər dəyişən adının keçmə ehtimalını minimuma endirsəniz, bu çox yaxşı fikirdir. Lakin, əmin olmaq üçün, bu həll çox estetik deyil, yüksək sənət yaradıcıları kimi, bizim bu qüsursuz funksiyada heç bir yerli dəyişən yaratmağa haqqımız yoxdur.

Gəlin görək nəyimiz var, amma ümumiyyətlə çox seçim yoxdur: bir şəkildə obyektdən istifadə edin bu və ya obyekt arqumentlər, hansı ki, dilin xüsusiyyətlərinə görə istifadəçi hələ də şablonlarda istifadə etməməlidir və əgər bacarırsa, yalnız hansısa xüsusi şəkildə. Müsbət və mənfi cəhətləri nəzərdən keçirdikdən sonra istifadə etmək qərarına gəldim arqumentlər, adsız arqumentlər massivi funksiyaya, onlardan birinə ötürülür və biz məzmunun düzgün formalaşması üçün lazım olan hər şeyi qoyacağıq.

İcra Xüsusiyyətləri

İndi tam şablon mühərriki həyata keçirmək üçün hər şeyimiz var. Dediyim kimi, orijinal EJS ilə tam uyğun olmayacaq, lakin onun üçün yaradılmış şablonlardan istifadə edə biləcək. Həmçinin, avtomatik şablon yükləyicisinin tətbiqi olmayacaq, bu xüsusi icra mühitində istifadə etdiyiniz çərçivənin prinsiplərinə əsaslanaraq onu özünüz bağlamalısınız.

Birbaşa koda keçməyin vaxtı gəldi, gəlin əsas və əsas olandan, yəni şablon obyektindən başlayaraq hər şeyi hissə-hissə nəzərdən keçirək:

// Konstruktor var EJS = function(src)( if(typeof src == "string")( // Şablon keçibsə this.compile(src); // Dərhal tərtib edin ) ); // Prototip EJS.prototype = ( regexp: /(?:\n\s*)?(<%[=]?)((?:[^%]|[%][^>])+)%>/gm, köməkçi: () // Köməkçi funksiyaları );

EJS.prototype.compile = function(src)( silin this.method; delete this.error; // əvvəlki tərtibçi çağırışının izlərini silin var p = src.split(this.regexp), // Nəticəni təhlil edin r = , // Nəticə montajı i, o; this.parsed = p; // təhlilin nəticəsini dərhal yadda saxlayın // (i = 0; i) üçün məzmun yaratma funksiyasını qurun< p.length; i++){ if(p[i] == "<%"){ // Если встречаем просто код o = p[++i]; // Вставляем, как есть }else{ // В противном случае, имеем дело с содержимым if(p[i] == "<%="){ // Если это переменная шаблона, o = p[++i]; // просто выводим её }else{ // Если это кусочек самого шаблона, o = "arguments[" + i + "]"; // будем брать его из результата разбора } o = "arguments+=" + o + ";"; // Формируем конструкцию для вывода } r.push(o); // Добавляем полученную часть кода к результату } // Вставляем начало и конец функции генерации содержимого r.unshift("this.method=function(){"+ "with(arguments){"+ "with(arguments){"); r.push("};};return arguments;};"); try{ // Пробуем вычислить полученный код, собрав в строку eval(r.join("\n")); return true; // Возвращаем истину }catch(e){ // Если что-то пошло не так, формируем ошибку if(typeof this.check == "function"){ // Если доступно, // выполняем продвинутое обнаружение ошибок // (например, с помощью JSLINT) e = this.check(r); } this.error = new EJS.CompileError(e.message); return this.error; // Возвращаем ошибку } };

Şablon göstərmə funksiyasını əlavə etmək qalır, lakin bu, əhəmiyyətsiz deyil:

EJS.prototype.render = function(data)( // Tək arqumenti, şablon dəyişənləri olan obyekti qəbul edin if(this.method instanceof Function)( // Əgər tərtib edilmiş şablon varsa cəhd edin( // Şablon qaytarılmasını tətbiq etməyə çalışın. this.method("" , this.parsed, this.helper, data); // Uğurlu olarsa, göstərilən məzmunu qaytarın )catch(e)( // Əgər uğursuz olarsa, render xətası yaradın this.error = new EJS.RenderError(e). .message); ) ) bunu qaytarın.səhv;// Səhvi qaytarın );

Əlbəttə ki, səhv funksiyaları əlavə etməyi unutmayın:

EJS.CompileError = function(message)( if(typeof message == "string")( this.message = message; ) ); EJS.CompileError.prototype = yeni Xəta(); EJS.CompileError.prototype.name = "EJS.CompileError"; EJS.RenderError = function(message)( if(typeof message == "string")( this.message = message; ) ); EJS.RenderError.prototype = yeni Xəta(); EJS.RenderError.prototype.name = "EJS.RenderError";

Yaxşı, istəsək, köməkçi funksiyalar əlavə edə bilərik:

// Köməkçi funksiyaları ilə gözəl iş üçün funksiya EJS.Helper = function(name, func)( // If(arguments.length) köməkçi funksiyalarını // almaq, əlavə etmək və silmək üçün ondan necə istifadə edəcəyini təxmin etmək çətin deyil.< 2){ return EJS.prototype.helper; } if(func === null){ delete EJS.prototype.helper; return; } if(typeof func == "function"){ EJS.prototype.helper = func; return true; } }; EJS.Helper("img_tag", function(src, alt){ // Тэг картинки return src ? "" : ""; )); EJS.Helper("bağlantı_to", funksiya(başlıq, href)( // Link teq başlığını qaytarın && href ? "" + başlıq + "" : ""; )); // Sonrakı əlavə edin onların

Bu, demək olar ki, hamısıdır, istisna olmaqla, yalnız bütün bunların ətrafında daha yüksək səviyyəli bir sarğı hazırlamağı təklif edə bilərəm.

Sonra nə var?

Əslində, mən bu çox yüksək səviyyədə həyata keçirilməsini təklif edirəm. Əgər siz artıq orada olanlardan razısınızsa, mövzu haqqında daha çox oxumağa ehtiyac yoxdur, çünki daha da daha da pisləşəcək real həyat nəzərə alınacaq.

Layihələrimdə RequireJS kimi bir şey istifadə olunur ki, bu da tətbiqlərinizin kodunu əlaqələndirmək üçün vahid bir mexanizm həyata keçirir və təkcə kodu deyil, ümumiyyətlə, hər hansı bir resurs növü və hansı mühitdə olmasından asılı olmayaraq. JavaScript kodu icra olunur. Məqalədə mən artıq bunun necə işlədiyini yazdım, lakin bir çox faydalı xüsusiyyət nəzərə alınmayıb. Bu, RequireJS plaginlərinin istifadəsi və inkişafıdır. Ancaq bu sual növbəti məqalənin mövzusu olacaq, bu olduqca kiçik oldu.

Burada server tərəfində sizə lazım olacaq bəzi testləri olan bir kitabxana göndərirəm NodeJS ilə qurulmuşdur RequireJS, müştəri tərəfində isə veb server nginx. Layihə kataloqundan make əmri ilə sınaqdan keçirilmişdir.

Şablon mühərrikləri mövzusunda çoxlu məqalələr, o cümlədən burada Habré-də yazılmışdır.
Əvvəllər mənə elə gəlirdi ki, özüm üçün bir şey etmək çox çətin olacaq - "diz üstə".
Amma elə oldu ki, mənə test tapşırığı göndərdilər.
Yaz, deyirlər, JavaScript şablon mühərriki, bu ssenariyə görə, sonra müsahibəyə gələcəksən.
Tələb, əlbəttə ki, həddindən artıq idi və əvvəlcə mən buna məhəl qoymamaq qərarına gəldim.
Amma maraqdan sınamağa qərar verdim.
Məlum oldu ki, hər şey o qədər də çətin deyil.

Əslində, əgər maraqlanırsınızsa, o zaman kəsik altında yaradılması prosesi ilə bağlı bəzi qeydlər və nəticələr var.

Sadəcə baxmaq istəyənlər üçün: nəticə , pişik .

Mənbə Şablonu JS String() və data bu JS Obyektidir().
Bloklar mehriban (% ad %) bədən (% / %), mümkündür limitsiz yuva salma.
Əgər adın dəyəri siyahı, sonra bütün elementlər göstərilir, əks halda qeyri-müəyyən deyilsə, çıxış bir element.
Əvəzetmələr növü: ((adı)).
Bloklarda və əvəzetmələrdə Ola bilər istifadə xal ad kimi, məsələn {{.}} və ya {%.%} nöqtə harada olacaq cari obyekt elementi üst səviyyə.
Daha çox şərh var (# çoxsətirli # hər hansı şərh).
Dəyərlərin özləri üçün filtrlər mümkündür, onlar iki nöqtə ilə təyin olunur: (( .:trim:böyük hərf... )).

Bu kimi işləməlidir:

var str = render(tpl, obj);

Sübut edin:
Özünə hörmətə +1.

UPD 2: Dərhal deyəcəyəm, nəyin və niyə olduğunu "aydın başa düşmək" üçün bunu etməyə başlamaq lazımdır, tercihen sazlayıcı ilə birlikdə.
UPD 3: "barmaqlarda" sökülür. Hələ "optimallaşdırmaq" üçün yer var. Ancaq daha az aydın olacaq.

Gəlin başlayaq.

Çünki Orijinal naxış sətir olduğu üçün müntəzəm ifadələrdən istifadə edə bilərsiniz.

Başlayanlar üçün şərhləri silə bilərsiniz ki, onlar parlamasın:

// şərhləri kəsmək üçün tpl = tpl.replace (/\(#[^]*?#\)/g, "");

İpucu: [^] hər hansı bir xarakter deməkdir, * - istənilən sayda.

İndi "təmiz" nəticəni necə təhlil edəcəyimizi düşünə bilərik.
Bloklar yuvalana bildiyi üçün hər şeyi ağac kimi saxlamağı təklif edirəm.
Ağacın hər səviyyəsində elementləri oxşar strukturu ehtiva edə bilən JS Array() olacaq.

Bu massivi yaratmaq üçün milçəkləri kotletlərdən ayırmaq lazımdır.
Bunun üçün String.split() və String.match() istifadə etdim.

Bizə də dərin lazımdır tərəfindən axtarın simli val obyekt daxilində ad obj.

Tətbiq olunan getObjDeep variantı:

var deeps = funksiya (obj, val) ( var hs = val.split("."); var len = hs.length; var dərin; var num = 0; üçün (var i = 0; i< len; i++) { var el = hs[i]; if (deep) { if (deep) { deep = deep; num++; } } else { if (obj) { deep = obj; num++; } } } if (num == len) { return deep; } else { return undefined; } };

Beləliklə, sətri hissələrə ayıraq və elementləri uyğunlaşdıraq:

// təhlil üçün regex: // əlifba-rəqəm simvolları, nöqtə, alt xətt, // iki nöqtə, slash və minus, istənilən sayda var ptn = /\(\%\s*+?\s*\%\)/g; // sətir parçaları var hissələri = tpl.split(ptn); // özlərinə uyğun gəlir var matches = tpl. match (ptn);

Uçuşları təhlil etmək üçün bizə iki massiv lazımdır.
Birində blokları saxlayacağıq, digərində kibritlər vasitəsilə dövriyyədən cari element olacaq.

// bütün bloklar var bloklar = ; // yuva var curnt = ; if(matches)( // çünki null ola bilər var len = matches.length; for (var i = 0; i)< len; i++) { // выкидываем {% и %}, и попутно делаем trim var str = matches[i].replace (/^\{\%\s*|\s*\%\}$/g, ""); if (str === "/") { // finalise block // ... } else { // make block // ... } // ...

Burada bloklar seçilmiş bloklarla yekun massivdir, cari isə cari yerləşdirmə ilə massivdir.

Döngənin hər bir addımında indi str-də nə olduğunu, blokun başlanğıcını və ya sonunu müəyyənləşdiririk.
Əgər blokun başlanğıcı, yəni. küç !== "/", sonra yeni element yaradırıq və onu massivə itələyirik.
Və həmçinin, çünki curnt üçün itələmək harada olduğumuzu başa düşməliyik.
Yol boyu xətlərin özlərini bloka daxil edirik.
Müvafiq olaraq, boş bir curnt varsa, o zaman ağacın sıfır səviyyəsindəyik.
Əgər curnt boş deyilsə, onda sonuncu cərəyan elementi yuvalanmalıdır.

// cari yuva uzunluğu var cln = curnt.length; if (cln == 0) ( // çünki bu, ən yüksək səviyyədir, onda sadəcə cari elementi onun içinə qoyun blocks.push (struct); // cari yuva yazın, o da null curnt.push (struct); ) else ( // cari iç-içə bloka daxil ediləcək curnt.nest.push (struct); // indi bu "son" elementi götürün və onu curnt var last = curnt.nest.length - 1-ə əlavə edin; curnt.push( curnt .yuva[son]); )

Müvafiq olaraq, massivin hər bir elementi ən azı:

Var struct = ( // cnt bloku üçün cari obj: deeps(obj, str), // iç içə bloklar yuvası: , // bütün iç içə bloklardan əvvəl sətir be4e: hissələr[ i + 1 ], // str -- sonra gedən sətir bu // cnt ana blokdur, biz sətri onun çərçivəsində təhlil edəcəyik af3e: ( cnt: null, str: "" ) );

Çünki bizdə elə bir vəziyyət ola bilər ki, blokdan sonra başqa bir şey var, sonra burada af3e.str və cari blokdan dərhal sonra (% / %) xətt olmalıdır. Blok tamamlanan anda bütün lazımi bağlantıları yerləşdirəcəyik ki, daha aydın olsun.
Eyni zamanda, sonuncu elementi, cari elementi çıxarırıq.

Əgər (str === "/") ( // cari elementin // əvvəlki elementi // hazırda dayandırılmış cari blokun anasıdırsa .af3e = ( cnt: (curnt [ cln - 2 ] ? curnt [ cln - 2 ].cnt: obj ), str: hissələr[ i + 1 ] );curnt.pop();

İndi biz birölçülü massiv toplaya bilərik, bu massiv öz cari obyekti ilə bütün lazımi alt sətirləri ehtiva edir.
Bunun üçün siyahıların ola biləcəyini nəzərə alsaq, yaranan blokları "analiz etmək" lazımdır.
Bir az rekursiya aparacaq, amma ümumilikdə o qədər də çətin olmayacaq.

// blokların elementar hissələrini təhlil etmək üçün sətirlər massivi var stars = [ [ hissələr, obj ] ]; parseBlocks(bloklar, ulduzlar);

parseBlocks() nümunə görünüşü

var parseBlocks = funksiya (bloklar, ulduzlar) ( var len = blocks.length; for (var i = 0; i)< len; i++) { var block = blocks [i]; // если определён текущий obj для блока if (block.cnt) { var current = block.cnt; // найдём списки switch (Object.prototype.toString.call(current)) { // если у нас массив case "": var len1 = current.length; for (var k = 0; k < len1; k++) { // кладём в stars текущий элемент массива и его строку stars.push ([ block.be4e, current[k] ]); // парсим вложенные блоки parseBlocks(block.nest, stars); } break; // если у нас объект case "": for (var k in current) { if (current.hasOwnProperty(k)) { // кладём в stars текущий элемент объекта и его строку stars.push ([ block.be4e, current[k] ]); // парсим вложенные блоки parseBlocks(block.nest, stars); } } break; // у нас не массив и не объект, просто выведем его default: stars.push ([ block.be4e, current ]); parseBlocks(block.nest, stars); } // кладём в stars то, что было после текущего блока stars.push ([ block.af3e.str, block.af3e.cnt ]); } } };

var pstr = ; var len = stars.length; üçün (var i = 0; i< len; i++) { pstr.push(parseStar (stars[i], stars[i])); } // Результат: return pstr.join ("");

parseStar() nümunə görünüşü

var parseStar = funksiya (hissə, cari) ( var str = ""; // əlavə var ptn = /\(\(\s*.+?\s*\)\)/g; var hissələri = hissəni çıxarın. split (ptn); var uyğunluqlar = hissə. uyğunluq (ptn); // sətir toplamağa başlayın str += hissələri; if (uyğunlaşır) ( var len = uyğun gəlir. uzunluq; üçün (var i = 0; i)< len; i++) { // текущий элемент со значением var match = matches [i]; // убираем лишнее и делаем trim var el = match.replace(/^\{\{\s*|\s*\}\}$/g, ""); var strel = ""; // находим элемент в текущем объекте var deep = deeps(current, el); // если нашли, то добавляем его к строке deep && (strel += deep); str += strel; } if (len >0) ( str += hissələr[ len ]; ) ) str qaytarın; )

Yuxarıdakı kod son nəticədən bir qədər kiçikdir.
Beləliklə, məsələn, cari element nöqtə kimi verilirsə, onunla nə edəcəyimi göstərmədim.
Həmçinin, mən filtr emalını təmin etməmişəm.
Bundan əlavə, son versiyada "cari element" və ya "qiymət" funksiyaları olduğu vəziyyətlərin işlənməsinə "öz başıma" əlavə etdim.

Amma məqsədim konsepsiyanın özünü göstərmək idi...

Və nəticə, məqalənin əvvəlində qeyd edildiyi kimi, tapıla bilər.
Yekun nümunə.

Ümid edirəm kiməsə faydalı olar.
Diqqətinizə görə təşəkkürlər!

Bu məqalə - front-end inkişafı üçün şablon mühərriklərinə ümumi baxış. Əgər siz JS ilə işləyirsinizsə, şablonlaşdırma mühərrikləri əla və uyğun seçimdir, çünki onlar sizə daha təmiz əsas kod yazmağa və tətbiqlərinizin işləməsini asanlaşdırmağa imkan verir. Vikipediyanın bizə təklif etdiyi ən məşhur JS şablon mühərriklərini nəzərdən keçirin. Bu şablon mühərrikləri ilə səmərəli işləmək üçün siz dili yaxşı başa düşməlisiniz və bu sahədə kifayət qədər bacarıqlara sahib olmalısınız.

ICanHaz.jsBığ şablonları ilə işləmək üçün kifayət qədər sadə və yüngül kitabxanadır. Bununla siz type=”text/html” ilə skript teqlərində şablon fraqmentlərini təyin edə və doğrulama ilə id vasitəsilə zəng edə bilərsiniz.

Mustache.jsbu tətbiq sahəsində çox məşhur şablon mühərrikidir. O, server və müştəri tərəfi həllər təqdim edir ki, birdən çox şablon mühərrikindən istifadə etməkdən narahat olmayasan. Onun yaxşı və aydın sənədləri, eləcə də böyük icması var. Şablonlarda JSON format məlumatlarından istifadə edir. Populyar proqramlaşdırma dillərində əla işləyir. Kitabxananın ən son versiyasını buradan yükləmək olarRəsmi səhifə .

Bığ üçün əlavədir və onunla tam uyğun gəlir. Lazımsız məntiqlə yüklənmədiyi üçün yüksək icra sürətinə malikdir. HTML JSON formatında verilənlərdən eyni şəkildə yaradılır. Əhəmiyyətli bir çatışmazlıq kitabxananın böyük çəkisidir.

Alt xətt.js- jQuery ilə işləmək üçün rahat və praktik vasitədir. 60-dan çox funksional kommunal var. Bu şablon mühərriki massivlər, funksiyalar, obyektlər, kolleksiyalar və s. ilə işləyərkən jQuery-nin funksionallığını artırır. jQuery UI-yə 5 alternativ.

Hogan.jsTwitter tərəfindən hazırlanmış şablon mühərriki. Veb brauzer tərəfindən sürətli dinamik emal üçün aralıq şablon qurucusu kimi istifadə olunur. Bığ bu şablon mühərrikinin inkişafı üçün əsas idi, lakin Hogan.js daha sürətlidir. Parser funksiyalarına daxil olmaq üçün API təklif olunur. Şablonların skan edilməsi və təhlili ayrı-ayrı üsullarla həyata keçirilir, bunun nəticəsində şablonlar serverdə əvvəlcədən emal oluna və müştəri tərəfində Javascript formasında istifadə oluna bilər.

- server şablonları ilə işləmək üçün istifadə olunur, lakin ümumiyyətlə başqa məqsədlər üçün tətbiq olunur. Yüksək kod oxunuşu və yaxşı təhlükəsizlik var. Müştəri hissəsindən işləyir, yardım proqramından istifadə edərək html şablonlarını komanda xəttindən tərtib etmək mümkündür. Şablon mühərrikinin adı Pug.js olaraq dəyişdirilib, lakin köhnə adla siz çoxlu sənədləşdirmə və tərtibatçı üçün faydalı məlumat tapa bilərsiniz.

şablon mühərriki ECTsürət üçün nəzərdə tutulmuşdur. O, Coffeescript şablon mühərrikinə əsaslanır. Onun Node.js ilə yaxşı uyğunluğu və kifayət qədər sadə sintaksisi var. Siz həmçinin bu kitabxananın performansını göstərən ilkin testləri görə bilərsiniz.

Şirkət Hyper Host™ Sizə JS dünyasında xoş iş arzulayır və gözəl layihələrinizi saytımızda yerləşdirməyə hazırdır!

4366 dəfə Bu gün 3 dəfə baxılıb