我的编程空间,编程开发者的网络收藏夹
学习永远不晚

vue中this.$message的实现过程详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

vue中this.$message的实现过程详解

一、vue中为什么可以直接使用this.$message

1、Message在开发中的使用频率很高,也算是Element-UI组件库中比较简单的,对于感兴趣的朋友可以一起探讨一下Message组件的实现

2、组件的使用

this.$message('这是一条消息提示');
this.$message({ message: '恭喜你,这是一条成功消息', type: 'success' });

3、整体的执行过程

Vue项目中的使用如下:

// main.js

// 1.引入组件库
import ElementUI from 'element-ui';
// 2.使用组件库
Vue.use(ElementUI); 

Element-UI组件库中逻辑如下:

每次当Vue.use的时候,在Element—UI内部会触发Element-UIinstall方法,然后将组件注册为全局组件,将方法放到Vue.prototype上,本次只看Message部分即可

// 文件目录:node-modules/element-ui/class="lazy" data-src/index.js
// 1.引入Message对象
import Message from '../packages/message/index.js';

// 2. 定义 install函数,
const install = function(Vue, opts = {}) {
  // 将组件遍历注册为全局组件,例如Button组件
  components.forEach(component => {
    Vue.component(component.name, component);
  });
  // 将方法放到Vue原型上
  Vue.prototype.$message = Message;
};

经过上述两步的处理,我们可以直接在项目中通过this.$message进行组件的展示控制,接下来继续探索Element-UI内部如何处理的。

二、message组件的内部实现原理

1、设计思路

Message的调用方式都是通过this.$message进行调用,通过传递不同的options进行组件样式和内容的控制,展示的html是动态的插入到document中并在duration之后移除,组件的展示通过vue实例访问并控制。

组件的整体结构分为展示部分和控制部分

展示部分(main.vue):单独抽离出一个组件,将组件的展示逻辑和交互封装集中处理

控制部分(main.js):是承接vue实例和组件展示

2、展示部分,即main.vue

首先看一下删减版本之后展示部分的组件内容,代码删除了容错和边界值判断的代码,仅仅展示了基本功能。

<template>
  <transition name="el-message-fade" @after-leave="handleAfterLeave">
    <div
      class="el-message"
      :style="positionStyle"
      v-show="visible">
      <slot>
        <p>{{ message }}</p>
      </slot>
    </div>
  </transition>
</template>

<script type="text/javascript">
export default {
  data() {
    return {
      visible: false,
      message: '',
      duration: 3000,
      onClose: null,
      closed: false,
      verticalOffset: 20,
      timer: null
    };
  },

  computed: {
    positionStyle() { // 控制当前组件的显示位置
      return {
        'top': `${ this.verticalOffset }px`
      };
    }
  },

  watch: {
    // 监听closed的变化,设置为true时,将组件销毁
    closed(newVal) {
      if (newVal) {
        this.visible = false;
      }
    }
  },

  methods: {
    // transtion组件的钩子,触发after-leave时执行
    handleAfterLeave() {
      this.$destroy(true); // 销毁组件
      this.$el.parentNode.removeChild(this.$el); // 将组件的DOM移除
    },

    close() {
      this.closed = true; // 组件隐藏
      
      if (typeof this.onClose === 'function') {
        this.onClose(this);
      }
    },
    // 每次手动启动编译之后 设置其展示时间duration之后关闭
    startTimer() {
      if (this.duration > 0) {
        this.timer = setTimeout(() => {
          if (!this.closed) {
            this.close();
          }
        }, this.duration);
      }
    }
  },
  mounted() {
    this.startTimer();
  }
};
</script>

使用了Vue官方封装的transition组件,不仅提供了良好的过渡效果,还提供了合适的钩子便于开发者控制,组件中使用after-leave钩子,当组件销毁时进行组件的销毁和DOM的移除,visible用于控制组件的展示与销毁,计算属性positionStyle用于设置组件的展示位置,message为组件展示的内容数据,搞明白这些变量、计算属性和方法的作用即可。

script部分可参考注释进行理解,需要注意两个地方

(1)首先需要注意生命周期钩子mount时做的事情,为何如此做?因为不存在el选项,实例不会立即进入编译阶段,需要显示调用$mount 手动开启编译

(2)还需要注意的时close函数中做了两件事,设置closed的值触发对应的watch,关闭组件,若是存在onClose方法则调用,注意这个onClose函数的定义是在控制部分定义,稍后会说明

3、控制部分 至此已经清楚Vue中是通过this.$message触发组件的展示,而展示部分的组件内容也已完成,现在就需要通过控制部分将两者连接,达到期望的功能

Vue关联比较简单,仅仅是定义一个方法并将其导出即可

const Message = options => {
  // 逻辑编写....
}
export default Message;

这个时候通过this.$message即可调用,接下来便是将Message函数与组件关联,并控制展示部分

Message核心需要做那些事情

  • 编译组件,使用渲染并插入到body
  • 控制组件内的visible变量,触发组件的展示
  • 控制组件内的verticalOffset变量,决定组件展示时的位置

手动开启组件编译,获取其实例访问内部data和渲染到页面上

// 1. 使用基础 Vue 构造器,创建一个“子类”
let MessageConstructor = Vue.extend(Main);
// 2. 组件实例, 可以通过instance访问 visible和verticalOffset
instance = new MessageConstructor({
  data: options
});

整个Message方法其余部分就是在做容错和健壮处理,整体简洁版代码如下

let MessageConstructor = Vue.extend(Main);

let instance; // 当前组件
let instances = []; // 将所有的message组件收集,用于位置的判断和销毁等
let seed = 1; // 每个message实例都有一个唯一标识

