不会封装函数式调用组件?也许你卡在了这里

引出

未命名.gif

在vue2当中,全局组件比如弹窗组件如何封装呢?

有些小伙伴可能就简单的封装一个,这种功能也是很完备的

image.png

缺点:需要引入额外响应式变量,方法去控制

优点:像el-dialog一样,适合需要定制性更大的场景

那么对于定制性要求更小的场景,因此适合展示较为简单的内容,ElementUI是推荐: messageBox组件,

看下它的用法:

image.png

这种类似于原生alert弹窗的,就是函数式调用,那么如何封装一个这样的组件呢? 下面会一一道来

如何封装?

为什么能this.$alert?

这个官方给出了答案

image.png

就是利用原型链

Vue.prototype.$alert = function(message, title, options){
    // 这里写逻辑
}

$alert当中怎么将弹窗组件创建出来?

看一下脚手架的工程文件,main.js

import Vue from "vue"
import App from "./App.vue"

const vm = new Vue({
    render: (h) => h(App),
});

vm.$mount("#app")

这里的过程其实就是,

  • 创建Vue实例(new Vue)
  • 创建实例的时候,会调用render方法生成vNode(虚拟节点),其中的参数h函数 是一个用来创建 vNode 的辅助函数。能将引入的APP组件,变成vNode
  • 最后实例挂载($mount)到#app这个真实dom当中

其实$alert里面做的事情无非就是这样嘛,将我们的.vue组件,挂载到真实dom下

可以看到el的MessageBox 是挂在body下的

那么来实现一个自己的Modal

回到之前开头实现Modal,分别3个属性,2个自定义事件

image.png

内部方法构成:

image.png

前面提到了,只需要构造一个用于创建和挂载的函数,然后挂载到Vue.prototype即可全局调用

现在的目标就是构造这样一个函数

新建一个index.js,

 
import Vue form 'vue'
import Modal from "./Modal.vue"
export default function $modal (){
        const vm = new Vue({
            render:(h) => h(Modal)
        })
        // 创建游离节点
        const div = document.createElement('div')
        // 放到body上
        document.body.appendChild(div)
        // 将vm挂载到这个节点上
        vm.$mount(div)
}

打印一下这个vm

image.png

可以看到$el这一项是一个注释节点,因为我们设计的是v-if,此时没命中,因此会创建一个注释节点。

此时我们需要将showModal等参数传进去,该怎么办呢?

h函数就派上用场了,它的第2个参数可以传一些配置项(就是.vue里面的配置项)进去

h(Modal,{props:{showModal:true}})

 

这样子就有渲染Modal了,但这个h函数的第2个参数只能传入包含模板相关属性(例如 propsclassstyle 等),如果要传入方法的话,只能另寻他法了

image.png

救星:VueExtend

所幸Vue提供了Vue.extend

image.png

从官方文档可以看到,extend需要传入一个配置项,但我们Modal.vue组件已经写好了呀,总不能重新写一份到template,或者写一个render函数吧?

知道你很急,但你先别急,此时你就要知道.vue文件,被import引入之后是什么?

.vue组件究竟是啥???

import Modal from './Modal.vue' 之后, 打印一下Modal

image.png

这不就是一个对象,这熟悉的属性名,不就options配置项

回忆一下.vue当中,是怎么写代码的

image.png

同时vue的编译器帮我们把<template>标签里的内容编译成了render函数

改造

所以就可以利用vue.extend进行改造啦,extend当中的配置项会以优先级更高的形式混入

import Vue form 'vue'
import Modal from "./Modal.vue"
export default function $modal (){
    const ModalCtor = Vue.extend(Modal)

    const modalVM = new ModalCtor({
        propsData: {
            showModal: true,
            title: "JetTsang's Title",
            text:"这是text"
        },
        data() {
            return { }
        },
        mounted(){
            console.log('mounted了')
        },
        methods:{
            传入的方法(){
                console.log('Hello JetTsang')
            }
        }
    })
    const div = document.createElement('div')
    document.body.appendChild(div)
    modalVM.$mount(div)
}

打印一下这个modalVM,这就是1个vue组件了啊,可以通过写配置项来传入方法和属性了.

image.png

组件销毁和卸载

可以借助下面的流程

最后 $modal(message, title, options)的参数设计,相信难不倒各位

promise调用的实现

这里是有promise的调用形式啊

image.png

其实就是在index.js暴露的$modal函数当中返回一个promise嘛,我们直接用promise包装一下即可:

import Vue form 'vue'
import Modal from "./Modal.vue"
export default function $modal (){
    const ModalCtor = Vue.extend(Modal)
    // 返回1个promise实例
    return new Promise((resolve,reject)=>{
        const modalVM = new ModalCtor({
            methods:{
                // 确认
                _confirm(){
                    // 在这里调用
                    resolve()
                    console.log('Hello JetTsang')
                }
            }
        })
        const div = document.createElement('div')
        document.body.appendChild(div)
        modalVM.$mount(div)
    })
    
}

当然这里面方法也是多种多样,相信诸君一定比我想的好。

总结

这种函数式全局组件的封装,需要考虑将组件挂载和卸载的过程,比较考验对vue组件本质的理解

当然要想实现一个好用的函数式组件,还需要考虑单例、层级z-index,初始生成位置等等

 

  • 33
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值