vue3中用全局服务的形式调用一个组件

在vue项目中,通常使用一个组件需要在template中以标准的标签形式来显示的使用,但是很多时候,我不希望写模板语法,而是希望通过纯js函数调用的形式来调用组件,那么又应该如何做呢?今天就参考element-plus来编写一个message组件,主要是记录一下这个过程。

使用过element ui 的人都知道它提供了很多全局方法来调用组件,比如一个提示组件message,其主要有两种用法:

  • 全局注册了组件后,在组件内部全局属性直接使用
// main.js

import message from './message.js'

app.use(message)



// 组件内部
this.$message.success('xxxx')
this.$message({
    type:'success',
    message:'成功2'
})
  • 通过导入服务的形式调用 ,可以用于选项式或者setup中通用
import message from './message.js'
message({
    type:'success',
    message:'成功'
})
message.success('成功')
message.success('失败')
  • 好废话不多说,我们先得有这么一个sfc组件,基本代码如下:
    message.vue
<template>
  <div class="message" :class="type ? 'message-' + type : ''">
    <span>{{ message }}</span>
    <span class="close" @click="close">x</span>
  </div>
</template>


<script setup>
import { defineProps, defineOptions, useAttrs } from "vue";
defineOptions({
  inheritAttrs: false,
});
const attrs = useAttrs();

const props = defineProps({
  message: {
    type: String,
  },
  type: {
    type: String,
  },
  duration: {
    type: Number,
    default: 3000,
  },
});
function close() {
  if(props.duration){
    attrs.close && attrs.close();
  }

}
</script>

<style scoped>
.message {
  padding: 8px 16px;
  border-radius: 4px;
  background-color: #ddd;
  display: flex;
  justify-content: space-between;
  color: #fff;
}

.close {
  cursor: pointer;
}

.message-success {
  background-color: #67c23a;
}
.message-error {
  background-color: #f56c6c;
}
</style>

要想通过app的use方法并且注册组组件,首先需要暴露一个函数,或者一个提供了install方法的对象,如下:
message.js

import { createVNode, render } from "vue";
import Message from "./message.vue";

function getInstance(config) {
  const div = document.createElement("div");
  const conf = Object.assign({}, config);
  if (conf.duration === undefined) {
    conf.duration = 3000;
  }

  const close = () => {
    try {
      document.body.removeChild(div);
    } catch (error) {}
  };
  conf.close = close;

  const vnode = createVNode(Message, conf);
  render(vnode, div);
  document.body.appendChild(div);

  if (conf.duration) {
    setTimeout(() => {
      try {
        document.body.removeChild(div);
      } catch (error) {
        
      }
    }, conf.duration);
  }


  return {
    close,
  };
}
const message = (opts) => {
  return getInstance(opts);
};

message.install = (app) => {
  // 这样就可以值选项式api中通过this.$message的形式调用了 返回一个包含close的对象,可以手动关闭,也支持自动关闭
  app.config.globalProperties.$message = message;
};

export default message;

为了丰富常用功能,需要给message提供两个快捷方法:

message.success = (msg) => {
  let conf = {
    type: "success",
    message: msg,
  };
  return getInstance(conf);
};
message.error = (msg) => {
  let conf = {
    type: "success",
    message: msg,
  };
  return getInstance(conf);
};

至此第一种方式通过this调用可以了,聪明的你也一定发现,其实可以不用全局注册,然后组合式api中直接导入message,然后就可以服务的形式来调用了。

最后,看了vue3的实现方式,是不是非常简单呢?你学废了吗?当然请想一下如果vue2又该如何实现呢? 欢迎点赞收藏吐槽指点。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYwmojdw' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片