Important tips!

Intro. Js for commercial use to give money !!!! So, I switched to driver.js. Driver.js does not distinguish between skip and complete. I am modifying the source code, but adding a skipped event callback. In Vue, the implementation idea is similar.

Driver.js source code added skipped event callback

Functional requirements

Companies require novice boot on their own platform, or cross-page, cross-route. I looked for a new boot plugin on the Internet, and finally chose intro.js to use.

Most of what I write are ideas, if you can understand it should be easy to achieve these effects, direct paste is estimated to hang ha.

It is recommended to go to the official website of intro.js to have a look at the demo, and then see the operation based on the demo.

I am just a small basic level programmer, if you have any ideas and logic to make everyone laugh, don’t laugh at me, please tell me gently thank you.

The following are their real problems and tried to solve, there are better solutions can be posted together to discuss.

Problems encountered with using Intro. Js and code

1. Do not cross routes

The biggest problem is that intra-js can’t be routed across because it gets and displays the newbie boot on the current page, based on the DOM’s unique Id, so it can’t get pages that aren’t rendered. So what I want to do is load intro.js from the beginning on each page, and after the previous page is booted, router.push directly to the next route, and then automatically load, boot, and then push to the next route. Ok, perfect nesting.

We will first encapsulate a utility class intr.js in the utils.js file so that each page can reference it directly. Here I directly post the final version of the code, I think it is better to understand.

utils -> intro.js

import introJs from 'intro.js'
import 'intro.js/introjs.css';
import router from '@/router'
import store 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) {
  // console.log(sessionStorage.getItem('isIntro'))
  if (!parseInt(sessionStorage.getItem('isIntro'))) {
    return
  }
  introJs().setOptions({
    steps: introSteps,
    /* The priority of position arrangement when position selection is automatic */
    positionPrecedence: ["top"."bottom"."right"."left"].prevLabel: "Step up".nextLabel: "Next step".skipLabel: "Skip".// 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-left'./* Specifies the style of the highlighted area */
    highlightClass: 'customHighlight'./* Bootstrap specifies the text box style */
    tooltipClass: 'customTooltip'
  }).onchange(function (targetElement) {
    // 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) {
    If count == 7, this is the last step
    // Change doneLabel from "Next" to "done" with JS dom manipulation
    if (count === 7) {
      let i = document.getElementsByClassName('introjs-donebutton') [0].innerHTML = 'Got it.'
    }
  }).oncomplete(function (targetElement) {
    // Events executed after the finish and skip buttons are clicked, regardless of completion or skip.
    state = 1
    setTimeout(() = > {
      if (state) {
        judgeCount()
      }
    }, 200)
  }).onexit(function (targetElement) {
    // The event that executes after clicking the Finish button
  }).onskip(function (targetElement) {
    // The event that executes after clicking the skip button
    // I could not find onskip in the official website API at that time, but I dug out the source code by myself.
    // After clicking "skip", the new boot is completed by default, so you need to pass the status to the backend to ensure that the next time you enter the page with intro.js, the new boot will not be loaded.
    // Since the VUE is written across routes, the completion of each page is not the user's complete novice boot
    // So without distinguishing between completed and skipped events, we don't know if the user is currently skipping (== finished boot) or just finished the current page and needs to move on to the next route.
    state = 0
    // Store it in the cache. The next time you enter the newbie boot routing page, it will not trigger intro.js
    store.state.introStepInfo.isIntro = state
    sessionStorage.setItem('isIntro', state)
  }).start();
}

// This is what should be done when the newbie clicks next for each step
On my side, 1,2 steps on a page, 3,4 steps on a page, 5,6 steps on a page, and 7 steps on a page
// so I don't need to do anything special at 1,3,5, just follow the Intro
function judgeCount () {
  // This is the pre-stored jump route need some data
  let _introStepInfo = JSON.parse(sessionStorage.getItem('introStepInfo'))
  switch (count) {
    case 1:
      break
    case 2:
      router.push({
        path: '/courseDetail'.query: {
          id: _introStepInfo.courseId
        }
      })
      break
    case 3:
      break
    case 4:
      let _introChapterName = sessionStorage.getItem('chapterName')
      router.push({
        path: '/coursePreview'.query: {
          id: _introStepInfo.courseId,
          chapterId: _introStepInfo.chapterId
        }
      })
      break
    case 5:
      break
    case 6:
      router.push({
        path: '/myCourses'
      })
      break
    case 7:
      sessionStorage.setItem('isIntro'.0)
      break}}Copy the code

2. Load intro.js after all the data required for the page boot is obtained and rendered

One issue to note here is that some DOM is rendered after the data is retrieved from the back end. Without rendering, the intro.js will not get a unique ID value.

So inside the AXIos wrapper, we set a Boolean variable isAxios globally with a value of false and set it to true when the request comes back. Add a global variable count (+1 for request, -1 for response) and set isAxios to true for count (0). Add a global variable count (+1 for request, -1 for response). Mounted () {/ / Set a 500ms/time timer for the Intro. Js page life cycle. If isAxios is set to true, then clear the page after completion.

These are all immature, if there is a better way you can come up with.

How to use the intro.js utility class

// Introduce a newbie bootstrap function wrapped in its own
import { guide } from '@/utils/intro'
Copy the code

Mounted () specifies the life cycle of a timer

let i = setInterval(() = > {
    if (!this.isAxios) {
            guide([
              {
                title: 'Open course'.intro: 'View all the courses you have purchased. (1/7) '.element: document.querySelector('#guide-step1')}, {title: 'Course Resources'.intro: 'Click on any course cover to enter the course. (2/7) '.element: document.querySelector('#guide-step2')})clearInterval(i)
     }
}, 500)
Copy the code

In fact, there are a lot of minor details that need to be paid attention to in the encapsulation of Axios, but they are not relevant to intro.