本系列教程是教你们如何根据开源js绘图库,打造一个属于本身的在线绘图软件。固然,也能够看着是这个绘图库的开发教程。若是你以为好,欢迎点个赞,让咱们更有动力去作好!html
本系列教程重点介绍如何开发本身的绘图软件,所以,react基础和框架不在此介绍。能够推荐react官网学习,或《React全家桶免费视频》。node
本系列教程源码地址:Githubreact
前面教程一,搭建了一个基础框架,如今咱们来实现顶部导航菜单栏功能。git
1、react组件间通讯 - 菜单事件
这里,咱们经过redux方式来实现组件间消息通讯。UmiJS作了一点封装,使用更简单。github
1. 新建store - model
咱们在src/models文件夹下新建event.ts文件,专门用于消息事件的store处理。 主要包含:redux
- namespace - 命名空间
- state - 数据
- reducers - 数据搬运工
给没有接触过redux的同窗简单介绍下,会的请自动跳过: models是数据存储的地方。用namespace来进行模块划分或避免命名冲突;state:相似于react的state,专门用于存放数据;reducers:接收更新命令,根据命令参数(state :原数据;action:新行为参数数据),而后加上本身的业务逻辑,去实现如何更新数据。好比下面,只是简单的赋值,没有额外的业务逻辑。 注意,有个硬性规定就是,reducers要返回一个新数据副本,而不是直接修改models里面的state。所以,这里return下面的第一行(...state)就是先拷贝原始state全部属性,而后第2、三行,赋值新数据。canvas
reducers: { emit(state, action) { return { ...state, event: action.payload.event, data: action.payload.data, }; }, },
2. 在onMenuClick里,用dispatch发送修改数据命令
UmiJs + DvaJS已经自动封装dispatch到react的props里了,咱们直接拿来使用。 目前为止,咱们的菜单事件很简单,没有额外数据,咱们就直接dispatch发生菜单命令(key值)就好。 其中,type表示在store的全部reducers(不单单是上面的model,还包含其余全部model)中查找用哪一个函数处理数据,格式:命名空间(event)/reducers函数(emit)。payload,更新数据用的参数。服务器
this.props.dispatch({ type: 'event/emit', payload: { event: key } });
3. 在须要接收菜单消息的page页面,connect链接绑定数据
- 导入链接函数:import { connect } from 'dva';
- 绑定connect:在pages/index.tsx底部添加:
export default connect((state: any) => ({ event: state.event }))(Index);
上面,state:any是指整个store,咱们这里暂时只用到event,故只返回event加入到pages/index的props。框架
4. 在page页面componentDidUpdate,接收消息
componentDidUpdate() { if (this.props.event !== this.state.event) { this.setState({ event: this.props.event }); if (this['handle_' + this.props.event.event]) { this['handle_' + this.props.event.event](this.props.event.data); } } }
咱们先判断消息是否已经处理过,避免无限循环。而后交给具体函数处理。ide
5. 最后,画布接口参考开发文档
https://www.yuque.com/alsmile/topology/canvas
2、react组件间通讯 - 右上角状态栏
1. 新建store - model
仍是先新建一个store用于通讯,src/models/canvas.data.ts。这个model用于全局canvas的数据保存。
2. 监听画布canvas消息,dispatch最新状态
在src/pages/index.ts里,前面已经设置监听了canvas的消息onMessage函数。 如今咱们添加‘resize’,‘scale’,‘locked’等事件的处理:
case 'resize': case 'scale': case 'locked': if (this.canvas) { this.props.dispatch({ type: 'canvas/update', payload: { data: this.canvas.data } }); } break;
3. 在layouts/headers.tsx页面,connect链接绑定数据
import { connect } from 'dva'; export default connect((state: any) => ({ canvasData: state.canvas }))(Headers);
4. render函数显示便可
render(): React.ReactNode { const { data } = this.props.canvasData; const scale = Math.floor(data.scale); ...... }
这里,咱们没有特别业务处理,直接格式化显示便可。
3、本篇最后
顶部菜单导航栏基础功能完成。仍是欢迎你们补充并提交GitHub的pr: 0. 阅读开发文档,了解相关属性。
- fork仓库到本身名下
- 本地修改并提交到本身的git仓库
- 在本身的fork仓库找到 “Pull request” 按钮,提交
其余
顶部工具栏和右键菜单功能待续。
开源项目不易,欢迎你们一块儿参与,或资助服务器: