用vue写了个toash组件,但是我该怎么用js调用它呢?

效果图:

clipboard.png

子组件:

<template>
    <div class="toash" :style="{display:ifShow}">
        <span>{{text}}</span>
    </div>
</template>

<script>
export default {
    props:["text","timer"],
    data () {
        return {
            ifShow:"block"
        }
    },
    mounted(){
        setTimeout(()=>{
            this.ifShow = "none";
        },this.timer)
    }
}
</script>

父组件:

<template>
    <div class="hello">
        <toash text="登录成功" timer=3000></toash>
    </div>
</template>

问题:
我看了很多框架,只要在js里:this.$toash("文字描述")就可以调用toash了,非常的方便操作。那我这个写的组件如何才能在js调用toash组件呢?

阅读 2.3k
3 个回答

最近正在抽vue的ui组件,其中有个message组件,和你这个差不多。简单的说这类组件的难点在于:

  1. 使用Vue.extend而不是把组件写在html里
  2. 需要实现一个单例模式

好多框架里面这类组件都有两个文件,一个xxx.vue,一个xxx.js。
message.vue

<template>
    <div :class="['jn-message','jn-message-'+icon]" :style="{'z-index':ZINDEX++}">
        <i :class="['jn-icon-'+icon,'jn-message-icon']" v-if="icon"></i>
        <div class="jn-message-content">
          <template v-if="htmlEnable">
              <div v-html="$slots.default[0]" class="jn-message-content" >

              </div>
          </template>
          <template v-else>
              <slot>

              </slot>
          </template>
        </div>
        <i v-if="closeButton" class="jn-message-close jn-icon-close" @click="closeMessage"></i>
    </div>
</template>
<script>
import {ZINDEX} from '@/js/utils/const.js'
export default {
  name: "jn-message",
  data(){
    return {
      ZINDEX
    }
  },
  mounted() {
    setTimeout(() => {
      this.close();
    }, this.delay);
  },
  props: {
    delay: {
      type: Number,
      default: 3000
    },
    htmlEnable: {
      type: Boolean,
      default: false
    },
    closeButton:{
      type:Boolean,
      default:false
    },
    callback:{
      type:Object
    },
    icon: {
      type: String,
      default: "info"
    }
  },
  methods: {
    close() {
      this.$el.remove();
      this.$emit("close");
      this.$destroy();
    },
    closeMessage() {
      var beforeClose = this.callback.beforeClose,
          afterClose = this.callback.afterClose
      beforeClose && beforeClose.call(this, this);
      this.close();
      afterClose && afterClose.call(this, this);
    }
  }
};
</script>
<style lang="scss">
@import "../../../css/message.scss";
</style>

message.js

import Vue from 'vue';
import Message from './message.vue';
import {mergeDeep} from '@/js/utils/tools.js'

let MessageConstructor = Vue.extend(Message);

const message = function () {
    var instance = null,
        uid = null
    return function (option) {
        if(typeof option == 'string'){
            option = {
                text: option
            }
        }
        var config = mergeDeep({
            props: {
                htmlEnable: false,
            },
            text: 'default'
        }, option)
        if (!instance || instance._uid != uid) {

            if (!instance) {
                instance = new MessageConstructor({
                    propsData: config.props
                })
                uid = instance._uid
            } else {
                let t = new MessageConstructor({
                    propsData: config.props
                })
                if (t._uid != uid) {
                    instance.closeMessage()
                    instance = t
                    uid = t._uid
                }
            }
            
            instance.$slots.default = [config.text]
            instance.$mount()
            instance.$on('close', function () {
                instance = null
                uid = null
            })

            document.body.appendChild(instance.$el)

        }
        return instance
    }
}

const plugin = {}
plugin.install = function (Vue, options) {
    Vue.prototype.$message = message()
}

export default plugin;

刚好有撸了一篇文章:Vue的插件与extend方法

简单的说,就是给Vue的原型上写一个$toash方法:Vue.prototype.$toash = function(desc){}
就可以在组件内this.$toash("文字描述")这样用了。

然后,在声明$toash方法里,要做的是拿到参数,生成一片dom片段,手动document.body.appendChild(),来达到把toash插入到页面里。并且合理的控制这块dom的隐藏。具体逻辑就得看你的需求了。

博文是我自己的笔记,可能写得不是很详细。你可以参(chao)考(xi) element UI 的$message源码

推荐问题
宣传栏