web技术分享| 基于vue3实现自己的组件库,第一章:Message组件


大家好今天将开始新的系列基于vue3实现自己的组件库,本文默认你会安装和创建vue3项目,如果不会请参考vue官网,废话不多说开始实现本章的目标Message组件;

创建组件库工程目录

  • vair是组件库的名字(名字大家随意)

image.png

安装项目依赖

npm install less -D
npm install less-loader -D

template


script

import { ref, defineComponent } from 'vue';

export default defineComponent({
    name: 'message',
    setup () {
        // 消息列表
        const messageList = ref([]);
        // ref列表
        const contentList = ref([]);

        const message = (options) => {
            computedConfig(options);
        }

        const success = (options) => {
            computedConfig(options, 'success');
        }

        const warning = (options) => {
            computedConfig(options, 'warning');
        }

        const error = (options) => {
            computedConfig(options, 'error');
        }

        const computedConfig = (options, type) => {
            var option = options || {};
            type && (option.type = type);
            const config = {
                type: option.type || 'prompt', // 没传消息类型就是默认消息
                message: option.message || '',
                iconClass: option.iconClass || computedIconClass(type || 'prompt'),
                customClass: option.customClass,
                duration: option.duration >= 0? option.duration : 3000,
                showClose: option.showClose,
                center: option.center,
                onClose: option.onClose,
                id: Math.floor(new Date())
            };
            messageList.value.push(config);
            // 如果延时不等于0,就要设置消失时间
            if (config.duration !== 0) {
                setTimeout(() => {
                    contentList.value[0].className += ' messageHide';
                    setTimeout(() => {
                        messageList.value.splice(0, 1);
                    }, 200);
                }, config.duration + messageList.value.length * 100);
            }
        };

        const computedIconClass = (type) => {
            switch (type) {
                case 'prompt':
                    return 'iconfont icon-tishi';
                case 'success':
                    return 'iconfont icon-success';
                case 'warning':
                    return 'iconfont icon-jinggao--';
                case 'error':
                    return 'iconfont icon-cuowu';
            }
        };

        const close = (config) => {
            const index = messageList.value.findIndex(item => item.id === config.id);
            if (index !== -1) {
                contentList.value[index].className += ' messageHide';
                setTimeout(() => {
                    messageList.value.splice(index, 1);
                    config.onClose && config.onClose(config);
                }, 200);
            }
        }

        return {
            messageList,
            contentList,
            close,
            message,
            success,
            warning,
            error
        }
    }
});

css


animation.css

  • 这个文件的功能就是定义组件所需的动画
@keyframes messageShow {
    0% {
        transform: translateY(-50px);
        opacity: 0;
    }
    100% {
        transform: translateY(0);
        opacity: 1;
    }
}

@keyframes messageHide {
    0% {
        transform: translateY(0);
        opacity: 1;
    }
    100% {
        transform: translateY(-50px);
        opacity: 0;
    }
}

编写message.js

import Message from "./Message.vue";
import { createApp } from "vue";

const createMessage = function () {
    const div = document.createElement("div");
    div.id = "v-message";
    document.body.appendChild(div);
    return createApp(Message).mount("#v-message");
};

export default createMessage();

编写vair出口 index.js

  • 后续这个文件会引入很多组件
// Message 消息提示
import Message from './components/Message/message.js';

const Vair = function(Vue) {
    // Message 消息提示
    Vue.config.globalProperties.$message = Message;
}

export default Vair;

使用组件库

  • 在main.js中引入
import { createApp } from 'vue';
import App from './App.vue';
import Vair from './libs/vair/index.js';

const app = createApp(App);
app.use(Vair).mount('#app');

App.vue中调用






效果展示

image.png
在这里插入图片描述