qiankun微服務使用intro.js總結

前言


最近在使用qiankun微服務架構,有個須要給系統加引導的需求,而後就決定使用intro.js。也是看了掘金的一位博主的帖子(連接以下)。

juejin.cn/post/696464…css


可是我要講的內容有,如何在微服務中進行主模塊和子模塊的完美引導樣式修改,以及踩的一些坑。vue

再附上一個官網的連接 introjs.com/typescript

注意

intro截圖.png 這個插件是GNU AGPLv3 也就是說若是你商用那是要公開源碼的,或者你得買他的版權(網上查的不知道對不對) 反正我是花錢買了受權9.99刀,固然當時爲了想省這六十幾塊人民幣也試過同類型的插件driver.js可是區別仍是蠻大的。ps:別問我怎麼知道的由於我用兩個插件都寫了一遍。 這裏在多說一點把若是你是小項目,且要求不是很高,功能不是不少,能夠選擇Dirver。畢竟他開源免費。固然你要是以爲這個點錢不算什麼別猶豫直接intro.js。緩存


基本用法

先說使用這個基本和上面的博主相同當時也發現了一些更好的使用技巧。這是封裝的代碼。下面具體細節一一講解。markdown

import introJs from 'intro.js'
import 'intro.js/introjs.css'
// import router from '@/router'
import Vuex from '@/store'
let count = 0 // 初始化爲0,後面會根據每一步傳入的dom的id選擇器 判斷當前在第幾步
// let state = 0 // skip: 0 ,done: 1;
export function guide(introSteps: Array<any>) {
  let isSkip: boolean = false
  const sesionData = JSON.parse(localStorage.getItem('isIntro') || 'null')
  if (localStorage.getItem('isIntro') && sesionData.state === 0) {
    return
  }

  introJs()
    .setOptions({
      steps: introSteps,
      /* 當位置選擇自動的時候,位置排列的優先級 */
      positionPrecedence: ['right', 'top', 'bottom', 'left'],
      prevLabel: '上一步',
      nextLabel: '下一步',
      skipLabel: '<div/>',
      // 這裏由於每一個頁面的最後一步其實就會顯示doneLabel了,而實際上咱們的新手引導操做並無完成,須要跳轉路由繼續,因此顯示的是下一步而非完成。
      doneLabel: '下一步',
      hidePrev: true,
      exitOnOverlayClick: false,
      /* 是否顯示說明的數據步驟*/
      showStepNumbers: false,
      /* 是否使用點點點顯示進度 */
      showBullets: false,
      /* 是否使用鍵盤Esc退出 */
      exitOnEsc: false,
      /* 默認提示位置 */
      hintPosition: 'top-right',
      /* 說明高亮區域的樣式 */
      highlightClass: 'customHighlight',
      /* 引導說明文本框的樣式 */
      tooltipClass: 'customTooltip',
    })
    .onchange(function (targetElement: any) {
      // 每次change時觸發,個人id樣式是「guide-step<id>」
      // id表明新手引導的第幾步,例如「guide-step1」,經過id判斷當前是第幾步
      count = parseInt(targetElement.id.slice(-1))
    })
    .onafterchange(function (targetElement: any) {
      // 跳轉完成後用js的dom操做將doneLabel由「下一步」改成「完成」
      if (count === 1) {
        document.getElementsByClassName('introjs-fullbutton')[0].innerHTML = '開始吧'
      }
      if (count === 2) {
        Vuex.commit('set_data', {
          guideChange: 'XXX',
        })
      }
    })
    .oncomplete(function (targetElement: any) {
      // 點擊完成以及跳過按鈕後執行的事件,不區分完成和跳過。
      console.log('這個是跳出或者完成')
    })
    .onexit(function (targetElement: any) {
      // 點擊完成按鈕後, 執行的事件
      if (isSkip) {
        return
      }
      setTimeout(() => {
        judgeCount()
      }, 200)
    })
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    .onskip(function (targetElement: any) {
      // 點擊跳過按鈕後, 執行的事件
      // 存儲進緩存,下次進入新手引導路由頁時將不在觸發Intro.js
      isSkip = true
      localStorage.setItem('isIntro', JSON.stringify({ nextGuideName: '', state: 0 }))
    })
    .start()
}

// 這個是每一步新手引導對應的點擊下一步時對應應該進行的操做
function judgeCount() {
  switch (count) {
    case 1:
    case 2:
      guide([
        {
          title: 'XX模板',
          intro:
            'XX模板 中有豐富的模板,您能夠「使用模板」 快速製做。固然,您也能夠新建一個空白的XX。',
          element: document.querySelector('#guide-step3'),
          position: 'right',
        },
      ])
      break
    case 3:
      localStorage.setItem('isIntro', JSON.stringify({ nextGuideName: 'page1', state: 1 }))
      window.postMessage({ startGuide: true }, '*')
      break
    case 4:
      localStorage.setItem('isIntro', JSON.stringify({ nextGuideName: 'page2', state: 1 }))
      window.postMessage({ startCRMGuide: true }, '*')
      break
  }
}

複製代碼

如下代碼是放在你所須要的引導的.vue頁面中,將他放入mounted中,vue2和3均可以,或者放入函數中經過點擊事件觸發均可以。架構

