写了一个基于svg的涂鸦组件,在说项目之前附上几张效果图:项目。关注组件之间的通信。一、项目描述本项目是一个基于webpack@3.x.x构建,使用ES6开发,以组件形式组织代码的多页面应用。gitclone项目后(文末附上项目的github仓库地址),npmi安装相关依赖,npmrundev运行项目。默认会打开应用的首页,也就是上面效果预览对应的界面。开发过程中会针对一些功能单独编写一些测试代码,所以项目提供了不同功能对应的不同页面,如:colorpicker组件测试页面:组件消息通信框架测试页面:svg底层绘图api测试页面:二1.组件间通信1、为了实现最大程度的封装和解耦,组件之间不直接通信,而是通过“消息订阅/发布管理中心”(以下简称“消息中心”)间接通信。组件通过声明自己为不同的角色而具有相应的通信能力:组件被声明为订阅者(Subscriber),以@Topics注解的形式从“消息中心”订阅自己感兴趣的主题消息,相应的消息会通过通知接口通知组件;组件声明为发布者(Publisher),可以通过Publisher角色注入的publish方法发布主题消息;该组件被声明为发布/订阅者(SubScatterer),并具有订阅者和发布者的通信能力。这里我们以项目中间区域的画板组件为例,因为画板组件只接收Toolbar组件发送的切换绘图能力,清除绘图内容并设置Settings组件发送的绘图参数信息,所以这个组件只是一个消息订阅者角色,编码设计如下:首先导入对应的角色类:importSubscriberfrom'../../supports/pubsub/base/subscriber';从“../../supports/pubsub/base/topics”导入主题;编写相应的组件://以@Topics的形式订阅感兴趣的消息类型@Topics(['function','resident_function','set_preference'])exportdefaultclassSketchpadextendsSubscriber{//Constructorconstructor(sketchpad){super();this.sketchpad=画板;//...}/***该接口由【发布订阅消息管理中心】调用。画板组件在该接口处理接收到的消息类型*1.处理Toolbar组件“切换画板绘图状态”对应的消息类型为:“函数”*2.Toolbar发送的“清除绘图内容”组件被处理,对应的消息类型为:"resident_function"*3、Settings组件发送的"resident_function"被处理。设置画板绘图参数”,对应的消息类型为:”set_preference”*@param{String}topicmessage主题标识*@param{Object}entitymessage实体对象*/notify(topic,entity){//这里处理接收Receivedmessage}}注意:@Topics是静态的,如果有些topic需要在运行时进行订阅,也可以调用Subscriber角色提供的subscribe方法动态订阅消息。2、由于PubSub(消息订阅/发布管理中心)的实现是底层通用能力,所以必须在没有具体业务的情况下实现。必须保证它在命名约定和编码实现方面是通用模块PubSub的实现。:/***主题订阅发布中心*/exportdefaultclassPubSub{//缓存主题和主题订阅者列表statictopics={};/***发布主题消息*@param{String}topictopic*@param{*}entity消息正文*/staticpublish(topic,entity){if(!PubSub.topics[topic])return;//获取该主题的订阅者列表constsubscribers=PubSub.topics[topic];//向该主题的所有订阅者发送主题消息for(letsubscriberofsubscribers){subscriber.notify&&subscriber.notify(topic,entity);}}/***一次注册一个主题*@param{String}topic*/staticregisterTopic(topic){consttopics=PubSub['topics'];!topics[主题]&&(主题[主题]=[]);}/***同时注册多个主题*@param{Array}主题*/staticregisterTopics(topics=[]){topics.forEach(topic=>{this.registerTopic(topic);});}/***添加主题订阅者*@param{String}topictopic*@param{Object}订阅者实现通知接口订阅者*/staticaddSubscriber(topic,subscriber){consttopics=PubSub['topics'];!topics[主题]&&(主题[主题]=[]);//将本主题的订阅者注册到对应的主题topics[topic].push(subscriber);}/***删除对应的订阅者*@paramsubscriber*/staticremoveSubscriber(subscriber){constsubs=[];//遍历所有主题下的订阅者列表,删除对应的订阅者consttopics=PubSub.topics;Object.keys(topics).forEach(topicName=>{consttopic=topics[topicName];for(leti=0;i
