Dash应用浏览器端回调常用方法总结
本文示例代碼已上傳至我的
Github倉庫https://github.com/CNFeffery/dash-master
大家好我是費老師,回調函數是我們在Dash應用中實現各種交互功能的核心,在絕大多數情況下,我們只需要以純Python的方式編寫常規服務端回調函數即可,這也貫徹了Dash無需編寫javascript即可構建web應用的理念。
但這并不代表在Dash應用中我們只能使用Python,更*地,Dash針對回調函數編寫還提供了client side callback(我們通常稱作瀏覽器端回調)相關功能,使得我們可以在仍然使用Python編排回調函數角色的基礎上,嵌入自定義的javascript代碼片段來執行相應的回調輸入輸出邏輯,從而解決一些特殊的需求。今天的文章中,我就將帶大家一起學習Dash瀏覽器端回調常用的方法和技巧??。
閱讀本文大約需要15分鐘
瀏覽器端回調,顧名思義,其對應的函數體計算過程是在每個用戶的本地瀏覽器中執行的,這在一些特殊的場景下,可以幫助我們節省服務器算力、網絡傳輸帶寬等消耗,還可以在用戶網絡狀況很差時,提升一些用戶交互功能的流暢度,亦或是可以讓我們在Dash應用中額外引入javascript生態的功能(譬如在Dash應用中高效渲染原生echarts圖表)。
而在Dash中,我們主要有兩種定義瀏覽器端回調的方式:
1 基于app.clientside_callback編寫簡單瀏覽器端邏輯
此種瀏覽器端回調定義方式適用于執行非常簡單的javascript代碼片段,只需要為app.clientside_callback()的第一個參數傳入字符串形式的javascript函數體即可(推薦使用箭頭函數),其中函數體內部參數的輸入,以及結果的輸出,原則類似常規的回調函數。
舉個例子,我們來實現一段非常簡單的邏輯,通過按鈕的點擊,來觸發對應模態框的打開:
對應app.clientside_callback的完整應用代碼如下:
app1.py
import dash
from dash import html
import feffery_antd_components as fac
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.layout = html.Div(
[
fac.AntdButton(
'打開模態框',
id='open-modal',
type='primary'
),
fac.AntdModal(
fac.AntdParagraph('測試內容'*100),
id='modal',
title='模態框示例'
)
],
style={
'padding': '50px 100px'
}
)
app.clientside_callback(
'(nClicks) => true',
Output('modal', 'visible'),
Input('open-modal', 'nClicks'),
prevent_initial_call=True
)
if __name__ == '__main__':
app.run(debug=True)
可以看到,寫法非常簡單,對于編寫此類簡單瀏覽器端回調的需求,我們只需要用到javascript最基礎的語法,非常的方便??,再來個稍微復雜一點的例子,我們基于輪詢組件,實現當前系統時間的實時更新:
app2.py
import dash
from dash import html, dcc
import feffery_antd_components as fac
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Interval(
id='interval',
interval=1000 # 每秒觸發一次
),
fac.AntdStatistic(
id='current-datetime',
title='當前時間'
)
],
style={
'padding': '50px 100px'
}
)
app.clientside_callback(
'''(n_intervals) => {
return `${new Date().toLocaleDateString().replaceAll("/", "-")} ${new Date().toLocaleTimeString()}`
}''',
Output('current-datetime', 'value'),
Input('interval', 'n_intervals')
)
if __name__ == '__main__':
app.run(debug=True)
2 基于ClientsideFunction編寫復雜瀏覽器端回調
如果我們想要執行的瀏覽器端回調邏輯比較復雜和冗長,那么在app.clientside_callback里用字符串的方式寫大段的javascript代碼就不太高效了???♂?,相應的我們可以改為使用ClientsideFunction來定義。
使用ClientsideFunction來定義瀏覽器端回調,我們首先需要在我們的Dash應用靜態資源目錄下(默認為assets)建立相應的js文件(名稱隨意,Dash應用會自動加載靜態資源目錄下的js文件到用戶瀏覽器中),并在該js文件中按照下列格式定義若干javascript回調函數:
window.dash_clientside = Object.assign({}, window.dash_clientside, {
clientside: {
func1: () => {
// write your code logic
}
}
});
接著在相應的Python程序中配合ClientsideFunction按照下列格式關聯編排回調函數即可:
app.clientside_callback(
ClientsideFunction(
namespace='clientside',
function_name='函數名稱'
),
# 照常編排回調角色
)
廢話不多說,我們直接將上文中實時刷新系統時間的示例改造成ClientsideFunction形式以便理解:
assets/clientside_callbacks.js
window.dash_clientside = Object.assign({}, window.dash_clientside, {
clientside: {
update_datetime: (n_intervals) => {
return `${new Date().toLocaleDateString().replaceAll("/", "-")} ${new Date().toLocaleTimeString()}`
}
}
});
app3.py
import dash
from dash import html, dcc
import feffery_antd_components as fac
from dash.dependencies import Input, Output, ClientsideFunction
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Interval(
id='interval',
interval=1000 # 每秒觸發一次
),
fac.AntdStatistic(
id='current-datetime',
title='當前時間'
)
],
style={
'padding': '50px 100px'
}
)
app.clientside_callback(
ClientsideFunction(
namespace='clientside',
function_name='update_datetime'
),
Output('current-datetime', 'value'),
Input('interval', 'n_intervals')
)
if __name__ == '__main__':
app.run(debug=True)
這樣做的好處在于,我們可以把相對復雜的javascript邏輯在原生的js程序里編寫,從而配合現代化ide獲得更高效的編程體驗,并且利用ClientsideFunction形式,可以很方便地實現外部js框架的引入使用,譬如引入使用原生echarts,篇幅有限,今天先按下不表,之后另外發文舉例介紹。
3 編寫瀏覽器端回調的常用技巧
通過上文,我們知曉了Dash中構建瀏覽器端回調的基本形式,下面我們補充一些有關瀏覽器端回調的實用技巧:
3.1 配合插件快捷生成模板代碼
編寫瀏覽器端回調,尤其是配合ClientsideFunction時,其代碼格式還是有些特殊的,不過別擔心,如果你恰好在使用vscode編寫Dash應用,可以在拓展里安裝由我開發維護的插件feffery-dash-snippets,安裝完成后,可以通過輸入一些快捷短語,進行相關代碼模板的生成。
目前針對瀏覽器端回調+ClientsideFunction,在py文件中可用的快捷短語有:
-
callback-cs:oi:快速初始化具有Input和Output角色的瀏覽器端回調函數
-
callback-cs:ois:快速初始化具有Input、Output及State角色的瀏覽器端回調函數
在js文件中可用的快捷短語有:
-
callback:init:快捷生成瀏覽器端回調函數定義模板
3.2 常用對象在瀏覽器端回調中的寫法
在常規的服務端回調函數中我們經常會使用到dash.no_update、PreventUpdate、dash.callback_context等對象來輔助回調函數功能邏輯的完成,而在瀏覽器端回調中,這些對象的寫法要做一定變化:
dash.no_update
dash.no_update在瀏覽器端回調中寫作window.dash_clientside.no_update,你也可以用feffery-dash-snippets插件中的dash.no_update快捷短語生成:
PreventUpdate
PreventUpdate在瀏覽器端回調中寫作PreventUpdate,你也可以用feffery-dash-snippets插件中的PreventUpdate快捷短語生成(注意,在瀏覽器端回調中throw window.dash_clientside.PreventUpdate等價于常規回調中的raise PreventUpdate):
dash.callback_context
dash.callback_context在瀏覽器端回調中寫作window.dash_clientside.callback_context,你也可以用feffery-dash-snippets插件中的dash.callback_context快捷短語生成:
3.3 在瀏覽器端回調中返回組件元素
我們在常規回調函數中,經常會以一些組件的children或其他組件型參數為Output目標,直接返回組件元素,在Python中這樣做很稀疏平常,但是在瀏覽器端回調中,我們如果有此類需求,則需要返回規定的JSON數據格式,來表示一個組件元素:
{
props: {
// 定義當前組件的各屬性,如
id: '組件id'
},
type: '組件完整名稱,如AntdButton',
namespace: '組件所屬組件庫完整名稱,如feffery_antd_components'
}
我們還是結合實際案例來做演示,這里我們的演示功能實現了通過按鈕點擊觸發新的消息提示彈出:
具體代碼如下,可以看到只要我們按照格式返回相應的組件JSON數據,Dash就會在瀏覽器中自動進行轉換及渲染:
app4.py
import dash
from dash import html
import feffery_antd_components as fac
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.layout = html.Div(
[
fac.AntdButton(
'新的消息',
id='new-message',
type='primary'
),
html.Div(id='new-message-container')
],
style={
'padding': '50px 100px'
}
)
app.clientside_callback(
'''(nClicks) => ({
props: {
content: "新的消息,nClicks:" + nClicks,
type: "info"
},
type: "AntdMessage",
namespace: "feffery_antd_components"
})''',
Output('new-message-container', 'children'),
Input('new-message', 'nClicks'),
prevent_initial_call=True
)
if __name__ == '__main__':
app.run(debug=True)
以上就是本文的全部內容,更多有關dash應用開發的前沿知識和技巧歡迎持續關注玩轉dash公眾號。
總結
以上是生活随笔為你收集整理的Dash应用浏览器端回调常用方法总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 隐私计算应用场景
- 下一篇: 前端升级客户端自动更新