以 this.$message 这种 API 形式调用组件的原因:

  • 使用自定义的非全局组件时,必须手动 import 和指定 components 对象属性,较为繁琐。以 API 的形式调用组件,方便快捷
  • 在 vue 中,所有页面和组件最终会以
    为根节点,这个根节点一般不会被限制 css position 属性,而弹窗类组件一般是绝对定位于页面中间,所以适合挂载于仅次于 的节点上 ```java // 组件实例的创建 import Vue from ‘vue’

function create(Component, props) { // 1.创建Vue实例,Component是当前组件实例的根组件 const vm = new Vue({ // 1.1 render:虚拟DOM的实现 // 1.2 h是createElement别名,返回虚拟DOM[VNode] // 1.3 参数props是要传递给Component的参数,{props: props, on: {click:onClick}} // 比如: render: h => h(Component, { props }) // 1.4 $mount()会把上面生成的VNode转化成真是DOM,并挂载到目标节点上 // 若不指定选择器,会执行转化过程,只是不挂载 }).$mount()

  1. // 2.手动挂载:使用原生dom api把它插入文档中
  2. // 2.1 vm.$el:真实dom元素
  3. document.body.appendChild(vm.$el)
  4. // 3.回收:防止内存泄漏
  5. // 3.1 vm.$children[0]获取组件实例
  6. const comp = vm.$children[0]
  7. comp.remove = () => {
  8. document.body.removeChild(vm.$el)
  9. comp.$destroy()
  10. }
  11. return comp

}

export default create

  1. ```java
  2. //main.js
  3. import Vue from 'vue'
  4. import create from 'create.js'
  5. Vue.prototype.$create = create
  1. <!--MyPopup.vue-->
  2. <template>
  3. <div class="my-popup" v-if="isShow">
  4. <!--弹窗遮罩-->
  5. <div class="my-popup-bg"></div>
  6. <!--弹窗容器-->
  7. <div class="my-popup-ctn">
  8. <p class="my-popup-ctt">
  9. <span class="inner-ctt">{{message}}</span>
  10. </p>
  11. </div>
  12. </div>
  13. </template>
  14. <script>
  15. export default {
  16. props: {
  17. message: {
  18. type: String,
  19. default: ""
  20. },
  21. duration: {
  22. type: Number,
  23. default: 1000
  24. }
  25. },
  26. data() {
  27. return {
  28. isShow: false
  29. };
  30. },
  31. methods: {
  32. show() {
  33. this.isShow = true;
  34. <!--指定一定时间间隔后自动隐藏弹窗-->
  35. setTimeout(this.hide, this.duration);
  36. },
  37. hide() {
  38. this.isShow = false;
  39. <!--调用组件实例提供的方法销毁组件实例-->
  40. this.remove();
  41. }
  42. }
  43. };
  44. </script>
  45. <style lang="scss" scoped>
  46. .my-popup {
  47. position: fixed;
  48. left: 0;
  49. right: 0;
  50. top: 0;
  51. bottom: 0;
  52. .my-popup-bg {
  53. position: absolute;
  54. left: 0;
  55. right: 0;
  56. top: 0;
  57. bottom: 0;
  58. background: rgba($color: #000000, $alpha: 0.4);
  59. }
  60. .my-popup-ctn {
  61. position: absolute;
  62. left: 50%;
  63. top: 50%;
  64. width: 600px;
  65. padding: 20px;
  66. transform: translate(-50%, -50%);
  67. background: rgba($color: #000000, $alpha: 0.8);
  68. border-radius: 16px;
  69. .my-popup-ctt {
  70. display: flex;
  71. min-height: 100px;
  72. align-items: center;
  73. justify-content: center;
  74. .inner-ctt {
  75. display: inline-block;
  76. text-align: left;
  77. font-size: 30px;
  78. line-height: 50px;
  79. color: #fff;
  80. }
  81. }
  82. }
  83. }
  84. </style>
  1. <!--TestMyPopup.vue-->
  2. <template>
  3. <div>
  4. </div>
  5. </template>
  6. import MyPopup from "MyPopup.vue";
  7. <script>
  8. export default {
  9. mounted () {
  10. const notice = this.$create(MyPopup, {
  11. message: '弹~弹~弹,弹走鱼尾纹',
  12. duration: 2000
  13. });
  14. notice.show();
  15. },
  16. }
  17. </script>

参考资料

  1. Vue弹窗类组件的设计与实现