angularjs和jquery在CRUD上的区别

对比直接使用jquery和angularjs,在CRUD中的区别。

Bind

angularjs最大的优势,在于对于CRUD采取了对象化。以前要用jquery将数据绑定到dom中,现在是直接对象处理。所以在这个层次上来讲,angularjs的定位和思路是很不错的。

对比下面jquery做的一个用户注册页面,其实jquery已经简化了很多工作:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>SRS监控系统</title>
    <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script type="text/javascript" src="js/bootstrap.min.js"></script>
    <script type="text/javascript" src="js/json2.js"></script>
    <script type="text/javascript" src="js/bsm.monitor.api.js"></script>
    <script type="text/javascript" src="js/bsm.logs.js"></script>
    <script type="text/javascript" src="js/bsm.utility.js"></script>
    <script type="text/javascript" src="js/winlin.utility.js"></script>
    <script type="text/javascript" src="js/bsm.page.template.js"></script>
    <style>
        body{
            padding-top: 55px;
        }
    </style>
    <script type="text/javascript">
        var query = parse_query_string();
        var api = new MonitorApi();

        // main entrance
        $(function(){
            render_footer($("#footer"));
            render_nav($("#nav"), null);
            logs.render($("#log"));

            logs.info("verify qq-auth, token=" + query.access_token);
            api.qqauths_verify(query.access_token, on_error, on_auth_success);
        });

        // when verify qq-auth success, login or create user.
        function on_auth_success(openid, nickname, gender, figureurl, qqurl) {
            logs.info("qq-auth ok, nickname=" + nickname);
            api.users_load(openid, on_error, function(user){
                if (user != null) {
                    on_user_login(user);
                    return;
                }
                create_user_for_openid(openid, nickname, gender, figureurl, qqurl);
            });
        }

        // create session when user is null.
        // the user corresponding to openid doesn't exists.
        function create_user_for_openid(openid, nickname, gender, figureurl, qqurl) {
            logs.info("create user for openid="+openid);
            var username = build_random_username();
            var password = build_random_password();

            $("#user_name").val(username);
            $("#user_password").val(password);
            $("#user_nickname").val(nickname);
            $("#user_openid").val(openid);
            $("#create_user").click(on_click_btn_create_user);
            $("#create_user_ui").show();
        }

        // submit to create new user
        function on_click_btn_create_user(){
            logs.info("submit to create user.");
            $("#create_user_ui").find("input").attr("disabled", true);
            $("#create_user_ui").find("button").attr("disabled", true);

            var reset =function() {
                $("#create_user_ui").find("input").attr("disabled", false);
                $("#create_user_ui").find("button").attr("disabled", false);
                $("#create_user_ui").hide();
            }

            var err = function(code, msg) {
                reset();
                on_error(code, msg);
            }

            var username = $("#user_name").val();
            var password = $("#user_password").val();
            var nickname = $("#user_nickname").val();
            var email = $("#user_email").val();
            var mobile = $("#user_mobile").val();
            var qq = $("#user_qq").val();
            var openid = $("#user_openid").val();

            api.users_create2(username, password, openid, nickname, email, mobile, qq, err, function(user){
                reset();
                on_user_login(user);
            });
        }

        // session created or loaded
        function on_user_login(user) {
            logs.info("user login ok");
            window.location.href = "index.html";
        }
    </script>
