一個封裝iframe的vue插件,可修改樣式,隱藏滾動條

最近有空,就抽空把之前作過的公司業務組件慢慢抽離出來作成插件,也算是對近年來的技術方面作一個總結吧。css

今天要寫的是一個用vue-jsx封裝的iframe插件,可修改iframe中的樣式,隱藏滾動條,默認設置保證頁面安全等功能。不想看想直接使用的話請前往項目處pikaz-iframehtml

背景

因爲公司爬取了一些文章,須要對文章進行展現,那麼第一時間想到的固然就是iframe了,雖然它有這樣那樣的缺點,但不得不說仍是一個方便快捷的解決方案。vue

iframe經常使用屬性

參數 說明
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插件封裝

由於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(){

    }
  }
}
複製代碼

處理iframe屬性

先使用一個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
}
複製代碼

修改srcdoc內容的樣式

另外由於產品有需求,就是修改文檔的滾動條,因此還須要一個修改樣式的功能:

在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加載完成回調

只須要在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,若有須要,可直接使用。

最後

若是對您有幫助,請點個贊吧。

相關文章
相關標籤/搜索