Встроенный Javascript с обезжиренными макетами

Я работаю с PHP Fat Free и пытаюсь создать систему макета/подмакета, которая в конечном итоге будет в некоторой степени имитировать MVC. У меня есть основной макет с заполнителями (по сути, серверная часть устанавливает разные вложенные макеты или частичные пути к файлам, а затем представление позаботится о вызове рендеринга этого имени файла. Все это прекрасно работает.

Проблема, с которой я сталкиваюсь, заключается в том, что мне нужен встроенный javascript в моем подмакете для запуска после скриптов в основном макете (например, после строки включения jquery). В предыдущем фреймворке, который я использовал, я мог выполнить буферизацию вывода ob_start и ob_get_clean, чтобы получить скрипт в подмакете, а затем передать его в макет для отображения под строкой скрипта. Я надеюсь, что это имеет смысл, но если нет, вот текущий код, с которым я работаю в F3.

Маршрут:

$f3->route('GET /test',
    function($f3) {
        // set the sublayout name
        $f3->set('sublayout', 'testpage.php');

        // render the whole shebang
        echo View::instance()->render('testlayout.php');
    }
);

Расположение:

<!DOCTYPE html>
<html>
<head>
    <title>Test Layout</title>
</head>
<body>
  <h1>Test Layout</h1>
  <?php echo View::instance()->render($sublayout) ?>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" />
  <!-- inline script should go here -->
</body>
</html>

Подмакет:

<h2>My Test Page</h2>
<div id='message'></div>

<script>
    // This code needs to be placed AFTER the jquery include in the main layout
    $(function(){
        $('#message').html('This is my message');
    });
</script>

Я попытался расширить представление, включив в него функции «beginRegion» и endRegion, которые в основном обрабатывали часть ob_start и ob_get_clean, чтобы можно было подобрать мой встроенный скрипт, но как только я оказался в подмакете, я не смог понять, как передайте этот буферизованный код обратно в макет, чтобы его можно было повторить после включения jquery.

Прежде чем вы скажете мне, что я не должен использовать встроенный скрипт, я знаю это, и большинство вещей, которые я делаю, находятся во внешних файлах скриптов, для которых у меня есть решение, но бывают случаи, когда мне нужно это встроено, и именно здесь я застрял .

Есть ли способ справиться с тем, что я пытаюсь сделать с буферизацией вывода, или, что еще лучше, есть ли лучший способ решить эту проблему, чем подход к буферизации вывода?

Обновление. Согласно рекомендациям, вы должны размещать скрипт внизу страницы прямо перед закрывающим тегом body. Если я помещу сценарий над вложенным макетом, это нарушит оба наших передовых метода FE и будет иметь тот недостаток, что остальная часть страницы будет заблокирована во время загрузки сценария. Вот почему я хотел бы, чтобы он был структурирован так, как я отметил, вместо того, чтобы размещать jquery include ВЫШЕ подмакета.


person tjans    schedule 02.06.2015    source источник


Ответы (3)


Я не понимаю, в чем проблема. Ваш макет:

<!DOCTYPE html>
<html>
<head>
    <title>Test Layout</title>
</head>
<body>
  <h1>Test Layout</h1>
  <?php echo View::instance()->render($sublayout) ?>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" />
  <!-- inline script should go here -->
</body>
</html>

Вы хотите включить подмакет после использования jquery. Так почему бы не написать так? :

<!DOCTYPE html>
<html>
<head>
    <title>Test Layout</title>
</head>
<body>
  <h1>Test Layout</h1>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" />
  <!-- inline script should go here -->
  <?php echo View::instance()->render($sublayout) ?>
</body>
</html>

Также вы можете написать пользовательскую функцию. Допустим, у вас есть папка с частичными файлами или что-то еще более структурированное, и вы хотите ее использовать:

$f3->set('partial',
    function($file) {
        $file .= (strpos($file, '.php')>0)? '' : '.php';
        if(!is_file($file)) return '';
        return View::instance()->render($file);
    }
);

а затем используйте его как:

<!DOCTYPE html>
<html>
<head>
    <title>Test Layout</title>
</head>
<body>
  <h1>Test Layout</h1>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" />
  <!-- inline script should go here -->
  {{ @partial('partials/testpage') }}
</body>
</html>
person num8er    schedule 02.06.2015
comment
Спасибо за ответ. Я должен уточнить и ответить на ваш вопрос о Так почему бы не написать это так? В соответствии с передовой практикой сценарий следует размещать внизу страницы прямо перед закрывающим тегом body. Если я помещу сценарий над вложенным макетом, это нарушит оба наших передовых метода FE и будет иметь тот недостаток, что остальная часть страницы будет заблокирована во время загрузки сценария. Я добавлю это в исходный пост, чтобы прояснить этот момент, и спасибо за частичный пример. Я буду использовать это в будущем, я уверен. Хотя мне придется адаптировать его, так как я не использую шаблоны F3. - person tjans; 02.06.2015

Я знал, почему Ты хочешь это сделать. Но в чем проблема разделить скрипты в файле scripts.php и HTML, часть php в другом файле и отображать их по мере необходимости? (:

person num8er    schedule 02.06.2015
comment
Да, это вариант, и я рассматривал его раньше. В конце концов, это может быть способ справиться с этим, хотя я пытался сохранить встроенный код рядом с соответствующей разметкой, которой он манипулировал, вместо того, чтобы переходить к внешнему файлу для его просмотра. В противном случае с предлагаемым вами решением я мог бы просто добавить его во внешний файл .js и включить его таким образом (как я уже упоминал, у меня есть решение для извлечения файлов js, а не встроенных). - person tjans; 02.06.2015
comment
Также я всегда храню в отдельных файлах код макета и js-файлы, а в конце минимизирую всю js-часть и включаю как один js-файл внизу. - person num8er; 02.06.2015
comment
Согласен, в 99% случаев я тоже так делаю. Иногда я включаю встроенный JS, если мне нужно, чтобы javascript был динамическим, например, при передаче идентификатора базы данных из PHP в скрипт. - person tjans; 02.06.2015

Из обсуждения в группах Google кто-то предложил решение JS, которое может работать:

внутри вашего макета:

<head>
  <script>
  var callbacks=[];
  </script>
</head>
<body>
  <script src="...jquery.min.js"/>
  <script>
    $.each(callbacks,function(i,func){func.call(null,jQuery);}) //<< triggers all queued callbacks
  </script>
</body>

внутри вашего подмакета:

<h2>My Test Page</h2>
<div id="message"></div>
<script>
  callbacks.push(function($){
    //do something with jQuery
  });
</script>

Вот ссылка: https://groups.google.com/forum/#!topic/f3-framework/iGcDuDueN8c

person tjans    schedule 02.06.2015
comment
Это обсуждение gg также предлагает метод, использующий буферизацию вывода вместе с решением javascript. Я собираюсь отметить это как ответ, потому что он напрямую касается всех пунктов исходной проблемы с двумя жизнеспособными решениями. Также спасибо @num8er за помощь. - person tjans; 02.06.2015