</head>
<body>
    <div id="nav"></div>
    <div id="log"></div>
    <div class="container">
        <div class="accordion hide" id="create_user_ui">
            <div class="accordion-group">
                <div class="accordion-heading">
                    <span class="accordion-toggle" data-toggle="collapse">
                        <strong>注册新用户</strong>
                    </span>
                </div>
                <div class="accordion-body collapse in">
                    <div class="accordion-inner form-horizontal">
                        <div class="control-group">
                            <label class="control-label" for="user_name">用户名</label>
                            <div class="controls">
                                <input id="user_name" class="input-large" type="text" value="">
                            </div>
                        </div>
                        <div class="control-group">
                            <label class="control-label" for="user_password">密码</label>
                            <div class="controls">
                                <input id="user_password" class="input-large" type="text" value="">
                            </div>
                        </div>
                        <div class="control-group">
                            <label class="control-label" for="user_nickname">昵称</label>
                            <div class="controls">
                                <input id="user_nickname" class="input-large" type="text" value="">
                            </div>
                        </div>
                        <div class="control-group">
                            <label class="control-label" for="user_email">Email</label>
                            <div class="controls">
                                <input id="user_email" class="input-large" type="text" value="" placeholder="Email">
                            </div>
                        </div>
                        <div class="control-group">
                            <label class="control-label" for="user_mobile">CellPhone</label>
                            <div class="controls">
                                <input id="user_mobile" class="input-large" type="text" value="" placeholder="CellPhone">
                            </div>
                        </div>
                        <div class="control-group">
                            <label class="control-label" for="user_qq">QQ</label>
                            <div class="controls">
                                <input id="user_qq" class="input-large" type="text" value="" placeholder="QQ">
                            </div>
                        </div>
                        <div class="control-group">
                            <div class="controls">
                                <button type="submit" class="btn" id="create_user">注册新用户</button>
                            </div>
                        </div>
                        <input type="hidden" id="user_openid">
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div id="footer"></div>
</body>
</html>
/**
 * verify the access token and got informations.
 * @param access_token the token when login success by qq.
 * @param on_error a function(code, msg) callback when error, where msg is optional.
 * @param on_success a function(openid, nickname, gender, figureurl, qqurl) when success.
 */
MonitorApi.prototype.qqauths_verify = function (access_token, on_error, on_success) {
    var url = "/api/v1/qqauths?access_token=" + access_token;
    this.__api_get(url, on_error, function(data){
        on_success(data.openid, data.nickname, data.gender, data.figureurl, data.qqurl);
    });
}
/**
 * load user from openid.
 * @param openid the openid response by qq-auth
 * @param on_error a function(code, msg) callback when error, where msg is optional.
 * @param on_success a function(user) when success, where user is a object identify the user by openid.
 *          user is null when user not find by the openid. please create a session by openid.
 */
MonitorApi.prototype.users_load = function (openid, on_error, on_success) {
    var url = "/api/v1/users?openid=" + openid;
    this.__api_get(url, on_error, function(data){
        on_success(data.user);
    });
}
/**
 * create/register new user
 * @param username the username of user.
 * @param password the password of user.
 * @param openid the openid response by qq-auth
 * @param nickname the user nickname response by qq-auth
 * @param on_error a function(code, msg) callback when error, where msg is optional.
 * @param on_success a function(user) when success, where user is a object.
 */
MonitorApi.prototype.users_create = function (username, password, openid, nickname, on_error, on_success) {
    var data = {};
    data.openid = openid;
    data.nickname = nickname;
    data.username = username;
    data.password = password;

    var url = "/api/v1/users";
    this.__api_post(url, data, on_error, function(data){
        on_success(data.user);
    });
}
/**
 * create/register new user
 * @param username the username of user.
 * @param password the password of user.
 * @param openid the openid response by qq-auth
 * @param nickname the user nickname response by qq-auth
 * @param email the email of user. optional, canbe null.
 * @param mobile the mobile of user. optional, canbe null.
 * @param qq the qq of user. optional, canbe null.
 * @param on_error a function(code, msg) callback when error, where msg is optional.
 * @param on_success a function(user) when success, where user is an object.
 */
MonitorApi.prototype.users_create2 = function (username, password, openid, nickname, email, mobile, qq, on_error, on_success) {
    var data = {};
    data.openid = openid;
    data.nickname = nickname;
    data.username = username;
    data.password = password;

    // optionals
    data.email = email;
    data.mobile = mobile;
    data.qq = qq;

    var url = "/api/v1/users";
    this.__api_post(url, data, on_error, function(data){
        on_success(data.user);
    });
}

