IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue进阶:弹窗类组件实现方式 -> 正文阅读

[JavaScript知识库]vue进阶:弹窗类组件实现方式

弹窗类组件的特点

弹窗类组件的特点就是他们在当前的vue实例之外独立存在,通常挂载于body。他们是通过纯JS创建的,不需要在任何组件中声明。常见的食用方式是这样:

this.$create(Notice, {
	title: '标题标题', 
	message: '提示信息'
}).show();

分析实现思路

根据上面的实用方式,我们要想实现在vue组件中全局使用this.$create()方法,就需要将该方法赋值到vue的原型对象上。假设我们已经实现了create方法:

Vue.prototype.$create = create

分析下create函数,它接受两个参数,一个是组件配置对象,命名为Component,一个是参数属性,我们将他命名为props。要想将该组件配置对象挂载到body上,就需要构建Component实例,这样才能生成真实的dom节点。顺着这个思路,拿到真实的dom元素后,将该元素append到body上。再给其添加个remove方法,在移除的时候删除节点销毁自身,就大功告成了。

实现方式

借鸡生蛋式——借助Vue构造函数

在vue项目的main.js中,我们要想在body上挂载app组件,是这样写的:

new Vue({
  render: h => h(App)
}).$mount('#app')

这里的h就是createElement,它可以返回一个vnode即虚拟dom。$mount方法则可以将render函数中返回的vnode转化为真实节点,并挂载到目标元素上。需要注意一点:
$mount()是覆盖性操作。

所以我们在实现create时,不能够直接使用$mount(body),将真实节点挂载到body上。但是可以不设置挂载目标,这样依然可以转换vnode为真实节点。

所以我们也可以借助这种方式:

import Vue from 'vue'
export default function create (Component, props) {
  // 1. 构建Component的实例
  const vm = new Vue({
    render: (h) => {
      return h(Component, {props})
    }
    // 不能直接挂载在body节点上,因为$mount()是覆盖性操作.
  }).$mount()
  
  // 2.将真实节点挂载到body上,vm.$el是实例的真实节点。
  document.body.appendChild(vm.$el)

  // 3.获取组件实例
  const comp = vm.$children[0]

  comp.remove = () => {
    document.body.remove(vm.$el)
    vm.$destroy()
  }

  return comp
}

这样我们就是实现了create方法。我们写个例子来验证它:

// Notice组件

<template>
    <div v-if="isShow" class="modal">
        <div class="title">{{ title }}</div>
        <div class="content">{{ content }}</div>
    </div>
</template>

<script>
export default {
  name: 'Notice',
  props: {
    title: {
      type: String,
      default: '警告'
    },
    content: {
      type: String,
      default: '我是内容我是内容'
    }
  },
  data () {
    return {
      timerId: null,
      isShow: false
    }
  },
  methods: {
    show () {
      this.isShow = true
      setTimeout(() => {
        this.hide()
      }, 1500)
    },
    hide () {
      this.isShow = false
    }
  }
}
</script>

<style scoped>
.modal{
    position: relative;
    top: 50px;
    left: 50%;
    margin-left: -250px;
    width: 500px;
    border: 1px solid #f7f7f7;
    border-radius: 6px;
    padding: 10px;
    background-color: papayawhip;
    animation: disappear 2s ease-in-out;
}
.title{
    text-align: left;
    font-weight: 500;
    font-size: 14px;
}
.content {
    margin-bottom: 10px;
    font-size: 12px;
}

@keyframes disappear {
    0% {
        top: 60px;
        opacity: 1;
    }
    30% {
        top: 10px;
        opacity: 1;
    }
    96% {
      opacity: 0.20;
    }
    100% {
        top: 10px;
        opacity: 0;
    }
}
</style>

// index页面

<template>
    <div>
      <button @click="showNotice">提示弹窗</button>
    </div>
</template>

<script>
import Notice from './Source/NoticeModal/Notice.vue'
export default {
  name: 'Source',
  methods: {
    showNotice () {
      const notice = this.$create(Notice, {
        title: '测试标题',
        content: '我是内容内容呀呀呀'
      })
      notice.show()
    }
  }
}
</script>

效果:

在这里插入图片描述
来对比看下dom的渲染:
在这里插入图片描述

Vue.extends()方法

Vue.extends()方法可以使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。extend 创建的是 Vue 构造器,而不是我们平时常写的组件实例。

export default function create (Component, props) {
  // 1. 构建Component的实例
  const Ctor = Vue.extend(Component)
  
  // 2. 将props传递给创建的实例并挂载
  const vm = new Ctor({propsData: props}).$mount()

  // 将真实节点挂载到body上
  document.body.appendChild(vm.$el)
  
  vm.remove = () => {
    document.body.remove(vm.$el)
    vm.$destroy()
  }
  
  return vm
}

至此,一个纯js调用的弹窗类组件就完成了。参考文档:vuejs.org

? ? ? ? ? ?
关注我,每日都有新收获!
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:22:00  更:2022-02-26 11:25:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:54:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码