vue3新拟态组件库开发流程——message组件源码

本文档详细介绍了如何在Vue项目中自定义一个类似ElementUI的Message组件和服务。首先通过创建服务方法实现消息显示和隐藏,然后逐步完善组件,包括设置不同类型的图标、添加消息内容以及自动关闭功能。最后,展示了如何在实际应用中调用这个自定义Message服务。
摘要由CSDN通过智能技术生成

elementui中可以message有两个调用方法,一种是服务service,一种是单独引用调用。我在使用的时候只用过$message,并且单独引用调用和普通组件一样,比较简单,这里就只做服务了。
有了上一篇文章Loading的基础,再整服务就比较简单了,这边就不重点写服务了,有需求可以回看:

https://blog.csdn.net/SanOrintea/article/details/126622591

先写测试用例

<script setup>
  import { sanorinMessage } from '@/sanorin/packages/message/service' // 因为没npm打包,后续改成import { sanorinMessage } from 'sanorinUI'

  const handleClick = () => {
    sanorinMessage.show();
    setTimeout(() => {
      sanorinMessage.hide()
    }, 5000)
  }
</script>
  
<template>
    <div @click="handleClick">111</div>
</template>

再实现message组件

<script setup>
  import { ref, computed } from 'vue'
  import { useProp, useNeumorphism } from '../mixin/neumorphism'
  const props = defineProps({
      ...useProp,
      ...{
      
      }
  })

  let verticalOffset = 80
  // timer 
  // type

  const { baseStyleObject } = useNeumorphism(props)
  let styleObject =  computed(() => ({ 
    'top': `${ verticalOffset }px`
  }))
</script>
  
<template>
    <div class="san-message neumorphism neumorphism-checked flex" :style="{...baseStyleObject,...styleObject}">
      <i class="message-icon iconfont" :class="typeObj.class"></i>
      <div class="flex-1"><slot></slot></div>
    </div>
</template>
  
<script>
  export default {
    name: 'sanorin-message',
  }
</script>
  
<style scoped>
  @import "../../style/index.css";
  @import "../../style/neumorphism.css";
  .message-icon {
    font-size: 12px;
    padding-right: 10px;
  }
  .san-message {
    min-width: 380px;
    box-sizing: border-box;
    border-radius: 4px;
    position: fixed;
    left: 50%;
    top: 20px;
    transform: translateX(-50%);
    transition: opacity .3s,transform .4s,top .4s;
    overflow: hidden;
    padding: 15px 15px 15px 20px;
    display: flex;
    align-items: center;
}
</style>

留出了verticalOffset timer type的位置先不写,verticalOffset 为了好看不顶格先给个定值80,后续再完善。
接下来写服务js。

import { createApp, ref } from 'vue'
import myLoad from './message.vue'

const $message = createApp(myLoad, {}).mount(document.createElement('div'))
const sanorinMessage = {
  show(e) {
    document.body.appendChild($message.$el)
  },

  hide() {
    document.body.removeChild($message.$el)
  }
}
export  { sanorinMessage }

到这里就能换出来组件了,接下来往组件里填充内容,加上类型,加上时间等完善。

先加类型

<script setup>
  import { ref, computed } from 'vue'
  import { useProp, useNeumorphism } from '../mixin/neumorphism'
  const props = defineProps({
      ...useProp,
      ...{
        type: {
          type: String,
          default: ''
        },
      }
  })
  let typeObj = computed(() => ((e) => ({
      success: () => ({ name: 'success', class: 'san-wancheng' }) ,
      warning: () => ({ name: 'warning', class: 'san-bangzhu' }),
      error: () => ({ name: 'error', class: 'san-shibai' })
    })[e] || (() => ({ name: 'info', class: 'san-zhuyi' })))(props.type.value)()
  )
  let verticalOffset = 80

  const { baseStyleObject } = useNeumorphism(props)
  let styleObject =  computed(() => ({ 
    'top': `${ verticalOffset }px`
  }))
</script>
  
<template>
    <div class="san-message neumorphism neumorphism-checked flex" :style="{...baseStyleObject,...styleObject}">
      <i class="message-icon iconfont" :class="typeObj.class"></i>
      <div class="flex-1"><slot></slot></div>
    </div>
</template>
  
<script>
  export default {
    name: 'sanorin-message',
  }
</script>
  
