Javascript简单实现模板引擎例子

一、背景

有两个大项目是从RD那边迁移过来,因为项目初期FE无人力跟进,所以都是后端同学直接用Smarty完成的前端部分;所以考虑到迁移的成本和方案,索性升级一下当前的JS模板引擎。
二、大致方案

支持extends标签

支持block标签

1、标签语法

为了便于模板词法分析,在模板左定界符后加上@来标识,标签名替换为属性设置方式,如extends标签:

<%@ extends="layout/layout.html" %>

2、extends实现方案

将整个extends标签替换成其指定的父模板的内容

3、block实现方案

首先理解block的概念:在父模板layout.html中提前挖好的坑,子模板中对block的实现,就好比萝卜,最后渲染的时候,就是一个萝卜一个坑的填充。

这样一来事情就好办多了,可将block的定义编译成js function的调用,假设父模板中block的定义是:
<%@ block="block_header" %>
最终可将其编译成:
block_header();
4、block进阶:父模板支持默认内容

smarty中的block是支持默认内容的,比如:(为了将smarty和js模板引擎区分开,下面用<&和&>分别标识smarty的定界符)
<&block name="block_header" &>
    <div class="x-header">
        ...
    </div>
<&/block&>

那么,我们可以对应的在js模板引擎中支持如下格式:

<% block="block_header" {%>
    <div class="x-header">
        ...
    </div>   
<%}%>

没错,用一个相对投机的{和}将block默认内容包围起来,编译时,将block_header编译成一个function即可,为了避免和子模板中的block实现(也是一个function)命名冲突,所以给父模板中的block name定义加上parent标识,如:
function block_header__parent_ (){
    __html += '<div class="x-header">\n';
    __html += '\t...\n';
    __html += '</div\n>';
}
这样,如果子模板中没有对该block的(function)实现,那么这里可以直接执行这个blockx__parent方法即可。最终的样子差不多是这样的:
block_header__parent_();
function block_header__parent_ (){
    __html += '<div class="x-header">\n';
    __html += '\t...\n';
    __html += '</div\n>';
}

5、block进阶:子模板有block实现,甚至设置prepend、append模式

如题,假设子模板中有对该block的实现,可以用function来解决,如:

<%function block_header(){%>
    我是header
<%}%>
那么,按照smarty的理解,应该是要用子模板中的block来覆盖父模板的block的,所以父模板block的定义处可编译为:

block_header();
function block_header__parent_ (){
    __html += '<div class="x-header">\n';
    __html += '\t...\n';
    __html += '</div\n>';
}

而对于smarty中定义的prepend模式继承block,如:

<&block name="block_header" prepend &>
    我是header
<&/block&>
我们可以这样来简单模拟:
<%function block_header(prepend){%>
    我是header
<%}%>

对,通过给block_header添加prepend参数的方式来解决。对于这种形式,父母般block的定义处可编译为:

block_header();
block_header__parent_();
function block_header__parent_ (){
    __html += '<div class="x-header">\n';
    __html += '\t...\n';
    __html += '</div\n>';
}

同理,对于append模式,我们可以把它编译成:

block_header__parent_();
block_header();
function block_header__parent_ (){
    __html += '<div class="x-header">\n';
    __html += '\t...\n';
    __html += '</div\n>';
}

6、block进阶:多级继承(layout.html ← middle.html ← child.html)

逐级prepend或者append貌似不太好整,不过可以变换下思路,采用smarty中的block嵌套形式,比如:
<&block name="block_header" &>
    我是header

    <&block name="block_header_inner" &>
        我是inner
    <&/block&>
<&/block&>

所以,在middle.html中,可以先实现block_header,再在其内部继续挖坑定义block_header_inner,比如:

<%function block_header(){%>
      我是header
     <%@ block="block_header_inner" %>
<%}%>
这样,在子模板child.html中只需要实现middle.html中的block_header_inner即可:
<%function block_header_inner(){%>
      我是子模板中的inner
<%}%>

7、如何保证子模板中不会出现父模板未定义的东西?

这个是必须得去保证的,可以这样简单处理:在extends标签被替换的地方,强制加上:
return __html;

三、实践一下

1、layout.html

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <header>
            <%@ block="block_header" %>
        </header>

        <section>
            <%@ block="block_content" {%>
                <div>
                    这里是父layout中的内容
                </div>
            <%}%>
        </section>

        <footer>
            <%@ block="block_footer" %>
        </footer>
    </body>
</html>

2、child.html

<%@ extends="layout.html" %>

<%function block_content(prepend){%>
    我是子模板中的内容
<%}%>

<%function block_footer(){%>
    我是子模板中的footer
<%}%>

我是子模板中多余的内容
3、编译后的中间文件

