最近在項目開發中遇到這樣一個問題:後端使用的是 Python Flask 框架,渲染方式爲後端渲染。而前端使用的 Vue 技術棧。頁面的顯示經過後端渲染生成的 dist 包中的 index.html
文件來實現。因爲項目的歷史包袱,後端須要傳值給前端,前端須要在某些組件中使用後端渲染傳遞過來的值。可是有一點略坑:後端渲染時只能識別 vue 生成的 index.html,在 vue 中是沒法直接經過 {{ 參數名 }}
的方式直接獲取傳入參數 。本文對於這個問題給出三種可行的解決方案。javascript
Python Flask 框架中使用 render_template
函數來渲染對應的模板,該函數的第二個參數就是傳入的參數。示例代碼以下:html
@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
來進行獲取。java
在 vue 工程中的 index.html 中設置 title 以下:python
<head>
<meta chartset=utf-8>
<title>{{parm_value}}</title>
</head>
複製代碼
當目標打包文件 index.html 被渲染成功後,param_value 就會被 flask 識別出來,渲染成傳入的值。在 vue 組件中,能夠進行如下的處理:flask
mounted(){
//1. 經過 document.title 獲取值
this.pValue = document.title
//2. 從新設置 document.title 爲正常的網頁 title
document.title = "測試網頁標題"
}
複製代碼
在 vue 組件中,pValue
就是後端渲染傳入的值了。後端
在 index,html 中添加一個與 app 同級的 dom 節點bash
<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 節點。app
在 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> window.pValue = '{{parm_value}}' </script>
</body>
</html>
複製代碼
在 vue 組件中,經過 window.pValue
直接獲取渲染值。
以上,就是 Vue 前端工程中獲取後端渲染方式傳遞值的三種方式。我的推薦第2、三種方式,孰優孰劣,可斟酌使用。因爲項目是從後端渲染模板的方式逐漸升級爲先後端分離的方式,在此過程當中遇到了這個問題,梳理並總結出來,供後續查閱,避免再次入坑。