徒手写 JS ,你还会吗?JS + jQuery 自定义类卡点汇总

发布于:2024-04-29 ⋅ 阅读:(32) ⋅ 点赞:(0)

背景

有了 React、Vue 等前端开发框架后,开发人员只用关注数据、而不用考虑 DOM 操作问题,前端开发相对容易多了。自从用了前端框架后,我已经六年没用过原生 JS 写过前端了。

最近维护一个老项目,纯 html 页面、数据控制全靠 jQuery 手堆。其中,有一个规则配置选项,十几个编辑页面都引用了它。旧的实现方式是拷贝,每个页面都拷贝了这段配置的代码,大约 500 行。真佩服当时的开发者,宁愿拷贝10次,也不抽取一个工具类。

上周要对这个功能调整,配置方式从前端分页变成后端分页。改十几个引用的地方,逐个拷贝确实挺费手的。心一横,重构一下吧。

卡住的几个点:

  1. 自定义 JS 类时,方法中如何访问类的变量?必须通过 this.变量名称访问。
  2. 类的方法中通过 JQuery 绑定事件/各种回调函数中,想要访问这个类的属性,怎么办法?通过外层先定义一个 this 的拷贝对象,copyThis = this,引用该副本,或者事件回调用 () => {} 表达式。
  3. 拼接的 html 中的事件方法是当前类的方法时,应该怎么访问?用引用该类的变量的方法调用。
  4. 弹框页面想要访问这个工具的方法,可以通过 parent.commonConfigUtil 访问。

公共代码抽取

重构思路,以 JS 类的思维,定义一个类,每个页面只需要创建这个类的对象,然后直接调用这个类的公共方法就可以,主要包含三类方法:

  1. 页面初始化时的按钮绑定事件
  2. 动态拼接数据到页面的配置显示区域
  3. 页面初始化时查询当前绑定的配置并回显
  4. 删除某配置

定义一个公共 js 文件,命名为 configUtil.js ,抽取的类定义如下:

var CommonConfigUtil = function (config) {
    this.config = config;
    this.att1 = 1;
    this.att2 = 20;
    this.pageData = 20;
    this.baseUrl = config.baseUrl;
    
    // 页面初始化绑定按钮事件
    this.bindEvent = function bindEvent() {
        $('#btn1').bind('click',  event => {
            const attr1 = this.attr1;
            // TODO 使用外层类的属性完成按钮的绑定事件
        });

        $('#btn2').bind('click',  event => {
            const aa1 = this.attr2;
			 // TODO 使用外层类的属性完成按钮的绑定事件
        });
    };

   // 动态拼接数据到页面,且绑定一个删除事件
   this.addData = function addData(arr, now, count) {
        let tr = '';
   		this.pageData.forEach(item => {
            tr += '<div id="' + item.id + '">' +
                '<div style="text-align: left;word-break:break-all">' +
                '<h2 class="bkm" id="dd">' + item.name + '</h2><div style="float: right;"></div>' +
                '<a href="javascript: void(0);" οnclick="(event.stopPropagation()||(event.cancelBubble = true))&& commonConfigUtil.deleleData(\'' + item.id + '\')" style="float: right;"><i class="layui-icon">&#xe640;</i></a>' +
                '</div>' +
                '</div>';
        });
        $('#configList').append(tr);
  });
  
  // 页面初始化 ajax 回显数据
  this.initConfig = function queryConfigById(id) {
        const copyThis = this;
        $.ajax({
            type: 'GET',
            url: this.baseUrl + "/xx.action",
            data: {
                "id": id
            },
            success: function (pageData) {
                // TODO 数据使用,赋给外部类的属性
                copyThis.pageData = pageData;
            }
        });
    }     

  // 删除
  this.deleteConfig = function deleteConfig(configId) {
  });  
}

公共引用

需要用的地方

<script src="${baseUrl}/xx/configUtil.js"></script>
<script>
     var baseUrl = '${baseUrl}';
     // TODO 从路径参数获取 ID
	 var id = '';	
     // 全局公告配置 变量
     var commonConfigUtil = new CommonConfigUtil({
         baseUrl: baseUrl,
     });
    
    //初始化页面
    $(document).ready(function(){
        commonConfigUtil.bindEvent();
        // 编辑回显
        if (id != '') {
            commonConfigUtil.initConfig(id);
        } 
    });
    ……
</script>

这样就能将 500 行的公告代码转换为十几行的工具类调用了。

启示录

这个抽取过程还是比较容易的,有几个卡壳的点,总结如下:

  1. 自定义 JS. 类的注意事项:方法中不能直接访问类的变量,必须通过 this.变量名称访问。
  2. 类的方法中通过 JQuery 绑定事件、各种回调函数中,想要访问这个类的属性,可以通过 copyThis = this,引用该副本,或者事件回调用 () => {} 表达式,后者有一个问题,它会改变 jQuery 的 $ 操作的 this 信息。所以最简单的还是先定义副本对象,后面需要用类信息时都通过该副本对象。
  3. 拼接的 html 中的事件方法必须时当前页面定义的,如果是引用的某个类的,可以通过该类的变量来访问类对应的方法。拼接的元素commonConfigUtil.deleleData() 这里真正触发时,会调用当前页面的全局变量 commonConfigUtil 对象来访问删除方法。
  4. 页面可以直接访问 commonConfigUtil 的各属性,没有权限问题,这点跟 Java 的类的属性的访问方式不同。
  5. 弹框页面想要访问这个工具的方法,可以通过 parent.commonConfigUtil 访问。

虽然代码拷贝很容易,但是大量重复拷贝,也很费劲呐,把所有的重复代码都删掉、换成这是十几行引用,搞了两天,手点鼠标都快断了。编码工作,懒是偷不了的:大脑想偷懒,徒手拷贝复制也挺受累。不是心累,就是手累!