用angularjs实现的版本:

<!DOCTYPE html>
<html ng-app="bsmApp">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>SRS监控系统</title>
    <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
    <script type="text/javascript" src="js/bootstrap.min.js"></script>
    <script type="text/javascript" src="js/angular.min.js"></script>
    <script type="text/javascript" src="js/angular-route.min.js"></script>
    <script type="text/javascript" src="js/angular-resource.js"></script>
    <script type="text/javascript" src="js/bsm.ng.router.js"></script>
    <script type="text/javascript" src="js/bsm.logs.js"></script>
    <script type="text/javascript" src="js/bsm.utility.js"></script>
    <style>
        body{
            padding-top: 55px;
        }
    </style>
    <script type="text/javascript">
        $(function() {
            logs.render($("#log"));
        });
    </script>
</head>
<body ng-controller="MainController">
    <div class="navbar navbar-fixed-top">
        <div class="navbar-inner">
            <div class="container">
                <a class="brand" href="javascript:void(0)" title="BSM(Bravo SRS Monitor)">监控</a>
                <div class="nav-collapse collapse">
                    <ul class="nav" ng-repeat="nav in navs">
                        <li class="{{nav.class}}"><a href="{{nav.url}}" target="{{nav.target}}">{{nav.text}}</a></li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
    <div id="log"></div>
    <div ng-view></div>
</body>
</html>

<div class="container">
    <div class="accordion {{user_reg_visible}}">
        <div class="accordion-group">
            <div class="accordion-heading">
                    <span class="accordion-toggle" data-toggle="collapse">
                        <strong>注册新用户</strong>
                    </span>
            </div>
            <div class="accordion-body collapse in">
                <div class="accordion-inner form-horizontal">
                    <div class="control-group">
                        <label class="control-label" for="user_name">用户名</label>
                        <div class="controls">
                            <input id="user_name" class="input-large" type="text" value="{{user_reg_username}}">
                        </div>
                    </div>
                    <div class="control-group">
                        <label class="control-label" for="user_password">密码</label>
                        <div class="controls">
                            <input id="user_password" class="input-large" type="text" value="{{user_reg_password}}">
                        </div>
                    </div>
                    <div class="control-group">
                        <label class="control-label" for="user_nickname">昵称</label>
                        <div class="controls">
                            <input id="user_nickname" class="input-large" type="text" value="{{user_reg_nickname}}">
                        </div>
                    </div>
                    <div class="control-group">
                        <label class="control-label" for="user_email">Email</label>
                        <div class="controls">
                            <input id="user_email" class="input-large" type="text" value="{{user_reg_email}}" placeholder="Email">
                        </div>
                    </div>
                    <div class="control-group">
                        <label class="control-label" for="user_mobile">CellPhone</label>
                        <div class="controls">
                            <input id="user_mobile" class="input-large" type="text" value="{{user_reg_phone}}" placeholder="CellPhone">
                        </div>
                    </div>
                    <div class="control-group">
                        <label class="control-label" for="user_qq">QQ</label>
                        <div class="controls">
                            <input id="user_qq" class="input-large" type="text" value="{{user_reg_qq}}" placeholder="QQ">
                        </div>
                    </div>
                    <div class="control-group">
                        <div class="controls">
                            <button type="submit" class="btn" ng-click="user_register()">注册新用户</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

