今天有这样一个需求,PC端新加一个第三方链接的字段,H5需要将第三方链接展示出来(之后再在小程序上展示)
最开始我配好的链接就直接拿去显示了,它会显示这个图标:
查了一下说是微信官方拒绝非同域网站用iframe将其嵌套,于是根据这个大佬的文章最后解决了这个问题:https://blog.csdn.net/weixin_46027556/article/details/146006993?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%9C%A8iframe%E4%B8%AD%E5%B5%8C%E5%85%A5%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7%E6%96%87&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-146006993.142^v102^pc_search_result_base4&spm=1018.2226.3001.4187
一、nginx配置
nginx配置用于解决前端项目访问微信域名时的跨域问题,并实现请求转发
将所有以wx代理到mp.weixin.qq.com(公众号链接的开头)
以wxImg开头的代理到https://mmbiz.qpic.cn(公众号里图片的链接开头)
proxy_pass就是将请求头转发到微信服务器
location /wx/ {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Allow-Methods' '*';
proxy_pass https://mp.weixin.qq.com/;
}
location /wxImg/ {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Allow-Methods' '*';
proxy_pass https://mmbiz.qpic.cn/;
}
二、前端配置
我们使用的是Vue2
先在data里配置这些:
这里的proxy写你后端请求的那个地址,图片的话我记得好像是有这两种开头的所以就写了两种
proxy: 'https://xxxxxxxxx.cn/',
mapper: {
'https://mp.weixin.qq.com': 'toinfo',
'http://mp.weixin.qq.com': 'toinfo',
'https://mmbiz.qpic.cn': 'wxImg',
'http://mmbiz.qpic.cn': 'wxImg',
'https://mmecoa.qpic.cn': 'wxmmecoa',
'http://mmecoa.qpic.cn': 'wxmmecoa',
}
这样写当你请求https://mp.weixin.qq.com/article
的时候它就给你代理去请求到https://xxxxxxxxxx/toinfo/article
然后写两个方法:
proxyUrl(url) {
for (const key in this.mapper) {
if (url.startsWith(key)) {
return this.proxy + this.mapper[key] + url.slice(key.length)
}
}
console.log(url, 'url')
return url
},
async iframeLoadWxmp(url) {
try {
const iframe = this.$refs.wxIframe
// console.log(iframe,'iframe')
if (!iframe) return
// 使用fetch替代jQuery.ajax
const response = await fetch(this.proxyUrl(url))
console.log(response, 'response')
let html = await response.text()
// 替换处理逻辑
html = html
.replace(/data-src="(http[^"]+)"/g, (_, g) => `src="${this.proxyUrl(g)}"`)
.replace(/background-image: url\("(http[^&]+)/g, (_, g) =>
`background-image: url(${this.proxyUrl(g)}`)
.replace(/<meta\s+name="referrer"\s+content="[^"]+"/g,
'<meta name="referrer" content="never"')
const doc = iframe.contentDocument || iframe.contentWindow.document
// 处理背景图片
const bgUrlReg = /url\(['"]?([^'")]+)['"]?\)/g
let bgMatches
while ((bgMatches = bgUrlReg.exec(html)) !== null) {
const imgUrl = bgMatches[1]
const img = document.createElement('img')
img.src = imgUrl
doc.body.appendChild(img)
}
doc.open()
doc.write(html)
doc.close()
} catch (error) {
console.error('加载失败:', error)
}
}
<iframe v-if="urlFlag" ref="wxIframe" style="width: 100vw; height: 100vh;"></iframe>
第一个方法是遍历、匹配、替换,拿到代理后的地址,已经拿到了主地址
第二个方法是处理一些嵌套的资源,图片之类的就不详细看了
iframe标签这里高度我写了100%之后还是那么一小条,然后我才想起来vh、vw这个单位,用这个就ok了
完事之后就在mounted里调用就可以了
this.$nextTick(() => {
setTimeout(() => {
this.iframeLoadWxmp(this.$route.query.thirdPartyUrl);
}, 100); // 适当延迟
});
本来是直接调用函数的,结果展示出来永远是一片白,本来以为是我哪里配置的不对,找半天发现是一开始就调用函数还没拿到iframe的实例,加个延迟就可以了。