应用场景:
1.在刷微博的时候,滑到某个头像上,会出现一张usercard(用户名片), 微博列表区有这个usercard, 推荐列表也有这个usercard,评论区也有。
2.在网上购物时,购物车安静的停留在页面的角落里,不声不响。你在页面上买了零食买了书,购物车还是安静的呆着,猛然间点开一看,安静的购物车已经躺满了。
以上两种,在模块化满天飞的今天,当然不可能面向过程的一一开发,你不能在微博列表,微博推荐和评论中逐一把用户名片功能开发一遍。实际上,常见
的做法是将usercard作为一个组件,当然,comment也是一个组件。购物车也是一个组件。怎么可以做到鼠标放到评论和回复的用户头像上显示名片呢?这里就涉及到了组件之间互相通信的机制。
组件的通信方法有多种,API 观察者 都可以。最好的方案我认为是使用事件机制。
所有组件之间可以通过一个叫eventbus通用组件进行信息的交互。
1. 在usercard组件中,可以监听 eventbus 的一个 usercard:show 事件。
2. 在需要展示usercard的组件中,可以触发eventbus的这个事件,必要的话传入对应的参数。
其实之前的时候也经常接触这样的用法,这次从一个博客中看到,就有了自己动手写的想法,一写之下发现也很简单,不知道是不是还有很多自己目前没想到的,先记录下来。
先看下这个事件机制组件(AMD规范下的代码)
define(function (require) { var config = {}; // 用于事件的存储; config.eventList = {}; /* * 事件定义 * @param {string} 事件的名称; * @param {function} function */ config.on = function (name, func) { var me = this; if (!me.eventList[name]) { me.eventList[name] = func; } else { alert('这个方法名已经被用过了,请换一个名字'); } }; /* * 事件触发 *@param {string} 事件名称; *@param {obj} 事件中的参数 */ config.emit = function (name, data) { var me = this; if (me.eventList[name]) { me.eventList[name](data); } else { alert('没有找到对应的方法'); } }; return config; });
一个是定义,一个是触发。看起来很简单的样子。现在写两个组件来试一下吧
第一个组件,usercard,需要在这里定义 usercard:show事件。
define(function (require) { var eventBus = require('eventBus'); var config = {}; config.add = function () { var obj = { name: 'usercard', type: 'mouseover' }; // 这里定义eventbus的事件 eventBus.on('usercard:show', function (data) { obj = $.extend(obj, data); data.node.title = data.sid; data.node.style.backgroundColor = 'red'; }); }; return config; })
再写一个组件 comment 用于触发eventbus的
define(function (require) { var eventBut = require('eventBut'); var config = {}; var DomEvent = { }; function domEvents() { $("#commentList").delegate('dt', 'click', function (e) { var target = e.target; var sid = target.getAttribute('sid'); // 触发事件 eventBut.emit('usercard:show',{ sid: sid, node: target }); }); } config.init = function () { domEvents(); } return config; });
写一个页面 来加载
<script> require(['comment', 'userCard'], function (comment, usercard) { usercard.add(); comment.init(); }) </script>
测试了一下 是可以的~~