【问题标题】:php templating system - Proper way to load default Javascript behavior for a templatephp 模板系统 - 为模板加载默认 Javascript 行为的正确方法
【发布时间】:2011-02-15 19:50:03
【问题描述】:

情况:

  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 块附加到每个模板(如上)是否合适?

【问题讨论】:

  • 另外,如果不清楚我在问什么,请告诉我,我可以添加更多具体信息。谢谢
  • 在我们的产品中,我们有类似的东西,我们这样做,在渲染模板时加载 {tpl_name}_js_bottom.tpl (如果存在)。

标签: php javascript template-engine


【解决方案1】:

我会做的与@Chris 非常相似。不过,我建议进行一些小改动:

  1. addJS 函数中添加一个参数,指示页面上的位置。默认情况下,您至少应该支持headfoothead 将它放在头部,foot 将它放在关闭&lt;/body&gt; 之前)。

    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 调用。另外,它将减少将每个输出包装在 &lt;script&gt; 标签中的开销(因为它包装了标签中的整个位置,而不是每条内容)...

  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 美元……

【讨论】:

  • 我也喜欢指定位置以插入内联 JS 的想法。非常有趣。我得坐下来好好想想
【解决方案2】:

有很多方法可以做到这一点。我建议你获取一些开源框架,看看它们是如何做事的,然后决定你的偏好。一些技术被认为是“最佳实践”,但很多框架结构归结为开发人员的偏好。

我有一个用于我自己的项目的框架,与您描述的类似,每个较小的模板都称为“组件”。每个组件都可以使用 addJS() 方法向自己添加任意数量的 javascript,css 和 html 也是如此。顶级控制器循环遍历给定页面的内容(就组件而言)。这让我有机会提前加载所有的 css、javascript 和 html。然后,我可以按我认为合适的任何顺序输出它们。

所以:

  • 页面控制器处理请求
    • 初始化一个或多个组件
      • 组件load 方法填充html、javascript 和css 类属性(文件名数组、html 字符串) 为自己
      • 组件有自己的一套模板、js、css
    • 输出站点范围的模板
      • 在页眉中包含所有组件 css
    • 遍历组件,输出组件 html,布局内容
    • 为页脚输出组件 JS

我有一个components 文件夹,其中包含每个组件的文件夹。每个组件文件夹中都有一个 php 文件(该组件的处理程序),可以选择一个或多个 css/js 文件。这样可以让一切井井有条。

【讨论】:

  • 不错。这一直是我的想法。该页面有一组 JS onload 函数/代码,并且在呈现页面时全部回显。您也正确地检查了许多其他模板引擎。我觉得也许我应该在发布之前在较低级别完成此操作:P
  • 注意:您所追求的不是模板引擎,而是应用程序框架。这是代码中使用模板引擎的部分 - 决定何时渲染、如何处理输出等的代码。模板引擎只关心制作 HTML。因此,当您购物时,请查找框架并观察它们使用的模板引擎。
  • 有趣,谢谢。我并没有真正这样想过,但我只是把所有东西放在一起作为一个“模板引擎”呵呵
  • 我也不是,我希望他们至少能提供一个解释。 :-/好吧,我+1。谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-11-23
  • 2013-06-19
  • 1970-01-01
  • 2013-10-01
  • 1970-01-01
  • 2017-04-15
  • 2019-03-14
  • 2017-04-20
相关资源
最近更新 更多