需求是這樣的:
後臺傳參傳過來一個 html 文本,需要渲染在頁面上
那按照通常的做法,是利用 vue 的 v-html 指令,直接渲染
像這樣: <span v-html="rawHtml"></span>
但問題是,後臺傳過來的 html 文本是帶有插值的字符串
像這樣: <div style="color:#67C23A">{{str.name}}</div>
我們知道 v-html 只能渲染靜態html,所以我們需要使用 Vue.component來註冊全局組件,在 template 屬性中插入帶有插值的 html
html:
<component
:is="mytemplate"
:str="showdata"
ref="printitem"
></component>
js:
添加測試數據:
data() {
return {
showdata:{
id:0,
name:'小明'
}
};
},
註冊模板
var mstr = '<div style="color:#67C23A">{{str.name}}</div>';
Vue.component("mytemplate", {
props: ["str"],
template: mstr
});
注意: html組件裏的傳參名稱,添加的 dom 節點中的對象名,註冊模板時的 props 名稱,這三者一定要一致
這裏插播一個開發時遇到的另一個問題,後臺接口傳過來的是一個 html 文件,而不是通常我們接收到的 json 對象,所以我們無法使用封裝好的請求函數,需要另外寫
axios
.post(
"/university-facade/file/download.shtml?id=" + this.queryObj.template,
{
headers: {
"Content-Type": "text/html"
}
}
)
.then(response=> {
},
err => {
}
);
像這樣把請求頭改成"text/html"就可以了
如果傳的是別的類型的文件,可以參考下圖修改器請求頭的參數
那如果我們需要加載很多組模板的時候應該怎麼辦呢
首先我們循環註冊多個組件
list.map((item, index) => {
var str = '<div style="color:#67C23A">{{item.htmlstr}}</div>';
Vue.component(`cmp-${index}`, {
props: ["row"],
template: str
});
});
在 html 中循環渲染註冊的這些組件
<component
v-for="(row,index) in list"
:key="index"
:is="getComponentName(index)"
:row="row"
></component>
在 getComponentName 函數中綁定is 屬性,從而確定應該渲染哪一個模板
getComponentName(index) {
return `cmp-${index}`;
}