最近有空,就抽空把之前作過的公司業務組件慢慢抽離出來作成插件,也算是對近年來的技術方面作一個總結吧。css
今天要寫的是一個用vue-jsx封裝的iframe插件,可修改iframe中的樣式,隱藏滾動條,默認設置保證頁面安全等功能。不想看想直接使用的話請前往項目處pikaz-iframe,html
因爲公司爬取了一些文章,須要對文章進行展現,那麼第一時間想到的固然就是iframe了,雖然它有這樣那樣的缺點,但不得不說仍是一個方便快捷的解決方案。vue
參數 | 說明 |
---|---|
frameborder | 是否顯示iframe的邊框 |
sandbox | 啓用iframe中內容的額外限制 |
src | 被嵌套的頁面的 URL 地址 |
srcdoc | html內容 |
iframe經常使用的屬性其實也很少,大體用到的也就上面幾個:react
frameborder控制iframe是否顯示邊框,通常是設置爲0的,也就是不顯示,而後再由css來書寫邊框樣式;git
sandbox控制對iframe的內容權限控制,若是隻是須要展現頁的話,設置爲allow-same-origin allow-scripts便可,前者爲同源,後者容許iframe啓用腳本,這樣展現頁就沒法作出提交表單,容許彈窗等危險操做!,另外,當被嵌入的文檔與主頁面同源時,強烈建議不要同時使用 allow-scripts 和 allow-same-origin。若是同時使用,嵌入的文檔就能夠經過代碼刪除 sandbox 屬性。若是還有其餘需求,能夠前往MDN-iframe查看;github
src大部分人就知道了,傳入url,顯示網頁;web
srcdoc能夠傳入html內容,顯示網頁,vue中其實也有一個v-html指令能夠展現html內容,可是缺點是易受全局css樣式污染,須要作額外封裝,並且權限控制也得封裝,因此權衡之下引入網頁內容的話仍是用iframe。npm
由於iframe中的屬性太多了,咱們不可能一個個屬性去寫在模板上,因此天然就得藉助vue的渲染函數來書寫。瀏覽器
ps:別問我爲啥要用vue,公司是什麼技術棧固然就用什麼嘍,通常確實不多用vue寫jsx,都是切換到react纔會去寫,不過此次寫的時候驚奇的發現vue的jsx可使用指令了,好比v-model!amazing!安全
上代碼!
.vue file:
export default {
props: {
setting:Object
},
render () {
return (
<iframe {...{ attrs: this.attrs }}> </iframe>
);
},
computed:{
attrs(){
}
}
}
複製代碼
先使用一個setting參數來接收全部所需參數,而後在computed裏處理參數iframe標籤所需,再返回。
在attr裏處理sandbox,frameborder的默認值,默認無邊框,使用url時設置爲'allow-same-origin allow-scripts',使用html內容時設置爲'allow-scripts',保障安全。
attrs(){
const attr = {}
Object.keys(this.setting).forEach(key => {
if (!(key === 'hideScrolling' || key === 'css')) {
attr[key] = this.setting[key]
}
// 處理css樣式
if (key === 'srcdoc' && this.setting.css && this.setting.srcdoc) {
// 查找head標籤
const pattern = "<head.*(?=>)(.|\n)*?</head>"
const html = this.setting.srcdoc.match(pattern)[0]
// 插入style
const style = `<style>${this.setting.css}</style></head>`
const newHtml = html.replace("</head>", style)
const doc = this.setting.srcdoc.replace(html, newHtml)
attr[key] = doc
}
})
// 設置默認值
if (!attr.sandbox || attr.sandbox !== '') {
// 同源文檔
if (this.setting.srcdoc) {
attr.sandbox = 'allow-scripts'
} else {
attr.sandbox = 'allow-same-origin allow-scripts'
}
}
// 無邊框
if (!attr.frameborder) {
attr.frameborder = 0
}
return attr
}
複製代碼
另外由於產品有需求,就是修改文檔的滾動條,因此還須要一個修改樣式的功能:
在setting裏傳入css參數,爲css樣式代碼,以後要作的就是將css樣式插入傳入的html內容中。
先查找head標籤
const pattern = "<head.*(?=>)(.|\n)*?</head>"
const html = this.setting.srcdoc.match(pattern)[0]
複製代碼
再對head末尾處添加css樣式,並賦值到srcdoc屬性中
const style = `<style>${this.setting.css}</style></head>`
const newHtml = html.replace("</head>", style)
const doc = this.setting.srcdoc.replace(html, newHtml)
attr['srcdoc'] = doc
複製代碼
另外有些頁面不須要滾動條,因此還須要一個隱藏滾動條的功能:
谷歌瀏覽器默認的滾動條是18px寬,因此只須要在外部的容器設置寬,並設置overflow-x: hidden;內部的iframe的width比外部大18px,便可隱藏滾動條,固然,還須要考慮兼容性問題,就是有些瀏覽器滾動條不必定是18px寬,因此還須要可接收寬度值,設置iframe比外部大於這個寬度。
render () {
return (
<div id="pikaz-iframe-container">
<iframe {...{ attrs: this.attrs }} style={this.hideScrollBar}>
</iframe>
</div>
);
},
computed:{
hideScrollBar () {
if (this.setting.hideScrolling) {
if (Object.prototype.toString.call(this.setting.hideScrolling) === "[object String]") {
return { width: `calc(100% + ${this.setting.hideScrolling})` }
} else {
return { width: `calc(100% + 18px)` }
}
}
return {}
},
}
...
<style scoped>
#pikaz-iframe-container {
width: 100%;
height: 100%;
overflow-x: hidden;
}
#pikaz-iframe-container::-webkit-scrollbar {
display: none;
}
#pikazIframe {
width: 100%;
height: 100%;
}
</style>
複製代碼
只須要在iframe的加載完的onload中加入回調函數便可,比較簡單
render () {
return (
<div id="pikaz-iframe-container"> <iframe {...{ attrs: this.attrs }} style={this.hideScrollBar} id="pikazIframe"> </iframe> </div>
);
},
mounted () {
this.iframeOnload()
},
methods: {
iframeOnload () {
this.$nextTick(() => {
const iframe = document.getElementById("pikazIframe");
const that = this
iframe.onload = function () {
that.$emit("onload")
}
})
}
},
複製代碼
Talk is cheap. Show you the code.
想查看完整代碼,可前往pikaz-iframe
已上傳至npm,若有須要,可直接使用。
若是對您有幫助,請點個贊吧。