• 需求:有一个 Toast.vue 组件,但是它的使用方式是要在父级组件的 template 里写 才能调用,现在想实现在任意地方都能以函数式方式 this.$toast 调用,该如何做?
    • 实现:利用 Vue.extend实现(返回Vue的子类,然后实例化该子类,再进行挂载)
    1. // Toast.js
    2. import ToastComponent from './toast.vue'
    3. const Toast = {};
    4. // 注册Toast
    5. Toast.install = function (Vue) {
    6. // 生成一个Vue的子类
    7. // 同时这个子类也就是组件
    8. const ToastConstructor = Vue.extend(ToastComponent)
    9. // 生成一个该子类的实例
    10. const instance = new ToastConstructor();
    11. // 将这个实例挂载在我创建的div上
    12. // 并将此div加入全局挂载点内部
    13. instance.$mount(document.createElement('div'))
    14. document.body.appendChild(instance.$el)
    15. // 通过Vue的原型注册一个方法
    16. // 让所有实例共享这个方法
    17. Vue.prototype.$toast = (msg, duration = 2000) => {
    18. instance.message = msg;
    19. instance.show = true;
    20. setTimeout(() => {
    21. instance.show = false;
    22. }, duration);
    23. }
    24. }
    25. export default Toast
    26. // Toast.vue
    27. <template>
    28. <transition name="fade">
    29. <div class="toast" v-show="show">
    30. {{message}}
    31. </div>
    32. </transition>
    33. </template>
    34. <script>
    35. export default {
    36. data() {
    37. return {
    38. show: false,
    39. message: ""
    40. };
    41. }
    42. };
    43. </script>
    44. <style lang="scss" scoped>
    45. .toast {
    46. position: fixed;
    47. top: 40%;
    48. left: 50%;
    49. margin-left: -15vw;
    50. padding: 2vw;
    51. width: 30vw;
    52. font-size: 4vw;
    53. color: #fff;
    54. text-align: center;
    55. background-color: rgba(0, 0, 0, 0.8);
    56. border-radius: 5vw;
    57. z-index: 999;
    58. }
    59. .fade-enter-active,
    60. .fade-leave-active {
    61. transition: 0.3s ease-out;
    62. }
    63. .fade-enter {
    64. opacity: 0;
    65. transform: scale(1.2);
    66. }
    67. .fade-leave-to {
    68. opacity: 0;
    69. transform: scale(0.8);
    70. }
    71. </style>
    • 使用:
    1. // main.js
    2. import Vue from 'vue'
    3. import App from './App'
    4. import Toast from './components/Toast.js'
    5. Vue.use(Toast) // 安装组件
    6. Vue.config.productionTip = false
    7. /* eslint-disable no-new */
    8. new Vue({
    9. render: h => h(App)
    10. }).$mount('#app')
    11. // 任意组件
    12. <template>
    13. <div id="app">
    14. <button @click="toast">显示taost弹出框</button>
    15. </div>
    16. </template>
    17. <script>
    18. export default {
    19. name: "app",
    20. methods: {
    21. toast() {
    22. this.$toast("你好");
    23. }
    24. }
    25. };
    26. </script>