<style scoped>
  @import "../../style/index.css";
  @import "../../style/neumorphism.css";
  .message-icon {
    font-size: 12px;
    padding-right: 10px;
  }
  .san-message {
    min-width: 380px;
    box-sizing: border-box;
    border-radius: 4px;
    position: fixed;
    left: 50%;
    top: 20px;
    transform: translateX(-50%);
    transition: opacity .3s,transform .4s,top .4s;
    overflow: hidden;
    padding: 15px 15px 15px 20px;
    display: flex;
    align-items: center;
}
</style>
import { createApp, ref, inject } from 'vue'
import myLoad from './message.vue'

const type = ref('')
const $message = createApp(myLoad, { type }).mount(document.createElement('div'))
const sanorinMessage = {
  show(e) {
    type.value = e
    document.body.appendChild($message.$el)
  },

  hide() {
    type.value = ''
    document.body.removeChild($message.$el)
  }
}
export  { sanorinMessage }

接下来加内容

<script setup>
  import { ref, computed } from 'vue'
  import { useProp, useNeumorphism } from '../mixin/neumorphism'
  // const input = ref() // 与html中ref=""对应,定位dom元素
  // const emit = defineEmits(['focus','blur','clear','change','update:modelValue'])
  // const handleFocus = (evt) => { focused.value = true; emit('focus', evt) }
  // const handleBlur = (evt) => { focused.value = false; emit('blur', evt) }
  const props = defineProps({
      ...useProp,
      ...{
        type: {
          type: String,
          default: ''
        },
        text: {
          type: String,
          default: ''
        },
        time: {
          type: Number,
          default: 3000
        }
      }
  })
  let typeObj = computed(() => ((e) => ({
      success: () => ({ name: 'success', class: 'san-wancheng' }) ,
      warning: () => ({ name: 'warning', class: 'san-bangzhu' }),
      error: () => ({ name: 'error', class: 'san-shibai' })
    })[e] || (() => ({ name: 'info', class: 'san-zhuyi' })))(props.type.value)()
  )
  let verticalOffset = 80
  // timer 
  // let visible = ref(true)
  // let timer = null
  // let closeMessage = () => {
  //   timer = null
  //   visible.value = false
  // }
  // if(props.time > 0) {
  //   timer = setTimeout(() => {
  //     closeMessage()
  //   }, props.time)
  // }

  const { baseStyleObject } = useNeumorphism(props)
  let styleObject =  computed(() => ({ 
    'top': `${ verticalOffset }px`
  }))
</script>
  
<template>
    <div class="san-message neumorphism neumorphism-checked flex" :style="{...baseStyleObject,...styleObject}">
      <i class="message-icon iconfont" :class="typeObj.class"></i>
      <div class="flex-1">{{text}}</div>
    </div>
</template>
  
<script>
  export default {
    name: 'sanorin-message',
  }
</script>
  
<style scoped>
  @import "../../style/index.css";
  @import "../../style/neumorphism.css";
  .message-icon {
    font-size: 12px;
    padding-right: 10px;
  }
  .san-message {
    min-width: 380px;
    box-sizing: border-box;
    border-radius: 4px;
    position: fixed;
    left: 50%;
    top: 20px;
    transform: translateX(-50%);
    transition: opacity .3s,transform .4s,top .4s;
    overflow: hidden;
    padding: 15px 15px 15px 20px;
    display: flex;
    align-items: center;
}
</style>
import { createApp, ref } from 'vue'
import myLoad from './message.vue'

const type = ref('')
const text = ref('')
const $message = createApp(myLoad, { type, text }).mount(document.createElement('div'))
const sanorinMessage = {
  show(e) {
    type.value = e.type
    text.value = e.text
    document.body.appendChild($message.$el)
  },

  hide() {
    type.value = ''
    text.value = ''
    document.body.removeChild($message.$el)
  }
}
export  { sanorinMessage }

接下来加一个设定时间隐藏,前面loading组件也可以加,只用改服务就行

import { createApp, ref, inject } from 'vue'
import myLoad from './message.vue'

const type = ref('')
const text = ref('')
const $message = createApp(myLoad, { type, text }).mount(document.createElement('div'))

let show = (e) => {
  type.value = e.type
  text.value = e.text
  document.body.appendChild($message.$el)
}
let hide = () => {
  type.value = ''
    text.value = ''
    document.body.removeChild($message.$el)
}
let auto = (e, t=2000) => {
  show(e)
  setTimeout(() => {
    hide()
  }, t);
}
const sanorinMessage = {
  show, hide, auto
}
export  { sanorinMessage }

接下来写可关闭

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值