// the application, system main object.
var bsmApp = angular.module('bsmApp', ['ngRoute', 'bsmControllers', 'bsmFilters', 'bsmServices']);
// the controllers, used to generate variety controllers for views.
var bsmControllers = angular.module('bsmControllers', []);
// the services, system model, RESTful data from backend api.
var bsmServices = angular.module('bsmServices', ['ngResource']);
// config the route
bsmApp.config([
    '$routeProvider', function($routeProvider) {
        $routeProvider.when('/servers', {
            templateUrl: 'views/servers.html',
            controller: 'BsmServers'
        }).when('/users', {
            templateUrl: 'views/users.html',
            controller: 'BsmUsers'
        }).otherwise({
            redirectTo: '/servers'
        });
    }
]);
// controller: BsmUsers, for the view users.html.
bsmControllers.controller('BsmUsers', ['$scope', '$routeParams', 'QQAuth', 'User', function($scope, $routeParams, QQAuth, User){
    $scope.$parent.nav_active_servers();

    $scope.user_reg_visible = "hide";
    $scope.user_reg_username = build_random_username();
    $scope.user_reg_password = build_random_password();
    $scope.user_reg_nickname = "";
    $scope.user_reg_email = "";
    $scope.user_reg_phone = "";
    $scope.user_reg_qq = "";
    $scope.user_reg_openid = "";

    $scope.user_register = function() {
        User.users_create2({
            openid: $scope.user_reg_openid,
            nickname: $scope.user_reg_nickname,
            username: $scope.user_reg_username,
            password: $scope.user_reg_password,
            // optionals
            email: $scope.user_reg_email,
            mobile: $scope.user_reg_phone,
            qq: $scope.user_reg_qq
        }, function(data) {
            $scope.__on_user_login(data.user);
        });
    };

    logs.info("正在验证access_token=" + $routeParams.access_token);
    QQAuth.get({access_token:$routeParams.access_token}, function(data) {
        var obj = data.data;
        $scope.__on_auth_success(obj.openid, obj.nickname, obj.gender, obj.figureurl, obj.qqurl);
    });

    $scope.__on_auth_success = function(openid, nickname, gender, figureurl, qqurl) {
        logs.info("验证access_token成功, openid=" + openid + ", nickname=" + nickname);
        User.load_by_openid({openid: openid}, function(data) {
            if (data.user) {
                $scope.__on_user_login(data.user);
                return;
            }

            logs.info("create user for openid="+openid);
            $scope.user_reg_nickname = nickname;
            $scope.user_reg_openid = openid;
            $scope.user_reg_visible = "show";
        });
    }
    $scope.__on_user_login = function(user) {
        logs.info("user login ok");
        window.location.href = "index.html";
    }
}]);

后者不仅在代码行数上要少,而且前端html和js的对象是直接对应,省去$("#xxx").val()这种取值和赋值的操作。若用于展示,优势更明显。


Filter

filter在处理数据变换,譬如init状态为“初始化”,时间从毫秒变成年月日等,这些变换上和jquery的区别也很大。

下面是jquery在展示数据变换的例子:

logs.info("render server list");
for (var i = 0; i < servers.length; i++) {
    var server = servers[i];

    var obj_id = "server_node_" + server.id;
    var obj = server_list.find('#' + obj_id);
    if (obj.length <= 0) {
        obj = $("<tr/>").html($("#server_list_tmpl").html());
        obj.attr("id", obj_id);
        server_list.append(obj);
    }

    obj.find("#server_list_server_id").html(server.id);
    obj.find("#server_list_server_ip").html(server.ip + ":" + server.rtmp_port);
    obj.find("#server_list_server_api_port").text(server.api_port).attr("href", servers_get_api_summaries(server.ip, server.api_port));
    obj.find("#server_list_server_desc").html(server.desc);
    obj.find("#server_list_server_status").empty().append(
        $("<span/>").addClass("label").addClass(servers_status2class(server.status)).html(servers_status2text(server.status))
    );

    if (server.basic == null) {
        obj.find("#server_list_basic_time").html("未知");
        obj.find("#server_list_basic_load").html("未知");
        obj.find("#server_list_basic_cpu").html("未知");
        obj.find("#server_list_basic_mem").html("未知");
        continue;
    }

    var basic_time = server.basic.time;
    if (basic_time.srs_uptime > 24 * 3600) {
        obj.find("#server_list_basic_time").html(parseInt(basic_time.srs_uptime / 24 / 3600) + "天 ");
        obj.find("#server_list_basic_time").append(relative_seconds_to_HHMMSS(basic_time.srs_uptime));
    } else {
        obj.find("#server_list_basic_time").html(relative_seconds_to_HHMMSS(basic_time.srs_uptime));
    }

    var basic_load = server.basic.load;
    obj.find("#server_list_basic_load").html(
        Number(basic_load.load_1m).toFixed(1) + ", " + Number(basic_load.load_5m).toFixed(1)
        + ", " + Number(basic_load.load_15m).toFixed(1)
    );

    var basic_cpu = server.basic.cpu;
    obj.find("#server_list_basic_cpu").html(
        basic_cpu.cpus + "U, " + Number(basic_cpu.cpus * basic_cpu.cpu_percent * 100).toFixed(1)
        + "%, " +  Number(basic_cpu.srs_cpu_percent*100).toFixed(1) + "%"
    );

    var basic_mem = server.basic.mem;
    obj.find("#server_list_basic_mem").html(
            parseInt(basic_mem.total / 1024) + "M, " + parseInt(basic_mem.total * basic_mem.used_percent / 1024)
                    + ", " + parseInt(basic_mem.total * basic_mem.srs_percent / 1024)
    );
}

