使用 vue3.0 封装组件与 vue 2.x 相比有一些区别:
- 创建组件时使用的函数不同
在 vue2.x 中创建一些独立组件,我们一般都是使用 Vue.extend + $mount 这对组合;而在 vue3.0中,我们可以使用 createApp + mount 这对组合
- 创建组件时使用的函数不同
const app = createApp({
render() {
return h(ToastComponent, { title });
}
}
// 动态创建元素
const toast = document.createElement('div');
// 子节点添加到body上
document.body.appendChild(toast);
app.mount(toast);
也可以使用 createVNode + render 这对组合
// 创建虚拟dom (组件对象, props)
const vnode = createVNode(ToastComponent, { title });
// 动态创建元素
const toast = document.createElement('div');
// 子节点添加到body上
document.body.appendChild(toast);
// 把虚拟dom渲染到div
render(vnode, toast);
- 全局使用时设置方式不同
在 vue2.x 中设置全局一般是在 vue 的原型上注册一个方法,让所有实例共享这个方法 Vue.prototype.$toast = () => {};而在 vue3.0 中可以使用 app.config.globalProperties 挂载原型方法
- 全局使用时设置方式不同
// 挂载原型
import Toast from '@src/components/Toast'
export default {
install (app) {
// 如果你想挂载全局的属性,能够通过组件实例调用的属性 this.$message
// 扩展一个实例方法
app.config.globalProperties.$toast = Toast // 原型函数
}
}
// 函数使用
import { getCurrentInstance } from 'vue'
setup () {
const instance = getCurrentInstance()
instance.proxy.$toast({ title: '登录成功' })
}
也支持直接导入函数使用 import Toast from '@src/components/Toast'
import Toast from '@src/components/Toast'
setup(){
Toast({ title: '登录成功' })
}
vue3.0 toast组件完整代码
- Toast.vue
<template>
<div
class="toast-wrap"
>
<div class="toast">
{{ title }}
</div>
</div>
</template>
<script lang="ts">
export default ({
name: 'Toast',
props: {
title: {
type: String,
default: '我是toast'
}
},
setup () {
return {};
}
});
</script>
<style lang="less" scoped>
.toast-wrap{
z-index: 1000;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
}
.toast {
max-width: 6rem;
color: #ffffff;
font-size: 14px;
text-align: center;
border-radius: 5px;
padding: 10px;
background: rgba(0, 0, 0, 0.8);
}
</style>
- index.ts
import { createVNode, render } from 'vue';
import Toast from '@src/components/Toast';
// 准备一个DOM容器
const div = document.createElement('div');
div.setAttribute('class', 'toast-wrapper');
document.body.appendChild(div);
let time: any = null;
// 初始数据
type title = string;
interface ToastType {
title: title;
duration?: number;
}
type union = title | ToastType;
export default (options: union) => {
let title, duration;
if (typeof options === 'string') {
title = options || '我是默认文案';
duration = 2000;
} else {
title = (options as ToastType).title || '我是默认文案';
duration = (options as ToastType).duration || 2000;
}
// 创建虚拟dom (组件对象, props)
const vnode = createVNode(Toast, { title });
// 把虚拟dom渲染到div
render(vnode, div);
clearTimeout(timer);
timer = setTimeout(() => {
render(null, div);
}, duration);
};
- 使用
import Toast from '@src/components/Toast';
setup (props) {
// 使用方法一
Toast({ title: '加入成功' });
// 使用方法二(组件中使用了联合类型,也可以直接传字符串)
Toast( '加入成功' );
}
注:本篇文章使用了 typescript,如果你是使用的 javascript,只需要把类型去掉即可