一起来做一下Vue全局提示组件

 更新时间:2022年06月07日 11:58:08   作者:阿远Carry  
前端开发的时候,在项目中引入组件以及使用是非常常见操作,下面这篇文章主要给大家介绍了关于Vue全局提示组件的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

全局提示组件在前端中算是比较重要的,在开发业务时候肯定能用的上,毕竟任何报错只要提示“服务器异常”就可以完美把锅扔给后台(手动滑稽)

全局提示组件在人气比较🔥的 UI 组件库必有他身影,可能叫法不太相同,有叫 message、toast、alert 等,但就是这么一玩意。

拿 ant-design-vue 组件库为例

其核心代码

message.info('This is a normal message')

他是API的方式进行调用组件,以平常使用components注册组件,之后在template中使用的方式不太相同

想要实现这个,其实并不困难

但在之前我想声明一下:ant-design-vue 的 message 做个type分类,有info、success、error等。但为了读者方便理解,我们统一就用message来进行调用,读者可以根据本文提供的demo源码自行进行调整(贴一下 ant-design-vue 源码)

首先,我们在 components 目录下创建 message 目录,同时创建 Message.vue 和 index.js 文件

然后在 Message.vue 中写

<!-- Message.vue -->
<template>
  <div>{{ content }}</div>
</template>

<script>
export default {
  name: 'Message',
  props: {
    content: {
      type: String,
      default: ''
    }
  }
}
</script>

再者在 index.js 中写

// index.js
import { render, createVNode } from 'vue'
import Message from './Message.vue'

export default function message (content) {
  const div = document.createElement('div')
  const vm = createVNode(Message, {
    content
  })
  render(vm, div)
  document.body.appendChild(div)
}

最后在 app.vue 引入使用

<!-- app.vue -->
<template>
</template>
<script>
import message from './components/message'
export default{
  setup() {
    message('消息组件1')
    message('消息组件2')
  }
}
</script>

效果:

ok,这样就实现了以API的方式进行调用组件

其核心代码其实只有以下

const div = document.createElement('div')
const vm = createVNode(Message, {
  content
})
render(vm, div)
document.body.appendChild(div)

createVNode 可以认为就是h函数,支持直接转成虚拟dom对象

再去调用 render,渲染至div下,再将div插入body中

由于我们做的是全局组件,应该不被任何因素干扰,比如 vue-router

但是上面例子我们会发现,我们只要调用一个 message 方法,就要创建一个div插入至body,这显然不是符合vue数据驱动视图的理念

那,接下里进行改造

先从 Message.vue 文件开始

我们先定义一个消息列表messages,之后提供添加 add 和删除delete消息列两方法,再暴露add方法出去

当然,删除消息是需要根据id进行删除,可不能瞎删

<!-- Message.vue -->
<script>
import { ref, unref } from 'vue'
export default {
  name: 'Message',
  setup (props, { expose }) {
    // 消息列表
    const messages = ref([])
    
    let id = 0
    // 生成id
    const uuid = () => `message_${id++}`
    
    // 添加消息对象
    const add = (message) => {
      const id = uuid()
      const _message = {
        ...message,
        id
      }
      unref(messages).push(_message)
      const { duration = 3 } =  message
      // 设置定时器
      const timer = setTimeout(() => {
        clearTimeout(timer)
        remove(id)
      }, duration * 1000)
    }
    
    // 根据 id 删除消息对象
    const remove = (id) => {
      messages.value = unref(messages).filter(message => message.id !== id)
    }
    
    // 暴露出add 和 remove
    expose({
      add
    })
    
    return {
      messages
    }
  }
}
</script>

用v-for把消息列表渲染出来,同时使用transition-group做一些列表过渡动画

<!-- Message.vue -->
<template>
  <transition-group
    class="message"
    tag="div"
  >
    <div
      class="message-content"
      v-for="message in messages"
      :key="message.id"
    >
      {{ message.content }}
    </div>
  </transition-group>
</template>

再编写一点消息列表样式和其弹出动画样式

<!-- Message.vue -->
<style scoped>
.message {
  position: fixed;
  z-index: 999;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
}

