Engee 文档

低代码用户界面应用程序接口

StippleUI 是一个反应式 UI 元素库,用于 Stipple.jl,它是一个功能强大的完整解决方案,可用于在纯 Julia 中构建美观、反应灵敏、反应式、高性能的交互式数据仪表盘。 StippleUI StippleUI 提供了 30 多种 UI 元素,包括表单和表单输入(按钮、滑块、复选框、单选框、切换、范围)、列表、数据表、更高级组件(徽章、横幅、卡片、对话框、芯片、图标)以及来自 Quasar Framework 的布局元素(行、列、仪表盘、标题、空间)。

julia> btn("Just do it!", @click(:mybutton), loading = :mybutton) |> println
<q-btn :loading="mybutton" label="Just do it!" v-on:click="mybutton = true"></q-btn>

julia> textfield("Label", :mytext) |> println
<q-input label="Label" v-model="mytext"></q-input>

类星体组件

StippleUI 为大多数 Quasar Vue 组件定义了函数。大多数函数的名称与 Quasar 对应函数相同,例如`btn()` 对应`q-btn` ,tab() 对应`q-tab` 等。为了清晰起见,有些函数使用了不同的名称,例如`textfield()` 代表文本类型的`q-input` ,numberfield() 代表数字类型的`q-input` 。大多数函数都有命名的位置参数,用于定义共同属性,如`label` 或`fieldname` 。除此之外,所有函数都有一个针对未命名参数和关键字参数的通用调用方案:

  • 如果组件支持内容,第一个非命名位置参数将作为内容传递给组件。

  • 以下任何非数组参数将作为参数传递给组件

  • 任何未命名的数组参数都会被连接并作为内容传递给组件

  • 如果组件不支持内容,如`btn()` ,则除数组外的所有非命名参数都将作为参数传递。(传递数组可用于为组件定义模板。更多详情请参见 Vue.js 文档)。

  • 关键字参数的传递方式与 Julia 表达式基本相同,只是

    • __ 转换为`-`

    • ! 转换为`.`

    • ! 在关键字末尾表示该参数应被视为 js 表达式

    • 符号作为关键字参数的值,表示该参数应被视为 js 表达式

    • 对于 Julia 变量名中不允许使用的非标准字符,可以使用var""符号,例如 span(var"v-html" = "My Text with <br>new lines")

    • Vue 语法中包含破折号的大多数变量名都会被自动替换,例如:"leftlabel" => "left-label" 。所有标准映射可在`StippleUI.API.ATTRIBUTES_MAPPINGS`

绑定

有两种分配组件属性的方法

  • 字符串值赋值: attribute = "lorem ipsum"

  • 为 Javascript 表达式赋值

    • 赋值`Symbol` attribute = :input

    • 或在属性中添加`!- 字符`attribute! = "input"

    在大多数情况下,这种语法用于直接绑定应用程序变量,但也可以绑定更复杂的表达式,例如数组元素(注意 js 的索引为 0): attribute = Symbol("data[0]") attribute = R"data[0]" attribute! = "data[0]" R"" 字符串宏是定义符号的便捷方法。

Javascript 代码

Vue.js 提供了嵌入 javascript 函数的可能性,这些函数可手动调用,称为`methods` 。要在应用程序中添加一个函数,请使用`@methods` 宏作为

@methods begin
"""
logdemo: function(text) {
    console.log("Text from Stipple: " + text)
    return text
},
squaredemo: function(number) {
    console.log("The square of " + number + " is " + number**2)
    return number**2
}
"""
end

方法可以从 Julia 代码中调用,如

@onchange trigger_variable begin
    @run raw"this.logdemo('hello world')"
end

或用户界面中的其他元素调用

btn("Call the method", @click("this.function()"))

您还可以添加在某些事件发生时自动触发的代码,例如`watch`,mounted,created,computed 。这些代码可以很容易地通过相应的宏`@watch`,@mounted,@created,@computed 来定义,例如

@created """"
    console.log('This app has just been created!')
"""

更多信息请参见 可编辑树演示。这些宏也适用于显式模型,例如

@created MyApp """"
    console.log('This app has just been created!')
"""

用户自定义事件

宏`@event` 支持用户自定义事件。

@event :uploaded begin
    println("Files have been uploaded!")
end

这些行定义了当客户端的事件被转发到服务器时要执行的 julia 代码。通常,客户端的事件源自某些 vue 组件,例如`q-uploader` 。可以通过调用带有两个符号参数的`@on` 宏来转发这些事件。

julia> uploader("Upload files", url = "/upload" , @on(:uploaded, :uploaded))
"<q-uploader url=\"/upload\" v-on:uploaded=\"function(event) { handle_event(event, 'uploaded') }\">Upload files</q-uploader>"

