原生 JS

原生 JS 让您可以在 Ninox 脚本中执行 JavaScript 代码,并与之共享函数和变量。这样,原生 JS 就能访问 Ninox 变量,并调用本地函数和全局函数。

图片.png

限制

在原生 JS 中修改 Ninox 变量不会影响该 Ninox 变量。

JavaScript 只在本地执行。把 JavaScript 加入在服务器上运行的代码不会产生任何效果。同样地,从服务器上执行的代码中调用包含 JavaScript 的全局函数也不会产生任何效果。

关于哪些代码在本地执行、哪些在服务器上执行,请参见此处:

图片.png

语法

执行

要告诉 Ninox 您正在切换到 JavaScript,需要把代码包在 #{ ... }# 之中:

#{ alert("hello world") }#;

请记住,Ninox 是一种预编译语言,需要事先知道每个变量和函数的类型。原生 JS 也一样:您必须指定 JavaScript 代码所返回的类型。默认情况下,原生 JS 返回文本,但您可以在代码最开头用 :[type] 的写法指明希望返回的变量类型。

返回值

#{:text return "hello world"}#;

可用的类型与函数调用中使用的类型相同:textnumberdatedatetimetimetimeintervalappointmentbooleanhtmlcoloriconemailphonelocationfileuser 以及 any

数组类型

要返回数组,请使用以下语法:

#{:number(array) return [1,2,3] }#;

记录类型

要返回记录,请使用表名后跟 nidrid

如果使用 nid,您必须返回一个文本值数组,其中包含完整的记录标识符,即表标识符 + 记录编号:

#{:nid(customer) return ['A1','A2','A3'] }#

如果使用 rid,则应返回记录编号:

#{:rid(customer) return [1,2,3] }#

对于由多个词组成的表名,不要像在 Ninox 中那样加上 ,直接使用表的完整名称即可:

#{:rid(my long name table) return [1,2,3] }#

使用这种写法,原生 JS 返回的变量其行为与 Ninox 代码中的变量相同。也就是说,您可以像使用 select 那样使用以下写法:

(#{:rid(customer) return [1,2,3] }# order by 'Last Name').'First Name';

图片.png

记录的修改

记录类型的变量以 JSON 格式传递,记录的每个字段对应一个键值对

var r := first(select Customer);
#{:text return r['First Name'] }#;

此时,变量 r 在 JavaScript 中的内容如下所示:

{
 "Created on": 1648910817206,
 "Id": "A1",
 "Last modified": 1714817525840,
 "Modified by": "7zBqhAKXxfQAPmH7Y",
 "First Name": "Sofia",
 "Last Name": "Young",
 "Company": "Kollwitz GmbH",
 "Postal Code": "12345",
 "City": "New Jersey",
 "Address": "11,South Commerce Street",
 "Email": "sofi@kollwitz-gmbh.com",
 "Customer No": "K0001",
 "Title": "2",
 "Invoices": [
  1,
  16,
  17
 ],
 "Photo": "shutterstock_307218608.jpg",
 "Category": "1",
 "Position": "Marketing head",
 "Checked": true,
 "ID": "A1",
 "id": "A1"
}

重要提示

代码是在 Mac 应用上还是在网页端执行,会影响 ID 的大小写形式。
为了应对这一点并避免不同平台之间的冲突,ID 会以所有可能的大小写形式重复出现

在 JavaScript 中修改记录并不会在 Ninox 中更新它。

异步执行

有时,把 Ninox 代码的执行与 JavaScript 同步起来会很有用。
例如在使用定时器时,代码必须在定时器执行完毕之后才结束,这一点很重要。
如果没有这种同步,JavaScript 执行之后的代码会立即运行,可能导致意料之外的行为。

在下面第一个例子中,值 “I don’t know” 会立即返回,alert 函数在问题呈现给用户之前就显示了结果。

var r:= #{:text
   setTimeout( () => {
      if (confirm("Are you ok ?"))
        return "of course";
      else
        return "Never !";
   }, 2000);
  return "I don't know";
}#;
alert( "Your answer is : "+r );

图片.png

切换到 callback 模式后,Ninox 的 alert 函数只会在 JavaScript 代码调用了回调函数之后才执行,也就是在问题呈现给用户之后

var r:= #{:text:callback
   setTimeout( () => {
      if (confirm("Are you ok ?"))
         callback( "of course" );
      else
        callback( "Never !" );
   }, 2000);
   return "I don't know";
}#;
alert( "Your answer is : "+r );

屏幕录制 2025-03-03 11.46.26.gif

函数调用

可以从 JavaScript 调用 Ninox 函数。该过程可以是本地的,也可以是全局的;只要处于该 JavaScript 代码的作用域内即可。

function display( message : text ) do
    alert( message );
end;
#{ display('hello world') }#;

图片.png

要取回函数的返回值,同样必须使用回调模式(参见上文:异步执行):

function add( a : number, b : number ) do
    a + b;
end;

#{:number:callback
   add( 1, 2, (returnValue) => {
     callback( returnValue )
   })
}#;

图片.png

如果调用该过程之后不再需要做其他处理,您可以直接把回调函数作为参数传入:

function add( a : number, b : number ) do
    a + b;
end;
#{:number:callback
   add( 1, 2, callback )
}#;

图片.png

操作记录与函数

如果您有一组记录 ID,可以调用一个 Ninox 函数来逐条修改这些记录。为此,只需调用该函数并把 ID 传给它即可。

function setCustomerChecked( id : text, checked : boolean ) do
   var n := number(replacex(id, "\D",""));
   var rec := record( Customer, n );
   rec.Checked := checked;
end;
var c := select Customer;
var isChecked := not first(c).Checked;
#{
   c.forEach( v => { setCustomerChecked( v, isChecked ) } );
}#;
c.checked;

执行错误

如果您的代码发生执行错误,将返回错误消息文本

图片.png