.message-content {
  padding: 8px 16px;
  border-radius: 3px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, .2);
  background: #fff;
  margin-bottom: 20px;
}

.v-enter-active,
.-leave-active {
  transition: all 200ms ease-in;
}
.v-enter-from,
.v-leave-to {
  opacity: 0;
  transform: translateY(-30px);
}
</style>

再改造一下入口文件

之前我们发现在 app.vue 中调用一次 message方法,就会一次 dom 操作,那我们使用闭包写一个单例模式进行改造

再者我们在 Message.vue 暴露出add的方法可以直接进行操作消息列表

// index.js
import { render, createVNode } from 'vue'
import Message from './Message.vue'

let vm
// 使用单例模式,不再重新插入body
function getMessageInstance () {
  if (vm) return
  const div = document.createElement('div')
  vm = createVNode(Message)
  render(vm, div)
  document.body.appendChild(div)
}

export default function message (content = '', duration) {
  getMessageInstance()
  vm.component.exposed.add({
    content,
    duration
  })
}

最后在 app.vue 文件中随便编写一些测试代码

<!-- app.vue -->
<template>
  <button @click="onClick">测试</button>
</template>
<script>
import message from './components/message'
export default{
  setup() {
    message('消息组件1', 4)
    message('消息组件2', 2)
    let index = 3
    const onClick = () => {
      message(`消息组件${index++}`)
    }
    return {
      onClick
    }
  }
}
</script>

看看最终效果

好,这就是全局提示组件设计大致思路。

回顾一下会发现,其实Vue的组件开发依旧绕不开 JavaScript,可见 JavaScript 在前端的份量。

总结

到此这篇关于Vue全局提示组件的文章就介绍到这了,更多相关Vue全局提示组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 在vue中nextTick用法及nextTick 的原理是什么

    在vue中nextTick用法及nextTick 的原理是什么

    这篇文章主要介绍了在vue中nextTick用法及nextTick 的原理是什么,Vue.js 是一个流行的前端框架,它提供了一种响应式的数据绑定机制,使得页面的数据与页面的 UI 组件之间能够自动同步,需要的朋友可以参考下
    2023-04-04
  • vue router使用query和params传参的使用和区别

    vue router使用query和params传参的使用和区别

    本篇文章主要介绍了vue router使用query和params传参的使用和区别,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • Ant Design_Form表单上传文件组件实现详解

    Ant Design_Form表单上传文件组件实现详解

    这篇文章主要为大家介绍了Ant Design_Form表单上传文件组件实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • 前端实现简单的sse封装方式(React hook Vue3)

    前端实现简单的sse封装方式(React hook Vue3)

    这篇文章主要介绍了前端实现简单的sse封装方式(React hook Vue3),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • vue 页面卡死,点击无反应的问题及解决

    vue 页面卡死,点击无反应的问题及解决

    这篇文章主要介绍了vue 页面卡死,点击无反应的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • Vue读取本地静态文件json的2种方法以及优缺点

    Vue读取本地静态文件json的2种方法以及优缺点

    这篇文章主要介绍了Vue读取本地静态文件json的2种方法以及优缺点说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • Vue3+Canvas实现坦克大战游戏(二)

    Vue3+Canvas实现坦克大战游戏(二)

    本文主要给大家讲解一下子弹击中物体、物体销毁、敌方坦克构建生成、运动算法、爆炸效果、以及障碍物的生成,感兴趣的小伙伴可以了解一下
    2022-03-03
  • Vue中的 DOM与Diff详情

    Vue中的 DOM与Diff详情

    这篇文章主要介绍了Vue中的 DOM与Diff详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下,希望对你的学习有所帮助
    2022-08-08
  • vuejs在解析时出现闪烁的原因及防止闪烁的方法

    vuejs在解析时出现闪烁的原因及防止闪烁的方法

    这篇文章主要介绍了vuejs在解析时出现闪烁的原因及防止闪烁的方法,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起看看吧
    2016-09-09
  • 详解vue中async-await的使用误区

    详解vue中async-await的使用误区

    这篇文章主要介绍了vue中async-await的使用误区,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-12-12

最新评论