Code前端首页关于Code前端联系我们

Vue3封装了后来者难以理解的组件,所以不是大佬的你随时都无法被取代

terry 2年前 (2023-09-08) 阅读数 155 #Vue

image.pngimage.png

image.pngimage.png

前言

惨了,这两个月工作生活都忙了(当然是给懒找借口了),好久没更新文章了,今天只是用加班(钓鱼)来写一下项目中最近的一个包,我认为这是一个非常繁忙的组件。在疯狂UI绘制的前提下,我发现很多灯光提示和弹出对话框都非常相似,需要支持定制,于是我就走上了打包路线。

好孩子首先要学会学习别人的作业

在第一个版本的灯光提示包中,我仍然使用老旧的传统道具来接收可见控制提示的显示和隐藏。归根结底,我还是不允许组件一出现就挂载到dom节点上。一旦编写了组件,使用它就很自然了,所以我很乐意发布代码。我自己在使用的过程中感觉很有问题,因为我要先实现组件,然后定义可见,然后在模板上再在页面上写,如果如果有多个调用,你要么写多个toast(不,不,那是没人会选择的),要么你疯狂地改变data中定义的数据。即使我发现了这个缺陷,一个不懒惰的程序员也不是一个好的程序员,仍然选择忽略这个问题。我也是这么想的呵呵)我无意中抱怨它用起来太复杂,不像element那么简单。 Inner 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>

 

有的朋友可能会问我为什么是可见的。我刚才不是说这东西要报废了吗?呵呵,写这篇纯粹是为了以后测试,没有实际作用。

第二步,使用vue构造函数创建“子类”

在翻阅官方文档的过程中,我们可以了解到vue.extend(options)中的选项一定是我们之前写的demo的一部分。我们需要知道的一件事是,数据必须是函数,但我相信朋友们必须编写函数。而且由于我们创建的并不是我们平时编写的组件的实例,所以我们不能使用 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是什么。说实话,在看纪录片之前我并不知道,哈哈哈。

image.pngimage.png

从文档中我们可以知道,这是判断是否在服务器上运行的,我们不需要它,因为我们在服务器上没有接口。当我们调用方法的时候,就可以正常传递参数了。我们需要在新的构造函数中接受参数,然后将它们附加到 $mount 上,最后将它们放入我们的主体中。

第三步调用结果收获方法

别着急,等我们把前面的准备都做完了,哪有那么容易。我们还需要导入我们在最外层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);
  },
 

image.pngimage.png

看到这里,有人会问boo是从哪里来的,为什么组件中不用props接收参数就可以显示出来,那就是构造函数的特殊地方。

开始在官方项目中使用

有了前面的铺垫,我自然很乐意将我的项目想法付诸实践。我突然想到之前挖的坑项目是用的vue3。不确定前面的写法是否可以,所以我先尝试一下。 。当然,没想到就报错了。查看vue3文档,因为现在不能直接从“vue”导入Vue,所以对应的vue.extend()就没有了。尽管该扩展已被正式删除,但我们还有一个新的 createApp 可用。

image.pngimage.png

最终修改后的代码如下:

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白菜
 

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门