利用element-ui popover 封装一个新手引导组件

890 阅读1分钟

目标

利用element-ui popover 封装一个新手引导组件,支持上一步、下一步

代码实现

组件代码 guidePop.vue

  <!-- 新手引导pop -->
  <el-popover
    ref="pop"
    :value="visible"
    open-filter
    popper-class="bg-4e83fd"
    placement="right"
    width="260"
    trigger="manual"
  >
    <div class="p8 pb20">{{ steps[currentStep].content }}</div>
    <div class="pull-right mr8 mb8">
      <el-button
        v-if="currentStep>0"
        class="btn-light-primary"
        @click="prev"
      >
        上一步
      </el-button>
      <el-button
        class="btn-light-primary"
        @click="next"
      >
        {{ currentStep>=steps.length-1?'我知道了': '下一步'}}
      </el-button>
    </div>
  </el-popover>
</template>

<script>
export default {
  props: {
    code: {
      type: String,
      default: '',
    },
    steps: {
      type: [Array],
      default: () => [
        // {
        //   content: '',
        //   target: null,
        // }
      ]
    }
  },
  data () {
    return {
      currentStep: 0,
      visible: false,
    }
  },
  methods: {
    init () {
      this.$nextTick(() => {
        // localStorage中无标识且传入了步骤
        if (window.localStorage.getItem(this.code) !== '1' && this.steps.length > 0) {
          this.hanldeOpenPop()
        }
      })
    },
    next () {
      // 不是最后一步,且下一步存在target dom元素
      if (this.currentStep < this.steps.length - 1 && this.steps[this.currentStep + 1] && this.steps[this.currentStep + 1].target) {
        this.currentStep++
        this.hanldeOpenPop()
      } else {
        this.handleDestroyPop()
        window.localStorage.setItem(this.code, 1)
      }
    },
    prev () {
      this.currentStep--
      this.hanldeOpenPop()
    },
    hanldeOpenPop () {
      const { pop = {} } = this.$refs
      this.visible = false
      pop.doDestroy(true)
      this.$nextTick(() => {
        const elm = this.steps[this.currentStep].target
        pop.referenceElm = elm;
        this.visible = true
      })
    },
    handleDestroyPop () {
      const { pop = {} } = this.$refs
      this.visible = false
      pop.doDestroy(true)
      pop.popperElm.remove()
    },
  }
}
</script>

组件代码 guidePop.js

import Main from './guidePop.vue';
import Vue from 'vue'
import router from '@/router'

const GuidePopConstructor = Vue.extend(Main)

let instance

const GuidePop = function (code, steps) {
  instance = new GuidePopConstructor({
    propsData: { code, steps }
  })

  instance.$mount()
  document.body.appendChild(instance.$el)
  instance.init()

}

router.beforeEach((to, from, next) => {
  instance.handleDestroyPop()
  next()
})

export default GuidePop

业务引用

  <div>
    <div ref="step1" class="step">第一步</div>
    <div ref="step2" class="step">第二步</div>
    <div ref="step3" class="step">第三步</div>
    <div ref="step4" class="step">第四步</div>
  </div>
</template>

<script>
import GuidePop from '@/components/guidePop'
export default {
  mounted () {
    this.$nextTick(()=>{
      GuidePop('guideFlag', [
        {content: '提示信息1', target: this.$refs.step1},
        {content: '提示信息2', target: this.$refs.step2},
        {content: '提示信息3', target: this.$refs.step3},
        {content: '提示信息4', target: this.$refs.step4},
      ])
    })
  },
}
</script>

<style lang="scss" scoped>
.step {
  margin: 20px;
  background: black;
  color: white;
  width: 100px;
  height: 100px;
}
</style>

效果

386E6544-A3D3-4f1f-8DC4-19E417E0CD4E.png