最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue3封装出让后来者难以理解的组件,让不是大佬的你变得不再随时可替代

    正文概述 掘金(wy白菜)   2021-05-22   454

    vue3封装出让后来者难以理解的组件,让不是大佬的你变得不再随时可替代

    前言

    害,最近两个月忙于工作和生活(明明就是给自己偷懒找借口),太久太久没更新文章了,正好趁着今天加班(摸鱼)来写一写最近在项目中封装的自以为很装的组件。在ui疯狂出图的前提条件下,我发现了很多轻提示和弹框dialog高度相似又要支持自定义,便开始了封装之路。

    好孩子要学会先借鉴别人的作业

    我在封装的第一版轻提示中,还是用的老传统props去接收一个visiable控制提示的显示和隐藏,归根结底还是不让组件一上来就挂载在dom节点上。组件写完了自然要使用不是吗,便高高兴兴的提交了代码。我自己在使用的过程中就感觉到很麻烦了,因为还要先引入组件,再定义一个visiable,再在template上写上一个<Toast :xxx="xxx" xxxxxxx/>,再一个页面上如果出现多次调用的话,要么你就多写几个toast(不会吧,不会吧,应该没人会选择这么做吧),要么就疯狂的改变data中定义的数据。虽然自己已经发现了这个弊端,但是不偷懒的程序员不是一个好的程序员,还是选择忽视了这个问题,害,躲的了初一躲不了十五,第二天旁边的仙女同事(她自认为的嘻嘻嘻)就在不经意间吐槽了使用起来过于复杂,完全没有element的好用。内心os:我要是能写的和element差不多就不坐在这了。当然,有其他人也提出了和我相同的问题,那自然要去解决不是吗。

    熟练的打开element ui翻到MessageBox组件哪里(此时的我还没意识到自己的项目是vue3环境),发现他们的调用方法也太简单了吧:

    
    <template>
    
    <el-button type="text" @click="open">点击打开 Message Box</el-button>
    
    </template>
    
    <script>
    export default {
      methods: {
        open() {
          this.$alert('这是一段内容', '标题名称', {
            confirmButtonText: '确定',
            callback: action => {
              this.$message({
                type: 'info',
                message: `action: ${ action }`
              });
            }
          });
        }
      }
    }
    </script>
    
    <style>
    
    </style>
    
    

    再看看自己的代码,简直不能看哈哈哈。古人云:师夷长技以制夷。打开自己开的vue2项目,打开庞大的node_modules包,找到对应的代码开始借鉴。

    第一步,先写好要展示的页面。

    工欲善其事,必先利其器。我们要想组件能使用,自然少不了我们的页面,我们写个demo演示一下:

    <template>
      <div>测试{{booo}}</div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          visiable: false
        };
      }
    };
    </script>
    
    <style></style>
    
    

    可能有小伙伴会问我写的visiable是干啥的,前面不是才说这个东西会抛弃掉吗?嘿嘿嘿,这里写只是单纯的为了后面测试用的,没有实际作用哈。

    第二步,使用vue构造器创造“子类”

    在翻阅官方文档过程中,我们可以得知vue.extend(options)中的options必须是一个组件,也就是我们前面写的demo,有一点必须要知道的是data必须是一个函数,不过,我相信小伙伴们肯定一直写的都是函数。又因为我们extend创建的不是平常我们写的组件实例,所以不能使用new Vue({ components: test }),这里官方为我们提供了挂在到节点的方法$mount。千说万说不如直接上代码靠谱。

    import Vue from "vue";
    import Main from "./main.vue";
    const MessageConstructor = Vue.extend(Main);
    let instance;
    const Message = function(options) {
      if (Vue.prototype.$isServer) {
        return;
      }
      console.log(Vue.prototype.$isServer);
      options = options || {};
      instance = new MessageConstructor({
        data: options
      });
      instance.$mount();
      document.body.appendChild(instance.$el);
      console.log(instance.visiable);
      console.log(instance.booo);
      return instance;
    };
    export default Message;
    

    在看完代码中,可能会有部分小伙伴会问Vue.prototype.$isServer是什么,说实话,在没看文档前我也不会哈哈哈。

    vue3封装出让后来者难以理解的组件,让不是大佬的你变得不再随时可替代

    通过文档中可以知道这是判断是否运行在服务器上,我们在服务器上又没有界面自然不需要了。当我们调用方法的时候可以将参数正常传递进来就需要在new构造器的时候接受参数,然后再挂载在$mount上,最后插入到我们的body上.

    第三步,收获成果调用方法

    我们前面的准备工作都做完之后先别着急,怎么会这么容易就让我们可以使用了呢。我们还需要在最外面的main.js导入我们写好的文件

    import Vue from "vue";
    import ElementUI from "element-ui";
    import Message from "@/components/test/main";
    import "element-ui/lib/theme-chalk/index.css";
    import App from "./App.vue";
    
    Vue.config.productionTip = false;
    Vue.use(ElementUI);
    // Vue.use(Message);
    Vue.prototype.$Message = Message;
    new Vue({
      render: h => h(App)
    }).$mount("#app");
    

    这样我们就可以正常使用啦。

     mounted() {
        setTimeout(() => {
          this.$Message({
            booo: true
          });
        }, 3000);
      },
    

    vue3封装出让后来者难以理解的组件,让不是大佬的你变得不再随时可替代

    看到这里有人会问这个booo哪里来的,为什么在组件中没有props去接收参数也可以显示,这个就是构造器特殊的地方哈。

    开始在正式项目中使用

    有了前面的铺垫,我自然兴致冲冲的把自己的思路在项目中实践,突然想到自己之前挖的坑项目使用的是vue3,不确定之前写的还可不可以,先放上去试试。果然不出意外的报错了。翻看vue3文档,因为现在不能直接import Vue from "vue";了,所以对应的vue.extend()也没有了。虽然官方删除了extend但是也提供了新的createApp给我们使用。

    vue3封装出让后来者难以理解的组件,让不是大佬的你变得不再随时可替代

    最后改造完的代码如下:

    import { createApp } from "vue";
    import ToastMessage from "./index.vue";
    
    const createMount = options => {
      const mountNode = document.createElement("div");
      document.body.appendChild(mountNode);
    
      const app = createApp(ToastMessage, {
        ...options,
        remove() {
          app.unmount(mountNode);
          document.body.removeChild(mountNode);
        }
      });
      return app.mount(mountNode);
    };
    
    const toast = options => {
      return createMount(options);
    };
    
    toast.install = app => {
      app.component("Toast", ToastMessage);
      app.config.globalProperties.$toast = toast;
    };
    
    export default toast;
    

    这里小伙伴们要注意了,在vue2中我们可以不用props接受数据也可以显示出来,但是vue3不行了哦。

    后记

    希望这篇文章能对大家有所帮助,如果有写的不对的地方也希望指点一二。

                                                                --wy白菜
    

    起源地下载网 » vue3封装出让后来者难以理解的组件,让不是大佬的你变得不再随时可替代

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元