页面上放置一个模板节点,隐藏:

<table id="server_list" class="table table-bordered table-hover">
    <tr>
        <th>
            <abbr title="监控新的服务器" class="initialism">
                <a href="javascript:void(0)" id="server_create_button"><i class="bravo-icon-plus"></i>添加</a>
            </abbr>
        </th>
        <th><abbr title="便于记忆的服务器名称" class="initialism">名称</abbr></th>
        <th><abbr title="服务器的IP,监控系统必须要能访问到" class="initialism">服务器IP</abbr></th>
        <th><abbr title="SRS的运行时间(天 时:分:秒),非系统运行时间。" class="initialism">时间</abbr></th>
        <th><abbr title="系统1分钟、5分钟、15分钟的负载,参考top命令。" class="initialism">负载</abbr></th>
        <th>
            <abbr title="系统的CPU个数(包括超线程的虚拟核)、系统CPU使用率百分比、SRS占用的百分比。" class="initialism">CPUs,Sys%,SRS%</abbr>
        </th>
        <th><abbr title="系统的总内存MB、系统已使用、SRS使用的内存。" class="initialism">内存MB,Sys,SRS</abbr></th>
        <th><abbr title="服务器的API地址,显示服务器的基本信息" class="initialism">API</abbr></th>
        <th><abbr title="服务器目前的状态,每隔一定时间监控系统会刷新数据" class="initialism">状态</abbr></th>
    </tr>
    <tr class="hide" id="server_list_tmpl">
        <td id="server_list_server_id"></td>
        <td id="server_list_server_desc"></td>
        <td id="server_list_server_ip"></td>
        <td id="server_list_basic_time"></td>
        <td id="server_list_basic_load"></td>
        <td id="server_list_basic_cpu"></td>
        <td id="server_list_basic_mem"></td>
        <td><a href="javascript:void(0)" id="server_list_server_api_port" target="_blank">#</a></td>
        <td id="server_list_server_status"></td>
    </tr>
</table>

换成angularjs的filter方式:

