dart - 如何在 Dart 中创建服务器端模板,我可以在其中设置不同的 for each page?</h1> <div id="body"><p>First of all, I really like Dart and keep trying to use it in real projects, but then I hit problems like this one where every other web framework has an obvious</a></h1> <div class="ml12 aside-cta flex--item print:d-none sm:ml0 sm:mb12 sm:order-first sm:as-end"> <a href="https://stackoverflow.com/questions/ask" target="_blank" class="ws-nowrap s-btn s-btn__primary">问问题</a></div> </div> <div class="d-flex fw-wrap pb8 mb16 bb bc-black-075"> <div class="flex--item ws-nowrap mr16 mb8"> <span class="fc-light mr2"></span> </div> <div class="flex--item ws-nowrap mr16 mb8" title="2022-04-17 15:46:40Z"> <span class="fc-light mr2">问问题</span> <time itemprop="dateCreated" datetime="2013-03-26T20:43:01.377">2013-03-26T20:43:01.377</time> </div> <div class="flex--item ws-nowrap mb8" title="Viewed 6 times"> <span class="fc-light mr2"></span> 1843 次 </div> </div> <div id="mainbar" role="main" aria-label="question and answers"> <div class="question" data-questionid="4" data-position-on-page="0" data-score="763" id="question"> <div class="post-layout"> <div class="votecell post-layout--left"> <div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="4"> <button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer " data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-peeufs8c"> <svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewBox="0 0 36 36"><path d="M2 25h32L18 9 2 25Z"></path></svg> </button> <div id="--stacks-s-tooltip-peeufs8c" class="s-popover s-popover__tooltip pe-none" aria-hidden="true" role="tooltip">This question shows research effort; it is useful and clear<div class="s-popover--arrow"></div></div> <div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value=""> 10 </div> <button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer " data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-04106eqn"> <svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewBox="0 0 36 36"><path d="M2 11h32L18 27 2 11Z"></path></svg> </button><div id="--stacks-s-tooltip-04106eqn" class="s-popover s-popover__tooltip pe-none" aria-hidden="true" role="tooltip">This question does not show any research effort; it is unclear or not useful<div class="s-popover--arrow"></div></div> <div id="--stacks-s-tooltip-tgvwendx" class="s-popover s-popover__tooltip pe-none" aria-hidden="true" role="tooltip">Bookmark this question.<div class="s-popover--arrow"></div></div> <a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-abwmy15k"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewBox="0 0 19 18"><path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a><div id="--stacks-s-tooltip-abwmy15k" class="s-popover s-popover__tooltip pe-none" aria-hidden="true" role="tooltip">Show activity on this post.<div class="s-popover--arrow"></div></div> </div> </div> <div class="postcell post-layout--right"> <div class="s-prose js-post-body" itemprop="text"> </div> <div class="mt24 mb12"> <div class="post-taglist d-flex gs4 gsy fd-column"> <div class="d-flex ps-relative fw-wrap"> <a href="/tags/dart" class="post-tag js-gps-track" title="show questions tagged 'dart'" rel="tag">dart</a> </div> </div> </div> </div> <span class="d-none" itemprop="commentCount">4</span> </div> </div> <div class="js-zone-container zone-container-responsive"> <div id="dfp-isb" class="everyonelovesstackoverflow everyoneloves__inline-sidebar mx-auto" style="min-height: auto; height: auto; display: none;"></div> <div class="js-report-ad-button-container mx-auto" style="width: 300px"></div> </div> <div id="answers"> <a name="tab-top"></a> <div id="answers-header"> <div class="answers-subheader d-flex ai-center mb8"> <div class="flex--item fl1"> <h2 class="mb0" data-answercount=""> 2 回答 <span style="display:none;" itemprop="answerCount">2</span> </h2> </div> </div> </div> <a name="7"></a> <div id="answer-7" class="answer js-answer accepted-answer" data-answerid="7" data-parentid="4" data-score="506" data-position-on-page="1" data-highest-scored="1" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="" itemtype="https://schema.org/Answer"> <div class="post-layout"> <div class="votecell post-layout--left"> <div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="7"> <button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer " data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-dgvag2l3"> <svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewBox="0 0 36 36"><path d="M2 25h32L18 9 2 25Z"></path></svg> </button><div id="--stacks-s-tooltip-dgvag2l3" class="s-popover s-popover__tooltip pe-none" aria-hidden="true" role="tooltip">This answer is useful<div class="s-popover--arrow"></div></div> <div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="13"> 13 </div> <button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer " data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-gn8ppsfv"> <svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewBox="0 0 36 36"><path d="M2 11h32L18 27 2 11Z"></path></svg> </button> </div> </div> <div class="answercell post-layout--right"> <div class="s-prose js-post-body" itemprop="text"> <p>试试<a href="http://pub.dartlang.org/packages/mustache" rel="nofollow">mustache ,一个</a><a href="http://mustache.github.com/mustache.5.html" rel="nofollow">mustache 模板</a>的 Dart 实现,一种广泛使用的模板语法,有多种语言的实现。</p> <p>这是一个例子:</p> <pre class="lang-dart prettyprint-override"><code>import 'package:mustache/mustache.dart'; main() { var source = '{{#names}}<div>{{lastname}}, {{firstname}}</div>{{/names}}'; var template = new Template(source); var output = template.renderString({'names': [ {'firstname': 'Greg', 'lastname': 'Lowe'}, {'firstname': 'Bob', 'lastname': 'Johnson'} ]}); print(output); } </code></pre> <p>Dart 团队目前专注于客户端开发,因此核心库中缺少许多基本的服务器端功能。但是看看<a href="http://pub.dartlang.org/" rel="nofollow">pub</a>,有许多社区维护的包可用。</p> <p>另请参阅这个类似的包:<a href="https://pub.dartlang.org/packages/mustache4dart" rel="nofollow">mustache4dart</a>。</p> </div> <div class="mt24"> <div class="user-action-time" style="color:#999;text-align:right;">于 2013-03-26T22:43:56.763 回答</div> </div> </div> </div> </div><a name="7"></a> <div id="answer-7" class="answer js-answer accepted-answer" data-answerid="7" data-parentid="4" data-score="506" data-position-on-page="1" data-highest-scored="1" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="" itemtype="https://schema.org/Answer"> <div class="post-layout"> <div class="votecell post-layout--left"> <div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="7"> <button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer " data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-dgvag2l3"> <svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewBox="0 0 36 36"><path d="M2 25h32L18 9 2 25Z"></path></svg> </button><div id="--stacks-s-tooltip-dgvag2l3" class="s-popover s-popover__tooltip pe-none" aria-hidden="true" role="tooltip">This answer is useful<div class="s-popover--arrow"></div></div> <div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="0"> 0 </div> <button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer " data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-gn8ppsfv"> <svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewBox="0 0 36 36"><path d="M2 11h32L18 27 2 11Z"></path></svg> </button> </div> </div> <div class="answercell post-layout--right"> <div class="s-prose js-post-body" itemprop="text"> <p>你可以试试<a href="https://pub.dev/packages/edart" rel="nofollow noreferrer">https://pub.dev/packages/edart</a>。<br> 嵌入式 Dart 模板引擎和编译器。将模板编译为 Dart 源代码。</p> <p>例子:</p> <p><code>products_index.html</code></p> <pre class="lang-html prettyprint-override"><code><%@ import uri="layout.html.g.dart" %> <%@ import uri="../models/product.dart" %> <%@ class extends="View" %> <%@ render params="List<Product> products, HttpRequest request" %> <p> Our cool products list </p> <ul class="w3-ul"> <% for (final product in products) { %> <li><%= product.name %>&nbsp;<%= product.price %></li><% } %> </ul> <% final layout = layout_html(); layout.title = 'Products'; layout.addTag(HtmlTag('meta', {'description': 'MegaSuperShop cool price list'})); layout.addBreadcrumb('Products', request.requestedUri.toString()); layout.render(out, request); %> </code></pre> <p>该模板将被编译成以下源代码:</p> <p><code>products_index.html.g.dart</code></p> <pre class="lang-dart prettyprint-override"><code>// ignore: unused_import import 'dart:convert'; import 'layout.html.g.dart'; import '../models/product.dart'; class products_index_html extends View { String render(List<Product> products, HttpRequest request) { final out = StringBuffer(); out.write('<p>\n'); out.write(' Our cool products list\n'); out.write('</p>\n'); out.write('<ul class="w3-ul">\n'); for (final product in products) { out.write(' <li>'); out.write(htmlEscape.convert('${product.name}')); out.write('&nbsp;'); out.write(htmlEscape.convert('${product.price}')); out.write('</li>'); } out.write('</ul>\n'); final layout = layout_html(); layout.title = 'Products'; layout.addTag( HtmlTag('meta', {'description': 'MegaSuperShop cool price list'})); layout.addBreadcrumb('Products', request.requestedUri.toString()); layout.render(out, request); return out.toString(); } } </code></pre> <p>布局模板也很简单易懂。</p> <p><code>layout.html</code></p> <pre class="lang-html prettyprint-override"><code><%@ import uri="../html/layout.dart" %> <%@ import uri="breadcrumbs.html.g.dart" %> <%@ import uri="footer.html.g.dart" %> <%@ import uri="header.html.g.dart" %> <%@ import uri="nav.html.g.dart" %> <%@ export uri="../html/breadcrumb.dart" %> <%@ export uri="../html/html_utils.dart" %> <%@ export uri="../html/view.dart" %> <%@ class extends="Layout" %> <%@ render params="StringBuffer body, HttpRequest request, {int statusCode = 400}" %> <html> <head> <title><%= title %></title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> <% for (final tag in tags) { %> <%== tag %> <% } %> </head> <body> <%== header_html().render(title) %> <%== nav_html().render(request) %> <div class="w3-container"> <%== breadcrumbs_html().render(breadcrumbs) %> </div> <div class="w3-container"> <%== body %> </div> <%== footer_html().render() %> </body> </html> <% body.clear(); body.write(out); final response = request.response; response.headers.add('Content-Type', 'text/html; charset=utf-8'); response.statusCode = statusCode; response.write(out); %> </code></pre> <p>最后是 class 的源代码<code>Layout</code>。<br> 它可以是任何东西,也可能根本不是(这不是很方便)。</p> <pre class="lang-dart prettyprint-override"><code>import 'breadcrumb.dart'; import 'html_utils.dart'; export 'dart:io'; export '../site/site_links.dart'; export 'html_utils.dart'; class Layout { final breadcrumbs = <Breadcrumb>[]; final tags = <HtmlTag>[]; String title = ''; void addBreadcrumb(String text, String url) { final item = Breadcrumb(text: text, url: url); breadcrumbs.add(item); } HtmlTag addTag(HtmlTag tag) { tags.add(tag); return tag; } } </code></pre> </div> <div class="mt24"> <div class="user-action-time" style="color:#999;text-align:right;">于 2020-10-18T15:44:25.957 回答</div> </div> </div> </div> </div></div> </div> <div id="sidebar" class="show-votes" role="complementary" aria-label="sidebar"> <div class="module sidebar-related"> <h4 id="h-related">Related</h4> <div class="related js-gps-related-questions" data-tracker="rq=1"> <div class="spacer"> <a href="/questions/11720268" title="Question score (upvotes - downvotes)"> <div class="answer-votes large">2</div> </a> <a href="/questions/11720268" class="question-hyperlink">android - 更改 Android Activity 的标签?</a> </div><div class="spacer"> <a href="/questions/11720269" title="Question score (upvotes - downvotes)"> <div class="answer-votes large">2</div> </a> <a href="/questions/11720269" class="question-hyperlink">jquery - 在这些演示中,我如何利用外部导航来创建任何内容滑块来创建上一个下一个外部控件</a> </div><div class="spacer"> <a href="/questions/11720270" title="Question score (upvotes - downvotes)"> <div class="answer-votes large">3</div> </a> <a href="/questions/11720270" class="question-hyperlink">ruby-on-rails - 如何更改 Rails 中的邮件内容传输编码设置?</a> </div><div class="spacer"> <a href="/questions/11720271" title="Question score (upvotes - downvotes)"> <div class="answer-votes large">5</div> </a> <a href="/questions/11720271" class="question-hyperlink">android - 当用户触发活动开始(按下按钮)时显示 ProgressDialog</a> </div><div class="spacer"> <a href="/questions/11720274" title="Question score (upvotes - downvotes)"> <div class="answer-votes large">0</div> </a> <a href="/questions/11720274" class="question-hyperlink">.net - 改进 FrameworkElementAdapters.ViewToContractAdapter</a> </div><div class="spacer"> <a href="/questions/11720275" title="Question score (upvotes - downvotes)"> <div class="answer-votes large">5</div> </a> <a href="/questions/11720275" class="question-hyperlink">php - 选中 HTML 复选框</a> </div><div class="spacer"> <a href="/questions/11720278" title="Question score (upvotes - downvotes)"> <div class="answer-votes large">3</div> </a> <a href="/questions/11720278" class="question-hyperlink">python - 如何将列表列表中的字符串转换为元组?</a> </div><div class="spacer"> <a href="/questions/11720280" title="Question score (upvotes - downvotes)"> <div class="answer-votes large">1</div> </a> <a href="/questions/11720280" class="question-hyperlink">wpf - 使用事件触发器的按钮控制动画</a> </div><div class="spacer"> <a href="/questions/11720285" title="Question score (upvotes - downvotes)"> <div class="answer-votes large">1</div> </a> <a href="/questions/11720285" class="question-hyperlink">php - 正则表达式中的前瞻、后视条件</a> </div><div class="spacer"> <a href="/questions/11720288" title="Question score (upvotes - downvotes)"> <div class="answer-votes large">7</div> </a> <a href="/questions/11720288" class="question-hyperlink">java - 接口是类吗?</a> </div> </div> </div> <div class="module js-gps-related-tags" id="related-tags"> <h4 id="h-related-tags">Reference</h4> <div data-name="javascript"> <a href="https://php.github.net.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">php</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">1429865</span> </span> </div> <div data-name="javascript"> <a href="https://c-cpp.com" class="post-tag no-tag-menu js-gps-track" target="_blank">c/c++</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">756500</span> </span> </div> <div data-name="javascript"> <a href="https://nginx.github.net.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">nginx</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">49975</span> </span> </div> <div data-name="javascript"> <a href="https://mongodb.net.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">mongodb</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">159057</span> </span> </div> <div data-name="javascript"> <a href="https://mybatis.net.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">mybatis</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">3233</span> </span> </div> <div data-name="javascript"> <a href="https://anaconda.org.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">anaconda</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">13410</span> </span> </div> <div data-name="javascript"> <a href="https://pycharm.net.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">pycharm</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">14671</span> </span> </div> <div data-name="javascript"> <a href="https://python.github.net.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">python</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">1902243</span> </span> </div> <div data-name="javascript"> <a href="https://vscode.github.net.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">vscode</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">56040</span> </span> </div> <div data-name="javascript"> <a href="https://dockerdocs.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">docker</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">110988</span> </span> </div> <div data-name="javascript"> <a href="https://github.net.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">github</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">49000</span> </span> </div> <div data-name="javascript"> <a href="https://flask.github.net.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">flask</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">49129</span> </span> </div> <div data-name="javascript"> <a href="https://ffmpeg.github.net.cn" class="post-tag no-tag-menu js-gps-track" target="_blank">ffmpeg</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">24037</span> </span> </div> <div data-name="javascript"> <a href="https://jmeter.net" class="post-tag no-tag-menu js-gps-track" target="_blank">jmeter</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">16910</span> </span> </div> <div data-name="javascript"> <a href="https://matplotlib.net" class="post-tag no-tag-menu js-gps-track" target="_blank">matplotlib</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">63493</span> </span> </div> <div data-name="javascript"> <a href="https://getbootstrap.net" class="post-tag no-tag-menu js-gps-track" target="_blank">bootstrap</a> <span class="item-multiplier"><span class="item-multiplier-x">×</span> <span class="item-multiplier-count">54641</span> </span> </div> </div> </div> </div> </div> </div> </div> <footer id="footer" class="site-footer js-footer" role="contentinfo"> <div class="site-footer--container"> <div class="site-footer--logo"> <a href="https://stackoverflow.com"><svg aria-hidden="true" class="native svg-icon iconLogoGlyphMd" width="32" height="37" viewBox="0 0 32 37"><path d="M26 33v-9h4v13H0V24h4v9h22Z" fill="#BCBBBB"/><path d="m21.5 0-2.7 2 9.9 13.3 2.7-2L21.5 0ZM26 18.4 13.3 7.8l2.1-2.5 12.7 10.6-2.1 2.5ZM9.1 15.2l15 7 1.4-3-15-7-1.4 3Zm14 10.79.68-2.95-16.1-3.35L7 23l16.1 2.99ZM23 30H7v-3h16v3Z" fill="#F48024"/></svg></a> </div> <nav class="site-footer--nav"> <div class="site-footer--col"> <h5 class="-title"><a href="https://stackoverflow.org.cn" class="js-gps-track" data-gps-track="footer.click({ location: 3, link: 15})">Stack Overflow 中文网</a></h5> <p>遵从 CC BY-SA 知识共享许可协议。</p> </div> </nav> </div> </footer> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?709ff2ad9744e86b5b0eee677fc13ede"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> <!-- Google tag (gtag.js) --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-1MW5BV8G8E"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-1MW5BV8G8E'); </script> <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6117966252207595" crossorigin="anonymous"></script> </body> </html>