最近有空,就抽空把以前做过的公司业务组件慢慢抽离出来做成插件,也算是对近年来的技术方面做一个总结吧。
今天要写的是一个用vue-jsx封装的iframe插件,可修改iframe中的样式,隐藏滚动条,默认设置保证页面安全等功能。不想看想直接使用的话请前往项目处pikaz-iframe,
背景
由于公司爬取了一些文章,需要对文章进行展示,那么第一时间想到的当然就是iframe了,虽然它有这样那样的缺点,但不得不说还是一个方便快捷的解决方案。
iframe常用属性
参数 | 说明 |
---|---|
frameborder | 是否显示iframe的边框 |
sandbox | 启用iframe中内容的额外限制 |
src | 被嵌套的页面的 URL 地址 |
srcdoc | html内容 |
iframe常用的属性其实也不多,大致用到的也就上面几个:
frameborder控制iframe是否显示边框,一般是设置为0的,也就是不显示,然后再由css来书写边框样式;
sandbox控制对iframe的内容权限控制,如果只是需要展示页的话,设置为allow-same-origin allow-scripts即可,前者为同源,后者允许iframe启用脚本,这样展示页就无法做出提交表单,允许弹窗等危险操作!,另外,当被嵌入的文档与主页面同源时,强烈建议不要同时使用 allow-scripts 和 allow-same-origin。如果同时使用,嵌入的文档就可以通过代码删除 sandbox 属性。如果还有其他需求,可以前往MDN-iframe查看;
src大部分人就知道了,传入url,显示网页;
srcdoc可以传入html内容,显示网页,vue中其实也有一个v-html指令可以展示html内容,但是缺点是易受全局css样式污染,需要做额外封装,而且权限控制也得封装,所以权衡之下引入网页内容的话还是用iframe。
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")
}
})
}
},
ps:评论区有小伙伴提醒iframe的onload在404的情况下也会触发,回去之后尝试着解决一下这个问题,结果发现传入url时iframe跨域没法获取iframe的dom,自然也没法判断是否是404页面了,如果有更好的方法欢迎在评论区留言。
项目地址
Talk is cheap. Show you the code.
想查看完整代码,可前往pikaz-iframe
已上传至npm,如有需要,可直接使用。
最后
如果对您有帮助,请点个赞吧。
今天的文章一个封装iframe的vue插件,可修改样式,隐藏滚动条分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/19832.html