Vue.extend实现全局Toast提示组件和Dialog对话框组件封装


Vue.extend实现全局Toast提示组件和Dialog对话框组件封装
Vue.extend() 使用
Vue.extend 属于 Vue 的全局 API,相比常用的 Vue.component 写法,使用 Vue.extend 步骤更加繁琐一些,但是在一些独立组件开发场景中,Vue.extend + $mount 这对组合使一些动态渲染或者使用 js 全局调用的组件变得更加灵活Vue.extend() 方法返回一个组件构造器,通过组件构造器创建组件实例,该实例的参数是一个包含组件选项的对象,用来在实例上扩展属性和方法
Vue.js官网全局 API 介绍:
在这里插入图片描述
Vue.extend 实现 Toast 提示组件封装
在 components 目录下新建 Toast 文件夹作为 Toast 组件文件,新建 index.vue 和 index.js 文件进行组件封装,并在 main.js 中将组件挂载到 vue 原型上实现全局使用
components/Toast/index.vue:
<template>    <div id="toast">        <p :class="[type ? `toast-${type}` : '', size ? `toast-${size}` : '']">            {{ message }}        </p>    </div></template><script>export default {    name: 'toast',    data() {        return {            //显示类型(success,info,warning,error),默认为info            type: 'info',            //显示大小(default,small,big),默认为default            size: 'default',            //显示文字内容            message: '',            //显示时间,默认为3000            duration: 3000        }    },    mounted() {        //指定时间后销毁组件        setTimeout(() => {            this.$destroy(true)  //销毁组件            this.$el.parentNode.removeChild(this.$el)  //父元素中移除dom元素($el为组件实例)        }, this.duration)    }}</script><style lang='less' scoped>    #toast {        position: fixed;        top: 10px;        left: 50%;        transform: translateX(-50%);        z-index: 9999;        p {            border-radius: 4px;        }        .toast-success {            background-color: #F0F9EB;            color: #67C23A;            border: 1px solid #E1F3D8;        }        .toast-info {            background-color: #F4F4F5;            color: #909399;            border: 1px solid  #EBEEF5;        }        .toast-warning {            background-color: #FDF6EC;            color: #E6A23C;            border: 1px solid #FAECD8;        }        .toast-error {            background-color: #FEF0F0;            color: #F56C6C;            border: 1px solid #FDE2E2;        }        .toast-default {            padding: 12px 35px;            font-size: 16px;        }        .toast-small {            padding: 10px 30px;            font-size: 14px;        }        .toast-big {            padding: 14px 40px;            font-size: 18px;        }    }</style>
components/Toast/index.js:
import Vue from 'vue'import Toast from './index.vue'//创建Toast构造器let ToastConstrutor = Vue.extend(Toast)let instanceconst toast = function(options = {}) {    //设置默认参数为对象,如果参数为字符串,参数中message属性等于该参数    if(typeof options === 'string') {        options = {            message: options        }    }    //创建实例    instance = new ToastConstrutor({        data: options    })    //将实例挂载到body下    document.body.appendChild(instance.$mount().$el)}export default toast
main.js:
import Vue from 'vue'import App from './App.vue'import Less from 'less'import router from './router'//引入Toast组件import Toast from './components/Toast'Vue.use(Less)Vue.config.productionTip = false//将Toast组件挂载到vue原型上Vue.prototype.$toast = Toastnew Vue({  router,  render: h => h(App),}).$mount('#app')
在需要使用 Toast 组件的地方调用 this.$toast() 并传入参数使用
//传入对象参数this.$toast({ type: 'success',    size: 'default',    message: '成功提示',    duration: 3000})this.$toast({    type: 'info',    size: 'default',    message: '消息提示',    duration: 3000})this.$toast({    type: 'warning',    size: 'default',    message: '警告提示',    duration: 3000})this.$toast({    type: 'error',    size: 'default',    message: '错误提示',    duration: 3000})//传入字符串参数(该参数会做为参数中message属性的值)this.$toast('提示消息')
效果:
在这里插入图片描述
Vue.extend 实现 Dialog 对话框组件封装
在 components 目录下新建 Dialog 文件夹作为 Dialog 组件文件,新建 index.vue 和 index.js 文件进行组件封装,并在 main.js 中将组件挂载到 vue 原型上实现全局使用
components/Dialog/index.vue:
<template>    <div id="dialog">        <div class="dialog-box">            <p class="title">{{ title }}</p>            <p class="content">{{ content }}</p>            <div class="btn-box">                <button class="left-btn" @click="cancel">{{ left_buttton }}</button>                <button class="right-btn" @click="ok">{{ right_buttton }}</button>            </div>        </div>    </div></template><script>export default {    name: 'dialog',    data() {        return {            //显示标题,默认为“提示”            title: '提示',            //显示内容            content: '',            //左按钮显示文本,默认为“取消”            left_buttton: '取消',            //右按钮显示文本,默认为“确定”            right_buttton: '确定'        }    },    methods: {        //点击取消按钮        cancel() {            this.onCancel()  //点击取消的回调函数            this.$destroy(true)  //销毁组件            this.$el.parentNode.removeChild(this.$el)  //父元素中移除dom元素($el为组件实例)        },        //点击确定按钮        ok() {            this.onOk()  //点击确定的回调函数            this.$destroy(true)  //销毁组件            this.$el.parentNode.removeChild(this.$el)  //父元素中移除dom元素($el为组件实例)        }    }}</script><style lang='less' scoped>    #dialog {        position: fixed;        top: 0;        left: 0;        right: 0;        bottom: 0;        background-color: rgba(0, 0, 0, 0.2);        z-index: 9999;        .dialog-box {            width: 400px;            border-radius: 2px;            background-color: #fff;            position: absolute;            top: 100px;            left: 50%;            transform: translateX(-50%);            padding: 20px 30px;            box-sizing: border-box;            .title {                font-size: 20px;                margin-bottom: 15px;                text-align: center;            }            .content {                font-size: 16px;                line-height: 22px;            }            .btn-box {                width: 100%;                height: 70px;                padding-top: 32px;                padding-left: 170px;                box-sizing: border-box;                button {                    width: 65px;                    height: 38px;                    font-size: 16px;                    margin-left: 20px;                    border-radius: 2px;                    border: none;                    outline: none;                    cursor: pointer;                }                .left-btn {                    background-color: #DCDFE6;                    color: #606266;                }                .right-btn {                    background-color: #409EFF;                    color: #fff;                }            }        }    }</style>
components/Dialog/index.js:
import Vue from 'vue'import Dialog from './index.vue'//创建Dialog构造器let DialogConstrutor = Vue.extend(Dialog)let instanceconst dialog = function(options = {}) {    //设置默认参数为对象,如果参数为字符串,参数中message属性等于该参数,回调函数为空    if(typeof options === 'string') {        options = {            content: options,            onOk: () => {},            onCancel: () => {}        }    }    //创建实例    instance = new DialogConstrutor({        data: options    })    //将实例挂载到body下    document.body.appendChild(instance.$mount().$el)}export default dialog
main.js:
import Vue from 'vue'import App from './App.vue'import Less from 'less'import router from './router'//引入Dialog组件import Dialog from './components/Dialog'Vue.use(Less)Vue.config.productionTip = false//将Dialog组件挂载到vue原型上Vue.prototype.$dialog= Dialognew Vue({  router,  render: h => h(App),}).$mount('#app')
在需要使用 Dialog 组件的地方调用 this.$dialog) 并传入参数使用
//传入对象参数this.$dialog({    title: '提示',    content: '这是一段提示信息',    left_buttton: '取消',    right_buttton: '确定',    onOk: () => {        console.log('ok');    },    onCancel: () => {        console.log('cancel');    }})//传入字符串参数(该参数会做为参数中content属性的值,回调函数为空)this.$dialog('这是一段提示信息')
效果:
在这里插入图片描述
到顶部