WebApp
概述
VDN 提供了对 Web Application 的支持,通过前端 H5+后台 PB实现的 Web 应用,区别于手机 App,适合应用于微信公众平台、手机端浏览器使用。
VDN 集成了功能强大的页面解析模块,动态解析 HTML 页面,实现了 HTML 标签的属性、事件的控制、登录验证等,结合 Ajax 技术可以开发出灵活的 Web 应用.
使用本功能需要了解一些 HTML 的知识。
以下文档看似复杂,但实际上很多内容都是相似的,比如一些相似功能的函数,可以先简单的浏览帮助,大概了解工作原理,结合实战,逐步熟悉。
演示环境的搭建及示例详解请见:Example\\Web 功能\\WebApp 示例.docx
页面指令
通过页面指令可以设置页面功能属性,告知分析器如何解析构建该页面。
位置
页面指令是以<!VDNDOC...>括起来,位于页面代码的第一行
格式
"属性名":属性值,多个属性之间逗号分隔。
属性值:为字符串型(string)时两边为双引号,布尔型(boolean)时直接为 true/false
示例:
<!VDNDOC "PageBase":"nvo\_obj","IniEvent":"pageini","NotValidLogin":true,"ResetSession":true>属性说明
页面指令包含下列属性,当不指明时分析器取默认值
V2020.1.1.1 版本后取消 ServerValueList 指令
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| PageBase | string | 空 | 页面对应的 PB 对象名称 例如:nvo_login 指定了 PageBase 后,调用函数格式会更简化,就可以直接调用该对象的函数/事件,系统会在后台建立一个 PB 对象与该页面相关联 例如上面的示例:"IniEvent":"pageini",则代表页面初始化会触发:nvo_obj 的 pageini 事件 |
| IniEvent | string | 空 | 页面加载时触发的 PB 对象的事件,进行初始化操作。 例如: f_ini(指定了 PageBase) or nvo_bill.f_ini |
| NotParse | boolean | false | 不需要 VDN 分析器进行解析,直接输出原始页面 |
| NotServerCache | boolean | false | VDN 分析器是否缓存该页面 页面被缓存后,如果手动修改磁盘中的页面文件,前台不会立即反应出来。只有当 发布 WebAPP或者点击【刷新配置】才会重新加载。 |
| ClientCache | boolean | false | 页面在客户端浏览器是否缓存该页面,允许回退操作 |
| ResetSession | boolean | false | 加载该页面是否重置 Session 站点的默认页该属性自动为 true |
| DisabledSession | boolean | false | 该页面禁用 Session |
| NotValidLogin | boolean | false | 页面加载是是否自动验证 Session 中的登录标志,如果没有登录标志则跳转到首页 无页面指令时默认为 true |
| NeedToken | boolean | false | 访问页面时是否需要令牌 |
| IsSubPage | boolean | false | 用于子页面输出 |
应用举例
<!VDNDOC "PageBase":"nvo\_login","IniEvent":"PageIni","NotValidLogin":true,"ResetSession",true>
<html>
.......
</html>解释:
- "PageBase":"nvo_login" 后台对应 nvo_login 组件
- "IniEvent":"PageIni" 页面第一次加载时触发 nvo_login.PageIni 事件进行初始化
- "NotValidLogin":true 该页面不验证是否登录
- "ResetSession":true 打开该页面后清空 Session 存储的值
事件设置
提交方式
首先了解一下页面的提交,分为两种方式
- form 提交
通过 submit form 来提交表单,是 HTML 最传统的提交方式,通过提交按钮或者组件触发提交,页面会刷新
当以下按钮位于 form 中是点击会执行 form 提交:
<input type="submit" name="..."/>
<button name="..."></button>
<button type="submit" name="...">...</button>
<button type="button AutoPost="true" name="...">...</button>以下按钮不会执行 form 提交,除非指定了 AutoPost="true"或者修改 run.config 里 TButtonSubmit=Y:
<input type="button" name="..."/>
<button type="button name="...">...</button>- ajax 提交
使用 ajax 方式将表单信息按照一定的格式组织为数据返回给后台,页面不会刷新新。
以上两种方式并无完全的优劣,适用于不同的情况。
事件设置的值只有在【form 提交】的情况下用到,这里的【事件】就是指定页面的按钮或者组件触发后对应后台 PB 组件的事件或者函数,
当存在一个或者多个按钮或输入组件,在 PB 端区分是哪个按钮或者组件触发的,然后分别进行处理。
相关属性
//默认触发 PB 组件的 commonEvent 事件
<input type="submit" name="b\_submit" value="确认预约" /> //默认触发 PB 组件的 submit 事件
<input type="submit" name="b_submit" value="确认预约" **ServerEvent="submit" ** />
//选择框值改变时将触发 PB 组件的 commonEvent 事件
<select name="d_store" id="d_store" **AutoPost="true" **\>
......
</select>| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| AutoPost | string | 当 AutoPost 等于 true 时,组件点击或值改变时将提交页面并触发 PageBase 指定的 PB 组件的 CommonEvent 事件。 所有的按钮(submit、button、imagebutton)默认为 True,其他组件需要手动设置。 不过不希望一个 button 自动触发服务器端事件则可设置 AutoPost="false" | |
| ServerEvent | string | 空 | 如果不想默认触发 CommonEvent 事件,则可以通过 ServerEvent 属性指定事件的名称。 ServerEvent 不要和 AutoPost 同时使用 例:ServerEvent="submit_1" 则将触发 PageBase 指定的 PB 组件的 submit_1 事件 |
| ServerArgs | string | 空 | 通过设置 ServerArgs 给函数指定额外的参数,多个参数用/分割 例如:ServerArgs="a1/a2" 注:一般不需要额外指定参数,因为触发后台事件时整个页面的组件的值都可以通过后台函数获取 |
<button type="button>...</button>
//及
<input type="button"/>注意
只要标注 type="button"的组件,在 V2018.3.1.1 版本之后不在自动执行提交操作,除非设置了 AutoPost="true"**
CommonEvent 事件
当 AutoPost="true"时,默认触发 PB 组件的 CommonEvent 事件,可以通过继承 nvo_pagebase 组件来获的该事件,也可以自己添加该事件
event CommonEvent(string sender,string args) return(none)\*\*sender:触发该事件的前端组件的 Name 或者 ID
args:如果通过 ServerArgs 指定了附加参数,则args=ServerArgs
提示
如果 AutoPost 同 ServerArgs 一起使用时,即便是 ServerArgs 指定了多个参数也会一起赋值给 args 参数,需要在代码中自行进行分解。 如果是同 ServerEvent 一起使用,则会被 VDN 分解为多个参数传送给指定的事件
CommonEvent:
Choose Case sender
Case "b_del"
//删除操作
Case "b_save"
//保存操作
Case Else
//未处理的操作
End Choose动态嵌入
有些情况需要在页面通过代码动态嵌入内容,比如动态的 HTML 或者在 JS 脚本中插入一段动态的代码,使用如下格式::
<!--INCLUDE:ID{;Type}-->ID:指定该文本块的 ID,代码通过 guo_vdn.wa_setContent(ID,text)来设置嵌入的内容内容
Type:(非必须),当插入的内容位于
<Scrtipt>...</Sctipt>时,需要指明类型为 JS,其余情况可以忽略
相对于 guo_vdn.wa_setConent 函数,动态嵌入位置更加灵活.
<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="block\_1"></div>
**<!--INCLUDE:block\_2-->**
<script>
**/\*<!--INCLUDE:block\_3;JS-->\*/** (或者 <!--INCLUDE:block\_3;JS-->)
alert(str\_1);
</script>
**<!--INCLUDE:block\_4-->**
</body>
</html>这个页面总共定四个可以动态设置文本内容的地方,其中 block_1 是通过设置 div 的内容的方式,其余三种为动态文本块.
注意
当动态嵌入位于 Script 脚本块中时,有的 IDE 编辑器会对<!--...-->提示语法错误,这时候可以使用/*...*/或者 "/*...*/" 将动态嵌入注释起来,VDN 最终会自动去掉该注释,当然也可以不理会这个语法错误提示.
我们通过如下代码设置:
guo_vdn.wa_setcontent("block_1","VDN WebAPP 如此简单")
guo_vdn.wa_setcontent("block_2","但我还是需要熟悉一下")
guo_vdn.wa_setcontent("block_3",'str_1="Hello world!";')
guo_vdn.wa_setcontent("block_4",‘<script>alert("很高兴能给你带来便捷!");</script>')结果:
<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="block\_1">VDN WebAPP如此简单</div>
<div>但我还是需要熟悉一下</div>
<script>
str\_1="Hello world!";
alert(str\_1);
</script>
<script>
alert("很高兴能给你带来便捷!");
</script>
</body>
</html>相关函数
uo_vdncore 组件提供了一系列函数配合 WebAPP 操作,函数均以 wa_开头,下面按照使用频率的高低次序进行解释
注意
函数中的键值 Key 均区分大小写
除非特别指定,根据 Key 查找值时,如果没有找到则返回:uo_vdncore.NOTFOUND
全局操作函数
| 函数 | 参数 | 说明 |
|---|---|---|
| wa_getGlobal | string as_key 键值 | 获取 Global 全局变量值,这个变量的作用范围是整个 VDN 服务,包括 WebAPI、WebApp、PB 插件、任务计划等 举例: ls_value=guo_vdn.wa_getGlobal("sToken") |
| wa_setGlobal | string as_key 键值 string as_value 值 | 设置 Global 全局变量值 举例: guo_vdn.wa_setGlobal("sToken","abcd") |
| wa_getSession | string as_key 键值 | 获取存储在 Session 中的变量值,一般使用在建立了 Session 的 WebAPP 中。该变量的作用范围为当前会话(Session),当用户退出登录后变量消失,相当于 PB 的 Global Variables 举例: ls_value=guo_vdn.wa_getSession("UID") |
| wa_setSession | string as_key 键值 string as_value 值 | 设置 Session 变量值 举例: guo_vdn.wa_setSession("UID","8888") |
| wa_getViewState | string as_key 键值 | 获取存储在 ViewState 中的变量值,使用在的 WebAPP 的页面中,该变量的作用范围为打开的当前页面,页面关闭或者跳转后变量值消失,相当于 PB 的 Instance Variables 举例: ls_value=guo_vdn.wa_getViewState("Key") |
| wa_setViewState | string as_key 键值 string as_value 值 | 设置 ViewState 变量值 举例: guo_vdn.wa_setViewState("Key","123") |
| wa_getCookie | string as_key 键值 | 获取客户端传入的 cookie 值 guo_vdn.wa_getCookie("UID") |
| wa_setCookie | string as_key 键值 string as_value 值 | 设置 Cookie 值 举例: go_vdn.wa_setCookie("UID","9999") |
| wa_getHeader | string as_key 键值 | 获取 Request 的 Header 的值 举例: guo_vdn.wa_setHeader("Content-Type") |
| wa_setHeader | string as_key 键值 string as_value 值 | 设置 Response 的 Header 值 举例: go_vdn.wa_setHeader("ABC","123") |
| wa_getQueryString | string as_key 键值 | 获取 QueryString 值,通过 URL 传递的参数值 举例: http://www.xxx.com:8088/webdemo?id=123ls_id=guo_vdn.wa_getQueryString("id") |
| wa_getBody | 无 | 获取页面的 body 值,即时整个页面的 html 值,可能为 post 过来的 XML 或者 JSON 值 |
| wa_getSystem | string as_key 键值 | 获取系统信息值 as_key 目前有如下的值: |
| wa_go | string as_path URL 地址 | 跳转到新的地址,可以为本站点内的相对地址,也可以为绝对 URL 地址 是 wa_redirect 名称简化函数,作用完全一样 举例: guo_vdn.wa_go("login.html") |
| wa_redirect | string as_path URL 地址 | 跳转到新的地址,可以为本站点内的相对地址,也可以为绝对 URL 地址 举例: guo_vdn.wa_redirect("http://www.vesn.net") |
| wa_setLogin | string as_value 值(可选) | 设置登录标志,VDN 根据该标志确定用户是否登录.,只要长度不等于 0,系统就认为登录,一般设置为用户 ID 示例: guo_vdn.wa_setlogin() 设置登录标志为默认值 guo_vdn.wa_setlogin("8888") 设置登录标志为用户 ID 8888 |
| wa_getLogin | 无 | 获取设置的用户登录标志 示例: ls_user=guo_vdn.wa_getLogin() |
| wa_alert | string as_msg 消息 | 显示消息对话框 举例: guo_vdn.wa_alert("无效的输入值.") |
| wa_setStartScript | {string as_key 键值} string as_script 脚本 | 设置放在 Form 开始位置的 JS 脚本块,根据 Key 的不同可以设置多部分脚本 举例: guo_vdn.wa_setStartScript("js_1","var str='abc';alert('动态设置的脚本块:' +str);") |
| wa_setStartBlock | {string as_key 键值} string as_script 脚本 | 设置放在 form 开始的文本块,根据 key 的不同可以设置多部分 可以动态的在 form 开始部分放置动态的 JS 脚本或者 HTML 组件、文本等 举例: wa_setStartBlock('h_items','<input name="h\_items" id="h\_items" type="hidden" />') 在 form 开始部分插入一个 hidden 标签 |
| wa_setClientScript | string as_key 键值 string as_script 脚本 | 设置放在 Form 末尾位置的 JS 脚本块,根据 Key 的不同可以设置多部分脚本 举例: guo_vdn.wa_setClientScript("js_1","var str='abc';alert('动态设置的脚本块:' +str);") |
| wa_setClientBlock | string as_key 键值 string as_script 脚本 | 设置放在 form 末尾的文本块,根据 key 的不同可以设置多部分 可以动态的在 form 开始部分放置动态的 JS 脚本或者 HTML 组件、文本等 举例: wa_setClientBlock('h_items','<input name="h\_items" id="h\_items" type="hidden" />')在 form 末尾部分插入一个 hidden 标签 |
| wa_sessionClear | - | 清除当前 session 值 |
| wa_sessionEnd | - | 结束当前 session |
| wa_getValue | string as_type 类型 常量 WA_ENUM_... 系列:global\session 等 string as_key 键值 组件的 Name 或者值的 Key 等 string as_pro 属性值 (备用) | 根据指定的类型及键值获取服务器参数列表对应的值 该函数很少直接使用,一般供内部函数调用,例如 wa_getsession 或者 wa_getcookie 最终都是调用的该函数 |
| wa_setValue | string as_type 类型 常量 WA_ENUM_... 系列值 session/viewstate.... string as_key 键值 组件的 name 或 id string as_pro 属性 string as_value 值 | 设置返回服务器端参数值。该函数同 wa_getvalue 相对应,不直接使用,一般供内部函数调用,例如 wa_setsession 或者 wa_setcookie 最终调用的都是该函数 |
| wa_sendmsg | 参数说明见[消息推送-发送消息] | 通过 VDN 直接推送消息给消息登录用户,无需登录。适用于 WebApi 及 WebApp 等后台插件的使用 |
组件操作函数
| 函数 | 参数 | 说明 |
|---|---|---|
| wa_getValue | string as_key 组件的 name | 获取页面组件的值,包括输入框、选择框、单选框、标签等组件的值 举例: guo_vdn.wa_getvalue("t_name")获取输入框 t_name 的值 |
| wa_setValue | string as_key 组件的 name 或 id string as_value 值 | 设置页面的组件的值,包括输入框、选择框、单选框、标签等组件的值 举例: guo_vdn.wa_setvalue("t_name","张三")设置输入框 t_name 的值guo_vdn.wa_setvalue("l_name","姓名:")设置标签(label)l_name 的值注:使用该函数设置的值会被进行 html 编码,例如: guo_vdn.wa_setvalue("div_name","<div>") 则前端直接显示为<div>``,源代码里的值为<div>`,这是被 html 编码过的,如果要动态加入新的 html 标签,则应该使用 wa_setcontent 函数 |
| wa_setContent | string as_key 组件的 name 或 id string as_content 内容 | 设置页面组件的值。一般用来设置组件或者动态嵌入的内容,该函数设置的值不会被进行 html 编码,可以动态的给页面增加新的组件,例如上面的动态嵌入就是调用的该函数 举例: <div id="div\_1"></div>guo_vdn.wa_setcontent("div_1","<div>abcd</div>")最后页面得到得结果为<div id="div\_1"><div>abcd</div></div>注:默认支持 SetContent 的组件有 div\span\label\button\a 如果要增加其他的组件的解析,可以手动设置 run.config 文件中的 ParseTags 节点,例如:,或者直接使用[动态嵌入] |
| wa_setEnabled | string as_key 键值 boolean ab_enabled 是否有效 | 设置指定的标签的有效性 举例: guo_vdn.wa_SetEnabled("b_save",false) |
| wa_setVisible | string as_key 键值 boolean ab_visible 是否可见 | 设置指定的标签是否可见 举例: guo_vdn.wa_SeVisible("b_save",false) |
| wa_setClass | string as_key 键值 string as_class class | 设置指定标签的 class 属性 举例: guo_vdn.wa_setClass("span_1","mui-icon mui-icon-person") |
| wa_setStyle | string as_key 键值 string as_style style | 设置指定标签的 style 属性 举例: guo_vdn.wa_setStyle("btn_1","width:50px;") |
| wa_setReadonly | string as_key 键值 boolean ab_readonly 是否只读 | 设置输入标签是否只读 示例: guo_vdn.wa_setReadonly("t_name",true)设置 t_name 输入框只读 |
| wa_setScript | string as_key 键值 string as_script JS 脚本 | 设置标签的默认事件执行的脚本 按钮等标签的默认事件为 onClick, 输入框的默认事件为 onChange 示例: guo_vdn.wa_setScript("b_submit","if(!confirm('确定提交数据?')){return false;}") |
| wa_addItem | string as_key 列表框 name string as_value 值(可选) string as_text 显示文本 | 给下拉框 select 的增加列表项 option 同一次响应的 additem 项目会累加,但是会清除上一次动态增加的项目 示例: guo_vdn.addItem("d_user","8888","管理员")guo_vdn.addItem("d_user","aaaa") //值同显示文本是一样的 |
| wa_setTarget | string as_key 键值 string as_value target 值 | 设置超级链接<a>标签的 target 属性,规定在何处打开链接文档示例: guo_vdn.wa_setTarget("a_1","\_top") |
| wa_showPassword | string as_key 键值 boolean ab_show 是否显示 | 是否显示密码(一串星号或者圆点),默认不显示,例如登录页面不需要显示,但是像 VDN 的帐套设置那里又需要显示。这个极少用到 示例: guo_vdn.wa_showPassword("t_pass",true) |
| wa_showOri | string as_key 键值 boolean ab_ori 是否原值 | 设置密码输入框(password)在前台源代码里否显示原值 true 显示原值 false 显示为"!nochange!" 无论是否显示原值,在前端展示的都是一串星号或者圆点,但如果显示为原值,通过查看页面源代码可以查看到这个值;默认不显示原值 示例: guo_vdn.wa_showOri("t_pass",true) |
vdn.js
vdn.js 集成了众多 vdn 的前台操作函数,包括 get\post 等操作,详见 vdn.js 文件
调试跟踪
前端开发可以更多的借助浏览器的调试功能(F12)或者微信的调试工具进行调试。VDN 还提供了 trace 函数用以跟踪前端和后台的信息。
这个特别是对于 PB 端的开发,因为普通模式不能使用 MessageBox 来调试,使用 trace 函数可以很好的替代这个功能,且可以在任意客户端跨网络进行跟踪。
跟踪窗口
通过系统设置--调试跟踪 可以打开跟踪窗口


trace 函数
前端调用 trace 是通过消息来实现的,所以需要打开系统设置--高级选项--[允许外部消息] 选中该选项
var data = [{"c_id":"201711192114101377","c_oper":"阿拉蕾","d_date":"2017-11-21","c_user":"测试用用用
户","c_store":"黄河路旗舰店","c_tel":"7654321","c_sex":"女"}......];
vdn.trace(data);
vdn.trace("你好");
vdn.trace(123);guo_vdn.trace("你好")
guo_vdn.trace("行号:",rowNum)
guo_vdn.trace("文字",123,"abc)注意要点
- 当以 form 形式提交表单时要具备下列属性
<form id='form1' method="post">- 当以 form 形式提交表单时标签必须要指明 name 属性,且 name 属性放在前端会加快解析速度
<input type="submit" name="b\_submit" value="确认预约" />- WebApp 的后台 PB 插件,必须要定义如下两个全局变量
//以下两行为必须
string \_\_LastError //在 SystemError 事件中记录系统错误,VDN 将获取这个错误并返回给调用者
uo_vdncore guo_vdn //全局的 VDN 对象,通过该对象获取和设置 global\\session\\header\\cookie....当使用 Ajax 调用时可以通过设置__LastError 来返回错误信息
在 application 的 systemerror 事件里对__LastError 进行赋值,当发生系统错误时,这个错误将被前台获取,便于显示

小技巧
- JPG 图片等文件浏览器直接打开还是提示保存下载
JPG 图片等文件作为超级链接的 href 时,默认都是浏览器直接打开显示的,如果想要浏览器提示下载则在 URL 地址后面跟上:download=1 参数
<a href="http://www.xx.net/image/loading.gif?download=1">图片下载</a>如果要指定另外的文件名称可在 URL 地址后面跟上:alias=别名 参数
<a href="http://www.xx.net/image/loading.gif?download=1&alias=b.gif">下载</a>