let i = setInterval(() => {
        guide([
          {
          // title: '新手教程',
          intro:
               'Hi,我是您的小助理,您能夠隨時點擊這裏召喚我,接下來讓我帶您熟悉一下操做流程吧!',
          element: document.querySelector('#guide-step1'),
          position: 'right',
         },
          {
            title: 'XX中心',
            intro:
              '左側的「XX」菜單裏包含 XXX、XX、XXX 三大應用,如今讓咱們從「XXX」應用開始瞭解吧!',
            element: document.querySelector('#guide-step2'),
            position: 'right',
          },
        ])
        clearInterval(i)
      }, 500)
複製代碼

以上主要是以前那位博主的思路,我加了些vue3+ts的寫法,個人跨頁面跨服務也基本採用他的思路,具體沒看明白的能夠先看他那篇。連接在最開頭。框架


分佈詳解

除了以上原博主封裝的方法外,還能夠這麼玩。dom

intro截圖2.png

直接在每一步的對象內,寫自定義的屬性值,而後在封裝的js裏來作處理。 ide

這邊用來處理剛剛寫的自定義的屬性值
.onexit(function () {
      // 點擊完成按鈕後, 執行的事件
      const { callback } = introSteps[count - 1]  //結構剛剛添加的callback屬性值
      if (callback) {
        handleCallback(callback)
      }
    })
複製代碼

這邊用來處理剛剛自定義方法的回調函數

// 處理callback回調方法
function handleCallback(callback) {
  switch (callback) {
    case 'openKnowledgeManagementMenuEdit':
      localStorage.setItem('startGuide', 'edit')
      openXXXXXXXXX()
      break
    case 'XXXXXXXXXXXXXXXXXX':
      localStorage.setItem('XXXXXXXXXXXX', 'XXXXXXXXXXX')
      openXXXXXX()
      break
  }
}
複製代碼

下面我來講下qiankun中微服務,主框架和子框架如何經過聯動經行引導。

兩個方法:

  1. 經過緩存經行信息傳遞和觸發。親測比較麻煩不方便。
  2. 經過window.postMessage

傳遞模塊

//在須要傳遞的框架中.onexit來觸發這個方法
 case 4:
      localStorage.setItem('isIntro', JSON.stringify({ nextGuideName: 'page2', state: 1 }))
      window.postMessage({ startCRMGuide: true }, '*')
      break
複製代碼

接收模塊

//在子框架中你須要觸發引導的界面中使用
   window.addEventListener('message', (message) => {
        const { data } = message
        if (data && data.startGuide) {
            guide([
          {
          // title: ''XX中心',
          intro:
               '左側的「XX」菜單裏包含 XXX、XX、XXX 三大應用,如今讓咱們從「XXX」應用開始瞭解吧!',
          element: document.querySelector('#guide-step1'),
          position: 'right',
         },
          {
            title: 'XX中心',
            intro:
              '左側的「XX」菜單裏包含 XXX、XX、XXX 三大應用,如今讓咱們從「XXX」應用開始瞭解吧!',
            element: document.querySelector('#guide-step2'),
            position: 'right',
          },
        ])
        }
      })

複製代碼

用法主要就是傳遞這塊。

樣式修改

使用qiankun的框架的話全部的樣式直接寫到主框架裏就好了

例如 想修改跳出按鈕的位置和樣式,直接在以下圖跳出按鈕內添加一個標籤就行(我這裏加了個div)

intro3截圖.png

css以下,這個就不解釋了應該看的懂,直接放入主框架全局樣式

.introjs-skipbutton {
  position: fixed;
  right: 45%;
  top: 20px;

  >div {
    width: 56px;
    height: 74px;
    background: url(./XXXXX.png) no-repeat;
    background-size: cover;
    cursor: pointer;
  }
}

複製代碼

若是你想隱藏某個按鈕也能夠經過樣式來直接控制,按照intro的每一個按鈕類名。

例如:想隱藏上一步這個按鈕

//上一步按鈕
.introjs-prevbutton {
  display: none !important;
}
複製代碼

下面來講一說坑

以下這個方法onskip官方API是沒有公佈出來的,我也是看了原博主的文章也去翻源碼了,發現確實是有。

你要是vue2且沒用ts的話,和原博主同樣直接用就好了。但你要是VUE3+ts那可要了命了他官方的@type/intro.js是沒有暴露這個方法的會一直報錯。必須加上下面的註釋才能在編譯和打包的時候不出錯。(唉,說多了都是淚,竟然兩行註釋解決了)

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    .onskip(function (targetElement: any) {
      // 點擊跳過按鈕後, 執行的事件
      // 存儲進緩存,下次進入新手引導路由頁時將不在觸發Intro.js
      isSkip = true
      localStorage.setItem('isIntro', JSON.stringify({ nextGuideName: '', state: 0 }))
    })
複製代碼

第二個坑

就是引選中一個按鈕,被選中的按鈕依然是能夠點擊的

intro4截圖.png

好比這個是一個按鈕的引導,這個編輯依然能夠點擊,這個時候點擊就會出現一些問題,那如何來阻止。

相信很多朋友確定和我同樣想到用css的pointer-events,或者用js來阻止。

可是真的不用,就在我就糾結的時候我同事發現只需調整z-index就能夠了,顯示效果不變。

//只需加入這個就能夠阻止
.introjs-helperLayer {
  z-index: 9999999 !important;
}
複製代碼

第三個坑 若是你在引導的過程當中有些自動的彈窗出現,它是不會關閉的,須要手動關閉。

//能夠在須要的地方加上這個兩行
import introJs from 'intro.js'
  introJs().exit()
複製代碼

準備下班,今天就寫到這裏,原本想繼續寫intro.js和Dirver.js的區別。

相關文章
相關標籤/搜索