vue3 也出来一段时间了,去年的新项目也用上了 vue3 + ts,所以一直想写点东西。对比两个版本的博客比比皆是,所以我就不写那些了(怕水平不够,文笔也不行,让人笑话)。所以干脆写点小东西,比如 – Toast 轻提示组件。有不正之处,望各位指正。
vue3 的写法
<!-- ./src/main.vue -->
<template>
<transition name="scale">
<div v-show="visible" class="jr-toast">
<div class="jr-toast_content">
{{ content }}
</div>
</div>
</transition>
</template>
<script>
import { defineComponent, reactive, ref, toRefs } from 'vue'
export default defineComponent({
setup() {
const state = reactive({
content: '',
type: '', // 可以根据不同的 type 显示不同的图标
delay: ''
})
const visible = ref(false)
let timer
const close = () => {
clearTimeout(timer)
visible.value = false
timer = null
}
const open = () => {
if (timer) clearTimeout(timer)
visible.value = true
timer = setTimeout(close, state.delay)
return close
}
return {
...toRefs(state),
visible,
open,
close
}
}
})
</script>
<style lang="scss" scoped>
.jr-toast {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
}
.jr-toast_content {
padding: 10px 20px;
color: #fff;
word-break: break-all;
background-color: rgba(0, 0, 0, .7);
border-radius: 10px;
}
.scale-enter-active, .scale-leave-active {
transition: transform .2s;
}
.scale-enter, .scale-leave-to {
transform: scale(0)
}
</style>
复制代码
// index.js
import { createApp } from 'vue'
import main from './src/main.vue'
let instance
const initInstance = () => {
// 这里就是与 vue2 最大的区别了
// 在 vue2 的时候,我们只需 instance.$mount() 便能得到节点,现在不行
const app = createApp(main)
// 需要一个容器
const container = document.createElement('div')
// 再进行挂载 - 挂载之后返回实例上下文
instance = app.mount(container)
document.body.appendChild(container)
}
const Toast = option => {
if (!instance) initInstance()
option = typeof option === 'string' ? { content: option } : option
const defaultOption = {
content: '',
delay: 1500,
type: 'info'
}
for (const key in defaultOption)
instance[key] = option[key] || defaultOption[key]
return instance.open()
}
const types = ['success', 'error', 'warn', 'info']
types.forEach(type => Toast[type] = content => Toast({ content, type }))
// 直接导出该方法
export default Toast
// // 或者挂载在根实例的全局配置上
// export default app => app.config.globalProperties.$Toast = Toast
复制代码
vue2 的写法
<!-- ./src/main.vue -->
<template>
<transition name="scale">
<div v-show="visible" class="jr-toast">
<div class="jr-toast_content">
{{ content }}
</div>
</div>
</transition>
</template>
<script>
export default {
props: {
content: String,
type: String,
delay: String
},
data() {
return {
timer: null,
visible: false
}
},
methods: {
open() {
const { timer, delay, close } = this
if (timer) clearTimeout(timer)
this.visible = true
this.timer = setTimeout(close, delay)
return close
},
close() {
clearTimeout(this.timer)
this.timer = null
this.visible = false
}
}
}
</script>
<style lang="scss" scoped>
.jr-toast {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
}
.jr-toast_content {
padding: 10px 20px;
color: #fff;
word-break: break-all;
background-color: rgba(0, 0, 0, .7);
border-radius: 10px;
}
.scale-enter-active, .scale-leave-active {
transition: transform .2s;
}
.scale-enter, .scale-leave-to {
transform: scale(0)
}
</style>
复制代码
// index.js
import Vue from 'vue'
import main from './src/main.vue'
// vue2 需要使用 Vue.extend() 扩展一个子类
const Constructor = Vue.extend(main)
let instance
const Toast = option => {
if (!instance) {
instance = new Constructor()
instance.$mount()
document.body.appendChild(instance.$el)
}
option = typeof option === 'string' ? { content: option } : option
const defaultOption = {
content: '',
delay: 1500,
type: 'info'
}
for (const key in defaultOption)
instance[key] = option[key] || defaultOption[key]
return instance.open()
}
const types = ['success', 'error', 'warn', 'info']
types.forEach(type => Toast[type] = content => new Toast({ content, type }))
export default Vue => Vue.prototype.$Toast = Toast
复制代码
完整代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END