Fun 语言怎么做界面 ..

作者: 一了 <1liao3@funlang.org>
日期: 2018-09-19

先看一个简单的例子, 下图是一个密码生成器, 有一个按钮, 点击生成一个新的随机密码. 鼠标移到密码上, 会自动全选, 并且将窗口标题改成当前密码. 为了方便, 给按钮配上了一组快捷键.



源代码如下:


var q = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*-_+=<>?';
fun get_password()
  result = '';
  for i = 0 * 0.random() to 8 + 8.random() do
    result &= q.substr(q.length().random(), 1);
  end do;
end fun;

use 'lib-ui.fun';
use 'lib-bind.fun';

class PwdForm = Form()
  autoEvent    = true;
  var databind = Bind(this, []);

  var P = get_password();
  fun Get(e)
    P = get_password();
  end fun;

  fun Body()
    return `
<table><tr><td>
 <input fun:data="P,r" onmousemove="javacript:this.select();Fun.call('SetCaption', this.value);">
</td><td>
 <button fun:click="Get" fun:key="Ctrl-R, &R, R, Ctrl-5, F5">下一个(<u>R</u>)</button>
</td></tr></table>
`;
  end fun;

  fun Style()
    return 'table{width:100%;height:100%}';
  end fun;
end class;

PwdForm('随机密码', 360, 80).Show();
Run();



先一段一段简要介绍一下:

第一段是个密码生成器函数, 没什么好介绍的.

接下来是引用两个库, 分别是 lib-ui.fun 和 lib-bind.fun, 然后声明一个类, 继承自 Form 基类, 这个基类是 lib-ui.fun 里定义好了的. autoEvent 表明是自动响应事件, Bind 函数的作用是将 DOM 和 Fun 变量做双向绑定. 然后是声明了一个类对象属性变量 P, 以及一个成员函数 Get, 接下来会介绍怎么用.

关键的地方来了, PwdForm 重载了基类的 Body 和 Style 成员函数, Style 函数就是写了一点样式表, 重点在 Body 函数. Body 函数定义了窗口的所有内容, 以及相应的数据绑定和事件响应. Fun 语言是用 HTML 作为界面描述语言, 支持标准的 CSS 和 Javascript. Fun 语言给 HTML 增加了少量标签属性, 皆以 fun: 开头表示, 最重要的是 fun:data, fun:click 和 fun:key.

fun:data 定义的是数据绑定, 内容格式如下:
  varName=propName,r,w,load:methodLoad;save=methodSave
varName 是 Fun 窗口对象的属性变量名, propName 是 DOM 属性名, 默认是 value, r/w 表示读写, load 和 save 是自定义读写函数. 举例如下:
  url=value,r,w,load:UrlLoad;save=UrlSave

fun:click 定义的是 Fun 窗口对象类的成员函数, 当按钮点击时触发.

fun:key 是快捷键定义, 当触发快捷键时, 调用 fun:click 定义的函数. 快捷键支持多个, 以逗号分隔, 支持 Ctrl-, Alt (&), Fn, 等.

Fun 语言支持和 js 双向互调, 本例中 onmousemove 时 js 调用 fun 语言函数 SetCaption, 传入了 this.value 作为参数.

上述例子的中文版源代码如下:


变量 甲 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*-_+=<>?';
函数 生成()
  @ = '';
  设 乙 = 0 * 0.random() 到 8 + 8.random() 执行
    @ &= 甲.substr(甲.length().random(), 1);
  结束 执行;
结束 函数;

引用 'lib-ui.fun';
引用 'lib-bind.fun';

类 密码窗 = Form()
  autoEvent    = 真;
  变量 databind = Bind(this, []);

  变量 P = 生成();
  函数 取()
    P = 生成();
  结束 函数;

  函数 Body() # fun:data 目前只能解析英文变量
    返回 `
<table><tr><td>
 <input fun:data="P,r" onmousemove="javacript:this.select();Fun.call('SetCaption', this.value);">
</td><td>
 <button fun:click="取" fun:key="Ctrl-R, &R, R, Ctrl-5, F5">下一个(<u>R</u>)</button>
</td></tr></table>
`;
  结束 函数;

  函数 Style()
    返回 'table{width:100%;height:100%}';
  结束 函数;
结束 类;

密码窗('随机密码', 360, 80).Show();
Run();