小白进阶: 教你撸一个简单的Vue自定义动态组件(一)

components下创建 toast 文件夹, 文件夹里面创建 toast.vue 和 index.js

 toast.vue:

<template>
  <div id="toastWrap" :class="[className,showAnimation ?'fadein':'fadeout',appointId==''?'fixed':'absolute']" v-if="show">
    <span  :class="['iconfont',type]"></span>
    {{text}}
    </div>
</template>
<script>
export default {
  name: '',
  data(){
    return {}
  },
  components: {},
  created(){},
  mounted(){},
  methods: {}
}
</script>
<style scoped>
 .fixed{
    position: fixed;
 }
 .absolute{
  position: absolute;;
 }
 #toastWrap{
    left: 50%;
    top:50%;
    background: rgba(0, 0, 0, 0.7);
    padding: 10px;
    border-radius: 5px;
    transform: translate(-50%,-50%);
    color:#fff;
  }
   .fadein {
    animation: animate_in 0.25s;
  }
  .fadeout {
    animation: animate_out 0.25s;
    opacity: 0;
  }
  @keyframes animate_in {
    0% {
      opacity: 0;
    }
    100%{
      opacity: 1;
    }
  }
  @keyframes animate_out {
    0% {
      opacity: 1;
    }
    100%{
      opacity: 0;
    }
  }
</style>

 

 

 

index.js:

import vue from 'vue'
import toastComponent from './toast.vue'
const ToastConstructor = vue.extend(toastComponent)
console.log("初始化一个vue构造器")
console.log(ToastConstructor)

function showToast(obj) {
    // 实例化一个 toast.vue
    let param = {
        text: obj.text || '',
        // className 自定义class
        className: obj.className || '',
        type: obj.type || 'icon-tishi1',
        // appointId 父元素class 用于定位
        appointId: obj.appointId || '',
        duration: obj.duration || 3000
    }
    console.log("传参情况")
    console.log(param)
    const toastDom = new ToastConstructor({
            el: document.createElement('div'),
            data() {
                return {
                    text: param.text,
                    show: true,
                    className: param.className,
                    type: param.type,
                    showAnimation: true,
                    appointId: param.appointId
                }
            }
        })
        //挂载到文档
    if (param.appointId !== '') {
        console.log("appointId不等于空")
        console.log(param.appointId)
        document.getElementById(param.appointId).appendChild(toastDom.$el)
    } else {
        console.log("appointId等于空")
        document.body.appendChild(toastDom.$el)
    }
    setTimeout(() => { toastDom.showAnimation = false }, param.duration - 1250)
    setTimeout(() => { toastDom.show = false }, param.duration)

}

function registryToast() {
    // 将组件注册到 vue 的 原型链里去,
    // 这样就可以在所有 vue 的实例里面使用 this.$toast()
    vue.prototype.$toast = showToast
}

export default registryToast

 

 
main.js:

import toastComponent from '../src/components/toast'
Vue.use(toastComponent)

 

 

在需要使用的地方调用

that.$toast({text:'填写用户名/手机号/邮箱',className:"loginTip",appointId:'loginFrom',duration:3500})

 

 我的理解:先写一个模板,然后通过vue.extend初始化为一个vue构造器,然后通过一个函数去实例化   挂载在Vue原型链和文档中,通过vue调用显示隐藏。欢迎讨论其他写法,和各种写法的优点缺点

 

搜索关键词: 

vue 自定义组件动态加载/vue 自定义组件封装

参考资料:

从零开始徒手撸一个vue的toast弹窗组件

https://blog.csdn.net/weixin_33831673/article/details/87961145

添加自定义vue全局方法,同时给自定义的方法 传递component调用其方法

https://blog.csdn.net/ling369523246/article/details/78450418

posted @ 2019-12-22 13:30  haveProgress  阅读(694)  评论(0编辑  收藏  举报