<table class="table table-bordered table-hover">
    <tr>
        <th>
            <abbr title="监控新的服务器" class="initialism">
                <a href="javascript:void(0)" id="server_create_button"><i class="bravo-icon-plus"></i>添加</a>
            </abbr>
        </th>
        <th><abbr title="便于记忆的服务器名称" class="initialism">名称</abbr></th>
        <th><abbr title="服务器的IP,监控系统必须要能访问到" class="initialism">服务器IP</abbr></th>
        <th><abbr title="SRS的运行时间(天 时:分:秒),非系统运行时间。" class="initialism">时间</abbr></th>
        <th><abbr title="系统1分钟、5分钟、15分钟的负载,参考top命令。" class="initialism">负载</abbr></th>
        <th>
            <abbr title="系统的CPU个数(包括超线程的虚拟核)、系统CPU使用率百分比、SRS占用的百分比。" class="initialism">CPUs,Sys%,SRS%</abbr>
        </th>
        <th><abbr title="系统的总内存MB、系统已使用、SRS使用的内存。" class="initialism">内存MB,Sys,SRS</abbr></th>
        <th><abbr title="服务器的API地址,显示服务器的基本信息" class="initialism">API</abbr></th>
        <th><abbr title="服务器目前的状态,每隔一定时间监控系统会刷新数据" class="initialism">状态</abbr></th>
    </tr>
    <tr ng-repeat="server in servers">
        <td>{{server.id}}</td>
        <td>{{server.desc}}</td>
        <td>{{server.ip + ":" + server.rtmp_port}}</td>
        <td>{{server.basic |servers_uptime}}</td>
        <td>{{server.basic |servers_load}}</td>
        <td>{{server.basic |servers_cpu}}</td>
        <td>{{server.basic |servers_mem}}</td>
        <td><a href="{{server |servers_link}}" target="_blank">{{server.api_port}}</a></td>
        <td><span class="label {{server.status |servers_status_class}}">{{server.status |servers_status_text}}</span></td>
    </tr>
</table>

使用angularjs的filter:

bsmFilters.filter('servers_status_class', function(){
    return function(status) {
        var status_dict = {
            init: "label-inverse",
            ready: "label-inverse",
            sync: "label-info",
            online: "label-success",
            offline: "",
            error: "label-important"
        };
        return status_dict[status]
    };
}).filter('servers_status_text', function(){
    return function(status) {
        var text_dict = {
            init: "未导入",
            ready: "待同步",
            sync: "同步中",
            online: "已上线",
            offline: "离线中",
            error: "异常中"
        }
        return text_dict[status]
    };
}).filter('servers_uptime', function(){
    return function(basic) {
        if (!basic) {
            return "未知";
        }
        var srs_uptime = basic.time.srs_uptime;
        if (srs_uptime > 24 * 3600) {
            return parseInt(srs_uptime / 24 / 3600) + "天 " + relative_seconds_to_HHMMSS(srs_uptime);
        } else {
            return relative_seconds_to_HHMMSS(srs_uptime);
        }
    };
}).filter('servers_load', function(){
    return function(basic) {
        if (!basic) {
            return "未知";
        }
        var basic_load = basic.load;
        return Number(basic_load.load_1m).toFixed(1) + ", " + Number(basic_load.load_5m).toFixed(1)
            + ", " + Number(basic_load.load_15m).toFixed(1);
    };
}).filter('servers_cpu', function(){
    return function(basic) {
        if (!basic) {
            return "未知";
        }
        var basic_cpu = basic.cpu;
        return basic_cpu.cpus + "U, " + Number(basic_cpu.cpus * basic_cpu.cpu_percent * 100).toFixed(1)
            + "%, " +  Number(basic_cpu.srs_cpu_percent*100).toFixed(1) + "%";
    };
}).filter('servers_mem', function(){
    return function(basic) {
        if (!basic) {
            return "未知";
        }
        var basic_mem = basic.mem;
        return parseInt(basic_mem.total / 1024) + "M, " + parseInt(basic_mem.total * basic_mem.used_percent / 1024)
            + ", " + parseInt(basic_mem.total * basic_mem.srs_percent / 1024);
    };
}).filter('servers_link', function(){
    return function(server) {
        return servers_get_api_summaries(server.ip, server.api_port);
    };
});

CodeLines

最后完成的代码行数对比,同样的功能,angularjs只有jquery一半的代码量,很赞:

[winlin@dev6 jquery.angularjs.compare]$ ~/srs/research/code-statistic/csr.py jquery *.html,*.js
total:1679 code:1404 comments:275(16.38%) block:220 line:55


[winlin@dev6 jquery.angularjs.compare]$ ~/srs/research/code-statistic/csr.py angularjs *.html,*.js
total:644 code:565 comments:79(12.27%) block:72 line:7
angularjs的代码只有jquery的一半不到。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

winlinvip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值