preface


Juejin. Cn/post / 696464…


But I’m going to talk about how to perfect the main and sub-modules in microservices, style modifications, and some of the pitfalls.

I also include a link to our website, introjs.com/

Pay attention to

This plug-in is GNU AGPLv3, that is to say, if you use it for commercial use, it should be open source, or you have to buy its copyright (online check does not know whether it is right). Anyway, I paid money to buy the authorization of 9.99 dollars, of course, in order to save the 60 yuan I also tried the same type of plug-in driver.js, but the difference is still quite big. Ps: Don’t ask me how I know because I wrote it with both plugins. Here’s a bit more: If you are a small project, not very demanding, not very functional, you can choose Dirver. After all, it’s open source and free. Of course, if you think this is not a small amount of money, don’t hesitate to direct intro.js.


Basic usage

First of all, using this is basically the same as the blogger above who discovered some better techniques at the time. This is wrapped code. The details are explained one by one.

import introJs from 'intro.js'
import 'intro.js/introjs.css'
// import router from '@/router'
import Vuex from '@/store'
let count = 0 // Initialize to 0, and determine the current step based on the DOM ID selector passed in at each step
// 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,
      /* The priority of position arrangement when position selection is automatic */
      positionPrecedence: ['right'.'top'.'bottom'.'left'].prevLabel: 'Previous step'.nextLabel: 'Next step'.skipLabel: '<div/>'.// The last step of each page will display doneLabel. In fact, the new boot operation is not complete, and the jump route needs to continue, so it shows next step instead of finished.
      doneLabel: 'Next step'.hidePrev: true.exitOnOverlayClick: false./* Whether to display the specified data step */
      showStepNumbers: false./* Whether to use dots to display progress */
      showBullets: false./* Whether to use the keyboard Esc exit */
      exitOnEsc: false./* Default prompt location */
      hintPosition: 'top-right'./* Specifies the style of the highlighted area */
      highlightClass: 'customHighlight'./* Bootstrap specifies the text box style */
      tooltipClass: 'customTooltip',
    })
    .onchange(function (targetElement: any) {
      // My id style is "guide-step
      
       "
      
      // id indicates the number of steps to guide the newbie, for example, guide-step1
      count = parseInt(targetElement.id.slice(-1))
    })
    .onafterchange(function (targetElement: any) {
      // Change doneLabel from "Next" to "done" with JS dom manipulation
      if (count === 1) {
        document.getElementsByClassName('introjs-fullbutton') [0].innerHTML = 'Here we go.'
      }
      if (count === 2) {
        Vuex.commit('set_data', {
          guideChange: 'XXX',
        })
      }
    })
    .oncomplete(function (targetElement: any) {
      // Events executed after the finish and skip buttons are clicked, regardless of completion or skip.
      console.log('This is jump out or finish')
    })
    .onexit(function (targetElement: any) {
      // The event that executes after clicking the Finish button
      if (isSkip) {
        return
      }
      setTimeout(() = > {
        judgeCount()
      }, 200)})// eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    .onskip(function (targetElement: any) {
      // The event that executes after clicking the skip button
      // Store it in the cache. The next time you enter the newbie boot routing page, it will not trigger intro.js
      isSkip = true
      localStorage.setItem('isIntro'.JSON.stringify({ nextGuideName: ' '.state: 0 }))
    })
    .start()
}

// This is what should be done when the newbie clicks next for each step
function judgeCount() {
  switch (count) {
    case 1:
    case 2:
      guide([
        {
          title: 'XX template'.intro:
            'XX templates have a wealth of templates that you can "use templates" to make quickly. Of course, you can also create a new blank XX. '.element: document.querySelector('#guide-step3'),
          position: 'right',}])break
    case 3:
      localStorage.setItem('isIntro'.JSON.stringify({ nextGuideName: 'page1'.state: 1 }))
      window.postMessage({ startGuide: true }, The '*')
      break
    case 4:
      localStorage.setItem('isIntro'.JSON.stringify({ nextGuideName: 'page2'.state: 1 }))
      window.postMessage({ startCRMGuide: true }, The '*')
      break}}Copy the code

The following code is placed in the.vue page that you need to boot, put it in mounted,vue2 or 3, or put it in a function that triggers by clicking on the event.

      let i = setInterval(() = > {
        guide([
          {
          // title: 'Tutorial ',
          intro:
               'Hi, I am your little assistant, you can click here to call me at any time, next let me take you familiar with the operation process! '.element: document.querySelector('#guide-step1'),
          position: 'right'}, {title: 'XX centers'.intro:
              'The left "XX" menu contains XXX, XX, XXX three applications, now let's start to understand from the "XXX" application! '.element: document.querySelector('#guide-step2'),
            position: 'right',}])clearInterval(i)
      }, 500)
