美文网首页全栈笔记让前端飞
tips:在iframe中嵌入微信公众号文章

tips:在iframe中嵌入微信公众号文章

作者: 韭菜的故事 | 来源:发表于2018-11-01 13:44 被阅读11次

    最近要做一个专门嵌入外部链接或者自定义文章的页面,结果发现一旦在iframe中使用了微信公众号url嵌入就会报错:



    于是乎在查阅资料后发现这是因为微信的页面设置了响应头“frame-ancestors 'self'”,简单来说就是微信阻止了外部页面将其嵌入的行为。那么该怎么办呢,我在网上寻找一番之后倒是发现了一些基于jQuery的解决方法,虽然我的项目是VUE移动端项目,不过还是可以借鉴修改一番的,直接上核心部分代码:

            getURL(url) {
                let http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
                let realurl = http + '//cors-anywhere.herokuapp.com/' + url;
                let that = this;
                $.ajax({
                    type: 'get',
                    url: realurl,
                    success: function (res) {
                        if (res) {
                            let data = res;
                            data = data.replace(/data-src/g, 'src');
                            let htmlSrc = 'data:text/html;charset=utf-8,' + data; // 解析码解决乱码
                            that.url = htmlSrc;
                        }
                    },
                    error: function (err) {
                        console.log(err);
                        Toast('好像出错了...');
                    }
                });
                //            axios.get(realurl).then(res=>{
                //                console.log(res);
                //            },rej=>{
                //                let data = rej.data;
                //                data=data.replace(/data-src/g, "src");
                //                let html_src = 'data:text/html;charset=utf-8,' + data; //解析码解决乱码
                //                this.url = html_src;
                //            })
            }
        }
    

    首先这个方法的核心就是利用cors-anywhere.herokuapp.com这个服务端的api,将跨域请求发送出去。而本来项目里的ajax请求是用axios的,但是通过axios发送的请求只能在reject中拿到返回值,感觉这样可能不太好,于是乎我换成了zepto的ajax请求方式。而通过这个服务端api返回的data-src属性需要替换成src,最后再放入iframe中的url即可。
    完整代码:

    <template>
    ...
          <iframe :src="url"></iframe>
    ...
    </template>
    <script>
    export default {
         data: {
              details: {},
              url: ''
          },
          created() {
              // 从接口取到iframe地址
             this.getDetails({id: this.$route.params.id, type: this.$route.params.type})
               .then(res => {
                this.details = res.data.obj;
                let head = this.details.href.slice(0, 24);
                if (head === 'https://mp.weixin.qq.com') {// 是微信公众号文章
                    this.getURL(this.details.href);
                } else {// 是其它网址直接使用
                    this.url = this.details.href;
                }
            }, rej => {});    
          },
          methods: {
              getURL(url) {
                let http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
                let realurl = http + '//cors-anywhere.herokuapp.com/' + url;
                let that = this;
                $.ajax({
                    type: 'get',
                    url: realurl,
                    success: function (res) {
                        if (res) {
                            let data = res;
                            data = data.replace(/data-src/g, 'src');
                            let htmlSrc = 'data:text/html;charset=utf-8,' + data; // 解析码解决乱码
                            that.url = htmlSrc;
                        }
                    },
                    error: function (err) {
                        console.log(err);
                        Toast('好像出错了...');
                    }
                });
                //            axios.get(realurl).then(res=>{
                //                console.log(res);
                //            },rej=>{
                //                let data = rej.data;
                //                data=data.replace(/data-src/g, "src");
                //                let html_src = 'data:text/html;charset=utf-8,' + data; //解析码解决乱码
                //                this.url = html_src;
                //            })
             }
          }
    }
    </script>
    

    写在后面:这种方法虽然解决了项目的燃眉之急,但还是存在两个问题,第一是从接口取到返回值的时候会报错(内容我还看不太懂,可能因为jQuery和zepto或axios的实现方式不太相同),目前看来不会影响正常使用;第二个就是cors-anywhere.herokuapp.com这是一个第三方的api,如果能够通过自己的后台实现这种代理会更好一点。此外,如果嵌入的页面中带有视频的话,似乎视频会无法播放,这一点有待证实。

    参考内容:
    JQ-ajax使用CORS-AnyWhere实现任意跨域请求
    Content Security Policy directive: "frame-ancestors 'self'

    相关文章

      网友评论

        本文标题:tips:在iframe中嵌入微信公众号文章

        本文链接:https://www.haomeiwen.com/subject/ocwtxqtx.html