vue 組件內嵌套外部頁面的實現與案例分享

1.前言

在 web 頁面開發中,經常會有這樣的需求:

   在當前頁面內打開一個外部頁面。

  若是僅僅是跳轉到外部頁面,對於有經驗的開發者來講,應該沒有什麼難度。但經常,須要打開的頁面僅僅是當前已有頁面的一部分,即須要嵌套到當前頁面內,每每就不太好實現了。

2.解決方案

使用 iframe 加載外部頁面。css

html 頁面內嵌套 iframe,並將 iframe 的 src 屬性綁定爲目標外部頁面連接。html

<div id="iframe-container">
      <iframe :src="iframeSrc" scrolling="auto" frameborder="0" id="iframe"></iframe>
  </div>

3.示例

需求: 點擊電商導航內菜單,打開相應頁面,在新開頁面中,顯示頁面加載狀態,能夠回退和直接關閉新開頁面。vue

iframe-example.png

分析:git

  • 圖一和圖二頂部樣式不一致,所以,是兩個獨立的組件。
  • 點擊圖一頁面中的菜單,跳轉到圖二頁面,須要配置路由。
  • 如何傳遞外部頁面的地址?路由傳參?vuex?

實現:
  Tips: 本例基於 vue + vue-router + vuex + vant 實現github

圖一頁面佈局:web

<div class="module-box">
      <div class="module-title">電商導航</div>
      <van-grid :column-num="3">
          <van-grid-item v-for="(item,index) in eShopNavItems"
                         :key="index"
                         :icon="item.iconPath"
                         :text="item.name"
                         @click="gotoPage(item.path)" />
      </van-grid>
 </div>

js 部分:vue-router

<script>
export default {
  components: {},
  props: {},
  data() {
    return {
      eShopNavItems: [
        {
          name: '京東',
          iconPath: require('../../../assets/images/lifeServices/index/jd.png'),
          path: '/home/lifeServices/jd',
        },
        <!-- 其餘菜單配置 -->
      ]
    }
  },
  methods: {
    onClickLeft() {
      this.$router.go(-1)
    },

    gotoPage(path) {
      this.$router.push(path)

      <!-- 存儲目標外鏈的url及要顯示的標題 -->
      <!-- 這部分寫在路由配置裏的meta參數下 -->

      this.$store.state.iframeSrc = this.$route.meta.link
      this.$store.state.iframeTitle = this.$route.meta.title
    }
  }
}
</script>

路由配置:vuex

const routes = [{
  path: '/home/lifeServices/externalLink',
  name: 'externalLink',
  component: LinkHome,
  children: [
    {
      path: '/home/lifeServices/jd',
      meta: {
        link: 'https://m.jd.com/',
        title: '京東(jd.com)'
      }
    },
];

接下來關鍵的實現,也是最核心的點在於「LinkHome」組件的實現。佈局

LinkHome.vueui

<template>
  <div class="link-home">
    <div class="header">
      <van-nav-bar
        :title="$store.state.iframeTitle"
        left-arrow
        @click-left="onClickLeft"
      ></van-nav-bar>
      <van-icon name="cross" class="close" @click="closeTab" />
    </div>

    <div id="iframe-container">
      <iframe :src="$store.state.iframeSrc" scrolling="auto" frameborder="0" id="iframe"></iframe>
    </div>
  </div>
</template>

<script>
import NProgress from 'nprogress'

export default {
  mounted() {
    let iframe = document.getElementById('iframe')
    NProgress.start()

    iframe.onload = function() {
      NProgress.done()
    }
  },
  methods: {
    onClickLeft() {
      this.$router.go(-1)
      NProgress.done()
    },

    closeTab() {
      this.$router.replace('/home/lifeServices/index')
      NProgress.done()
    }
  }
}
</script>

<!-- css樣式省略 -->

給 iframe 的 src 屬性綁定值,且爲目標外部頁面地址。便可嵌套加載外部頁面。

頁面加載狀態使用NProgress

在 vue.js 的 mounted 生命週期內,開始加載進度條。

NProgress.start()

獲取 iframe 元素,當 iframe 頁面加載完成後,關閉進度條。

iframe.onload = function() {
  NProgress.done()
}

當後退或者關閉當前頁面時,也應該一併關閉進度條提示。由於當頁面尚未加載完時,後退或者關閉頁面,將會致使進度條一直存在。

特別提示: 關閉頁面,即回到主頁時,應使用 this.$router.replace 而不是 this.$router.push,這兩個一樣是跳轉到指定的 url,可是 this.$router.replace 不會向 history 裏面添加新的記錄。回到主頁,再後退,應該是回到進入主頁的上一個頁面,而不是剛纔打開的外部頁面。

相關文章
相關標籤/搜索