Copy the code

The above is mainly the idea of the blogger before, I added some vue3+ TS writing method, my cross-page cross-service also basically adopt his idea, specific do not understand can read his article first. The link is at the beginning.


The distribution,

In addition to the original blogger encapsulation method above, you can also play this way.

Write custom property values directly in each step of the object, and then do the processing in the encapsulated JS.

   .onexit(function () {
      // The event that executes after clicking the Finish button
      const { callback } = introSteps[count - 1]  // Structure the value of the just-added callback attribute
      if (callback) {
        handleCallback(callback)
      }
    })
Copy the code

This is used to handle the callback of the method you just customized

// Handle callback callback methods
function handleCallback(callback) {
  switch (callback) {
    case 'openKnowledgeManagementMenuEdit':
      localStorage.setItem('startGuide'.'edit')
      openXXXXXXXXX()
      break
    case 'XXXXXXXXXXXXXXXXXX':
      localStorage.setItem('XXXXXXXXXXXX'.'XXXXXXXXXXX')
      openXXXXXX()
      break}}Copy the code

Now I will talk about the micro services in Qiankun and how the main frame and sub-frame are guided through linkage.

Two methods:

  1. Information is passed and triggered through the cache. Pro test more troublesome inconvenient.
  2. Through the window. PostMessage

Relay module

// In the frame that needs to be passed.onexit to trigger this method
 case 4:
      localStorage.setItem('isIntro'.JSON.stringify({ nextGuideName: 'page2'.state: 1 }))
      window.postMessage({ startCRMGuide: true }, The '*')
      break
Copy the code

Receiving module

// Use in subframes where you need to trigger the boot interface
   window.addEventListener('message'.(message) = > {
        const { data } = message
        if (data && data.startGuide) {
            guide([
          {
          // title: 'XX center ',
          intro:
               'The left "XX" menu contains XXX, XX, XXX three applications, now let's start to understand from the "XXX" application! '.element: document.querySelector('#guide-step1'),
          position: 'right'}, {title: 'XX centers'.intro:
              'The left "XX" menu contains XXX, XX, XXX three applications, now let's start to understand from the "XXX" application! '.element: document.querySelector('#guide-step2'),
            position: 'right',},])}})Copy the code

Usage is mostly passing this.

Style changes

With the Qiankun frame, all the styling will be written directly into the main frame

For example, if you want to change the position and style of the jump button, just add a label inside the jump button as shown below (I added a div here).

CSS as follows, this will not explain should understand, directly put in the main frame global style

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

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

If you want to hide a button you can also control it directly by styling it according to the intro class name of each button.

For example, you want to hide the previous button

// Previous button
.introjs-prevbutton {
  display: none ! important;
}
Copy the code

pit

Let’s talk about pits

The following method onskip official API has not been published, I also read the original blogger’s article and looked at the source code, and found that it does exist.

If you don’t use TS for vue2, just use it like the original blogger. VUE3+ts does not expose this method in its official @type/intro.js file. The following comments must be added to compile and package without errors. (Alas, said too many are tears, incredibly two lines of comment solved)

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    .onskip(function (targetElement: any) {
      // The event that executes after clicking the skip button
      // Store it in the cache. The next time you enter the newbie boot routing page, it will not trigger intro.js
      isSkip = true
      localStorage.setItem('isIntro'.JSON.stringify({ nextGuideName: ' '.state: 0}})))Copy the code

The second pit

A button is selected, the selected button is still clickable

For example, if this is a button guide, the editor can still be clicked. At this time, there will be some problems when clicked. How to prevent it?

I believe that many friends would like to use CSS pointer-Events or JS to prevent it.

But no, just when I was struggling with it, my colleague found out that you just need to adjust the Z-index, and the display remains the same.

// Just add this to block it
.introjs-helperLayer {
  z-index: 9999999 ! important;
}
Copy the code

The third pit will not be closed if some automatic popover appears while you are booting, it will have to be closed manually.

// Add the two lines where necessary
import introJs from 'intro.js'
  introJs().exit()
Copy the code

Ready to go off work, today write here, originally wanted to continue to write the difference between intro.js and dirver.js.