Vue和iframe跨域调用

Test.js 在iframe内的html页面引入

// 在iframe子页面引入该js
window.addEventListener ('message', function(event) {
    /**
     * 可以在这个地方调用HTML
     */
    console.log('调用HTML')
    if (event&&event.data){
        console.log(event.data)
        console.log('开始执行调用HTML')
        //ifream加载完成时调用vue中的load方法,将父组件的所有方法告诉ifream中的页面
        event.data.parentFunctions&&event.data.parentFunctions.forEach(key=>{
            this.__proto__[key]=function (params) {
                //调用父类
                window.parent.postMessage ({functionName:key,params:params}, '*');
            }
        })
        //vue页面传入数据如果是调用html方法 则使用此方法
        event.data.functionName&&this[event.data.functionName](event.data.params)
    }
});

child2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="Test.js"></script>
    <script>
        function lodaTable(data) {
            this.skipHtml({name:'test01',functionName:'changge',params:{personName:'张三'}})
            console.log('name---->'+data)
        }
    </script>
</head>
<body>
<button onclick="lodaTable()">打开下一页</button>
<h1>首页</h1>
</body>
</html>

404.html 页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>404</h1>
</body>
</html>

Home.vue 

<template>
  <div class="iframestyleset">
    <button @click="invokeHtmlMethod({
        name:'test01',
        url:'static/test01.html'
      })">调用html方法
    </button>
    <a href="https://www.baidu.com/">打开百度</a>
    <button @click="goBack()">回退</button>
    <iframe style="background-color: #42b983" v-for="(item,index) in cachePath " name="iframeMap" :id="item.name"
            :src="item.url" width="100%" height="200px" @load="load(item)" frameborder="0" scrolling="no"
            ref="iframeDom"></iframe>
  </div>
</template>
<script>
export default {
  data() {
    return {
      getPageUrl: 'static/child2.html',
      currentPages: [{
        name: 'test01',
        url: 'static/test01.html'
      }, {
        name: 'test02',
        url: 'static/test02.html'
      }, {
        name: 'test03',
        url: 'static/test03.html'
      }],
      cachePath: [{
        name: 'child2',
        url: 'static/child2.html'
      }]
    }
  },
  created() {
    // 绑定监听,主要是为了接收html页面发来的消息
    window.addEventListener('message', event => {
      console.log('html子页面传来的数据')
      console.log(event)
      //执行子页面想要调用的方法
      if (event && event.data) {
        event.data.functionName && this[event.data.functionName](event.data.params)
      }
    })
  },
  mounted() {
    let jz = this.cachePath.findIndex(item => item.name == 'child3')
    console.log('jz===>' + jz)
  },
  methods: {
    skip(page={name:undefined,functionName:undefined,params:undefined,type:undefined}) {
      if (page.type === 'html' || page.type == '1') {
        this.skipHtml(page)
      } else if (page.type === 'vue' || page.type == '2') {
        this.skipVue(page)
      } else {
        throw Error('page type no null (缺少type参数 vue | html | 1 | 2)')
      }
    },
    /**
     * vue 跳转
     * {name:vue名称,params:要传入的数据}
     */
    skipVue(page={name:undefined,params:undefined}) {
      // {name: "deepReadingDetail", params: {'id': data.id, 'title': data.title}}
      console.log('跳转Vue:' + page)
      this.$router.push(page)
    },
    /**
     * html 跳转
     *  {name:html名称,functionName:要调用的函数名称,params:要调用的函数要传入的数据}
     */
    skipHtml(page={name:undefined,functionName:undefined,params:undefined}) {
      console.log('跳转html:' + JSON.stringify(page))
      alert('跳转html:' + JSON.stringify(page))
      //1.首先判断这个地址是否存在
      let currentPage = this.currentPages.find(item => item.name == page.name)
      if (currentPage) {
        //2.判断是否已经加载过
        let jz = this.cachePath.findIndex(item => item.name == page.name)
        Object.assign(page, currentPage)//合并对象
        alert('page--->' + JSON.stringify(page))
        if (jz > -1) {
          //已经记载 则置顶
          alert('已经记载 则置顶'+jz)
          if (!(jz>=this.cachePath.length-1)){
            alert(5555555)
            this.cachePath.push(this.cachePath.splice(jz, 1)[0])
          }
          this.load(page)
        } else {
          alert('没有加载过 则添加')
          //没有加载过 则添加
          this.cachePath.push(page)
        }
      } else {
        if (this.cachePath[this.cachePath.length-1].name!='404'){
          this.cachePath.push({name: '404',url: 'static/404.html'})
        }
      }
    },

    invokeHtmlMethod(page) {
      let frame = document.getElementById(page.name)
      frame.contentWindow.postMessage(page, '*');
    },

    load(page) {
      this.$nextTick(() => {
        //1.获取到iframe对象
        let frame = document.getElementById(page.name)
        //2.给对象的contentWindow添加监听事件 parentFunctions(当前vue页面中的方法不要以$和_开头)
        let parentFunctions = Object.keys(this).filter(key => {
          if (!key.startsWith('$') && !key.startsWith('_') && typeof this[key] === 'function') {
            return key
          }
        })
        //3.告诉html页面 上个页面 要对他进行的操作 {parentFunctions:当前vue页面中的方法集合(必传),
        // functionName:要调用的html中的方法(可空),
        // params:要调用的html中的方法所传的参数(可空)
        // }
        //在将要进入的页面 可以直接使用this.方法名(参数)使用当前vue页面中的所有方法
        frame.contentWindow.postMessage(Object.assign({parentFunctions: parentFunctions},page), '*');
      })
    },
    goBack() {
      if (this.cachePath.length>1){
        this.cachePath.pop()
      }
    }
  }
}
</script>

Vue目录结构

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue中可以使用iframe标签来调用外部的网页或者插件,但是由于浏览器的同源策略限制,可能会出现跨域访问的问题。 要解决跨域访问问题,可以在Vue的配置文件中进行一些设置。首先,需要在vue.config.js文件中添加以下配置: ```javascript module.exports = { devServer: { proxy: { "/api": { // 需要代理的路径 target: "http://example.com", // 目标服务器的地址 changeOrigin: true, // 是否改变origin字段的值 pathRewrite: { "^/api": "" // 将path中符合“/api”的部分替换为空字符 } } } } } ``` 上述配置中,我们定义了一个代理路径`/api`,它会指向目标服务器`http://example.com`。而在iframe调用插件时,可以将src属性设置为代理路径`/api`加上插件的地址,例如: ```html <iframe src="/api/plugin"></iframe> ``` 这样,Vue会将请求转发到目标服务器,绕过跨域限制,从而实现调用插件功能。 同时,需要在后端服务器的响应头中设置正确的CORS(跨域资源共享)规则。在目标服务器上的接口响应中添加以下响应头: ```javascript Access-Control-Allow-Origin: * ``` 这样就能允许所有的来源都可以访问目标服务器上的接口。 需要注意的是,由于跨域访问涉及到安全问题,浏览器和服务器会限制一些跨域请求,比如限制了跨域访问的Cookie等信息,因此在实际开发中,可能还需要进行更多的配置和处理来确保安全和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值