欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue3中如何使用iframe嵌入vue2頁面

 更新時間:2023年10月10日 17:10:46   作者:小何同學(xué)要加油  
這篇文章主要介紹了vue3中如何使用iframe嵌入vue2頁面問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

vue3使用iframe嵌入vue2頁面

vue3中使用iframe嵌入vue2頁面或vue頁面和iframe頁面的相互傳參問題

記錄一個開發(fā)過程中遇到的問題,Vue3項目中嵌入了一個iframe,iframe里面的是一個vue2項目的頁面,是項目趕工計較著急,來不及把vue2集成到vue3中,這時候想到用Vue3和Vue2之間來回互調(diào)傳參,下面提供解決思路。

Vue3 父組件

<template>
  <div class="content">
    <iframe
      id="unityiframe"
      ref="iframeRef"
      name="iframeContain"
      seamless
      scrolling="yes"
      :src="srcUrl"
      style="width: 100%; height: 70vh; border: 0"
    >
    </iframe>
  </div>
</template>
<script>
import { reactive, toRefs,  onMounted, ref,watch, nextTick,
         getCurrentInstance,} from "vue";
export default {
setup() {
    //接受子組件穿過來的值
    function handleMessage(event) {
      console.log("子頁面?zhèn)鬟^值event", event.data);
      var datalist = event.data;
      if (datalist) {
        sendMessage();
      }
    }
    // 調(diào)用vue中g(shù)etCurrentInstance方法(此參考V2和V3中this.$refs區(qū)別)
    const currentInstance = getCurrentInstance();
    function sendMessage() {
      //  currentInstance.ctx.$refs是vue3的寫法。vue2中是 this.$refs
      if (currentInstance.ctx.$refs.iframeRef) {
        //判斷他不為空,可根據(jù)自己的頁面判斷
        currentInstance.ctx.$refs.iframeRef.contentWindow.postMessage(
          // 向子頁面iframe傳遞
          "aaa", //傳遞的參數(shù)
          "http://10.1.0.238:88/#/workspace/formsPanel" //iframe的頁面地址
        );
      }
    }
    nextTick(() => {
      window.addEventListener("message", handleMessage);
    });
    return{
    handleMessage,
    currentInstance,
    sendMessage
    }
    }}
   </script>