也可以通过在客户端调用`handle_event(event, 'uploaded')` 手动触发事件。

更多信息请参阅 文件上传演示。同样,@event 宏也适用于显式模型,例如

@event MyApp :uploaded begin
    println("Files have been uploaded to MyApp!")
end

缺失的组件

如果某个类星体组件尚未包含在 StippleUI 中,您仍然可以使用`quasar()` 函数将其添加到您的用户界面中:

julia> quasar(:btn, label = "Action!") |> println
<q-btn label="Action!"></q-btn>

与此类似,您也可以集成 vue 组件或任何其他 HTML 组件:

julia> vue(:calender, date = "today", "This is still a dream!")
"<vue-calender date=\"today\">This is still a dream!</vue-calender>"

julia> xelem(:br)
"<br></br>"

使用布局

布局定义可用于设置跨页面的通用结构,例如在添加导航栏时。您可以定义布局并将其传递给`html` 函数,作为

function layout()
    #the layout kwarg takes a string, so we join the HTML strings
    join([head(title("Genie app")),
     body([h1("Welcome!"), "<% @yield %>"])])
end
ui() = p("Genie!")

@page("/layout", ui, layout=layout())

在这里,@yield 将页面内容注入布局中。

解析 HTML 代码到 Julia

StippleUIParser 是一款非常新的工具。它能将 html 代码转换为相应的 Julian 代码,并对 html 代码进行美化。这是一个辅助工具,用于将演示代码从互联网移植到 Stipple/Genie 应用程序中。

julia> using StippleUI.StippleUIParser
julia> doc_string = """
<template>
    <div class="q-pa-md">
    <q-scroll-area style="height: 230px; max-width: 300px;">
        <div class="row no-wrap">
            <div v-for="n in 10" :key="n" style="width: 150px" class="q-pa-sm">
                Lorem @ipsum \$dolor sit amet consectetur adipisicing elit.
            </div>
            <q-btn color=\"primary\" label=\"`Animate to \${position}px`\" @click=\"scroll = true\"></q-btn>
            <q-input hint=\"Please enter some words\" v-on:keyup.enter=\"process = true\" label=\"Input\" v-model=\"input\"></q-input>
            <q-input hint=\"Please enter a number\" label=\"Input\" v-model.number=\"numberinput\" class=\"q-my-md\"></q-input>
        </div>
    </q-scroll-area>
    </div>
</template>
""";

julia> parse_vue_html(html_string, indent = 2) |> println
template(
  Stipple.Html.div(class = "q-pa-md",
    scrollarea(style = "height: 230px; max-width: 300px;",
      Stipple.Html.div(class = "row no-wrap", [
        Stipple.Html.div(var"v-for" = "n in 10", key! = "n", style = "width: 150px", class = "q-pa-sm",
          "Lorem @ipsum dolor sit amet consectetur adipisicing elit."
        )
        btn(raw"`Animate to ${position}px`", color = "primary", var"v-on:click" = "scroll = true")
        textfield("Input", :input, hint = "Please enter some words", var"v-on:keyup.enter" = "process = true")
        numberfield("Input", :numberinput, hint = "Please enter a number", class = "q-my-md")
      ])
    )
  )
)

测试解析结果

还有一个测试工具`test_vue_parsing()` ,可以测试解析是否成功:

julia> test_vue_parsing(raw"""<a :hello="I need $$$">asap</a>""")

Original HTML string:
<a :hello="I need $$$">asap</a>

Julia code:
a(hello! = raw"I need $$$",
    "asap"
)

Produced HTML:
<a :hello="I need $$$">
    asap
</a>

该工具了解绑定语法的细节,并尊重 html 保留标记 <pre>

julia> test_vue_parsing(raw"""<q-test :hello-world="I need $$$"> asap\n    or\ntoday <pre>asap\n    or\ntoday </pre></q-test>"""; indent = 2)

Original HTML string:
<q-test :hello-world="I need $$$"> asap\n    or\ntoday <pre>asap\n    or\ntoday </pre></q-test>

Julia code:
quasar(:test, var"hello-world" = R"I need $$$", [
  "asap\n    or\ntoday",
  pre(
      "asap\n    or\ntoday "
  )
])

Produced HTML:
<q-test :hello-world="I need $$$">
  asap
  or
  today
  <pre>
asap
    or
today </pre>
</q-test>

美化 HTML 代码

test_vue_parsing() 默认已使用新的预修饰器

julia> prettify("""<div  class="first">single line<div> more\nlines</div></div>"""; indent = 5) |> println
<div class="first">
     single line
     <div>
          more
          lines
     </div>
</div>