HTML 模板分为页面模板控件模板,它们都匹配绑定一个同名的 js / ts 文件,区别在于页面模板扩展名为 .page.html 并且最终将生成模板展开后的 .html 文件。
HTML 模板在浏览器端依赖于配套的基础脚本类库,所以需要在页面模板中引用引导脚本。
绑定了服务端 .cs 的页面模板引用 /Js/loadPage.js,否则引用 /Js/load.jsPage 可以通过 Include 参数来处理。

参考示例 AutoCSer\Example\WebView\Include\Header.html

. 模板标签,为了保持 HTML 的“干净”,模板标签采用 HTML 注释格式,以冒号(:)分割标签名称与标签参数,没有标签参数的情况下也不需要冒号(:),比如 <!--标签名称:标签参数--> 或者 <!--标签名称-->
某些模板标签需要成对出现用于标识作用域的开始与结束,开始与结束标签不允许跨 HTML tag 层级,否则可能造成模板渲染错乱。
为了简化模板规则,AutoCSer 的 WEB 视图只支持几个必要的模板标签,比如 Include / Value / Loop / If / Client / NoMark

数据值表达式由服务端表达式与客户端表达式组合而成,当两个表达式不相同时,中间用(#)连接起来。
服务端表达式用于引用服务端数据的相关字段与属性,除了连接符(.),只支持 数字 / 字母 / 下划线(_)。
客户端表达式用于引用客户端数据的相关属性与无参函数,除了连接符(.),只支持 数字 / 字母 / 下划线(_)。
如果表达式为空字符串(字符串长度为 0),则表示当前数据作用域上的数据对象。
第一个名称前面的小数点(.)表示跳过当前数据作用域向外回溯,几个点就表示回溯几层,最后回溯到最外层的数据作用域的根对象。
当多个数据作用域中的数据对象存在相同的属性名称,而当前需要引用的数据作用域不符合最近原则,则可以使用小数点(.)跳过这些数据作用域对象。

参考示例 AutoCSer\Example\WebView\Template\Expression.page.html
参考示例 AutoCSer\Example\WebView\Template\Expression.cs

. Include 表示引用某个控件模板,标签参数是相对于项目路径的绝对路径文件名(忽略扩展名 .html),支持静态字符串数组传参,在模板中使用 =@At[索引编号] 替换为数组数据。

参考示例 AutoCSer\Example\WebView\Template\Include.page.html
参考示例 AutoCSer\Example\WebView\Include\AjaxReturnSkin.html
数组传参定义 参考示例 AutoCSer\Example\WebView\Include\Header.html

单纯的 .js 也支持 Include 引用,但不支持传参,且必须写在文件开始位置,同一个页面多次引用同一个 .js 在展开时会自动去重。
参考示例中的引用仅作为示例存在,因为页面已经引用了控件模板 Include\AjaxReturnSkin,会自动绑定引用它的脚本。
参考示例 AutoCSer\Example\WebView\Template\Include.page.ts

.css 也支持 Include 引用,但不支持传参,多个引用之间用 , 分隔。
参考示例 AutoCSer\Example\WebView\Template\IncludeCss.page.css

. Value 表示使用某个数据建立一个数据作用域,标签参数是一个数据值表达式,标签必须成对
模板引擎在搜索数据时优先搜索最近的数据作用域,当数据查找失败时将回溯到最近的上一个数据作用域,直到根对象建立最外层的数据作用域(对于页面模板而言就是页面绑定的 class)。

参考示例 AutoCSer\Example\WebView\Template\Value.page.html
参考示例 AutoCSer\Example\WebView\Template\Value.cs

. Loop 表示循环使用某个数组对象的子元素数据建立数据作用域(用于列表操作),标签参数是一个数据值表达式,标签必须成对

参考示例 AutoCSer\Example\WebView\Template\Loop.page.html
参考示例 AutoCSer\Example\WebView\Template\Loop.cs

. If 表示如果某个数据对象符合 JavaScript 的 if 判定则继续输出 HTML,标签参数是一个逻辑值表达式,标签必须成对
对于 JavaScript 的 if 判定,数据对象为 null 返回 false,数字为 0 返回 false,对于长度为 0 的字符串返回 false。
逻辑值表达式用于If标签参数,允许使用 & 或者 | 拼接若干子逻辑值表达式,不允许在同一个表达式中混合使用 &|
可选的感叹号 ! 前缀用于取反操作,比如 If:! 等价于 Not:
子逻辑值表达式 可选后缀 =字符串 用于判断数据值表达式转换成字符串以后是否等于指定的字符串。

参考示例 AutoCSer\Example\WebView\Template\If.page.html
参考示例 AutoCSer\Example\WebView\Template\If.cs

. Client 没有标签参数,表示该段 HTML 模板仅对客户端有效(客户端模板引擎忽略这个标签),标签必须成对
服务端模板引擎在输出 HTML 或者 JSON 的时候跳过这个标签不输出(可用于 SEO 过滤输出)。

参考示例 AutoCSer\Example\WebView\Template\Client.page.html
参考示例 AutoCSer\Example\WebView\Template\Client.cs

. NoMark 没有标签参数,表示客户端模板引擎在解析该段 HTML 模板时禁止输出范围标识,服务端模板引擎则忽略这个标签,标签必须成对
正常情况下,AutoCSer 的客户端模板引擎在输出 HTML 的时候会附加输出一些成对的隐藏的 span 用来标识某个子模版在 document 中的开始与结束位置,用于在数据更新时快速定位需要更新的 document 节点。
但是某些情况可能需要生成“干净”的 HTML(比如 textarea),又或者可能想减少生成的 HTML 的 document 节点数量以减轻浏览器的压力,这时候就可以使用 NoMark 标签将这段 HTML 模板包起来。
需要知道的是,使用了 NoMark 以后,里面包含的任何数据的更新都需要处理整个被 NoMark 包起来的 HTML 模板重新生成 HTML 代码。

参考示例 AutoCSer\Example\WebView\Template\NoMark.page.html
参考示例 AutoCSer\Example\WebView\Template\NoMark.cs

=@At,作为数据值表达式的前缀使用,用于将数据转换成字符串输出。
=@At* 作为数据值表达式的前缀使用,先将数据转换成字符串,然后调用 .ToTextArea() 输出。

String.prototype.ToTextArea = function () {
    return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
};

=@At@ 作为数据值表达式的前缀使用,先将数据转换成字符串,然后调用 .ToHTML() 输出。
String.prototype.ToHTML = function () {
    return this.ToTextArea().replace(/ /g, '&nbsp;').replace(/"/g, '&#34;').replace(/'/g, '&#39;');
};