写一个方便维护的 jquery 代码

前言

最近碰到这样一个项目,业务逻辑全部都搬到前端,后端只提供API。
但是是在已有的项目上面做这样做,也就是在已有的项目上添加模块,这个模块采用前后端分工的方式来做。
因为各种原因,所以只有 jquery 可以用一下,万恶的ie。

jquery代码示例

先上代码,如果要运行,需要额外导入mock.js。
js

$(function() {
    var list = {
        init: function() {
            // 初始化
            this.$list = $("#list");
            this.render();
        },
        render: function() {
            // 渲染
            this.getData();
            this.bind();
        },
        renderData: function(data) {
            // 渲染数据
            var temp = {
                listTemp: ''
            }
            $.each(data, function(i, iObj) {
                temp.listTemp += 
                    '<tr data-id="' + iObj.id + '">'+
                        '<td>' + iObj.name + '</td>'+
                        '<td>' + iObj.price + '</td>'+
                        '<td>' + 
                            '<span class="color-simple" style="background-color:' + iObj.color + '"></span>'+
                            '<span>' + iObj.color + '</span>'+
                        '</td>'+
                        '<td>' + iObj.name + '</td>'+
                    '</tr>';
            });
            
            this.$list.html(temp.listTemp);
        },
        bind: function() {
            // 绑定事件
            var self = $(this);
            this.$list.on("click", "tr", function() {
                alert($(this).data("id"));
            });
        },
        getData: function() {
            // 获取数据
            var self = this;
            Mock.mock('http://data.cn', {
                'list|1-20': [
                    {
                    'id|+1': 1,
                    'name': '@name',
                    'price|1-1000': 1000,
                    'color': '@color',
                    'remark': '@remark'
                    }
                ]
            });
            $.ajax({
                type: "get",
                url: "http://data.cn",
                success: function(data) {
                    self.renderData($.parseJSON(data).list);
                }
            });
        }
    }
    list.init();
});

html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <link rel="stylesheet" type="text/css" href="css/page.css"/>
    </head>
    <body>
        <div>
            <table class="table" border="1" cellpadding="0">
                <thead>
                    <tr>
                        <th>名称</th>
                        <th>价格</th>
                        <th>颜色</th>
                        <th>备注</th>
                    </tr>
                </thead>
                <tbody id="list">
                    
                </tbody>
            </table>
            <script src="js/jquery.js" type="text/javascript" charset="utf-8"></script>
            <script src="js/mock-min.js" type="text/javascript" charset="utf-8"></script>
            <script src="js/list.js" type="text/javascript" charset="utf-8"></script>
        </div>
    </body>
</html>

css

body {
  margin: 0;
  font-family: "微软雅黑";
}
.table {
  width: 80%;
  margin: 20px auto;
  border-collapse: collapse;
  border-spacing: 0;
}
.table td,
.table th {
  text-indent: 2%;
  text-align: left;
}
.table thead tr {
  height: 40px;
}
.table .body {
  height: 400px;
  overflow: auto;
  display: block;
}
.table tbody tr {
  height: 40px;
  cursor: pointer;
}
.table tbody tr:nth-child(2n + 1) {
  background-color: #eafff4;
}
.table tbody tr:nth-child(2n) {
  background-color: #fff;
}
.table tbody tr:hover {
  background-color: #b0e5ff;
}
.table tbody tr span {
  vertical-align: middle;
}
.table tbody tr .color-simple {
  width: 20px;
  height: 20px;
  margin-right: 10px;
  border-radius: 2px;
  display: inline-block;
}

解析

这是一个简单的例子,首先 js 内部执行顺序是这样的:

  1. init(初始化)

  2. render(渲染页面)

  3. bind(绑定事件)getData(加载数据)

  4. renderData(渲染数据)

init

  • 初始化,加载一个模块的开始。

  • 主要用来缓存一些成员变量,如果是 jquery对象的 话就在之前加个 “$”,这样做是为了跟普通元素区别开来。

render

  • 渲染页面,顾名思义,就是渲染页面的函数。

  • 在这个函数内部调用了 getData() 和 bind() 两个方法,getData()是为了去取数据,但为什么要在这里调用 bind() 方法呢,难道不应该在渲染完数据之后再绑定事件呢,说到 bind() 的时候再说为什么。

  • 如果有另外的子模块需要渲染的话,也可以放在这里加载。 (比如在 list 模块下面有个 editPrice子模块,是一个单独的模块,就可以并列着写,然后在这里调用。)

$(function() {
    // 我是父模块
    var list = {
        init: function() {
            // 初始化
            this.$list = $("#list");
            this.render();
        },
        render: function() {
            // 渲染
            this.getData();
            // 我调用了子模块
            editPrice.init();
            this.bind();
        },
        renderData: function() {},
        bind: function() {},
        getData: function() {}
    }

    // 我是子模块
    var editPrice = {
        init: function() {},
        render: function() {},
        renderData: function() {},
        bind: function() {},
        getData: function() {}
    }
    list.init();
});

bind:

  • 绑定事件,所有的绑定事件全部都在这里处理。

  • 这里定义了一个 “self” 变量,这是因为再绑定事件的 on 的函数内部由于作用域不同,所以调用不了其它 list 对象的成员变量和方法,所以事先缓存了起来,有的人会叫 _this、me、that 这些名字,我的习惯是叫 self。

  • 关于上一点其实还可以再函数尾部加上 bind() 方法绑定作用域的,这样就不需要额外申明一个变量了,没有用是因为我不大习惯。。。

  • 这里讲一下为什么 bind() 方法要放在 render() 里面,之所以不 renderData() 之后做是因为数据可能会重复调用,比如分页,就可能会重复调用 renderData() 这个方法,所以才利用了事件委托的办法。

getData:

  • 获取数据,就是在这里用 ajax 和后端进行通信。

  • 用 Mock.js 去模拟一个后端Api,如果你还不知道这个东西,点这里

  • 这里的 self 跟 bind() 里的 self 同理,为了调用成员方法 renderData()。

renderData:

  • 渲染数据,用最原始的方法对代码拼接HTML。

  • 拼接数据的时候,前后用单引号的话,就可以不用担心会跟里面 class 或者其它属性的双引号起冲突了。

  • 拼接好数据之后再一口气 html 进事先在 init() 方法缓存好的 jquery对象 里。

另外: 如果我的模块要在其它的 js 的里调用怎么办,我的做法是 把数据绑定到 window 对象上。

$(function() {
    var list = {}
    list.init();
    window.list = list;
});

最后

这样子的写法我觉得还是比较方便维护的。

如果有什么想跟我讨论的话,请私信。
    原文作者:viewweiwu
    原文地址: https://segmentfault.com/a/1190000007469809
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