澳门新葡萄京官网首页NodeJS框架Express的模板视图机制分析_javascript技巧_脚本之家

以下由我们在信易网络公司开发项目的时候终结出的一些经验
在进行页面输出渲染的时候。

模板引擎

1.render 输出父模板的内容,将渲染的内容,嵌入父模板。|
2.renderPartial 则不输出父模板的内容。只对本次渲染的局部内容,进行输出。

Express支持许多模板引擎,常用的有:

同时还有个重要的区别:

haml 的实现Haml haml.js 接替者,同时也是Express的默认模板引擎Jade
嵌入JavaScript模板EJS 基于CoffeeScript的模板引擎CoffeeKup
的NodeJS版本jQuery模板引擎 视图渲染

render 函数内部默认执行processOutput($output)函数, 会将把组件,比如
CTreeView 里面注册到 CClientScript 里面的
需要的脚本进行渲染输出。

视图的文件名默认需遵循“.”的形式,这里是要被加载的模块的名字。比如视图layout.ejs就是在告诉视图系统要require,被加载的模块必须输出exports.compile方法,并要返回一个函数来遵守Express的模板接口约定。我们也可以使用app.register()来映射模板引擎到其它文件扩展名,从而实现更灵活的模板引擎行为,如此一来就可以实现“csser.html”可以被ejs引擎所渲染。

而renderPartial()
默认不自动渲染输出客户端脚本,需要进行参数的指定,才会输出:
renderPartial($view,$data=null,$return=false,$processOutput=false)
指定processOutput 为 true 即可。

下面我们将用Jade引擎来渲染index.html,因为我们没有设置layout:false,index.jade渲染后的内容将被作为body本地变量传入layout.jade。复制代码 代码如下: app.get(‘/’, function{ res.render(‘index.jade’,
{ title: ‘CSSer, 关注Web前端技术!’ }); }); 新增的“view
engine”设置可以指定默认模板引擎,如果我们想使用jade可以这样设置: 复制代码 代码如下: app.set(‘view engine’, ‘jade’);
于是我们就可以通过下面的方式: 复制代码
代码如下:res.render; 代替如下方式:
复制代码 代码如下:res.render; 当“view
engine”设置后,模板的扩展名就成了可选项,同时我们还可以混合匹配多模板引擎:
复制代码 代码如下:res.render;
Express同时提供了视图选项设置,这些设置会在每次视图渲染后应用,比如你并不经常使用layouts,就可以这样设置:
复制代码 代码如下:app.set(‘view options’, { layout: false });
如果需要,这些设置可以在后续的res.render()调用中被覆盖: 复制代码 代码如下:res.render(‘csser-view.ejs’, { layout: true });

比如要局部输出 CTreeView ,用renderPartial
进行渲染,如果按照默认processOutput=false 则输出内容,不含有客户端脚本
输出内容则为 正常的 ul 列表。没有树形的折叠效果。 主动设定
processOutput=true 后,CTreeView
所需的,所有客户端脚本就会被正常输出在列表的前面。

可以通过指定一个路径的方式来实现用自己的layout来代替系统默认的,比如如果我们将“view
engine”设置为jade并且自定义了一个名为“./views/mylayout.jade”的layout,我们可以这样使用它:
复制代码 代码如下:res.render(‘page’, { layout: ‘mylayout’ });
否则必须指定扩展名: 复制代码
代码如下:res.render(‘page’, { layout:
‘mylayout.jade’ }); 这些路径也可以是绝对路径: 复制代码 代码如下:res.render(‘page’, { layout: __dirname +
‘///www.jb51.net/mylayout.jade’ });
这方面较好的例子就是自定义ejs模板的开始和关闭的标记: 复制代码 代码如下:app.set(‘view options’, { open: ‘{{‘, close:
‘}}’ }); 局部视图
Express视图系统原生支持局部和集合视图,这称作微型视图,主要用于渲染一个文档片段。比如与其在视图中循环显示评论,不如使用局部集合:
复制代码 代码如下:partial(‘comment’, { collection: comments });

下面介绍下要用到的几个相关的函数:

如果不需要其它选项或本地变量,我们可以省略对象而简单的传入评论数组,这和上面的示例是一样的:
复制代码 代码如下:partial;
当使用局部集合时,支持一些“魔术”本地变量:

render,renderPartial 不再介绍
processOutput()

firstInCollection 当为第一个对象时该值为true indexInCollection
集合中对象的索引值 lastInCollection 当为最后一个对象时为true
collectionLength 集合的长度

beforeRender($view))
  {
    $output=$this->renderPartial($view,$data,true);
    if(($layoutFile=$this->getLayoutFile($this->layout))!==false)
      $output=$this->renderFile($layoutFile,array('content'=>$output),true);
    $this->afterRender($view,$output);
    $output=$this->processOutput($output);
    if($return)
      return $output;
    else
      echo $output;
  }
}
publicfunction renderPartial($view,$data=null,$return=false,$processOutput=false)
{
  if(($viewFile=$this->getViewFile($view))!==false)
  {
    $output=$this->renderFile($viewFile,$data,true);
    if($processOutput)
      $output=$this->processOutput($output);
    if($return)
      return $output;
    else
      echo $output;
  }
  else
    thrownewCException(Yii::t('yii','{controller} cannot find the requested view "{view}".',
      array('{controller}'=>get_class($this),'{view}'=>$view)));
}
publicfunction processOutput($output)
{
  Yii::app()->getClientScript()->render($output);
  // if using page caching, we should delay dynamic output replacement
  if($this->_dynamicOutput!==null&& $this->isCachingStackEmpty())
  {
    $output=$this->processDynamicOutput($output);
    $this->_dynamicOutput=null;
  }
  if($this->_pageStates===null)
    $this->_pageStates=$this->loadPageStates();
  if(!empty($this->_pageStates))
    $this->savePageStates($this->_pageStates,$output);
  return $output;
}

Local variables passed take precedence, however locals passed to the
parent view are available in the child view as well. So for example if
we were to render a blog post with partial it would generate the post
local, but the view calling this function had the local user, it would
be available to the blog/post view as well.

以上在实际操作中还是比较有用的,比如你不想用大组建,可以直接将变量输到模板,也可以将多个变量组成数组输到模版里面去.

传入的本地变量优先,但传入父视图的本地变量在子视图仍有效。因此如果我们用partial来渲染博客日志时,将生成post的本地变量,但调用本函数的视图拥有本地用户,它在blog/post视图依然有效。。

性能提示:当使用局部集合渲染100长度的数组就意味着需要渲染100次视图,对于简单的集合你可以将循环内联,而不要使用局部集合,这样可以减少系统开销。

视图查找

视图查找是相对于父视图进行的,比如我们有一个名为“views/user/list.jade”的页面视图,如果在该视图中调用
partial,视图系统将会尝试查找并加载“views/user/edit.jade”,而partial将加载“views/messages.jade”。

视图系统还支持索引模板,这样你就可以使用一个同名的目录。比如,在一个路由中我们执行res.render,这将指向“views/users.jade”或者“views/users/index.jade”。

当使用上面的索引视图时,我们可以通过partial从同名目录下引用“views/users/index.jade”,同时视图系统会尝试“../users/index”,这能减少我们调用partial的需要。

发表评论

电子邮件地址不会被公开。 必填项已用*标注