Skip to content

与其他编程语言类似,Slint 中的函数是对一段逻辑/代码进行命名、组织和复用的方式。

函数可以作为组件的一部分定义,也可以作为组件内某个元素的一部分定义。 无法声明全局(顶级)函数,也无法在 结构体或枚举中声明函数。同样也不能在其他函数内嵌套定义函数。

声明函数

Slint 中的函数使用 function 关键字进行声明。例如:

slint
export component Example {    // ...    function my-function(parameter: int) -> string {        // Function code goes here        return "result";    }}

函数可以带有参数,参数在圆括号内声明,格式为 name: type。 这些参数可以在函数体内通过其名称引用。参数按值 传递。

函数也可以返回一个值。返回类型在函数 签名的 -> 之后指定。如果未指定返回类型,则返回类型为 voidreturn 关键字用于 在函数体内返回所声明类型的表达式。如果一个函数期望 返回一个值但没有显式的 return 语句,那么默认会返回 最后一个语句的值。

函数可以使用 pure 关键字进行标注。 这表示该函数不会产生任何副作用。 更多详细信息可在 Purity 章节找到。

调用函数

函数可以不带元素名称进行调用(与其他语言中的函数调用类似),也可以 带元素名称调用(与其他语言中的方法调用类似):

slint
import { Button, VerticalBox } from "std-widgets.slint";
export component Example {    // Call without an element name:    property <string> my-property: my-function();    // Call with an element name:    property <int> my-other-property: my_button.my-other-function();
    pure function my-function() -> string {        return "result";    }
    VerticalBox {        Text {            // Called with a pre-defined element:            text: root.my-function();        }
        my_button := Button {            text: "Click me";            clicked => { self.text = root.my-other-property; }            pure function my-other-function() -> int {                return 42;            }        }    }}

函数可见性

默认情况下,函数是私有的,不能从其他组件中访问。

但是,可以使用 publicprotected 关键字修改其可访问性。

  • 使用 public 标注的根级函数可被任何组件访问。

若要在不同组件中访问此类函数,你始终需要一个目标,实际上 意味着调用方组件必须将被调用的组件声明为其子元素之一。

slint
export component HasFunction {    public pure function double(x: int) -> int {        return x * 2;    }}
export component CallsFunction {    property <int> test: my-friend.double(1);
    my-friend := HasFunction {    }}

如果函数是在子元素中声明的,即使标记为 public,也无法从 另一个组件中调用它,因为子元素本身不是 public,并且不存在一个有效的目标来 调用该函数:

slint
export component HasFunction {    t := Text {        public pure function double(x: int) -> int {            return x * 2;        }    }}
export component CallsFunction {    // Compiler error!    // property <int> test: my-friend.t.double(1);
    my-friend := HasFunction {    }}

在被导出组件中标记为 public 的函数也可以从后端代码(Rust、C++、JS)中调用。 请参阅特定语言的文档了解要使用的生成代码。

  • 使用 protected 标注的函数只能被直接继承自它的组件访问。

函数与回调

函数和 回调 之间有许多相似之处:

  • 它们都是可调用的逻辑/代码块
  • 它们以相同的方式被调用
  • 它们都可以带有参数和返回值
  • 它们都可以被声明为 pure

但它们之间也存在区别:

  • 回调中的代码/逻辑可以在后端代码中设置并由后端语言 (Rust、C++、JS)实现,而函数必须完全在 slint 中定义
  • 定义回调的语法不同
  • 回调可以在不为其分配代码块的情况下声明
  • 回调有一种特殊的语法,可使用双向绑定操作符 <=> 声明别名
  • 回调的可见性始终类似于 public 函数

一般来说,使用回调最重要的原因是为了能够从后端代码中处理它们。如果不需要这种能力,请使用 函数。

回调

组件可以声明回调,用于向外部传达状态的 变化。回调通过像调用函数一样“调用”它们来 被触发。

你可以通过使用 => 箭头语法声明一个处理程序来响应回调的调用。 内置的 TouchArea 元素声明了一个 clicked 回调,当用户触摸该元素所覆盖的矩形区域或用鼠标 点击该区域时,该回调会被触发。在下面的示例中,通过声明一个处理程序并调用我们的 自定义回调(hello),将该回调的调用转发给了另一个自定义回调(hello):

slint
export component Example inherits Rectangle {    // declare a callback
    callback hello;
    area := TouchArea {        // sets a handler with `=>`
        clicked => {            // emit the callback
            root.hello()        }    }}

也可以为回调添加参数:

slint
export component Example inherits Rectangle {    // declares a callback
    callback hello(int, string);    hello(aa, bb) => { /* ... */ }}

回调也可以返回一个值:

slint
export component Example inherits Rectangle {    // declares a callback with a return value
    callback hello(int, int) -> int;    hello(aa, bb) => { aa + bb }}

回调参数也可以带有名称。 参数名称目前没有语义上的作用,但它们能提高代码的可读性。

slint
export component Example inherits Rectangle {    // Declare a callback with named argument
    callback hello(foo: int, bar: string);    // The names can be overridden with
    // anything when setting a handler
    hello(aa, bb) => { /* ... */ }}

别名

可以以与双向绑定类似的方式声明回调别名:

slint
export component Example inherits Rectangle {    callback clicked <=> area.clicked;    area := TouchArea {}}

基于 MIT 协议发布