条纹
#
Stipple.Reactive
— Type
mutable struct Reactive{T} <: Observables.AbstractObservable{T}
Reactive
是由模型处理的变量的基本类型。它是一个`AbstractObservable` ,其内容可通过在`Reactive` 变量名后追加`[]` 来获得。为方便起见,Reactive
可缩写为`R` 。
创建 Reactive 变量有几种方法:
-
r = Reactive(8)
-
r = Reactive{Float64}(8)
-
r = Reactive{Float64}(8, READONLY)
-
r = Reactive{String}("Hello", PRIVATE)
-
r = Reactive(jsfunction"console.log('Hi')", JSFUNCTION)
#
Stipple.ReactiveModel
— Type
type ReactiveModel
Stipple 模型继承的抽象类型。Stipple 模型用于在 Julia 后端和 JavaScript/Vue.js 前端之间自动进行双向数据同步和数据交换。
示例
Base.@kwdef mutable struct HelloPie <: ReactiveModel
plot_options::R{PlotOptions} = PlotOptions(chart_type=:pie, chart_width=380, chart_animations_enabled=true,
stroke_show = false, labels=["Slice A", "Slice B"])
piechart::R{Vector{Int}} = [44, 55]
values::R{String} = join(piechart, ",")
end
#
Stipple.render
— Function
function render
抽象函数。需要由插件进行专门处理。Stipple
会自动调用该函数,将 Julia 数据类型(与`ReactiveModel` 实例中的字段相对应)序列化为 JavaScript/JSON。一般来说,专用方法应返回 Julia`Dict` ,并由`Stipple` 自动进行 JSON 编码。如果需要对生成的`Dict` 中的某些类型进行自定义 JSON 序列化,则应针对特定类型专用`JSON.lower` 。
示例
function Stipple.render(ps::PlotSeries, fieldname::Union{Symbol,Nothing} = nothing)
Dict(:name => ps.name, ps.plotdata.key => ps.plotdata.data)
end
Specialized JSON rendering for Undefined
JSON.lower(x::Undefined) = "__undefined__"
#
Stipple.update!
— Function
function update! :: {M<:ReactiveModel}
抽象函数,用于根据前台数据更新`ReactiveModel` 中的字段值。可以针对专用类型进行专门处理,但通常没有必要。如果专门化,则必须返回作为第一个参数提供的`ReactiveModel` 的更新实例。
示例
function update!(model::M, field::Any, newval::T, oldval::T)::M where {T,M<:ReactiveModel}
setfield!(model, field, newval)
model
end
#
Stipple.js_methods
— Function
function js_methods(app::T) where {T<:ReactiveModel}
为 vue 元素的`methods` 部分定义 js 函数。函数的预期结果类型为
-
String
包含 javascript 代码 -
Pair
的函数名和函数代码 -
Function
返回 javascript 代码字符串 -
Dict
函数名和函数代码的字符串 -
Vector
的 Example 1
js_methods(::MyDashboard) = """
mysquare: function (x) {
return x^2
}
myadd: function (x, y) {
return x + y
}
"""
Example 2
js_methods(::MyDashboard) = Dict(:f => "function(x) { console.log('x: ' + x) })
Example 3
js_greet() = :greet => "function(name) {console.log('Hello ' + name)}" js_bye() = :bye => "function() {console.log('Bye!')}" js_methods(::MyDashboard) = [js_greet, js_bye]
#
Stipple.js_computed
— Function
function js_computed(app::T) where {T<:ReactiveModel}
定义 vue 元素`computed` 部分的 js 函数。每次内部参数的值发生变化时,这些属性都会更新。函数的预期结果类型为
-
String
包含 javascript 代码 -
Pair
的函数名和函数代码 -
Function
返回 javascript 代码字符串 -
Dict
函数名和函数代码的字符串 -
Vector
的
示例
js_computed(app::MyDashboard) = """
fullName: function () {
return this.firstName + ' ' + this.lastName
}
"""
#
Stipple.js_watch
— Function
function js_watch(app::T) where {T<:ReactiveModel}
为 vue 元素的`watch` 部分定义 js 函数。每次相应属性发生变化时,都会调用这些函数。函数的预期结果类型为
-
String
包含 javascript 代码 -
Pair
的函数名和函数代码 -
Function
返回 javascript 代码字符串 -
Dict
函数名和函数代码的字符串 -
Vector
的
示例
每次`firstName` 或`lastName` 发生变化时,都会更新`fullName` 。
js_watch(app::MyDashboard) = """
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
"""
#
Stipple.js_created
— Function
function js_created(app::T)::Union{Function, String, Vector} where {T<:ReactiveModel}
定义 vue 元素`created` 部分的 js 语句。
函数的结果类型可以是
-
String
包含 javascript 代码 -
Function
返回 javascript 代码字符串 -
Vector
的字符串 Example 1
js_created(app::MyDashboard) = """
if (this.cameraon) { startcamera() }
"""
Example 2
startcamera() = "if (this.cameraon) { startcamera() }"
stopcamera() = "if (this.cameraon) { stopcamera() }"
js_created(app::MyDashboard) = [startcamera, stopcamera]
检查结果的方法如下
julia> render(MyApp())[:created] JSONText("function(){ if (this.cameraon) { startcamera() } if (this.cameraon) { stopcamera() } }")
#
Stipple.js_mounted
— Function
function js_mounted(app::T)::Union{Function, String, Vector} where {T<:ReactiveModel}
定义 vue 元素`mounted` 部分的 js 语句。
函数的结果类型可以是
-
String
包含 javascript 代码 -
Function
返回 javascript 代码字符串 -
Vector
的字符串 Example 1
js_mounted(app::MyDashboard) = """
if (this.cameraon) { startcamera() }
"""
Example 2
startcamera() = "if (this.cameraon) { startcamera() }"
stopcamera() = "if (this.cameraon) { stopcamera() }"
js_mounted(app::MyDashboard) = [startcamera, stopcamera]
检查结果的方法如下
julia> render(MyApp())[:mounted] JSONText("function(){ if (this.cameraon) { startcamera() } if (this.cameraon) { stopcamera() } }")
#
Stipple.client_data
— Function
function client_data(app::T)::String where {T<:ReactiveModel}
定义仅浏览器可见的附加数据。
它用于保存不稳定的数据,例如需要先通过验证的表单数据。为了使用这些数据,您可能还需要定义 js_methods
示例
import Stipple.client_data
client_data(m::Example) = client_data(client_name = js"null", client_age = js"null", accept = false)
将为模型`Example` 定义附加字段`client_name` 、client_age
和`accept` 。当然,这些字段不应与模型的现有字段重叠。
#
Stipple.register_components
— Function
function register_components(model::Type{M}, keysvals::AbstractVector) where {M<:ReactiveModel}
用于添加需要在 Vue.js 应用程序中注册的 Vue 组件的实用程序。在注册 Stipple 插件提供的组件时通常需要使用该函数。
示例
Stipple.register_components(HelloPie, StippleCharts.COMPONENTS)
#
Stipple.components
— Function
function components(m::Type{M})::String where {M<:ReactiveModel}
function components(app::M)::String where {M<:ReactiveModel}
ReactiveModel
M
注册的 Vue.js 组件的 JSON 表示形式。
#
Stipple.setindex_withoutwatchers!
— Function
setindex_withoutwatchers!(field::Reactive, val; notify=(x)->true)
setindex_withoutwatchers!(field::Reactive, val, keys::Int...; notify=(x)->true)
在不触发监听器的情况下更改反应式字段的内容。如果指定了键,则只有这些侦听器可以免于触发。
#
Stipple.setfield_withoutwatchers!
— Function
setfield_withoutwatchers!(app::ReactiveModel, field::Symmbol, val; notify=(x)->true)
setfield_withoutwatchers!(app::ReactiveModel, field::Symmbol, val, keys...; notify=(x)->true)
更改 ReactiveModel 的字段而不触发监听器。如果指定了键,则只有这些侦听器免于触发。
#
Stipple.init
— Function
function init(::Type{M};
vue_app_name::S = Stipple.Elements.root(M),
endpoint::S = vue_app_name,
channel::Union{Any,Nothing} = nothing,
debounce::Int = JS_DEBOUNCE_TIME,
transport::Module = Genie.WebChannels,
core_theme::Bool = true)::M where {M<:ReactiveModel, S<:AbstractString}
通过设置与 Vue.js 前端集成的自定义 JavaScript 来初始化模型`M` 的反应性,并执行后端与前端的双向数据同步。返回模型实例。
示例
hs_model = Stipple.init(HelloPie)
#
Stipple.setup
— Function
function setup(model::M, channel = Genie.config.webchannels_default_route)::M where {M<:ReactiveModel}
为模型的反应属性配置反应处理程序。内部调用。
#
Base.push!
— Method
Base.push!(app::M, vals::Pair{Symbol,T}; channel::String,
except::Union{Genie.WebChannels.HTTP.WebSockets.WebSocket,Nothing,UInt}) where {T,M<:ReactiveModel}
通过`channel` 广播`vals` ,将数据有效载荷推送到前端。
#
Stipple.rendering_mappings
— Function
function rendering_mappings(mappings = Dict{String,String})
将额外的`mappings` 注册为 Julia 到 Vue 属性映射(例如`foobar` 到`foo-bar` )。
#
Stipple.julia_to_vue
— Function
function julia_to_vue(field, mapping_keys = mapping_keys())
将 Julia 名称转换为 Vue 名称(例如,将`foobar` 转换为`foo-bar` )。
#
Stipple.parse_jsfunction
— Function
function parse_jsfunction(s::AbstractString)
检查字符串是否是一个有效的 js 函数,并返回一个`Dict` ,后台的 reviver 函数可据此构建一个函数。
#
Stipple.replace_jsfunction!
— Function
function replace_jsfunction!(js::Union{Dict, JSONText})
将包含有效 js 函数的所有 JSONText 值替换为`Dict` ,该 为 reviver 函数编码。对于 JSONText 变量,它会将 dict 封装在 JSONText 中,使函数类型保持稳定。
#
Stipple.replace_jsfunction
— Function
替换输入内容副本上的所有 JSONText 值,请参见 replace_jsfunction!
.
#
Stipple.deps
— Function
function deps(channel::String = Genie.config.webchannels_default_route)
输出在页面中注入依赖项所需的 HTML 代码(页面中的
#
Stipple.@R_str
— Macro
创建一个与 vue 组件的字段绑定的 js 表达式。从内部看,这只不过是转换为符号,但它是创建带空格符号的简短版本。
示例
julia> btn("", @click("toggleFullscreen"), icon = R"is_fullscreen ? 'fullscreen_exit' : 'fullscreen'") "<q-btn label v-on:click="toggleFullscreen" :icon="is_fullscreen ? 'fullscreen_exit' : 'fullscreen'"></q-btn>"
注意:对于只包含变量名的表达式,我们建议使用符号符号表示法
julia> btn("", @click("toggleFullscreen"), icon = :fullscreen_icon) "<q-btn label v-on:click="toggleFullscreen" :icon="fullscreen_icon"></q-btn>"
#
Observables.on
— Function
on(f, observable::AbstractObservable; weak = false, priority=0, update=false)::ObserverFunction
将函数`f` 添加为`observable` 的监听器。每当观察值
的值通过`observable[] = val` 被设置,f
就会被`val` 调用。
返回一个封装了`f` 和`observable` 的`ObserverFunction` ,并允许通过调用`off(observerfunction)` 而不是`off(f, observable)` 来轻松断开连接。如果想从一个旧的`Observable` 计算出一个新的 ,请使用`map(f, ::Observable)` 。
如果设置了`weak = true` ,一旦返回的`ObserverFunction` 不再被任何地方引用并被垃圾回收,新连接就会被删除。如果某个父对象与外部可观察对象建立连接,并存储由此产生的`ObserverFunction` 实例,这将非常有用。然后,一旦该父对象被垃圾回收,弱可观察对象连接就会自动移除。
示例
julia> obs = Observable(0)
Observable(0)
julia> on(obs) do val
println("current value is ", val)
end
ObserverFunction defined at REPL[17]:2 operating on Observable(0)
julia> obs[] = 5;
current value is 5
我们还可以给回调设置优先级,这样就可以在调用其他回调之前或之后调用特定的回调,而不受注册顺序的影响。优先级最高的回调会被优先调用,默认值为 0,可以使用整个 Int 范围。因此可以这样做
julia> obs = Observable(0)
julia> on(obs; priority=-1) do x
println("Hi from first added")
end
julia> on(obs) do x
println("Hi from second added")
end
julia> obs[] = 2
Hi from second added
Hi from first added
如果设置`update=true` ,on 将立即调用 f(obs[]):
julia> on(Observable(1); update=true) do x
println("hi")
end
hi
onbutton(f::Function, button::R{Bool}; async = false, weak = false)
将函数与反应布尔参数(通常代表应用程序的一个按钮)相连。函数调用后,参数会被设置为 false。async
关键字指定调用是否应同步进行。
示例
onbutton(model.save_button) do
# save what has to be saved
end
#
Stipple.@js_str
— Macro
@js_str -> JSONText
构建一个 JSONText,如`js"button=false"` ,无需插值和取消转义(引号除外`“ ,仍需转义)。避免转义`”
可以通过js"""alert("Hello World")""
来实现。
#
Stipple.@kwredef
— Macro
@kwredef(expr)
开发过程中的辅助函数,可一对一替代`@kwdef` ,但允许重新定义结构体。
它在内部定义了一个新的结构体,并在原结构体名称后附加了一个数字,然后将该结构体赋值给一个具有原结构体名称的变量。
#
Stipple.@kwdef
— Macro
Stipple.@kwdef
模型定义的辅助函数,可一对一地替代`Base.@kwdef` 。
当`Genie.Configuration.isprod() == true` 时,该宏调用`@kwredef` 并允许重新定义模型。否则,它将调用`Base.@kwdef` 。