feat: add event bus

pr675
Hufe921 3 years ago
parent 2d16866892
commit 0bacc113cd

@ -11,7 +11,9 @@
"deletable",
"dppx",
"esbenp",
"eventbus",
"inputarea",
"keyof",
"linebreak",
"noopener",
"Parens",

@ -39,7 +39,8 @@ export default defineConfig({
{
text: '监听',
items: [
{ text: '事件监听', link: '/guide/listener' }
{ text: '事件监听(listener)', link: '/guide/listener' },
{ text: '事件监听(eventBus)', link: '/guide/eventbus' }
]
},
{

@ -0,0 +1,101 @@
# 事件监听(eventBus)
## 使用方式
```javascript
import Editor from "@hufe921/canvas-editor"
const instance = new Editor(container, <IElement[]>data, options)
// 注册
instance.eventBus.on<K keyof EventMap>(
eventName: K,
callback: EventMap[K]
)
// 移除
instance.eventBus.off<K keyof EventMap>(
eventName: K,
callback: EventMap[K]
)
```
## rangeStyleChange
功能:选区样式发生改变
用法:
```javascript
instance.eventBus.on('rangeStyleChange', (payload: IRangeStyle) => void)
```
## visiblePageNoListChange
功能:可见页发生改变
用法:
```javascript
instance.eventBus.on('visiblePageNoListChange', (payload: number[]) => void)
```
## intersectionPageNoChange
功能:当前页发生改变
用法:
```javascript
instance.eventBus.on('intersectionPageNoChange', (payload: number) => void)
```
## pageSizeChange
功能:当前页数发生改变
用法:
```javascript
instance.eventBus.on('pageSizeChange', (payload: number) => void)
```
## pageScaleChange
功能:当前页面缩放比例发生改变
用法:
```javascript
instance.eventBus.on('pageScaleChange', (payload: number) => void)
```
## contentChange
功能:当前内容发生改变
用法:
```javascript
instance.eventBus.on('contentChange', () => void)
```
## controlChange
功能:当前光标所在控件发生改变
用法:
```javascript
instance.eventBus.on('controlChange', (payload: IControl | null) => void)
```
## pageModeChange
功能:页面模式发生改变
用法:
```javascript
instance.eventBus.on('pageModeChange', (payload: PageMode) => void)
```
## saved
功能:文档执行保存
用法:
```javascript
instance.eventBus.on('saved', (payload: IEditorResult) => void)
```
## zoneChange
功能:区域发生改变
用法:
```javascript
instance.eventBus.on('zoneChange', (payload: EditorZone) => void)
```

@ -1,4 +1,6 @@
# 事件监听
# 事件监听(listener)
> listener只能响应一个方法推荐使用eventBus进行事件监听
## 使用方式

@ -79,6 +79,8 @@ import { INLINE_ELEMENT_TYPE } from '../../dataset/constant/Element'
import { ListParticle } from './particle/ListParticle'
import { Placeholder } from './frame/Placeholder'
import { WORD_LIKE_REG } from '../../dataset/constant/Regular'
import { EventBus } from '../event/eventbus/EventBus'
import { EventBusMap } from '../../interface/EventBus'
export class Draw {
private container: HTMLDivElement
@ -95,6 +97,7 @@ export class Draw {
private elementList: IElement[]
private footerElementList: IElement[]
private listener: Listener
private eventBus: EventBus<EventBusMap>
private i18n: I18n
private canvasEvent: CanvasEvent
@ -146,7 +149,8 @@ export class Draw {
rootContainer: HTMLElement,
options: DeepRequired<IEditorOption>,
data: IEditorData,
listener: Listener
listener: Listener,
eventBus: EventBus<EventBusMap>
) {
this.container = this._wrapContainer(rootContainer)
this.pageList = []
@ -159,6 +163,7 @@ export class Draw {
this.elementList = data.main
this.footerElementList = data.footer || []
this.listener = listener
this.eventBus = eventBus
this._formatContainer()
this.pageContainer = this._createPageContainer()
@ -336,6 +341,9 @@ export class Draw {
if (this.listener.visiblePageNoListChange) {
this.listener.visiblePageNoListChange(this.visiblePageNoList)
}
if (this.eventBus.isSubscribe('visiblePageNoListChange')) {
this.eventBus.emit('visiblePageNoListChange', this.visiblePageNoList)
}
}
public getIntersectionPageNo(): number {
@ -347,6 +355,9 @@ export class Draw {
if (this.listener.intersectionPageNoChange) {
this.listener.intersectionPageNoChange(this.intersectionPageNo)
}
if (this.eventBus.isSubscribe('intersectionPageNoChange')) {
this.eventBus.emit('intersectionPageNoChange', this.intersectionPageNo)
}
}
public getPageNo(): number {
@ -569,6 +580,10 @@ export class Draw {
return this.listener
}
public getEventBus(): EventBus<EventBusMap> {
return this.eventBus
}
public getCursor(): Cursor {
return this.cursor
}
@ -709,6 +724,9 @@ export class Draw {
if (this.listener.pageModeChange) {
this.listener.pageModeChange(payload)
}
if (this.eventBus.isSubscribe('pageModeChange')) {
this.eventBus.emit('pageModeChange', payload)
}
})
}
@ -1801,9 +1819,17 @@ export class Draw {
if (this.listener.pageSizeChange) {
this.listener.pageSizeChange(this.pageRowList.length)
}
if (this.eventBus.isSubscribe('pageSizeChange')) {
this.eventBus.emit('pageSizeChange', this.pageRowList.length)
}
// 文档内容改变
if (this.listener.contentChange && isSubmitHistory) {
this.listener.contentChange()
if (isSubmitHistory) {
if (this.listener.contentChange) {
this.listener.contentChange()
}
if (this.eventBus.isSubscribe('contentChange')) {
this.eventBus.emit('contentChange')
}
}
})
}

@ -7,13 +7,15 @@ import {
IControlOption
} from '../../../interface/Control'
import { IElement, IElementPosition } from '../../../interface/Element'
import { EventBusMap } from '../../../interface/EventBus'
import { IRange } from '../../../interface/Range'
import { deepClone, splitText } from '../../../utils'
import { deepClone, nextTick, splitText } from '../../../utils'
import {
formatElementContext,
pickElementAttr,
zipElementList
} from '../../../utils/element'
import { EventBus } from '../../event/eventbus/EventBus'
import { Listener } from '../../listener/Listener'
import { RangeManager } from '../../range/RangeManager'
import { Draw } from '../Draw'
@ -29,6 +31,7 @@ export class Control {
private draw: Draw
private range: RangeManager
private listener: Listener
private eventBus: EventBus<EventBusMap>
private options: IControlOption
private activeControl: IControlInstance | null
@ -36,6 +39,8 @@ export class Control {
this.draw = draw
this.range = draw.getRange()
this.listener = draw.getListener()
this.eventBus = draw.getEventBus()
this.options = draw.getOptions().control
this.activeControl = null
}
@ -132,16 +137,23 @@ export class Control {
this.activeControl = new CheckboxControl(element, this)
}
// 激活控件回调
setTimeout(() => {
if (this.listener.controlChange) {
let payload: IControl
const value = this.activeControl?.getValue()
if (value && value.length) {
payload = zipElementList(value)[0].control!
} else {
payload = pickElementAttr(deepClone(element)).control!
}
this.listener.controlChange(payload)
nextTick(() => {
const controlChangeListener = this.listener.controlChange
const isSubscribeControlChange =
this.eventBus.isSubscribe('controlChange')
if (!controlChangeListener && !isSubscribeControlChange) return
let payload: IControl
const value = this.activeControl?.getValue()
if (value && value.length) {
payload = zipElementList(value)[0].control!
} else {
payload = pickElementAttr(deepClone(element)).control!
}
if (controlChangeListener) {
controlChangeListener(payload)
}
if (isSubscribeControlChange) {
this.eventBus.emit('controlChange', payload)
}
})
}
@ -153,9 +165,16 @@ export class Control {
}
this.activeControl = null
// 销毁控件回调
setTimeout(() => {
if (this.listener.controlChange) {
this.listener.controlChange(null)
nextTick(() => {
const controlChangeListener = this.listener.controlChange
const isSubscribeControlChange =
this.eventBus.isSubscribe('controlChange')
if (!controlChangeListener && !isSubscribeControlChange) return
if (controlChangeListener) {
controlChangeListener(null)
}
if (isSubscribeControlChange) {
this.eventBus.emit('controlChange', null)
}
})
}

@ -0,0 +1,46 @@
export class EventBus<EventMap> {
private eventHub: Map<string, Set<Function>>
constructor() {
this.eventHub = new Map()
}
public on<K extends string & keyof EventMap>(
eventName: K,
callback: EventMap[K]
) {
if (!eventName || typeof callback !== 'function') return
const eventSet = this.eventHub.get(eventName) || new Set()
eventSet.add(callback)
this.eventHub.set(eventName, eventSet)
}
public emit<K extends string & keyof EventMap>(
eventName: K,
payload?: EventMap[K] extends (payload: infer P) => void ? P : never
) {
if (!eventName) return
const callBackSet = this.eventHub.get(eventName)
if (!callBackSet) return
if (callBackSet.size === 1) {
const callBack = [...callBackSet]
return callBack[0](payload)
}
callBackSet.forEach(callBack => callBack(payload))
}
public off<K extends string & keyof EventMap>(
eventName: K,
callback: EventMap[K]
) {
if (!eventName || typeof callback !== 'function') return
const callBackSet = this.eventHub.get(eventName)
if (!callBackSet) return
callBackSet.delete(callback)
}
public isSubscribe<K extends string & keyof EventMap>(eventName: K): boolean {
const eventSet = this.eventHub.get(eventName)
return !!eventSet && eventSet.size > 0
}
}

@ -308,6 +308,10 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
if (listener.saved) {
listener.saved(draw.getValue())
}
const eventBus = draw.getEventBus()
if (eventBus.isSubscribe('saved')) {
eventBus.emit('saved', draw.getValue())
}
evt.preventDefault()
} else if (evt.key === KeyMap.ESC) {
// 退出格式刷

@ -4,9 +4,12 @@ import { TEXTLIKE_ELEMENT_TYPE } from '../../dataset/constant/Element'
import { ControlComponent } from '../../dataset/enum/Control'
import { IEditorOption } from '../../interface/Editor'
import { IElement } from '../../interface/Element'
import { EventBusMap } from '../../interface/EventBus'
import { IRangeStyle } from '../../interface/Listener'
import { IRange, RangeRowArray, RangeRowMap } from '../../interface/Range'
import { getAnchorElement } from '../../utils/element'
import { Draw } from '../draw/Draw'
import { EventBus } from '../event/eventbus/EventBus'
import { HistoryManager } from '../history/HistoryManager'
import { Listener } from '../listener/Listener'
import { Position } from '../position/Position'
@ -16,6 +19,7 @@ export class RangeManager {
private options: Required<IEditorOption>
private range: IRange
private listener: Listener
private eventBus: EventBus<EventBusMap>
private position: Position
private historyManager: HistoryManager
@ -23,6 +27,7 @@ export class RangeManager {
this.draw = draw
this.options = draw.getOptions()
this.listener = draw.getListener()
this.eventBus = draw.getEventBus()
this.position = draw.getPosition()
this.historyManager = draw.getHistoryManager()
this.range = {
@ -241,7 +246,10 @@ export class RangeManager {
}
public setRangeStyle() {
if (!this.listener.rangeStyleChange) return
const rangeStyleChangeListener = this.listener.rangeStyleChange
const isSubscribeRangeStyleChange =
this.eventBus.isSubscribe('rangeStyleChange')
if (!rangeStyleChangeListener && !isSubscribeRangeStyleChange) return
// 结束光标位置
const { startIndex, endIndex, isCrossRowCol } = this.range
if (!~startIndex && !~endIndex) return
@ -281,7 +289,7 @@ export class RangeManager {
const painter = !!this.draw.getPainterStyle()
const undo = this.historyManager.isCanUndo()
const redo = this.historyManager.isCanRedo()
this.listener.rangeStyleChange({
const rangeStyle: IRangeStyle = {
type,
undo,
redo,
@ -300,18 +308,27 @@ export class RangeManager {
level,
listType,
listStyle
})
}
if (rangeStyleChangeListener) {
rangeStyleChangeListener(rangeStyle)
}
if (isSubscribeRangeStyleChange) {
this.eventBus.emit('rangeStyleChange', rangeStyle)
}
}
public recoveryRangeStyle() {
if (!this.listener.rangeStyleChange) return
const rangeStyleChangeListener = this.listener.rangeStyleChange
const isSubscribeRangeStyleChange =
this.eventBus.isSubscribe('rangeStyleChange')
if (!rangeStyleChangeListener && !isSubscribeRangeStyleChange) return
const font = this.options.defaultFont
const size = this.options.defaultSize
const rowMargin = this.options.defaultRowMargin
const painter = !!this.draw.getPainterStyle()
const undo = this.historyManager.isCanUndo()
const redo = this.historyManager.isCanRedo()
this.listener.rangeStyleChange({
const rangeStyle: IRangeStyle = {
type: null,
undo,
redo,
@ -330,7 +347,13 @@ export class RangeManager {
level: null,
listType: null,
listStyle: null
})
}
if (rangeStyleChangeListener) {
rangeStyleChangeListener(rangeStyle)
}
if (isSubscribeRangeStyleChange) {
this.eventBus.emit('rangeStyleChange', rangeStyle)
}
}
public shrinkBoundary() {

@ -59,6 +59,10 @@ export class Zone {
if (listener.zoneChange) {
listener.zoneChange(payload)
}
const eventBus = this.draw.getEventBus()
if (eventBus.isSubscribe('zoneChange')) {
eventBus.emit('zoneChange', payload)
}
})
}

@ -57,10 +57,13 @@ import { IPlaceholder } from './interface/Placeholder'
import { defaultPlaceholderOption } from './dataset/constant/Placeholder'
import { Plugin } from './core/plugin/Plugin'
import { UsePlugin } from './interface/Plugin'
import { EventBus } from './core/event/eventbus/EventBus'
import { EventBusMap } from './interface/EventBus'
export default class Editor {
public command: Command
public listener: Listener
public eventBus: EventBus<EventBusMap>
public register: Register
public destroy: () => void
public use: UsePlugin
@ -179,6 +182,8 @@ export default class Editor {
})
// 监听
this.listener = new Listener()
// 事件
this.eventBus = new EventBus<EventBusMap>()
// 启动
const draw = new Draw(
container,
@ -188,7 +193,8 @@ export default class Editor {
main: mainElementList,
footer: footerElementList
},
this.listener
this.listener,
this.eventBus
)
// 命令
this.command = new Command(new CommandAdapt(draw))

@ -0,0 +1,25 @@
import {
IContentChange,
IControlChange,
IIntersectionPageNoChange,
IPageModeChange,
IPageScaleChange,
IPageSizeChange,
IRangeStyleChange,
ISaved,
IVisiblePageNoListChange,
IZoneChange
} from './Listener'
export interface EventBusMap {
rangeStyleChange: IRangeStyleChange
visiblePageNoListChange: IVisiblePageNoListChange
intersectionPageNoChange: IIntersectionPageNoChange
pageSizeChange: IPageSizeChange
pageScaleChange: IPageScaleChange
saved: ISaved
contentChange: IContentChange
controlChange: IControlChange
pageModeChange: IPageModeChange
zoneChange: IZoneChange
}
Loading…
Cancel
Save