Vue.extend 构造器的应用

267 阅读1分钟

在vue项目中,vue组件通过import引入注册使用,像弹层组件,我们希望使用更加灵活,实现API式的弹窗组件调用,我们可以使用Vue.entend构造器来创建组件,把它封装为单独的vue插件,实现全局调用

toast.vue 动态组件模板

// 动态组件模板
<template>
  <div v-if="isShow" class="wrap">
    <i>{{ msg }}</i>
  </div>
</template>

<script>
export default {
  name: 'Toast',
  props: {
    msg: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      isShow: false
    }
  }
}
</script>

<style lang="scss">
.wrap {
  position: fixed;
  padding: 5px;
  top: 40%;
  left: 50%;
  transform: translateX(-50%);
  max-width: 40%;
  background: #333;
  z-index: 1000;
  padding: 5px 10px;
  background: rgba(29, 29, 29, 0.73);
  border-radius: 5px;
  color: #fff;
  text-align: center;
  min-width: 100px;
  pointer-events: none; // 点击穿透
  animation: enter 1.5s ease;
  animation-fill-mode:forwards;

  i {
    font-size: 40px;
    display: block;
  }
}
@keyframes rotate-loop {
  from {
    transform: rotateZ(0deg);
  }
  to {
    transform: rotateZ(360deg);
  }
}

@keyframes enter {
  from {
    transform: translateY(40%)
  }
  to {
      transform: translateY(0)
  }
}
</style>

toast.js

import Toast from './toast.vue'
import Vue from 'vue'

// 生成构造函数 构造器
const ToastConstructor = Vue.extend(Toast)

// text 传入的文字
function showToast(text, time = 3000) {
  const toastDOM = new ToastConstructor({
    el: document.createElement('div'), // el 生成dom 节点
    data: {
      isShow: true
    },
    propsData: {
      msg: text
    }
  })

  // 在body中动态创建一个div元素,之后此div将会替换成整个vue文件的内容
  // 此时的 toastDOM 通俗讲就是相当于是整个组件对象,通过对象调用属性的方法来进行组件中数据的使用
  // 可以通过$el属性来访问创建的组件实例
  document.body.appendChild(toastDOM.$el)
  setTimeout(() => {
    toastDOM.isShow = false
  }, time)
}

const toast = {
  install(Vue) {
    Vue.prototype.$toast = showToast
  }
}

export default toast

main.js 引入

import toast from './toast/toast'
Vue.use(toast)

页面使用

<template>
  <div>
    <h1>{{ msg }}</h1>
    <button @click="add"> 动态添加组件</button>
  </div>
</template>

<script>
export default {
  props: {
    msg: {
      type: String,
      default: ''
    }
  },
  methods: {
    add() {
      this.$toast('我是大美女')
    }
  }
}
</script>

<style>

</style>