{"id":13527069,"url":"https://github.com/PaulGuo/Juicer","last_synced_at":"2025-04-01T09:31:02.629Z","repository":{"id":49761103,"uuid":"1959064","full_name":"PaulGuo/Juicer","owner":"PaulGuo","description":"A Lightweight JavaScript Template Engine.","archived":false,"fork":false,"pushed_at":"2018-05-10T05:52:24.000Z","size":695,"stargazers_count":914,"open_issues_count":86,"forks_count":263,"subscribers_count":71,"default_branch":"master","last_synced_at":"2024-05-22T00:12:23.647Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://juicer.name","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PaulGuo.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-06-27T07:57:59.000Z","updated_at":"2024-05-10T07:40:47.000Z","dependencies_parsed_at":"2022-08-27T06:40:34.420Z","dependency_job_id":null,"html_url":"https://github.com/PaulGuo/Juicer","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaulGuo%2FJuicer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaulGuo%2FJuicer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaulGuo%2FJuicer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaulGuo%2FJuicer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PaulGuo","download_url":"https://codeload.github.com/PaulGuo/Juicer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246615939,"owners_count":20806031,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T06:01:40.296Z","updated_at":"2025-04-01T09:31:02.295Z","avatar_url":"https://github.com/PaulGuo.png","language":"JavaScript","funding_links":[],"categories":["Uncategorized","Repository","JavaScript","18. 模板引擎 ##","18. 模板引擎","Packages"],"sub_categories":["Uncategorized","Templating","13.20 视差滚动(Parallax Scrolling) ###","13.20 视差滚动(Parallax Scrolling)","Template Engine"],"readme":"## Juicer 中文文档\n\n__当前最新版本: 0.6.14__\n\nJuicer 是一个高效、轻量的前端 (Javascript) 模板引擎，使用 Juicer 可以是你的代码实现数据和视图模型的分离(MVC)。除此之外，它还可以在 Node.js 环境中运行。\n\n你可以在遵守 MIT Licence 的前提下随意使用并分发它。Juicer 代码完全开源并托管在 [Github](https://github.com/PaulGuo/Juicer) 上，如果你在使用的过程中发现什么 Bug 抑或是一些好的建议都欢迎在 [Github Issue](https://github.com/PaulGuo/Juicer/issues) 上提交。\n\n[](!about)\n### 名字的由来\n\n倘若我们把数据比作新鲜可口的水果，把模板看做是水，Juicer 就是把水果和水榨出我们需要的HTML代码片段的榨汁机。\n\n### Juicer 的引入\n\n\t\u003cscript type=\"text/javascript\" src=\"juicer-min.js\u003e\u003c/script\u003e\n\n## * 使用方法\n\n\u0026gt; 编译模板并根据所给的数据立即渲染出结果.\n\n\tjuicer(tpl, data);\n\n\u0026gt; 仅编译模版暂不渲染，它会返回一个可重用的编译后的函数.\n\n\tvar compiled_tpl = juicer(tpl);\n\n\u0026gt; 根据给定的数据，对之前编译好的模板进行数据渲染.\n\n\tvar compiled_tpl = juicer(tpl);\n\tvar html = compiled_tpl.render(data);\n\n\u0026gt; 注册/注销自定义函数（对象），在下边 ${变量} 中会有实例.\n\n\tjuicer.register('function_name', function);\n\tjuicer.unregister('function_name');\n\n\u0026gt; 自定义模板语法边界符，下边是 Juicer 默认的边界符。你可以借此解决 Juicer 模板语法同某些后端语言模板语法冲突的情况.\n\n\tjuicer.set({\n    \t'tag::operationOpen': '{@',\n    \t'tag::operationClose': '}',\n    \t'tag::interpolateOpen': '${',\n    \t'tag::interpolateClose': '}',\n    \t'tag::noneencodeOpen': '$${',\n    \t'tag::noneencodeClose': '}',\n    \t'tag::commentOpen': '{#',\n    \t'tag::commentClose': '}'\n\t});\n\n### 默认参数配置\n\n\t{\n    \tcache:          true [false],\n    \tstrip:          true [false],\n    \terrorhandling:  true [false],\n    \tdetection:      true [false]\n\t}\n\n默认配置是 Juicer 推荐的使用方式，如果你使用过程中的确需要更改这些参数，可以这么做：\n\n#### 逐条参数更改：\n\n\tjuicer.set('strip',false);\n\tjuicer.set('cache',false);\n\n#### 批量参数更改：\n\n\tjuicer.set({\n    \t'strip': false,\n    \t'cache': false\n\t};\n\nJuicer 默认会对编译后的模板进行缓存，从而避免同一模板多次数据渲染时候重复编译所耗的时间，如无特殊需要，强烈不建议关闭默认参数中的 cache，这么做将会令 Juicer 缓存失效从而降低性能.\n\n[](!syntax)\n## * 语法\n\n#### a. ${变量}\n\n使用 `${}` 输出变量值，其中`_`为对数据源的引用（如`${_}`，常用于数据源为数组的情况）。支持自定义函数（通过自定义函数你可以实现很多有趣的功能，类似 `${data|links}` 就可以通过事先定义的自定义函数 links 直接对 data 拼装出`\u003ca href=\"..\" alt=\"..\" /\u003e` ）.\n\n\t${name}\n\t${name|function}\n\t${name|function, arg1, arg2}\n\n让我们通过一个例子演示一下自定义函数的奇妙用法吧.\n\n\tvar json = {\n\t\tlinks: [\n    \t\t{href: 'http://juicer.name', alt: 'Juicer'},\n    \t\t{href: 'http://benben.cc', alt: 'Benben'},\n    \t\t{href: 'http://ued.taobao.com', alt: 'Taobao UED'}\n\t\t]\n\t};\n\n\tvar tpl = [\n\t\t'{@each links as item}',\n\t\t\t'${item|links_build} \u003cbr /\u003e',\n\t\t'{@/each}'\n\t].join('');\n\n\tvar links = function(data) {\n\t\treturn '\u003ca href=\"' + data.href + '\" alt=\"' + data.alt + '\" /\u003e';\n\t};\n\njuicer.register('links_build', links); //注册自定义函数\njuicer(tpl, json);\n\u003c/code\u003e\u003c/pre\u003e\n\n上述代码执行后我们会发现结果是这样的：\n\n\t\u0026lt;a href=\u0026quot;http://juicer.name\u0026quot; alt=\u0026quot;Juicer\u0026quot; \u003cbr /\u003e\n\t\u0026lt;a href=\u0026quot;http://benben.cc\u0026quot; alt=\u0026quot;Benben\u0026quot; \u003cbr /\u003e\n\t\u0026lt;a href=\u0026quot;http://ued.taobao.com\u0026quot; alt=\u0026quot;Taobao UED\u0026quot; \u003cbr /\u003e\n\n可以看得出，结果被转义了，如果我们上边使用 $${item|links} 就会得到我们预期的结果，这就是下边即将提到的避免转义。\n\n__转义/避免转义__\n\n出于安全角度的考虑，`${变量}` 在输出之前会对其内容进行转义，如果你不想输出结果被转义，可以使用 `$${变量}` 来避免这种情况。例如：\n\n\tvar json = {\n\t\tvalue: '\u0026lt;strong\u0026gt;juicer\u0026lt;/strong\u0026gt;'\n\t};\n\n\tvar escape_tpl='${value}';\n\tvar unescape_tpl='$${value}';\n\n\tjuicer(escape_tpl, json); //输出 '\u0026lt;strong\u0026gt;juicer\u0026lt;/strong\u0026gt;'\n\tjuicer(unescape_tpl, json); //输出 '\u003cstrong\u003ejuicer\u003c/strong\u003e'\n\n#### b. 循环遍历 {@each} ... {@/each}\n\n如果你需要对数组进行循环遍历的操作，就可以像这样使用 `each` .\n\n\t{@each list as item}\n\t\t${item.prop}\n\t{@/each}\n\n如果遍历过程中想取得当前的索引值，也很方便.\n\n\t{@each list as item, index}\n\t\t${item.prop}\n\t\t${index} //当前索引\n\t{@/each}\n\n#### c. 判断 {@if} ... {@else if} ... {@else} ... {@/if}\n\n我们也会经常碰到对数据进行逻辑判断的时候.\n\n\t{@each list as item,index}\n\t\t{@if index===3}\n\t\t\tthe index is 3, the value is ${item.prop}\n\t\t{@else if index === 4}\n\t\t\tthe index is 4, the value is ${item.prop}\n\t\t{@else}\n\t\t\tthe index is not 3, the value is ${item.prop}\n\t\t{@/if}\n\t{@/each}\n\n#### d. 注释 {# 注释内容}\n\n为了后续代码的可维护性和可读性，我们可以在模板中增加注释.\n\n\t{# 这里是注释内容}\n\n#### e. 辅助循环 {@each i in range(m, n)}\n\n辅助循环是 Juicer 为你精心设置的一个语法糖，也许你会在某种情境下需要它.\n\n\t{@each i in range(5, 10)}\n\t\t${i}; //输出 5;6;7;8;9;\n\t{@/each}\n\n#### f. 子模板嵌套 {@include tpl, data}\n\n子模板嵌套可以让你更灵活的组织你的模板代码，除了可以引入在数据中指定的子模板外，当然你也可以通过指定字符串`#id`使用写在`script`标签中的模板代码.\n\nHTML代码：\n\n\t\u003cscript type=\"text/juicer\" id=\"subTpl\"\u003e\n\t\tI'm sub content, ${name}\n\t\u003c/script\u003e\n\nJavascript 代码：\n\n\tvar tpl = 'Hi, {@include \"#subTpl\", subData}, End.';\n\n\tjuicer(tpl, {\n\t\tsubData: {\n\t\t\tname: 'juicer'\n\t\t}\n\t});\n\n\t//输出 Hi, I'm sub content, juicer, End.\n\t//或者通过数据引入子模板，下述代码也将会有相同的渲染结果：\n\n\tvar tpl = 'Hi, {@include subTpl, subData}, End.';\n\n\tjuicer(tpl, {\n\t\tsubTpl: \"I'm sub content, ${name}\",\n\t\tsubData: {\n\t\t\tname: 'juicer'\n\t\t}\n\t});\n\n[](!node.js)\n## * 在 Node.js 环境中运行\n\n\t在命令行中执行:\n\tnpm install juicer\n\n\t在代码中这么引入:\n\tvar juicer = require('juicer');\n\tvar html = juicer(tpl, data);\n\n#### 在 Express.js 框架中使用\n\n在 Express 2.x 系列版本中：\n\n\tnpm install juicer\n\tvar juicer = require('juicer');\n\tapp.set('view engine', 'html');\n\tapp.register('.html', {\n\t\tcompile: function(str, options) {\n\t\t\treturn juicer.compile(str, options).render;\n\t\t}\n\t});\n\n在 Express 3.x 系列版本中：\n\n\tnpm install juicer\n\tvar juicer = require('juicer');\n\tvar fs = require('fs');\n\tapp.set('view engine', 'html');\n\tapp.engine('html', function(path, options, fn){\n\t\tfs.readFile(path, 'utf8', function(err, str){\n\t\t\tif (err) return fn(err);\n\t\t\tstr = juicer(str, options);\n\t\t\tfn(null, str);\n\t\t});\n\t});\n\n在 Express 4.x 系列版本中：\n\n\tvar juicerExpressAdapter = require('juicer-express-adapter');\n\tapp.set('view engine', 'html');\n\tapp.engine('html', juicerExpressAdapter);\n\n在命令行预编译模板文件：\n\n\tnpm install -g juicer\n\tjuicer example.juicer.tmpl -f example.js\n\n\t// type `juicer` after install for more help.\n\t// 全局模式安装 `juicer` 后，在命令行下输入 `juicer` 可以获得更多帮助信息。\n\n为模板引擎设置外部Cache存储：\n\n\tvar juicer = require('juicer');\n\tvar LRUCache = require('lru-native');\n\tvar cache = new LRUCache({ maxElements: 1000 });\n\n\tjuicer.set('cachestore', cache);\n\n[](!demo)\n## * 一个完整的例子\n\n\tHTML 代码:\n\n\t\u003cscript id=\"tpl\" type=\"text/template\"\u003e\n\t\t\u003cul\u003e\n\t\t\t{@each list as it,index}\n\t\t\t\t\u003cli\u003e${it.name} (index: ${index})\u003c/li\u003e\n\t\t\t{@/each}\n\t\t\t{@each blah as it}\n\t\t\t\t\u003cli\u003e\n\t\t\t\t\tnum: ${it.num} \u003cbr /\u003e\n\t\t\t\t\t{@if it.num==3}\n\t\t\t\t\t\t{@each it.inner as it2}\n\t\t\t\t\t\t\t${it2.time} \u003cbr /\u003e\n\t\t\t\t\t\t{@/each}\n\t\t\t\t\t{@/if}\n\t\t\t\t\u003c/li\u003e\n\t\t\t{@/each}\n\t\t\u003c/ul\u003e\n\t\u003c/script\u003e\n\n\tJavascript 代码:\n\n\tvar data = {\n\t\tlist: [\n\t\t\t{name:' guokai', show: true},\n\t\t\t{name:' benben', show: false},\n\t\t\t{name:' dierbaby', show: true}\n\t\t],\n\t\tblah: [\n\t\t\t{num: 1},\n\t\t\t{num: 2},\n\t\t\t{num: 3, inner:[\n\t\t\t\t{'time': '15:00'},\n\t\t\t\t{'time': '16:00'},\n\t\t\t\t{'time': '17:00'},\n\t\t\t\t{'time': '18:00'}\n\t\t\t]},\n\t\t\t{num: 4}\n\t\t]\n\t};\n\n\tvar tpl = document.getElementById('tpl').innerHTML;\n\tvar html = juicer(tpl, data);\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPaulGuo%2FJuicer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FPaulGuo%2FJuicer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPaulGuo%2FJuicer/lists"}