/*--/Users/zhaoxianlie/SourceCode/biz/trunk/demo/views/child.html--*/
exports.html = function ($_ROOT) {
    return function ($_DATA) {
        var __html = '';
        __html += '';
        __html += '<!doctype html><html> <head> ' +
            '<meta charset="UTF-8"> <title>Document</title> ' +
            '</head> <body> <header> ';

        __html += ' </header> <section> ';
        block_content();
        block_content__parent_();
        function block_content__parent_() {
            __html += ' <div> 这里是父layout中的内容 </div> ';
        }
        __html += ' </section> <footer> ';
        block_footer();
        __html += ' </footer> </body></html>';
        return __html;

        // 其实故事到这里就结束了。。。
        __html += '';
        function block_content(prepend) {
            __html += '我是子模板中的内容';
        }
        __html += '';
        function block_footer() {
            __html += '我是子模板中多余的内容';
        }
        __html += ' haha';
        return __html;
    };
};
4、运行以后

我是子模板中的内容
这里是父layout中的内容
我是子模板中的footer

差不多也就这点儿东西,就这么个原理,之后的smarty项目就好迁移了。

时间: 2024-10-26 03:00:25

Javascript简单实现模板引擎例子的相关文章

简单PHP模板引擎的实现例子

简单php教程模板引擎的实现例子 <!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equ

说说如何用JavaScript实现一个模板引擎

前言 不知不觉就很长时间没造过什么轮子了,以前一直想自己实现一个模板引擎,只是没付诸于行动,最近终于在业余时间里抽了点时间写了一下.因为我们的项目大部分用的是 swig 或者 nunjucks ,于是就想实现一个类似的模板引擎. 至于为什么要做这么一个东西?基本上每一个做前端的人都会有自己的一个框架梦,而一个成熟的前端框架,模板编译能力就是其中很重要的一环,虽然目前市面上的大部分框架 vue.angular 这些都是属于 dom base 的,而 swig nunjucks ejs这些都是属于

简单php 模板引擎

class  TEMPLATE    {                                                         private  $path = "." ;          #根目录                                                          private $var;                                       private $tplDir = &quo

PHP原生模板引擎 最简单的模板引擎_php模板

复制代码 代码如下: <?php $a = array( 'a','b','c' ); require 'template/demo.php';//引用模板 ?> 模板文件: 复制代码 代码如下: <!DOCTYPE html> <html lang="zh"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-

教你使用javascript简单写一个页面模板引擎_javascript技巧

于是我又想着能不能写一些简单的代码来完善这个模板引擎,又能与其它现有的逻辑协同工作.AbsurdJS本身主要是以NodeJS的模块的形式发布的,不过它也会发布客户端版本.考虑到这些,我就不能直接使用现有的引擎了,因为它们大部分都是在NodeJS上运行的,而不能跑在浏览器上.我需要的是一个小巧的,纯粹以Javascript编写的东西,能够直接运行在浏览器上.当我某天偶然发现John Resig的这篇博客,我惊喜地发现,这不正是我苦苦寻找的东西嘛!我稍稍做了一些修改,代码行数差不多20行左右.其中的

JavaScript模板引擎简介

国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私募机构九鼎控股打造,九鼎投资是在全国股份转让系统挂牌的公众公司,股票代码为430719,为"中国PE第一股",市值超1000亿元.    ----------------------------------------------------------------------------

常用的JavaScript模板引擎介绍

这篇文章主要介绍了常用的JavaScript模板引擎介绍,本文介绍了8款常用JavaScript 模板引擎,着重讲解了artTemplate模板引擎,需要的朋友可以参考下     最近工作内容慢慢接近我的理想化(web前端),所以关注比较多的是前端性能!后台同事介绍使用ajax模板引擎,提高渲染速度! 下面介绍几款 JavaScript 模板引擎 1. Mustache 基于javascript 实现的模板引擎,类似于 Microsoft's jQuery template plugin,但更简

常用的JavaScript模板引擎介绍_javascript技巧

最近工作内容慢慢接近我的理想化(web前端),所以关注比较多的是前端性能!后台同事介绍使用ajax模板引擎,提高渲染速度! 下面介绍几款 JavaScript 模板引擎 1. Mustache 基于javascript 实现的模板引擎,类似于 Microsoft's jQuery template plugin,但更简单易用! 2. doT.js doT.js 包含为浏览器和Node.js 准备的 JavaScript 模板引擎. 3. jSmart jSmart 是著名的 PHP 模板引擎 S

javascript轻量级模板引擎juicer使用指南_javascript技巧

使用方法 编译模板并根据数据立即渲染出结果 juicer(tpl, data); 仅编译模板暂不渲染,返回一个可重用的编译后的函数 var compiled_tpl = juicer(tpl); 根据给定的数据对之前编译好的模板进行渲染 var complied_tpl = juicer(tpl); var html = complied_tpl.render(data); 注册/注销自定义函数(对象) juicer.register('function_name', function); ju