Vue

Vue - 如何开发一个命令式弹窗组件

Posted on 04-13 2020,6 min read

Vue - 如何开发一个命令式弹窗组件


Organized by安南 City

Completion time2020-04-13

Send error to emailcity@nanzc.com


Description

​ 在最近开发个人博客时,少不了用到命令式弹窗组件,于是...

顺便记录下吧。

 

要实现命令式弹窗组件,需要涉及:Vue.extend()vm.mount()](https://cn.vuejs.org/v2/api/#vm-mount)、[vm.el

 

涉及知识


 

Vue.extend( options )


params:

options {Object} - 组件选项的对象

​ 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

 

如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。

可以使用 vm.$mount() 手动地挂载一个未挂载的实例。

 

vm.$mount( [elementOrSelector] )


params:

[elementOrSelector] {Element | String} - 元素或选择器

[hydrating] {boolean}

return:

vm - 实例自身

可以使用该方法手动挂载一个未挂载的实例。

如果没有提供 elementOrSelector 参数,模板将被渲染为文档之外的的元素,并且你必须使用原生 DOM API 把它插入文档中。

 

这里在后面代码中,我们将采用原生 API 插入文档末尾。

当然你也可以直接提供 elementOrSelector 参数,那就无需使用 vm.$el

 

vm.$el


type:

Element

Vue 实例使用的根 DOM 元素。

 

使用 vm.$mount() 手动挂载后,并且没有提供 elementOrSelector 参数,需要手动插入文档。

还有一个知识,将在使用组件时讲到,为了可读流程就暂不讲。

 

这里我们将以一个简洁的提示框为例。

 

目录结构


  • message:组件目录
    • index.vue:组件布局、样式、交互逻辑
    • index.js: 组件实例化、挂载方法、暴露安装函数

 

组件规划


这是一个命令式调用组件,所以我们需要定义形参

形参 key 说明 默认值
options
title 提示信息 ""
time 存在时间 (ms) 4000

 

代码实践


由于这里只是示例,我就不过多解释了,大家拿出平时的基操就行。

具体重点看代码中文注释(英文注释的作用就是练单词)。

自由编码没有固定的格式,练得就是随机应变。

 

  • index.vue

    /**
     * @author City
     * @description 消息组件
     * TODO: 这里仅供参考,不细封。
     */
    
    <template>
        <div class="message" :style="{top}">{{title}}</div>
    </template>
    
    <script>
    export default {
        name: "Message",
        data() {
            return {
                /* style */
                top: "-40px"
                
                /* params */
                // 1.可传参数
                // 不传则为此处定义默认值,传递将被使用的 Object.assign() 方法覆盖;
                title: "",
                time: 4000,
            };
        },
        methods: {
            /* show message */
            // 2.show 方法将在初始化实例挂载组件、DOM 追加到文档之后调用
            show() {
                // trigger start transition
                setTimeout(() => {
                    this.top = "40px";
                }, 50);
    
                // time out hide
                setTimeout(() => this.hide(), this.time - 1000);
            },
            /* hide message */
            hide() {
                // trigger end transition
                this.top = "-40px";
    
                // destroy component
                setTimeout(() => {
                    // 3.删除 DOM 节点,并销毁组件
                    document.body.removeChild(this.$el);
                    this.$destroy();
                }, 1000);
            }
        }
    };
    </script>
    
    <style lang="stylus" scoped>
    .message
        position fixed
        top -40px
        right 80px
        z-index 1001
        padding 0 30px
        height 40px
        line-height @height
        border-radius 15px
        transition top 1s
        text-align center
        background #3d86af
        color white
    </style>
    

    这里没有使用 mounted 生命周期,而是在命令调用组件时触发 show 方法,当然你可以不这样。

     

  • index.js

    /**
     * @author City
     * @description 组件实例化 挂载方法 暴露安装函数
     */
    
    import Vue from "vue";
    import message from "./index.vue";
    
    /* extend message create constructor */
    // 1.创建组件构造函数
    const MessageConstructor = Vue.extend(message);
    
    /* init instance function */
    const init = options => {
        // instantiation constructor
        // 2.实例化组件
        const instance = new MessageConstructor();
    
        // merge data property
        // 3.将传递参数直接覆盖原实例 data 定义参数
        Object.assign(instance, options);
    
        // create virtual DOM and append to document
        // 4.渲染为文档之外元素,也可理解为虚拟 DOM,然后追加到文档
        document.body.appendChild(instance.$mount().$el);
    
        // return this instance
        // 5.返回组件实例
        return instance;
    };
    
    /* caller */
    // 5.创建命令调用函数,并接受参数
    // 形参需要为对象形式,并且命名需要和 data 定义参数一致,当然你也可以细化封装
    const caller = options => {
        // init instance
        // 6.初始化 DOM
        const instance = init(options);
    
        // call show function
        // 7.调用实例 show 方法
        instance.show();
    };
    
    /* export install function */
    // 8.导出安装方法
    export default function(vue) {
        // 9.在 Vue 原型上挂载命令调用函数
        vue.prototype.$message = caller;
    };
    

    这里面重点为 传参方式 体现在第 3 步。

    这里封装的并不是很好,这里为了示例没有修改,按照实际需求走就行。

 

使用组件


使用组件需要知道 Vue.use() 方法的知识。

 

Vue.use( plugin )


params:

plugin {Object | Function}

安装 Vue.js 插件。如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入

该方法需要在调用 new Vue() 之前被调用。

install 方法被同一个插件多次调用,插件将只会被安装一次。

 

这里我们就直接在 main.js 中使用,你也可以在项目中将UI当做插件引入,在UI中处理组件 install 方法。

  • main.js

    import massage from "./components/massage"; // 示例目录
    // ...
    Vue.use(massage)
    // ...
    

     

命令式调用组件


this.$message({title: "信息内容"})

好了调用就是这么简单,还一个 time 我们不传则为默认值。

 

下一篇: Webpack - 前端工程化