Without further ado, let’s look at the architecture
Still come some nonsense (everybody see officer beg don’t hit me, don’t close first, still a little dry goods)
Hello, this is merry the pig, after these days of learning outcomes, everything comes to him who waits, team boss finally passed the open examination (we are interested in can also join ha, directly add group of official documentation, old convention examination to you), members of the team have a chance to become open source wangEditor, have stronger way, Haha so share my joy with you. But before to join the team, a lot of knowledge I don’t know, such as ts (are useless, in the actual work are oneself peacetime XJB make a play), test automation (jest, etc., are also oneself XJB make a play), the team’s document very serious very detailed, eldest brother want to be familiar with all kinds of specification before I joined (including source structure, development and specification, test specification, etc.), So for the source code structure, I looked at the menu-related code (architecture as shown above), so this article was born
Menu architecture Analysis
Before analysis, we should first understand the Menu of our products
It’s never a bad idea to look at the document first. Take a screenshot of the document
What’s a Button, a DropList, a Panel?
Listen to me. You’ll get it right away. Give me a couple of examples
-
Bold function – click the button, directly trigger the effect, the selected word rub on the bold (here will not show the picture after all, click on the trigger function) – BtnMenu
-
Title function – drop down menu appears when mouse moves up, there are H1 ~ H6, the menu disappears after mouse moves away – DropListMenu
- Insert picture – click and a box pops up, and then the user can operate foolishly – PanelMenu
So far, we know the wangEditor product. There are three types of menus, which are easy to understand
Let’s talk briefly about class inheritance
From the diagram, we can clearly see that all menu classes inherit menus of the three parent types, simply speaking
- Bold menu – inherit BtnMenu
- Title Menu – Inherit DropListMenu
- Insert picture menu – Inherit PanelMenu
These three menus then inherit the largest parent, Menu
A few words about interfaces
Interfaces are a specification, and we found several of them in the architecture diagram
- Methods must be implemented after menuactive-implementstryChangeActive
- For example, if you have rich text with bold font and no bold font, when you click the cursor on the bold font, the bold menu will not be highlighted, but when you click on the bold font, the menu will be highlighted, so it must be for every menu
implements MenuActive
And,tryChangeActive
Method name see name know meaning, big guy structure cow force!
- For example, if you have rich text with bold font and no bold font, when you click the cursor on the bold font, the bold menu will not be highlighted, but when you click on the bold font, the menu will be highlighted, so it must be for every menu
There are a lot of details did not say, first to casually post a source code for everyone to see, analyze the source code
First take a look at the largest parent class, the source code is as follows
/ * * *@description Menu class parent *@author wangfupeng* /
import { DomElement } from '.. /.. /utils/dom-core'
import Editor from '.. /.. /editor/index'
import Panel from './Panel'
export interface MenuActive {
/** * Change the menu activation status, whether the menu is highlighted */
tryChangeActive(): void
}
class Menu {
public key: string | undefined
public $elem: DomElement
public editor: Editor
private _active: boolean // Whether the menu is active. For example, when a bold text is selected, the bold menu is active (that is, highlighted).
constructor($elem: DomElement, editor: Editor) {
this.$elem = $elem
this.editor = editor
this._active = false
// Bind menu click events
$elem.on('click'.(e: Event) = > {
Panel.hideCurAllPanels() // Hide all current panels
// Trigger the menu click hook
editor.txt.eventHooks.menuClickEvents.forEach(fn= > fn())
e.stopPropagation()
if (editor.selection.getRange() == null) {
return
}
this.clickHandler(e)
})
}
/** * menu click event, subclass can be overridden *@param e event
*/
protected clickHandler(e: Event): void {}
/** * Activate menu, highlight */
protected active(): void {
this._active = true
this.$elem.addClass('w-e-active')}/** * Deactivates, no longer highlights */
protected unActive(): void {
this._active = false
this.$elem.removeClass('w-e-active')}/** * Whether to activate */
public get isActive() {
return this._active
}
}
export default Menu
Copy the code
The notes are so detailed that I feel I don’t even need to explain them. The specific explanation is put in the bold menu of the sun Tzu class
The source code for the bold menu is as follows
/ * * *@description Bold *@author wangfupeng* /
import BtnMenu from '.. /menu-constructors/BtnMenu'
import $ from '.. /.. /utils/dom-core'
import Editor from '.. /.. /editor/index'
import { MenuActive } from '.. /menu-constructors/Menu'
class Bold extends BtnMenu implements MenuActive {
constructor(editor: Editor) {
const $elem = $(
` < div class = "w - e - the menu data -" title = "bold" > < I class = "w - e - icon - bold" > < / I > < / div > `
)
super($elem, editor)
}
/** * click event */
public clickHandler(): void {
const editor = this.editor
const isSelectEmpty = editor.selection.isSelectionEmpty()
if (isSelectEmpty) {
// The selection range is empty, insert and select a "blank"
editor.selection.createEmptyRange()
}
// Run bold
editor.cmd.do('bold')
if (isSelectEmpty) {
// Need to fold the selection range
editor.selection.collapseRange()
editor.selection.restoreSelection()
}
}
/** * Try to change menu activation status */
public tryChangeActive(): void {
const editor = this.editor
if (editor.cmd.queryCommandState('bold')) {
this.active()
} else {
this.unActive()
}
}
}
export default Bold
Copy the code
Ridicule: once upon a time, I felt that joining the open source team and helping to write notes is also a contribution, and then the boss said that the official army was really fierce, notes so detailed and perfect, do not give the opportunity. Ha ha, it seems to be more valuable to be a contributor, without further ado, analysis of source code
- Import import related, do not explain, do not know the small partner spank
- Look at the source line
class Bold extends BtnMenu implements MenuActive
, inherit BtnMenu, MenuActive - Constructor code, not on the definition of the bold DOM element, because of the inheritance of BtnMenu, need to call super
constructor(editor: Editor) {
const $elem = $(
` < div class = "w - e - the menu data -" title = "bold" > < I class = "w - e - icon - bold" > < / I > < / div > `
)
super($elem, editor)
}
Copy the code
- Click on the event source code comment is too detailed, that’s what you do after you click, subclass overrides the parent class method
clickHandler
/** * click event */
public clickHandler(): void {
const editor = this.editor
const isSelectEmpty = editor.selection.isSelectionEmpty()
if (isSelectEmpty) {
// The selection range is empty, insert and select a "blank"
editor.selection.createEmptyRange()
}
// Run bold
editor.cmd.do('bold')
if (isSelectEmpty) {
// Need to fold the selection range
editor.selection.collapseRange()
editor.selection.restoreSelection()
}
}
Copy the code
- Implement tryChangeActive,
queryCommandState
Look at the states, if this state is active or not, if this state is not active, some of you might ask, “Where do active and unActive come from?”, “Here, here, here, here, here, here, here, here, here, here, here, here, here, here, here, here, what does the largest parent of Menu do?
/** * Activate menu, highlight */
protected active(): void {
this._active = true
this.$elem.addClass('w-e-active')}/** * Deactivates, no longer highlights */
protected unActive(): void {
this._active = false
this.$elem.removeClass('w-e-active')}Copy the code
conclusion
Is the first look at the architecture diagram, in the more think, in the more look at the source code, this article only analyzed a macro, details did not say more, at most about the implementation of a bold menu, the rest of the source code we are interested in their own to see oh ~ continue to stick big guy’s architecture diagram, convenient for everyone to see more
Today’s water article to this, after the source code analysis will continue to produce, including the development of specifications, test specifications ~ thank you for your support