bokeh + vue

2019/3/6 更新
修改了 js 和 css 的加载方式,具体代码的修改看 github。
原本的思路其实无法解决 bokeh 的前端后台版本不同的问题。

2018/12/29 更新
我封装了一个 npm 包
https://www.npmjs.com/package/bokeh-vueopen in new window
对应的 github 地址
https://github.com/cclc/bokeh-vueopen in new window

原文:
bokeh 是 python 用来生成图表的库,类似于百度的 echart,不过 bokeh 和后台代码结合的更紧密些,可以直接导出 html 文件。
在 vue 里显示 bokeh 的图表有两种办法:
1.使用 iframe 加载 bokeh 导出的 html 文件
缺点:
① 因为不知道 html 内容的高度,事先定义高度的话会有滚动条,不美观
② 同时加载多个 iframe 时会造成页面的卡死,我本地加载 5 个页面会卡大概 10 秒,因为无法知道 iframe 内的内容什么时候加载完成,所以我也没法做 loading 界面去掩饰页面卡死
优点:
① 简单!
2.把 bokeh 的 div 和 script 传给页面,在页面上进行渲染
使用 bokeh 的 components 功能,将 div 和 js 从 plotting 里分离出来
python 的相关代码如下:

script, div = components(p, wrap_script=False)
return {'div':div, 'script':script}

wrap_script=false 是将原本包在 js 代码外的< script >标签删除,我选择了删除,因为我在页面添加节点的时候会手动加入 script 标签
在 vue 的 template 里没法加入 script 标签,所以我需要通过在 body 下动态地添加 script 的方式来运行 bokeh 的 js 代码
vue 的相关代码如下:

<!-- 通过v-html在template里加入bokeh的div -->
<div v-html="html">
</div>
// 在头部插入css代码
// 因为要保持前端和后台的bokeh版本一致,所以使用了拼接cdn路径的方式
let link = document.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute(
  "href",
  "https://cdn.pydata.org/bokeh/release/bokeh-" + bokehVersion + ".min.css"
);
link.setAttribute("type", "text/css");
document.head.appendChild(link);
// 在头部插入js代码
let script = document.createElement("script");
script.setAttribute(
  "src",
  "https://cdn.pydata.org/bokeh/release/bokeh-" + bokehVersion + ".min.js"
);
script.async = "async";
document.head.appendChild(script);
// cdn的js加载完毕后再请求bokeh参数
script.onload = () => {
  _this.axios.get("/yourUrl").then((response) => {
    _this.html = response.data.div;
    // 插入绘制script代码
    let bokehRunScript = document.createElement("SCRIPT");
    bokehRunScript.setAttribute("type", "text/javascript");
    let t = document.createTextNode(response.data.script);
    bokehRunScript.appendChild(t);
    document.body.appendChild(bokehRunScript);
    // 绘制代码执行完后关闭等待画面
    _this.loading = false;
  });
};

缺点:
① 相比 iframe 方式要多写代码
优点:
① 性能更好,每次只传输所需的内容,数据包小
② 显示更好,没有上下滚动条了
③ 体验更好,可以加入 Loading 画面了

踩坑点:
①npm 上的 vue-bokeh 库是不能用的
它通过在 template 里添加 script 标签来运行 bokeh 的 js 代码,首先编译就通不过,不过它提供给我了 components 的思路

<template>
  {{{plot.div}}}
  <script>
    {
      {
        {
          plot.script;
        }
      }
    }
  </script>
</template>

<script>
export default {
  props: {
    plot: Object,
  },
  ready() {
    eval(this.plot.script);
  },
};
</script>

② 注意前端和后台的 bokeh 版本,版本不同会有渲染问题
③ 我有试过用 eval()的方式运行 bokeh 的 js,可能因为作用域的问题无法正常运行

如果有相关问题可以联系我