如何实现一个经过js调用使用的消息提示组件(Vue)

在项目开发过程当中可能咱们习惯了使用各类现成的UI库,它能够帮助咱们快速的完成项目开发,例如咱们在项目中常常使用到的Toast、Message提示组件,咱们一般只须要经过js来调用就可使用了,和咱们日常使用组件的方式(import导入、components注册)并不同,那接下来咱们就本身来实现一个经过js方法来使用的组件。咱们最后要实现的组件就是element-UI的Message消息提示vue

1、准备工做

咱们首先在项目中新建一个文件夹来存放这个组件,我建在了/src/components/Message/,很显然Message就是我放提示组建的目录。api

接着咱们在Message下再建一个index.vueindex.js的文件,js是咱们组件的入出口也是用来导出方法被调用的主体。bash

2、编写组件模板

咱们先写一个基础的样式,而后经过js调用渲染出来,以后咱们在对组件进行细节优化app

  • index.vue内容
<template>
  <div class="message">
    <p>这是一条消息提示</p>
  </div>
</template>

<script>
export default {
  name: 'Message'
}
</script>

<style scoped lang="stylus">
.message
  position fixed
  top 3vh
  left 50vw
  transform translateX(-50%)
  border 1px solid #EBEEF5
  background-color #edf2fc
  min-width 340px
  min-height 50px
  display flex
  align-items center
  box-sizing border-box
  padding 0 15px
  border-radius 5px
</style>
复制代码
  • index.js内容
import Vue from 'vue';
import Message from './index.vue';

const MessageConstructor = Vue.extend(Message);

export const $message = () => {
  const instance = new MessageConstructor().$mount();
  document.body.appendChild(instance.$el);
}
复制代码
  • 在页面中引入$message方法使用
<script>
import { $message } from '@/components/Message/index';
export default {
  name: 'home',
  mounted() {
    // 正常应该在点击按钮或者某些操做执行后调用,我这里为了直观显示就在生命周期内调用了
    $message();
  }
}
</script>
复制代码
  • 效果

  • 详解

index.vue中是咱们编写组件的代码,和咱们正常编写Vue组件使一毛同样的。咱们之因此能够经过调用js方法来使用组件,最关键的代码是在index.js中。函数

index.js中只有7行代码,看一眼,很容易猜到最核心的确定就是extend$mountappendChild三个api,那咱们就看下这三个API到底作了什么flex

  1. extend是Vue的一个全局api,它接收一个包含组件选项的对象,例如这个样子(官方示例)
Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
  }
})
复制代码

而后extend会建立一个Vue‘子类’(猜想就是一个没有被实例化的Vue组件)优化

  1. $mount:若是咱们对extend建立的子类进行实例化的时候没有传入 el 选项,那此时这个组件就处于未挂载的状态,咱们就须要调用$mount方法,手动将其挂载,$mount方法若是没有传入参数,那么它挂载后会自动关联此组件的顶层元素,若是传入参数(能够接收元素、元素选择器)则关联传入的元素。基于此其实咱们也能够不调用$mount方法,在实例化的时候传入el选项;
import Vue from 'vue';
import Message from './index.vue';

const MessageConstructor = Vue.extend(Message);

export const $message = () => {
  const instance = new MessageConstructor({
    el: document.createElement('div'),
  });
  document.body.appendChild(instance.$el);
}
复制代码
  1. appendChild: 至此就很容易理解了,最后将组件加入到body主体中渲染出来
  2. 最后使用的时候调用$message方法,没什么说的。

很关键的内容都在这里。那么接下来咱们就再实现个东西,Element-UI的这个组件是能够传入自定义消息内容的,也能够传入不一样的type来显示成功或警告样式的消息,更进一步,好比咱们须要在消息关闭的时候来作别的操做,又要如何处理呢?ui

3、组件完善

1. 自定义组件内容

  • 修改index.js代码
import Vue from 'vue';
import Message from './index.vue';

const MessageConstructor = Vue.extend(Message);

// 方法接收个options参数,options必须是object类型
export const $message = (options) => {
  const instance = new MessageConstructor({
    el: document.createElement('div'),
    // 组件实例生成的时候在给组件动态传入data
    data: options
  });
  document.body.appendChild(instance.$el);
}
复制代码
  • 修改index.vue代码
<template>
  <div class="message">
    // 内容改成可变的
    <p>{{message}}</p>
  </div>
</template>

<script>
export default {
  name: 'Message',
  // data是新增的
  data() {
    return {
      message: '',
    }
  }
}
</script>

<style scoped lang="stylus">
.message
  position fixed
  top 3vh
  left 50vw
  transform translateX(-50%)
  border 1px solid #EBEEF5
  background-color #edf2fc
  min-width 340px
  min-height 50px
  display flex
  align-items center
  box-sizing border-box
  padding 0 15px
  border-radius 5px
</style>
复制代码
  • 调用时传入内容
$message({message: '对不起,注册失败'});
复制代码

2. 增长提示关闭按钮,提示被关闭后调用者能够感知

  • 修改index.vue代码
<template>
  <div class="message">
    <p>{{message}}</p>
    <i class="close" @click="handleClose">&times;</i>
  </div>
</template>

<script>
export default {
  name: 'Message',
  data() {
    return {
      message: '',
    }
  },
  methods: {
    emitClose() {},
    handleClose() {
      this.$el.parentNode.removeChild(this.$el);
      this.emitClose();
    }
  }
}
</script>

<style scoped lang="stylus">
.message
  position fixed
  top 3vh
  left 50vw
  transform translateX(-50%)
  border 1px solid #EBEEF5
  background-color #edf2fc
  min-width 340px
  max-width 500px
  min-height 50px
  display flex
  align-items center
  justify-content space-between
  box-sizing border-box
  padding 0 15px
  border-radius 5px
  .close
    font-size 25px
    align-self flex-start
    margin-top -5px
    margin-right -9px
    cursor pointer
</style>
复制代码
  • 修改index.js代码
import Vue from 'vue';
import Message from './index.vue';

const MessageConstructor = Vue.extend(Message);

export const $message = (options,methods = {}) => {
  const instance = new MessageConstructor({
    el: document.createElement('div'),
    data: options,
    methods
  });
  document.body.appendChild(instance.$el);
}
复制代码
  • 调用
$message({message: '对不起,注册失败对不起'}, {
  emitClose() {
    console.log('组件被关闭了');
  },
});
复制代码

TIP: 若是关闭的时候但愿被调用者能够被感知,除了传methods,其实也能够直接传入data,不过传入的就是一个函数,相似于this

$message({
    message: '对不起,注册失败对不起',
    onClose() {
        console.log('组件被关闭了');
    },
});
复制代码

4、补充

至此其实咱们讲这个组件的目的已经完成了,就是告诉你如何经过js来使用”消息提示“这类的组件,其他的成功失败警告定时关闭等功能,就不一一实现了,时间空闲的各位能够自行实现一下。spa

若是这篇文章对你有做用还望不吝点个赞,若是有其余疑问或内容有误能够在评论留言指正啊。拜拜!

相关文章
相关标签/搜索