preface
Recently, I was reconstructing an old project with VUe3. I came across toast component rewrite and explored it, mainly learning UI encapsulation methods of Vant and Element-UI
Ready to demand
- If you want to build an API that can be called and mounted toa Vue instance, you can call it in the SFC using this.$toast
- Write a toast.vue template for rendering
- Write a toast.ts export toast method and provide it to Vue for mounting
- Referenced in main.ts for global mount
Further refinement
1. The template
- Provide a message argument for popover content
- You need a fade-in effect, so you need transition and a showToast state
2. Export method
- Generate instances from templates
- Mount the instance to the DOM
- Provide a duration and set a duration timer
- Delete the DOM instance after the timer is executed
- Finally, export a mountable object
3. Create an instance
- Write a generic Composition API
- Export the mounted instance
- Export the uninstallation method of the corresponding instance
code
1. Template Toast. Vue
<style lang="less">
.toast {
position: fixed;
left: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
margin: auto;
padding: 0.1rem;
max-width: 80%;
border-radius: 0.05rem;
color: #fff;
background: rgba(0.0.0.0.7);
font-size: 0.28rem;
z-index: 99999;
transition: opacity 0.3s linear;
}
.toast-wrapper-enter-from,
.toast-wrapper-leave-to {
opacity: 0;
}
</style>
<template>
<transition name="toast-wrapper">
<div class="toast" v-show="showToast">{{ message }}</div>
</transition>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
// Message content
props: ['message'].data() {
return {
// state
showToast: false}}})</script>
Copy the code
2. Generate instance usemountComponent.ts
import { Component, createApp } from 'vue'
export function useMountComponent(rootComponent: Component) {
const app = createApp(rootComponent);
const root = document.createElement('div');
document.body.appendChild(root);
return {
instance: app.mount(root),
unmount() {
app.unmount();
document.body.removeChild(root); }}; }Copy the code
3. Export method index.ts
import ToastConstructor from './Toast.vue'
import { nextTick, createVNode, App } from 'vue';
import { useMountComponent } from '.. /.. /lib/utils/useMountComponent'
interface ToastOption {
message: string,
duration: number
}
const toast = (options: ToastOption | string) = > {
const duration = typeofoptions ! = ='string' ? options.duration : 3000
const { instance, unmount } = useMountComponent(createVNode(
ToastConstructor,
{
message: typeof options === 'string' ? options : options.message
}
));
// The agent that gets the instance and the data agent can get the DOM object data and set the state
const { proxy, data } = instance.$
const RemoveSelf = function (event: TransitionEvent) {
unmount()
}
// Perform show and disappear after the TOAST instance is mounted to the DOM
nextTick(() = > {
data.showToast = trueproxy? .$el.removeEventListener('transitionend', RemoveSelf)
~duration && (setTimeout(function () {
data.showToast = falseproxy? .$el.addEventListener('transitionend', RemoveSelf)
}, duration));
});
return instance;
}
export default {
// The install method is required to mount objects
install: (app: App) = > {
app.config.globalProperties.$toast = toast
}
}
Copy the code
4. Mount main.ts globally
import { createApp } from 'vue'
import Toast from './components/toast/index'
const app = createApp(App)
app.use(Toast)
Copy the code
5. Call
export default defineComponent({
name: "TestToast".setup() {
const { proxy } = getCurrentInstance() asComponentInternalInstance proxy? .$toast('test in setup');
},
methods: {TestToast() {
this.$toast('test in method')}}});Copy the code
conclusion
Getting an instance and modifying its properties in Vue3 feels a little strange and is not as convenient as in VUe2. This may be a minor side effect of proxy