前言
最近在项目开发中遇到这样一个问题:后端使用的是 Python Flask 框架,渲染方式为后端渲染。而前端使用的 Vue 技术栈。页面的显示通过后端渲染生成的 dist 包中的 index.html
文件来实现。由于项目的历史包袱,后端需要传值给前端,前端需要在某些组件中使用后端渲染传递过来的值。但是有一点略坑:后端渲染时只能识别 vue 生成的 index.html,在 vue 中是无法直接通过 {{ 参数名 }}
的方式直接获取传入参数 。本文对于这个问题给出三种可行的解决方案。
后端如何传值
Python Flask 框架中使用 render_template
函数来渲染对应的模板,该函数的第二个参数就是传入的参数。示例代码如下:
@app.route('/test')
def test_pass_parm():
parm_value = 'I am value from backend'
return render_template('test/dist/index.html', parm_value)
上面代码是一个 Flask 中比较常规的写法。parm_value 是后端要传给 index.html 模板中的值, index.html 是 Vue 中生成的打包文件。在 index.html 中,可以使用 {{ parm_value }}
在模板中展示后端传入的值。
PS: Python Flask 渲染时,可能会因为 {{ }} 符号原因,与 vue 的插值语法有冲突,后端无法识别并正常渲染,需要修改 Vue 的分隔符 delimiters 项来避免后端渲染错误。
Vue 中如何获取
方式一
通过 index.html 中的 title 渲染值,在 vue 组件中通过 document.title
来进行获取。
在 vue 工程中的 index.html 中设置 title 如下:
<head>
<meta chartset=utf-8>
<title>{{parm_value}}</title>
</head>
当目标打包文件 index.html 被渲染成功后,param_value 就会被 flask 识别出来,渲染成传入的值。在 vue 组件中,可以进行以下的处理:
mounted(){
//1. 通过 document.title 获取值
this.pValue = document.title
//2. 重新设置 document.title 为正常的网页 title
document.title = "测试网页标题"
}
在 vue 组件中,pValue
就是后端渲染传入的值了。
方式二
在 index,html 中添加一个与 app 同级的 dom 节点
<html>
<head>
<meta>
<title></title>
</head>
<body>
<input id="test-dom" type="hidden" value="{{parm_value}}">
<div id="app"></div>
</body>
</html>
也许你会问一个问题,为什么不将 dom 结点放在 div#app
内部?答案很简单:因为生成的 dom 节点若在 div#app
内,运行时会被替换掉,在 vue 组件中无法获取到对应的 dom 节点。
在 vue 组件中处理:
mounted() {
// 1. 获取对应的 dom 节点
let testDom = document.getElementById('test-dom')
// 2. 获取 dom 节点对应的值
let pValue = testDom.value
}
方式三
在 index.html 中新增 script 标签进行渲染,通过 window.xxx 进行获取
<html>
<head>
<meta>
<title></title>
</head>
<body>
<input id="test-dom" type="hidden" value="{{parm_value}}">
<div id="app"></div>
<script></script>
</body>
</html>
在 vue 组件中,通过 window.pValue
直接获取渲染值。
总结
以上,就是 Vue 前端工程中获取后端渲染方式传递值的三种方式。个人推荐第二、三种方式,孰优孰劣,可斟酌使用。由于项目是从后端渲染模板的方式逐渐升级为前后端分离的方式,在此过程中遇到了这个问题,梳理并总结出来,供后续查阅,避免再次入坑。