php система за шаблони - Правилен начин за зареждане на поведението на Javascript по подразбиране за шаблон

Ситуация:

  1. PHP система за шаблони, която отговаря за изграждането на HTML страници.
  2. Всички основни функции на Javascript са във външни файлове
  3. Всеки шаблон има някои Javascript функции по подразбиране, които трябва да бъдат извикани за всеки шаблон

Когато се изобрази страница, следващото трябва да извика набор от Javascript функции: т.е.

<script type="text/javascript">
     $(document).ready(function{
         API.loadThis();  // all these Javascript functions are in an external JS file
         API.loadThat();
         API.buildDateSelector("#idForSelector");
         // etc
    });
</script>

Досега просто добавях това като текст към всеки от HTML шаблоните. Въпреки това, в случай на страница, която се състои от множество по-малки шаблони (всеки евентуално съдържащ собствен инициализиращ Javascript), тогава имам множество битове вграден Javascript, разпръснати из цялата ми уеб страница.

Въпросът ми е:

  1. как трябва правилно да организирам всичко, така че да мога лесно да „регистрирам“ или „задействам“ някакъв Javascript по подразбиране, който да бъде извикан при зареждане на страницата?
  2. Или добавянето на всеки блок от Javascript към всеки шаблон (както по-горе) е подходящо?

person Kenny Cason    schedule 15.02.2011    source източник
comment
Освен това, ако не е ясно какво точно питам, уведомете ме и мога да добавя по-конкретна информация. Благодаря   -  person Kenny Cason    schedule 15.02.2011
comment
В нашия продукт имаме нещо подобно и го правим по този начин, като имаме {tpl_name}_js_bottom.tpl, който се зарежда, ако съществува, при рендиране на шаблона.   -  person ludesign    schedule 15.02.2011


Отговори (2)


Това, което бих направил, е доста подобно на @Chris. Все пак бих предложил няколко дребни промени:

  1. Добавете параметър към функцията addJS, който показва позицията на страницата. По подразбиране трябва да поддържате поне head и foot (head ще го постави в главата, foot ще го постави точно преди затварящото </body>).

    public function addJS($string, $position = 'head') {
        if (!is_array($this->js[$position])) {
            $this->js[$position] = array($string);
        } elseif (!in_array($string, $this->js[$position])) {
            $this->js[$position][] = $string;
        }
    }
    

    След това включете токени в шаблона, за да посочите позициите:

        {{js_head}}
    </head>
    <body>
        <!--content here-->
        {{js_foot}}
    </body>
    

    След това, когато изобразявате, просто направете нещо като:

    $js = $this->js;
    $positions = preg_replace_callback(
        '/{{js_(inline_)?([a-zA-Z0-9]+)}}/', 
        function ($match) use ($js) {
            if (isset($js[$match[2]])) {
                $js = implode("\n", $js[$match[2]]);
                if ($match[1] == 'inline') {
                    return $js;
                } else {
                    return '<script type="text/javascript">'.$js.'</script>';
            }
            return '';
        },
        $templateBody
    );
    

    Сега истинската полза е, че вашите шаблони могат чисто и тривиално да дефинират собствените си позиции за повторно използвани и често използвани битове:

    $this->addJS('return this.form.submit();', 'submit_form');
    $html = '
        <input type="text" onblur="{{js_inline_submit_form}}" />
        <button name="submit" onclick="{{js_inline_submit_form}}" />
    ';
    

    Може да бъде доста полезно, тъй като сега не дублирате JS извикванията навсякъде във вашия код. Освен това ще намали излишните разходи за опаковане на всеки изход в <script> тагове (тъй като обвива цялата позиция в таговете, а не всяка част от съдържанието)...

  2. Това ще ви позволи след това да вземете всички невградени JS и да компилирате поредица от файлове по време на изпълнение, които да изпратите на браузъра, за да се погрижите за кеширането. Той добавя предимството да можете да поддържате вашия JS близо до вашите изгледи (за поддръжка), но въпреки това да обслужвате кеширани JS и да не се налага да го изпращате отново всеки път...

    public function buildJSCache($position) {
        if (!isset($this->js[$position]) || empty($this->js[$position])) {
            return '';
        }
        $file = implode($this->js[$position]);
        $name = 'js/'.md5($file) .'.js';
        if (!file_exists($name)) {
            file_put_contents($name, $file);
        }
        return $name;
    }
    

    След това в кода на вашия шаблон просто направете:

    $replace = $this->buildJSCache('head');
    if ($replace) {        
        $replace = '<script type="text/javascript" src="'.$filename.'"></script>';
    }
    $template = str_replace('{{js_head}}', $replace, $template);
    

    Получавате двойна печалба от поддръжка и скорост за потребителя (можете дори да го минимизирате, ако желаете).

Забележка: целият този код е само демонстрация, ако трябваше да го използвате в производството, щях да го изчистя и да го обмисля малко повече...

Това са поне моите $0,02...

person ircmaxell    schedule 15.02.2011
comment
Харесва ми идеята за посочване на местоположения за вмъкване и на вграден JS. Доста интересно. Ще трябва да седна и да помисля за всичко - person Kenny Cason; 15.02.2011

Има много начини да направите това. Предлагам ви да вземете някои рамки с отворен код, да видите как правят нещата и да решите какви са предпочитанията ви. Някои техники се считат за „най-добра практика“, но голяма част от структурата на рамката се свежда до предпочитанията на разработчиците.

Имам рамка, която използвам за собствените си проекти, която е подобна на това, което описвате, всеки от по-малките шаблони се нарича "компонент". Всеки компонент може да добавя произволно количество javascript към себе си с помощта на метод addJS(), подобно на css и html. Контролер от най-високо ниво преминава през съдържанието на дадена страница (по отношение на компоненти). Това ми дава шанс да заредя предварително целия css, javascript и html. След това мога да ги изведа в произволен ред, който преценя.

So:

  • page controller handles request
    • inits one or more components
      • component load method populates html, javascript, and css class properties (arrays of file names, string for html) for itself
      • компоненти има собствен набор от шаблони, js, css
    • outputs site-wide templates
      • includes all component css within page header
    • итерира компоненти, извежда компонент html, оформление
    • извежда компонент JS за долен колонтитул на страница

Имам папка components, в нея има папки за всеки компонент. Във всяка папка на компонент има php файл (манипулатор на този компонент), по желание един или повече css/js файла. Това поддържа всичко организирано добре.

person Chris Baker    schedule 15.02.2011
comment
хубаво. това донякъде беше моето мислене. страницата има масив от функции/код за зареждане на JS и всички се отразяват, когато страницата се визуализира. Също така сте прави, като проверите много други машини за шаблони. Чувствам, че може би трябваше да направя това на по-ниско ниво, преди да публикувам :P - person Kenny Cason; 15.02.2011
comment
Забележка: Това, което преследвате, не е шаблонната машина, а рамката на приложението. Това е частта от вашия код, която използва механизма за шаблони - кодът, който решава кога да рендира нещата, какво да прави с изхода и т.н. Механизмът за шаблони се занимава само с създаване на HTML. Така че, когато пазарувате, потърсете рамките и наблюдавайте коя машина за шаблони използват. - person Chris Baker; 15.02.2011
comment
Интересно, благодаря за това. Наистина не бях мислил за това по този начин, но вместо това просто събрах всичко заедно като шаблонна машина хехе - person Kenny Cason; 15.02.2011
comment
Нито пък аз, иска ми се поне да дадат обяснение. :-/ добре, +1 от мен. Благодаря! - person Kenny Cason; 16.02.2011