const Message = options => {
  options = options || {
    message: 'content' + Date.now(),
    onClose(message){
      console.log('关闭时的回调函数, 参数为被关闭的 message 实例',message);
    }
  };

  if (typeof options === 'string') {
    options = {
      message: options
    };
  }

  // 关闭时的回调函数, 参数为被关闭的 message 实例
  let userOnClose = options.onClose;
  let id = 'message_' + seed++;
  
  // 增加 onClose 方法,组件销毁时,在组件内部调用
  options.onClose = function() { 
    Message.close(id, userOnClose);
  };

  // 组件实例,此时options与组件的data关联
  instance = new MessageConstructor({
    data: options
  });
  instance.id = id; // 设置ID
  
  instance.$mount(); // 因为不存在el选项,实例不会立即进入编译阶段,需要显示调用$mount 手动开启编译
  document.body.appendChild(instance.$el); // 将Message 组件插入到body中

  // 设置组件距离顶部的距离,每个message组件会有16px的间距
  let verticalOffset = options.offset || 20;
  instances.forEach(item => {
    verticalOffset += item.$el.offsetHeight + 16;
  });
  instance.verticalOffset = verticalOffset;

  instance.visible = true; // 控制展示
  instance.$el.style.zIndex = 99; // 控制层级
  instances.push(instance);
  return instance;
};

this.$message.error('')的实现

Message组件支持this.$message.error('错了哦,这是一条错误消息');调用使用,到目前为止还不支持,代码比较简单直接上代码

// 为每个 type 定义了各自的方法,如 Message.success(options),可以直接调用
['success', 'warning', 'info', 'error'].forEach(type => {
  Message[type] = options => {
    if (typeof options === 'string') {
      options = {
        message: options
      };
    }
    options.type = type;
    return Message(options);
  };
});

展示组件内部会调用this.onClose(this),组件内部设置this.visible=false关闭弹框,并且移除其对应的DOM结构,但是页面展示多个组件时需要修改其余组件的位置

onClose函数是在Message函数中定义

// 关闭时的回调函数, 参数为被关闭的 message 实例
let userOnClose = options.onClose;

// 增加 onClose 方法,组件销毁时,在组件内部调用
options.onClose = function() { 
  Message.close(id, userOnClose);
};

onClose函数最终调用的是Message上的静态方法close

函数Message.close内部主要做了几件事情

  • 在页面显示的组件数组中找到需要关闭的组件,将其移除
  • 重新计算剩余组件的位置

三、总结

至此基础版本的Message已经完成,组件的代码不到200行,通过源码的简单阅读和分析,知识点并不是很多,但是优秀组件封装的思路还是值得学习和借鉴

到此这篇关于vue中this.$message的实现过程详解的文章就介绍到这了,更多相关vue中this.$message实现内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

vue中this.$message的实现过程详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

vue中this.$message的实现过程详解

Message在开发中的使用频率很高,也算是Element-UI组件库中比较简单的,对于感兴趣的朋友可以一起探讨一下Message组件的实现,本文详细介绍了vue中this.$message的实现过程,感兴趣的同学可以参考一下
2023-05-18

Vue分页组件实现过程详解

Web应用程序中资源分页不仅对性能很有帮助,而且从用户体验的角度来说也是非常有用的。在这篇文章中,将了解如何使用Vue创建动态和可用的分页组件
2022-12-09

vue项目中的this.$get,this.$post等$的用法案例详解

vue.js的插件应该暴露一个install方法。这个方法的第一个参数是vue构造器,第二个参数是一个可选的选项对象,首页要安装axios,本文结合案例代码给大家详细讲解vue中的this.$get,this.$post等$的用法,一起学习下吧
2022-12-10

Java 中This用法的实例详解

Java 中This用法的实例详解用类名定义一个变量的时候,定义的只是一个引用,外面可以通过这个引用来访问这个类里面的属性和方法。 那们类里面是够也应该有一个引用来访问自己的属性和方法纳? 呵呵,Java提供了一个很好的东西,
2023-05-31

Vue中的过滤器(filter)详解

vuefilter过滤器处理数据的作用,使用位置:mustache插值和v-bind表达式,过滤器用于文本转换,复杂的数据处理则用computed,这篇文章主要介绍了Vue中的过滤器(filter),需要的朋友可以参考下
2022-11-13

SpringAOP的概念与实现过程详解

AOP为AspectOrientedProgramming的缩写,意为:面向切面编程,可通过运行期动态代理实现程序功能的统一维护的一种技术。AOP是Spring框架中的一个重要内容
2023-02-22

SpringBoot集成tomcat详解实现过程

采用springboot之后,一切变得如此简单,打包->java-jar->运维,只需要一个jar包便可以随意部署安装。这篇文章,将对springboot集成tomcat的源码进行分析,探索其内部的原理
2023-02-23

Aptos SDK交互实现过程详解

这篇文章主要为大家介绍了Aptos SDK交互实现过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-03-03

Vue项目中实现ElementUI按需引入过程解析

这篇文章主要介绍了Vue项目中实现ElementUI按需引入,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-05-19

Spring中的注解@Autowired实现过程

本篇内容介绍了“Spring中的注解@Autowired实现过程”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前言使用 Spring 开发时
2023-06-20

Vue编译优化实现流程详解

编译优化指的是编译器将模板编译为渲染函数的过程中,尽可能多的提取关键信息,并以此指导生成最优代码的过程,优化的方向主要是区分动态内容和静态内容,并针对不同的内容采用不同的优化策略
2023-01-28

编程热搜

目录