vue

vue 3.0 封装 Toast 组件

2021-12-15  本文已影响0人  异想天不开_9950

使用 vue3.0 封装组件与 vue 2.x 相比有一些区别:

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);
// 挂载原型
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组件完整代码

<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>
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,只需要把类型去掉即可

上一篇 下一篇

猜你喜欢

热点阅读