最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • TS类与接口 之 结合看wangEditor大佬架构学习

    正文概述 掘金(梅利奥猪猪)   2021-02-02   878

    废话不多说,先看架构图

    TS类与接口 之 结合看wangEditor大佬架构学习

    还是来点废话吗(各位看官求不要打我,先别关,还是有点干货的)

    大家好,这里是梅利奥猪猪,经过这几天的学习产出,功夫不负有心人,总算通过了开源团队老大的考核(大家有兴趣也可以来加入哈,直接官方文档里加群,老大会对你考核的),有机会成为开源团队wangEditor的成员,有了变强的途径,哈哈所以和大家来分享我的喜悦。但是加入团队前,很多知识我都不熟悉,比如ts(实际工作中都没有用,都是自己平时XJB搞着玩),自动化测试(jest等,也都是自己XJB搞着玩),团队的文档很严谨很详细,老大要我加入前先要熟悉各种规范(包括源码结构,开发规范,测试规范等),所以对于源码结构这块,我看了会menu相关的代码(架构如开头的图这样),所以这篇文章出生了

    Menu架构分析

    分析前先要了解我们产品的Menu

    先看文档总没错的,来张文档的截图

    TS类与接口 之 结合看wangEditor大佬架构学习

    Button是什么,DropList什么鬼,Panel嗯??

    来来来听我娓娓道来,你们立马就懂,分别举几个例子

    • 加粗功能 - 是不是点下按钮,就直接触发效果了,选中的字蹭的一下就加粗了(这里就不展示图片了毕竟点一下就触发功能了) - BtnMenu

    • 标题功能 - 鼠标移上去出现了下拉菜单,有h1~h6,鼠标移开后菜单消失 - DropListMenu

    TS类与接口 之 结合看wangEditor大佬架构学习

    • 插入图片 - 点击后弹出了个框,然后用户就可以傻瓜式操作啦 - PanelMenu

    TS类与接口 之 结合看wangEditor大佬架构学习

    到这里,我们就知道了wangEditor产品,菜单目前一共就3种类型,简单易懂~

    先简单说说类的继承吧

    通过架构图,我们可以清楚的看到,所有的菜单类,都会继承这3种父类型的菜单,简单的说就是

    • 加粗菜单 - 继承BtnMenu
    • 标题菜单 - 继承DropListMenu
    • 插入图片菜单 - 继承PanelMenu

    然后这3类菜单又会继承最大的父类Menu

    再简单说说接口吧

    接口就是一种规范,我们发现架构图里有这么几个接口

    • MenuActive - implements后必须要实现方法tryChangeActive
      • 这个方法其实就是激活菜单的,比如你富文本中有加粗的字体和没有加粗的字体,当你点击光标在没加粗的字体的时候,加粗的菜单不会高亮,但你点到加粗的字体的时候,菜单就要高亮,所以对于每个菜单来说都必须implements MenuActive, 且tryChangeActive方法名见名知意,大佬架构牛逼!
    • DropList - implements后必须要实现方法showhide
      • 下拉菜单的展示和隐藏很好理解,所以DropListMenu会去实现DropList接口,大佬架构牛逼!
    • Pannel - implements后必须要实现createremove
      • 创建pannel和移除pannel简单易懂,所以PanelMenu会去实现Panel接口,大佬架构牛逼!

    还有很多细节没说,先来随便贴一个源码给大家一起看看,分析源码啦

    先来看看最大父类,源码如下

    /**
     * @description Menu class 父类
     * @author wangfupeng
     */
    
    import { DomElement } from '../../utils/dom-core'
    import Editor from '../../editor/index'
    import Panel from './Panel'
    
    export interface MenuActive {
        /**
         * 修改菜单激活状态,菜单是否高亮
         */
        tryChangeActive(): void
    }
    
    class Menu {
        public key: string | undefined
        public $elem: DomElement
        public editor: Editor
        private _active: boolean // 菜单是否处于激活状态,如选中一段加粗文字时,bold 菜单要被激活(即高亮显示)
    
        constructor($elem: DomElement, editor: Editor) {
            this.$elem = $elem
            this.editor = editor
            this._active = false
    
            // 绑定菜单点击事件
            $elem.on('click', (e: Event) => {
                Panel.hideCurAllPanels() // 隐藏当前的所有 Panel
    
                // 触发菜单点击的钩子
                editor.txt.eventHooks.menuClickEvents.forEach(fn => fn())
    
                e.stopPropagation()
                if (editor.selection.getRange() == null) {
                    return
                }
                this.clickHandler(e)
            })
        }
    
        /**
         * 菜单点击事件,子类可重写
         * @param e event
         */
        protected clickHandler(e: Event): void {}
    
        /**
         * 激活菜单,高亮显示
         */
        protected active(): void {
            this._active = true
            this.$elem.addClass('w-e-active')
        }
    
        /**
         * 取消激活,不再高亮显示
         */
        protected unActive(): void {
            this._active = false
            this.$elem.removeClass('w-e-active')
        }
    
        /**
         * 是否处于激活状态
         */
        public get isActive() {
            return this._active
        }
    }
    
    export default Menu
    

    注释详细到,我感觉都不用我讲解了, 具体解释放到孙子类加粗菜单

    加粗菜单的源码如下

    /**
     * @description 加粗
     * @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-menu" data->
                    <i class="w-e-icon-bold"></i>
                </div>`
            )
            super($elem, editor)
        }
    
        /**
         * 点击事件
         */
        public clickHandler(): void {
            const editor = this.editor
            const isSelectEmpty = editor.selection.isSelectionEmpty()
    
            if (isSelectEmpty) {
                // 选区范围是空的,插入并选中一个“空白”
                editor.selection.createEmptyRange()
            }
    
            // 执行 bold 命令
            editor.cmd.do('bold')
    
            if (isSelectEmpty) {
                // 需要将选区范围折叠起来
                editor.selection.collapseRange()
                editor.selection.restoreSelection()
            }
        }
    
        /**
         * 尝试修改菜单激活状态
         */
        public tryChangeActive(): void {
            const editor = this.editor
            if (editor.cmd.queryCommandState('bold')) {
                this.active()
            } else {
                this.unActive()
            }
        }
    }
    
    export default Bold
    

    吐槽: 曾几何时,觉得加入开源团队,帮忙写写注释也是贡献,然后老大说的正式军果然厉害,注释这么详细完美,都不给机会。哈哈,看来要做更有价值的贡献者,废话不多说,分析源码啦

    • 导入import相关,不解释了,不清楚的小伙伴打屁屁
    • 来看源码这行class Bold extends BtnMenu implements MenuActive,继承BtnMenu,实现MenuActive
    • 构造函数的代码,不就定义的加粗的dom元素,因为继承了BtnMenu,需要调用super
    constructor(editor: Editor) {
        const $elem = $(
            `<div class="w-e-menu" data->
                <i class="w-e-icon-bold"></i>
            </div>`
        )
        super($elem, editor)
    }
    
    • 点击事件源码注释太详细了,就是点击后要做的事,子类重写父类的方法clickHandler
    /**
     * 点击事件
     */
    public clickHandler(): void {
        const editor = this.editor
        const isSelectEmpty = editor.selection.isSelectionEmpty()
    
        if (isSelectEmpty) {
            // 选区范围是空的,插入并选中一个“空白”
            editor.selection.createEmptyRange()
        }
    
        // 执行 bold 命令
        editor.cmd.do('bold')
    
        if (isSelectEmpty) {
            // 需要将选区范围折叠起来
            editor.selection.collapseRange()
            editor.selection.restoreSelection()
        }
    }
    
    • 实现tryChangeActive,queryCommandState看状态,有这个状态激活没这个状态不激活,可能有小伙伴会问,active和unActive怎么来的,来来来,你们去看下Menu最大的父类做了什么
    /**
     * 激活菜单,高亮显示
     */
    protected active(): void {
        this._active = true
        this.$elem.addClass('w-e-active')
    }
    
    /**
     * 取消激活,不再高亮显示
     */
    protected unActive(): void {
        this._active = false
        this.$elem.removeClass('w-e-active')
    }
    

    总结

    就是先看架构图,在多想想,在多看看源码,本次文章只分析了个宏观的,细节的也没多说,最多讲了个加粗菜单的实现,剩下的源码大家有兴趣自己去看哦~ 继续贴大佬的架构图,方便大家多看多想

    TS类与接口 之 结合看wangEditor大佬架构学习

    今天的水文章就到这,之后有源码上的分析有空会持续产出,包括之后开发规范,测试规范相关~谢谢大家支持


    起源地下载网 » TS类与接口 之 结合看wangEditor大佬架构学习

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元