Vue2 子組件(1)

  mounted() {
    //給父頁面發(fā)送消息
    window.parent.postMessage(
      "111",
      "http://10.1.0.238:8080/#/application/function"
    );
    //監(jiān)聽父頁面發(fā)送過來的消息
    window.addEventListener("message", this.handleMessageFromParent);
  },
  methods: {
    // 接收父頁面發(fā)送的消息
    handleMessageFromParent(event) {
      console.log("父頁面?zhèn)鬟^值event", event.data);
    },

Vue2 子組件(2)

 mounted() {
    //給父頁面發(fā)送消息
    window.parent.postMessage(
      "111",
      "http://10.1.0.238:8080/#/application/function"
    );
   window.addEventListener("message", (e) => {
       //接收父頁面發(fā)送的消息
        console.log("e",e)
  })
  },
  methods: {

vue項目嵌套(vue2嵌套vue3)

實(shí)現(xiàn)思路

  • 產(chǎn)品測評通過 iframe 將產(chǎn)品庫加載進(jìn)來。
  • 創(chuàng)建 template.vue 中間頁,使用path參數(shù)攜帶產(chǎn)品庫url,并通過傳遞用戶信息和路由信息實(shí)現(xiàn)產(chǎn)品庫自動登陸。
  • 使用 postMessgae API 實(shí)現(xiàn)父子項目間的數(shù)據(jù)通信。

實(shí)現(xiàn)步驟

創(chuàng)建 Store/template 模塊,定義產(chǎn)品庫相關(guān)數(shù)據(jù)。

// src/store/modlues/template.ts
const state = {
  sign: 'productLibrary', // 產(chǎn)品庫路由標(biāo)識
  routePath: '/template', // 產(chǎn)品庫跳轉(zhuǎn)中間頁path
  isFullFrame: false, // 是否設(shè)置產(chǎn)品庫Iframe全屏
  NODE_ENV: process.env.NODE_ENV, // 環(huán)境變量
  ENV_URLS: {
    development: 'http://127.0.0.1:3000',
    test: 'http://cms-test.shenlanbao.com',
    uat: 'http://cms-uat.shenlanbao.com',
    production: 'http://cms.shenlanbao.com',
  },
};
const mutations: MutationTree<any> = {
  SET_isFullFrame(state, val) {
    state.isFullFrame = val;
  },
}; 

創(chuàng)建 template.vue 中間跳轉(zhuǎn)頁路由。

// src/router/modules/page-productLibrary-router.ts
{
    path: '/template',		// 對應(yīng)Store/template.ts 的 routePath
    name: 'productLibrary',   // 對應(yīng)Store/template.ts 的 sign
    cn: '產(chǎn)品庫',
    hidden: true,
    component: () => import('@/views/productLibrary/template.vue'),
    children: [],
  }, 

點(diǎn)擊左側(cè)菜單將符合條件的路由跳轉(zhuǎn)到產(chǎn)品庫。

// src/components/common/MenuItem.vue
<script>
  methods: {
    navigateTo(e): void {
      const { frontPermission, url } = e;
      const { sign, routePath } = this.$store.state.template;
      if (frontPermission.includes(sign)) {
        if (!url) return;
        this.$router.push({
          path: routePath,
          query: { path: url },
        });
      } else {
        if (this.$route.path === url) return;
        this.$router.push({ path: url });
      }
    },
  }
</script> 

template.vue 監(jiān)聽路由并更新產(chǎn)品庫路由,同時傳遞用戶登陸信息實(shí)現(xiàn)自動登陸

// src/views/productLibrary/template.vue
<div :class="{ wrapper: true, hidemenu: $store.state.template.isFullFrame }">
	<iframe
	  :src="src"
	  frameborder="0"
	  class="sub-frame"
	  ref="frames"
	  @load="frameLoad"
	></iframe>
</div>
<script lang="ts">
@Component
export default class Index extends Vue {
  @Ref() readonly frames;
  src: string = ''; // 產(chǎn)品庫跳轉(zhuǎn)路由
  // 監(jiān)聽路由,更新產(chǎn)品庫路由
  @Watch('$route')
  toggleRoute(data) {
    this.$nextTick(() => {
      this.frameLoad();
    });
  }
  frameLoad() {
    const { path = '' } = this.$route.query;
    const auth = localStorage.getItem('auth') || '';
    if (!path || !auth) return;
    this.setSrc(path); // 設(shè)置產(chǎn)品庫跳轉(zhuǎn)路由
    const productLibraryRoutes = this.getRoutes(); // 過濾產(chǎn)品庫路由
    const permission = {
      auth,
      path,
      userInfo: localStorage.getItem('userInfo'),
      routes: productLibraryRoutes[0].childPermissionResList,
    };
	  // 傳遞用戶登陸信息實(shí)現(xiàn)自動登陸
    this.frames.contentWindow.postMessage(permission, '*');
  }
  getRoutes() {
    const localRoutes = localStorage.getItem('routes') || '';
    if (!localRoutes) return '';
    const { sign } = this.$store.state.template; // 產(chǎn)品庫跳轉(zhuǎn)路由標(biāo)識
    const routes: any[] = JSON.parse(localRoutes) || [];
    return routes.filter((i) => {
      return i.frontPermission === sign &amp;&amp; i.childPermissionResList;
    });
  }
  setSrc(path) {
    const { NODE_ENV, ENV_URLS } = this.$store.state.template;
    const domain = ENV_URLS[NODE_ENV];
    if (path &amp;&amp; domain) this.src = `${domain}${path}`;
  }
}
</script> 

產(chǎn)品庫獲取登陸信息及路由信息進(jìn)行模擬登陸操作。

// index.html
<body>
  <div id="app"></div>
  <script type="module" src="/src/main.ts"></script>
  <script>
    window.addEventListener(
      'message',
      function (event) {
        const {
          data
        } = event
        if (data.auth) {
          window.localStorage.setItem('auth', data.auth)
          window.localStorage.setItem('routes', JSON.stringify(data.routes))
          window.localStorage.setItem('userInfo', data.userInfo)
          window.localStorage.setItem('path', data.path)
        }
      },
      false,
    )
  </script>
</body>
// src/router/routerGuards.ts
export function createRouterGuards(routers: Router) {
  routers.beforeEach(async (to, _, next) => {
    const isFrame = JSON.parse(localStorage.getItem('isFrame') || '') // 是否是 iframe 加載
    if (!isFrame) {
      // 正常登陸操作
    } else {
      const hasToken = localStorage.getItem('auth') || ''
      const { addRouter } = store.state.global
      if (hasToken &amp;&amp; addRouter) {
        next()
        return
      }
      localStorage.setItem('auth', localStorage.getItem('auth') || '')
      await store.commit('global/setRoutes', JSON.parse(localStorage.getItem('routes') || ''))
      await store.commit('global/setUserInfo', JSON.parse(localStorage.getItem('userInfo') || ''))
      // 路由添加/標(biāo)記
      store.commit('global/isAddRouter', true)
      const getNewRouter = store.getters['global/getNewRouter']
      getNewRouter.forEach((route: Iroute) => {
        routers.addRoute(route)
      })
      const path = localStorage.getItem('path')
      to.path = path
      const newTo = {
        ...to,
        name: to.name || undefined,
      }
      next({ ...newTo, replace: true })
    }
  })
} 

產(chǎn)品庫向產(chǎn)品測試進(jìn)行通信

// src/utils/template.ts
// ifarame 內(nèi)嵌時向產(chǎn)品測評窗口進(jìn)行通信事件定義
const source = 'productLibrary' // 產(chǎn)品庫跳轉(zhuǎn)路由標(biāo)識
const posMessage = function (config) {
  const message = Object.assign({ source }, config)
  return new Promise((resolve) => {
    top.postMessage(message, '*')
    resolve(true)
  })
}
// 是否設(shè)置全屏遮罩
export function postFrameCover(val) {
  const config = {
    fnName: 'setIframeCover',
    params: val,
  }
  return posMessage(config)
}
// 跳轉(zhuǎn)產(chǎn)品測評頁面
export function postTopRouter(path) {
  if (!path) return
  const config = {
    fnName: 'setRoute',
    params: path,
  }
  return posMessage(config)
} 

問題總結(jié)及解決方案

左側(cè)菜單路由高亮狀態(tài)

展示產(chǎn)品庫頁面時,對應(yīng)左側(cè)菜單路由要相應(yīng)高亮選中。

在監(jiān)聽路由跳轉(zhuǎn)時,判斷當(dāng)跳轉(zhuǎn)產(chǎn)品庫頁面時,取 query 中的 path 字段為 url 做高亮處理。

// src/components/Nav.vue
<script>
@Watch('$route', { immediate: true })
  handlerRouteChange(to: Route): void {
    this.active = to.path;
    this.setProductRoute(to); // 判斷產(chǎn)品庫路由
  }
  setProductRoute(to) {
    const { name = '', query = {} } = to;
    const { sign } = this.$store.state.template; // 產(chǎn)品庫跳轉(zhuǎn)路由標(biāo)識
    const isProductLibRoute = name === sign &amp;&amp; query.path;
    if (isProductLibRoute) {
      this.active = query.path;
    }
  }
</script> 

產(chǎn)品測評面包屑導(dǎo)航頁面路徑

展示產(chǎn)品庫頁面時,對應(yīng)上方面包屑導(dǎo)航要顯示正確的路由名稱。

在監(jiān)聽路由跳轉(zhuǎn)時,判斷當(dāng)跳轉(zhuǎn)產(chǎn)品庫頁面時,取 query 中的 path 字段為 url 做高亮處理。

// src/components/common/BaseHeard.vue
<script>
@Watch('$route')
  $routeWatch(to: Iobj) {
    this.getBar(to);
  }
  getBar(route) {
    let pathName = this.getRoutePath(route);
    let name = '';
    let barList: Array<Iobj> = [];
    let pathArr = pathName.split('/').filter((_) => _);
    let newArr = [
      ...this.getNewRouter,
      ...(this.$router as any).options.routes,
    ];
    for (let i of pathArr) {
      name = name + `/${i}`;
      for (let j of newArr) {
        if (j.path === name) {
          barList.push({
            cn: j.cn,
            path: j.path,
          });
          break;
        }
      }
    }
    this.arr = barList;
  }
  // 獲取當(dāng)前路由path
  getRoutePath(route) {
    let { path: pathName, query } = route;
    const { routePath } = this.$store.state.template;
    // 如果產(chǎn)品庫的路由,修改為取query下的path為路由名稱
    if (pathName === routePath) {
      const { path = '' } = query;
      if (path) return path;
    } else {
      return pathName;
    }
  }
</script> 

Dialog彈出窗遮罩覆蓋

當(dāng)點(diǎn)擊彈窗時,通知父窗口,同步修改外層樣式。

// 產(chǎn)品庫
<el-button @click="handleMask()">測試彈窗</el-button>
<script>
import { postFrameCover } from '@utils/template'
handleMask() {
  postFrameCover(true).then(() => {
	  this.showDialog = true
  })
}
</script>
// 產(chǎn)品測評 template.vue
setIframeCover(val) {
  this.$store.commit('template/SET_isFullFrame', val);
}
// 產(chǎn)品測評 App.vue
// 修改左側(cè)菜單的z-index,使遮罩在最頂層
<nav class="nav" :class="{ hidemenu: $store.state.template.isFullFrame }">
  <app-nav />
</nav>
.hidemenu {
  background: rgba(0, 0, 0, 0.5);
  z-index: 100;
}
// 產(chǎn)品測評 template.vue
<div :class="{ wrapper: true, hidemenu: $store.state.template.isFullFrame }">
	<iframe
	  :src="src"
	  frameborder="0"
	  class="sub-frame"
	  ref="frames"
	  @load="frameLoad"
	></iframe>
</div>
.hidemenu {
  background: rgba(0, 0, 0, 0.5);
  z-index: 100;
} 

產(chǎn)品庫子項目跳轉(zhuǎn)產(chǎn)品測評頁面

// 產(chǎn)品庫
<el-button type="primary" @click="handleArticle()">跳轉(zhuǎn)產(chǎn)品測評文章詳情</el-button>
<script>
import { postTopRouter } from '@utils/template'
handleArticle() {
  const route = {
	path: '/article/articleAdd',
	query: {
	  id: '795964024911646720',
	},
  }
  postTopRouter(route)
}
</script> 

產(chǎn)品庫判斷當(dāng)前項目是在iframe中還是web中

// index.html
<head>
  <script>
    // 判斷是在iframe還是web
    let isFrame = false
    if (window.frames.length != parent.frames.length) isFrame = true
    window.localStorage.setItem('isFrame', isFrame)
  </script>
</head> 

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue中使用iframe嵌入網(wǎng)頁,頁面可自適應(yīng)問題

    vue中使用iframe嵌入網(wǎng)頁,頁面可自適應(yīng)問題

    這篇文章主要介紹了vue中使用iframe嵌入網(wǎng)頁,頁面可自適應(yīng)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue3+vite assets動態(tài)引入圖片的三種方法及解決打包后圖片路徑錯誤不顯示的問題

    vue3+vite assets動態(tài)引入圖片的三種方法及解決打包后圖片路徑錯誤不顯示的問題

    這篇文章主要介紹了vue3+vite assets動態(tài)引入圖片的幾種方式,解決打包后圖片路徑錯誤不顯示的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • vuex新手進(jìn)階篇之取值

    vuex新手進(jìn)階篇之取值

    Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式,下面這篇文章主要給大家介紹了關(guān)于vuex新手進(jìn)階篇之取值的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • 56個實(shí)用的JavaScript 工具函數(shù)助你提升開發(fā)效率

    56個實(shí)用的JavaScript 工具函數(shù)助你提升開發(fā)效率

    今天來看看JavaScript中的一些實(shí)用的工具函數(shù),希望能幫助你提高開發(fā)效率!需要的朋友可以參考下面文章的具體內(nèi)容
    2021-10-10
  • Vue?關(guān)于$emit與props的使用示例代碼

    Vue?關(guān)于$emit與props的使用示例代碼

    父組件使用 props 把數(shù)據(jù)傳給子組件,子組件使用 $emit 觸發(fā)父組件的自定義事件,今天通過示例給大家詳細(xì)介紹下Vue?關(guān)于$emit與props的使用,感興趣的朋友一起看看吧
    2022-03-03
  • vue.js入門(3)——詳解組件通信

    vue.js入門(3)——詳解組件通信

    這篇文章主要介紹了vue.js入門(3)——詳解組件通信 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。
    2016-12-12
  • vue.js的安裝方法

    vue.js的安裝方法

    這篇文章主要為大家詳細(xì)介紹了vue.js的安裝方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Vue實(shí)現(xiàn)Tab選項卡切換

    Vue實(shí)現(xiàn)Tab選項卡切換

    這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)Tab選項卡切換,點(diǎn)擊不同標(biāo)題顯示對應(yīng)圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • vue元素樣式實(shí)現(xiàn)動態(tài)改變方法介紹

    vue元素樣式實(shí)現(xiàn)動態(tài)改變方法介紹

    vue通過js動態(tài)修改元素的樣式,如果是固定的幾個樣式,我常用的是綁定元素的calss,給不同的class寫好需要的樣式,js控制是否使用這個class
    2022-09-09
  • vue如何根據(jù)權(quán)限生成動態(tài)路由、導(dǎo)航欄

    vue如何根據(jù)權(quán)限生成動態(tài)路由、導(dǎo)航欄

    這篇文章主要介紹了vue如何根據(jù)權(quán)限生成動態(tài)路由、導(dǎo)航欄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論