本系列教程是教你們如何根據開源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」 按鈕,提交
其餘
頂部工具欄和右鍵菜單功能待續。
開源項目不易,歡迎你們一塊兒參與,或資助服務器: