StippleUI.jl
StippleUI 是一个反应式用户界面元素库,用于 Stipple.jl。
与
它是 GenieFramework的一部分。
它是 [GenieFramework] 的一部分。
StippleUI
它提供了 30 多种用户界面元素,包括表单和表单输入(按钮、滑块、复选框、单选框、切换框、范围)、列表和数据表、
更高级别的组件(徽章、横幅、卡片、对话框、芯片、图标)以及布局元素(行、列、仪表盘、标题、空格),这些元素来自 Quasar Framework。
新闻:Vue 3 / Quasar 2
从 0.24 版开始,StippleUI 已将前端库升级至 Vue3 / Quasar 2,因为 Vue-2 已达到生命周期终点。
我们花了很多精力使迁移尽可能简单。不过,在某些地方,高级用户界面可能需要稍作调整。
版本 >= v0.24 的主要变更
组件
-
常规:同步附加字段不再使用`fieldname.sync` 语法,而是使用`v-model:fieldname` 。这已由组件的应用程序接口处理,例如`table()` 中的`paginationsync` 。如果您手动添加了此类字段,则需要调整您的代码。
-
Quasars 的 Table 组件已将 content 属性的命名从`data` 改为`rows` 。 因此,从长远来看,模板中的所有引用都应更改为`rows` ,例如
table(:mytable, @showif("mytable.data.length"))
应更改为`table(:mytable, @showif("mytable.data.length"))` 。 不过,我们已经引入了一个监视器,将名为 "data "的第二个字段设置为 "rows "字段,这样在大多数情况下就能保持旧代码的运行。该解决方案的唯一缺点是,将表内容同步回服务器时会发送双倍的数据量;因此该辅助程序将来可能会被弃用。
更多迁移支持
-
Stipple 的 README https://github.com/GenieFramework/Stipple.jl/blob/master/README.md
-
Quasar 升级指南:网站:https://quasar.dev/start/upgrade-guide/
-
Vue 迁移指南:https://v3-migration.vuejs.org/
使用方法
类星体组件
StippleUI 为大多数类星体 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`
-
示例
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()` 函数将其添加到您的用户界面中:
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>"
绑带
有两种分配组件属性的方法
-
字符串值赋值:
attribute = "lorem ipsum"
-
通过
-
赋值`Symbol`
attribute = :input
-
或在属性中添加`!
- 字符 `attribute! = "input"
在大多数情况下,这种语法用于直接绑定应用程序变量,但也可以绑定更复杂的表达式,例如数组元素(注意 js 采用基于 0 的索引):
attribute = Symbol("data[0]")
attribute = R"data[0]"
attribute! = "data[0]"
R""
字符串宏是定义符号的一种便捷方式。+ === 辅助宏
-
Vue.js 定义了几种快捷方式,通常以`@- 字符开头。在 Julia 中,
@- 字符是为宏所保留的。因此,我们决定使用宏来实现类似的语法。但我们也提供了宏来添加其他 "禁止 "字符的属性,如
.` 或`-` 。
请查看`@click`,@on
,@iif
,@els
,@elsiif
,@recur
,@text
,@bind
,@data
和`@showif` 的文档说明,了解更多信息。要尝试渲染是否正确,请在 REPL 中输入暂定表达式,例如
julia> span(@showif(true))
"<span v-show=\"true\"></span>"
julia> span(@click(:mybutton))
"<span v-on:click=\"mybutton = true\"></span>"
Quasar 的柔性电网
Quasar 实现了一种名为 "Flexgrid "的网格系统,可轻松按类定义用户界面。
网格可以是垂直的(class = "column"
),也可以是水平的(class = "row"
)。子元素在该容器中的大小是通过设置类`"col"` 来获得的,如果是等间距的子元素,则设置`"col-6"` ,如果是容器大小的 1/12 的固定倍数(此处`6` ,即 50%),则设置 。
此外,Quasar 还允许根据容器的大小改变子元素的大小,方法是在 col 类之后添加一个大小条件,例如`"col-md-3"` ,或直接`"col-md"` 。
在 StippleUI-API 中,我们定义了属性`col`,xs
,sm
,md
,lg
,xl
,以便更方便地定义类,例如
row(htmldiv(col = 2, md = 4)) |> println
# <div class="row"><div class="col-2 col-md-4"></div></div>
此外,子元素之间的间隔可以通过设置 class="gutter-md" 来添加。如果是柔性容器中的子元素(row
或`column` ),则需要设置为`class = "gutter-col-md"` 。同样,我们也定义了一个属性来处理这种差异,并自动选择正确的设置。
julia> row(gutter = "md", htmldiv(col = 2, md = 4), "Hello World") |> println
<div class="row q-col-gutter-md" Hello World><div class="col-2 col-md-4"></div></div>
此外,由于 Quasar 设置边距和填充的方式不同,如果子元素有背景设置,可能会导致显示效果不佳。解决的办法是用一个额外的`div` 元素来包裹子元素,使用@gutter
宏就可以方便地做到这一点。
julia> row(gutter = "md", @gutter htmldiv(col = 2, md = 4, "Hello World")) |> println
<div class="row q-col-gutter-md"><div class="col-2 col-md-4"><div>Hello World</div></div></div>
更多详细信息,请参阅文档说明。
Javascript 代码
Vue.js 提供了嵌入 javascript 函数的可能性,这些函数可以手动调用 (methods
) 或在特定事件发生时自动调用,例如`watch`,mounted
,created
,computed
。这些代码可以很容易地通过相应的宏来定义`@methods`,@watch
,@mounted
,@created
,@computed
, 例如
@methods """
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
}
"""
@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 构建反应式用户界面。你可以找到三种不同的触发处理程序的方法。
-
输入字段中的每次输入都会触发一个函数,在输出字段中设置反转的输入字符串。
-
按下输入框中的`Enter` 键可反转输出字符串。
-
按下操作按钮可反转输出字符串。 StippleUI
using Stipple, StippleUI
@vars Inverter begin
process = false
input = ""
output::String = "", READONLY
end
function handlers(model)
on(model.input) do input
model.output[] = input |> reverse
end
onbutton(model.process) do
model.output[] = model.output[] |> reverse
end
model
end
function ui()
row(cell(class = "st-module", [
textfield(class = "q-my-md", "Input", :input, hint = "Please enter some words", @on("keyup.enter", "process = true"))
btn(class = "q-my-md", "Action!", @click(:process), color = "primary")
card(class = "q-my-md", [
card_section(h2("Output"))
card_section("Variant 1: {{ output }}")
card_section(["Variant 2: ", span(class = "text-red", @text(:output))])
])
]))
end
route("/") do
model = Inverter |> init |> handlers
page(model, ui()) |> html
end
Genie.isrunning(:webserver) || up()
StippleUIParser
工具
-
parse_vue_html
-
test_vue_parsing
-
prettify
StippleUIParser 是一款非常新颖的工具。它能将 html 代码转换为相应的 Julian 代码,并对 html 代码进行美化。这是一个辅助工具,可将演示代码从互联网移植到 Stipple/Genie 应用程序中。
将 vue 的 HTML 代码解析为 Julia 代码
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>
演示
StippleDemos
我们在 Github 上专门开辟了一个 Stipple 演示页面,其中包含许多可下载的示例: https://github.com/GenieFramework/StippleDemos (并非所有示例都已更新至 API 的最新版本。但它们中的大部分都能正常运行)。
鸢尾花数据集 k-Means 聚类仪表板
完整的应用程序可在以下网址获取: https://github.com/GenieFramework/Stipple-Demo-IrisClustering
更多信息
虽然 Stipple/StippleUI 文档仍在不断完善中,但您可以通过函数的文档说明找到帮助和许多小例子。
help?> btn
search: btn Btn btngroup btndropdown q__btn q__btn__group q__btn__dropdown button Buttons onbutton SubString @onbutton bitstring
Stipple has a component called btn which is a button with a few extra useful features. For instance, it comes in two shapes:
rectangle (default) and round. It also has the material ripple effect baked in (which can be disabled).
The button component also comes with a spinner or loading effect. You would use this for times when app execution may cause a
delay and you want to give the user some feedback about that delay. When used, the button will display a spinning animation as
soon as the user clicks the button.
When not disabled or spinning, btn emits a @click event, as soon as it is clicked or tapped.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> btn("Move Left", color = "primary", icon = "mail", @click("press_btn = true"))
julia> btn("Go to Hello World", color = "red", type = "a", href = "hello", icon = "map", iconright = "send")
julia> btn("Connect to server!", color="green", textcolor="black", @click("btnConnect=!btnConnect"), [
tooltip(contentclass="bg-indigo", contentstyle="font-size: 16px",
style="offset: 10px 10px", "Ports bounded to sockets!")]
)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Arguments
≡≡≡≡≡≡≡≡≡≡≡
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1. Behavior
• loading::Bool - Put button into loading state (displays a spinner – can be overridden by using a 'loading'
slot)
• percentage::Union{Int, Float64} - Percentage (0.0 < x < 100.0); To be used along 'loading' prop; Display a
progress bar on the background ex. 23
• darkpercentage::Bool - Progress bar on the background should have dark color; To be used along with
'percentage' and 'loading' props
2. Content
• label::Union{String, Int} - The text that will be shown on the button ex. Button Label
• icon::String - Icon name following Quasar convention; Make sure you have the icon library installed unless
you are using 'img:' prefix; If 'none' (String) is used as value then no icon is rendered (but screen real
estate will still be used for it) ex. map ion-add img:https://cdn.quasar.dev/logo/svg/quasar-logo.svg
img:path/to/some_image.png
• iconright::String - Icon name following Quasar convention; Make sure you have the icon library installed
unless you are using 'img:' prefix; If 'none' (String) is used as value then no icon is rendered (but screen
real estate will still be used for it) ex. map ion-add img:https://cdn.quasar.dev/logo/svg/quasar-logo.svg
img:path/to/some_image.png
• nocaps::Bool - Avoid turning label text into caps (which happens by default)
• nowrap::Bool - Avoid label text wrapping
• align::String - Label or content alignment default. center accepted values. left right center around between
evenly
• stack::Bool - Stack icon and label vertically instead of on same line (like it is by default)
• stretch::Bool - When used on flexbox parent, button will stretch to parent's height
3. General
• type::String - 1) Define the button native type attribute (submit, reset, button) or 2) render component with
<a> tag so you can access events even if disable or 3) Use 'href' prop and specify 'type' as a media tag
default. button ex. a submit reset button image/png href="https://some-site.net" target="_blank"
• tabindex::Union{Int, String} - Tabindex HTML attribute value
4. Navigation
• href::String - Native <a> link href attribute; Has priority over the 'to' and 'replace' props ex.
https://quasar.dev href="https://quasar.dev" target="_blank"
• target::String - Native <a> link target attribute; Use it only with 'to' or 'href' props ex. _blank _self
_parent _top
5. State
• loading::Bool - Put button into loading state (displays a spinner – can be overridden by using a 'loading'
slot)
• padding::String - Apply custom padding (vertical [horizontal]); Size in CSS units, including unit name or
standard size name (none|xs|sm|md|lg|xl); Also removes the min width and height when set
• color::String - Color name for component from the Color Palette (https://quasar.dev/style/color-palette) eg.
primary teal-10
• textcolor::String - Overrides text color (if needed); Color name from the Color Palette
(https://quasar.dev/style/color-palette) eg. primary teal-10
• dense::Bool - Dense mode; occupies less space
• round::Bool - Makes a circle shaped button
致谢
StippleUI 基于优秀的 Quasar Vue 组件和底层 Vue.js Javascript 框架。