Partage de technologie Web | Réalisez votre propre bibliothèque de composants basée sur vue3, Chapitre 1 : Composant de message

Bonjour à tous, je vais commencer une nouvelle série aujourd'hui 基于vue3实现自己的组件库. Cet article suppose que vous installez et créez un projet vue3. Si vous ne le faites pas, veuillez vous référer au site officiel de vue . Ne parlons pas de bêtises et commençons à réaliser les Messagecomposants cibles de ce chapitre ;

Créer un répertoire de projet de bibliothèque de composants

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

image.png

Installer les dépendances du projet

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

modèle

<template>
    <div class='v-message'>
        <div v-for='(config, index) in messageList' :key='config.id' 
        :ref= 'el => { if (el) contentList[index] = el}'
        :class='["message-item", config.customClass, config.type, { center: config.center }]'>
            <i :class='[config.iconClass, "icon"]'></i>
            <p class='content'>{
   
   { config.message }}</p>
            <i class='close iconfont icon-guanbi1' @click='close(config)' v-if='config.showClose'></i>
        </div>
    </div>
</template>

scénario

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

<style lang='less' scoped>
@import url('../../assets/css/animation.css');
.v-message {
    position: fixed;
    z-index: 99999;
    top: 50px;
    left: 0;
    right: 0;
    margin: auto;
    width: 380px;
    .message-item {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-bottom: 14px;
        box-sizing: border-box;
        border-radius: 6px;
        padding: 14px;
        overflow: hidden;
        border: 1px solid transparent;
        animation: messageShow .5s;
        animation-fill-mode: forwards;
        .content {
            font-size: 12px;
            line-height: 20px;
            flex: 1;
        }
        .close {
            cursor: pointer;
            &:hover {
                color: #6b6b6b;
            }
        }
        i {
            font-size: 18px;
        }
        .icon {
            margin-right: 14px;
        }
    }
    .center {
        justify-content: center;
        .content {
            flex: 0 1 auto;
        }
    }
    .messageHide {
        animation: messageHide .2s linear;
        animation-fill-mode: forwards;
    }
    .prompt {
        border: 1px solid #ebeef5;
        background-color: #edf2fc;
        .content, i {
            color: #909399;
        }
    }
    .success {
        background-color: #f0f9eb;
        border-color: #e1f3d8;
        .content, i {
            color: #67C23A;
        }
    }
    .warning {
        background-color: #fdf6ec;
        border-color: #faecd8;
        .content, i {
            color: #E6A23C;
        }
    }
    .error {
        background-color: #fef0f0;
        border-color: #fde2e2;
        .content, i {
            color: #F56C6C;
        }
    }
}
</style>

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;
    }
}

Ecrire 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();

Ecrire vair export index.js

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

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

export default Vair;

Utiliser la bibliothèque de composants

  • 在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');

Appelé dans App.vue

<template>
    <div class='message'>
        <p class='button' @click='addMsg("success")'>成功</p>
        <p class='button' @click='addMsg("warning")'>警告</p>
        <p class='button' @click='addMsg("error")'>错误</p>
        <p class='button' @click='addMsg("close")'>可关闭</p>
        <p class='button' @click='addMsg("center")'>文字居中</p>
    </div>
</template>

<script>
import { getCurrentInstance, defineComponent } from 'vue';
export default defineComponent({
    setup () {
        const app = getCurrentInstance();

        const addMsg = (type) => {
            if (type === 'success') {
                app.ctx.$message.success({
                    message: '这是一条成功消息'
                });
            }
            
            if (type === 'warning') {
                app.ctx.$message.warning({
                    message: '这是一条警告消息'
                });
            }

            if (type === 'error') {
                app.ctx.$message.error({
                    message: '这是一条错误消息'
                });
            }

            if (type === 'close') {
                app.ctx.$message.success({
                    message: '这是一条可关闭的消息',
                    showClose: true,
                    onClose: (config) => {
                        console.log(config)
                    },
                });
            }

            if (type === 'center') {
                app.ctx.$message.success({
                    message: '这是一条居中的消息',
                    center: true
                });
            }
        };

        return {
            addMsg
        }
    }
})
</script>

<style lang='less' scoped>
.message {
    width: 500px;
    display: flex;
    justify-content: space-between;
}
.button {
    width: 76px;
    line-height: 34px;
    border-radius: 4px;
    color: #fff;
    background-color: #1890FF;
    text-align: center;
    cursor: pointer;
    font-size: 12px;
}
</style>

Montrer les résultats

image.png
insérez la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/anyRTC/article/details/125181606#comments_23548479
conseillé
Classement