可以看到,我们安插在回调函数里的dash.callback_context帮我们记录了从访问Dash开始,到最近一次执行回调期间,对应回调的输入输出信息变化情况、最近一次触发信息,非常的实用,可以支撑起很多复杂应用场景。
2.4 在浏览器端执行回调过程Dash虽然很方便,使得我们可以完全不用书写js代码就可以实现各种回调交互,但把所有的交互响应计算过程都交给服务端来做,省事倒是很省事,但会给服务器带来不小的计算和网络传输压力。
因此很多容易频繁触发且与主要的数值计算无关的交互行为,完全可以搬到浏览器端执行,既快速又不吃服务器的计算资源,这也是当初JavaScript被发明的一个重要原因,而在Dash中,也为略懂js的用户提供了在浏览器端执行一些回调的贴心功能。
从一个很简单的点击按钮,实现部分网页内容的打开与关闭出发,这里我们提前使用到dbc.Collapse部件,用于将所包含的网页内容与其它按钮部件的点击行为进行绑定:
app5.py
import dash import dash_bootstrap_components as dbc import dash_html_components as html from dash.dependencies import Input, Output, State app = dash.Dash(__name__) app.layout = html.Div( dbc.Container( [ html.Br(), html.Br(), html.Br(), dbc.Button('服务端回调',), dbc.Collapse('服务端折叠内容',), html.Hr(), dbc.Button('浏览器端回调',), dbc.Collapse('浏览器端折叠内容',), ] ) ) @app.callback( Output('server-collapse', 'is_open'), Input('server-button', 'n_clicks'), State('server-collapse', 'is_open'), prevent_initial_call=True ) def server_callback(n_clicks, is_open): return not is_open # 在dash中定义浏览器端回调函数的特殊格式 app.clientside_callback( """ function(n_clicks, is_open) { return !is_open; } """, Output('browser-collapse', 'is_open'), Input('browser-button', 'n_clicks'), State('browser-collapse', 'is_open'), prevent_initial_call=True ) if __name__ == '__main__': app.run_server(debug=True)可以看到,服务端回调我们照常写,而浏览器端回调通过传入一个非常简单的js函数,在每次回调时接受输入并输出is_open的逻辑反值,从而实现了折叠内容的打开与关闭切换:
function(n_clicks, is_open) { return !is_open; }便实现了浏览器端回调!
图6而如果你想要执行的浏览器端js回调函数代码有点长,还可以按照下图格式,把你的大段js回调函数代码放置于assets目录下对应路径里的js脚本中:
图7接着再在dash中按照下列格式编写关联输入输出与上述js回调的简短语句即可:
app.clientside_callback( ClientsideFunction( namespace='命名空间名称', function_name='对应js回调函数名' ), ''' 按顺序组织你的Output、Input以及State... ... ''' )下面我们直接以大家喜闻乐见的数据可视化顶级框架echarts为例,来写一个根据不同输入值切换渲染出的图表类型,注意请从官网把依赖的echarts.min.js下载到我们的assets路径下对应位置,它会在我们的Dash应用启动时与所有assets下的资源一起自动被载入到浏览器中:
app6.py
import dash import dash_bootstrap_components as dbc import dash_html_components as html import dash_core_components as dcc from dash.dependencies import Input, Output, ClientsideFunction app = dash.Dash(__name__) # 编写一个根据dropdown不同输入值切换对应图表类型的小应用 app.layout = html.Div( dbc.Container( [ html.Br(), dbc.Row( dbc.Col( dcc.Dropdown(, options=[ {'label': '折线图', 'value': '折线图'}, {'label': '堆积面积图', 'value': '堆积面积图'}, ], value='折线图' ), width=3 ) ), html.Br(), dbc.Row( dbc.Col( html.Div( html.Div(, style={ 'height': '100%', 'width': '100%' } ), style={ 'width': '800px', 'height': '500px' } ) ) ) ] ) ) app.clientside_callback( # 关联自编js脚本中的相应回调函数 ClientsideFunction( namespace='clientside', function_name='switch_chart' ), Output('main', 'children'), Input('chart-type', 'value') ) if __name__ == '__main__': app.run_server(debug=True) 图8效果十分惊人,从此我们使用Dash不仅仅可以使用Python生态的工具,还可以配合对前端内容支持更好的js,起飞!