练手项目1笔记 day02AnglaJS

目标

  • 运用AngularJS前端框架的常用指令
  • 完成品牌管理的列表功能
  • 完成品牌管理的分页列表功能
  • 完成品牌管理的增加功能
  • 完成品牌管理的修改功能
  • 完成品牌管理的删除功能
  • 完成品牌管理的条件查询功能

1. 入门

1. 简介

AngularJS 诞生于2009年,由Misko Hevery 等人创建,后为Google所收购。是一款优秀的前端JS框架,已经被用于Google的多款产品当中。AngularJS有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、依赖注入等等。

2. 四大特征

1. mvc模式

Angular遵循软件工程的MVC模式,并鼓励展现,数据,和逻辑组件之间的松耦合.通过依赖注入(dependency injection),Angular为客户端的Web应用带来了传统服务端的服务,例如独立于视图的控制。 因此,后端减少了许多负担,产生了更轻的Web应用。

Model:数据,其实就是angular变量($scope.XX);

View: 数据的呈现,Html+Directive(指令);

Controller: 操作数据,就是function,数据的增删改查

在这里插入图片描述

2. 双向绑定

AngularJS是建立在这样的信念上的:即声明式编程应该用于构建用户界面以及编写软件构建,而指令式编程非常适合来表示业务逻辑。框架采用并扩展了传统HTML,通过双向的数据绑定来适应动态内容,双向的数据绑定允许模型和视图之间的自动同步。因此,AngularJS使得对DOM的操作不再重要并提升了可测试性。

在这里插入图片描述

3. 依赖注入

依赖注入(Dependency Injection,简称DI)是一种设计模式, 指某个对象依赖的其他对象无需手工创建,只需要“吼一嗓子”,则此对象在创建时,其依赖的对象由框架来自动创建并注入进来,其实就是最少知识法则;模块中所有的service和provider两类对象,都可以根据形参名称实现DI.

4. 模块化设计

高内聚低耦合法则

  1. 官方提供的模块 ng、ngRoute、ngAnimate
  2. 用户自定义的模块 angular.module(‘模块名’,[ ])

2. 入门小demo

1. 表达式
<!DOCTYPE html>
<html>
<head>
	<title>angularJS入门小demo-表达式</title>
	<script src="angular.min.js"></script>
</head>
<body ng-app>
{{100+100}}
</body>
</html>
2. 双向绑定
<!DOCTYPE html>
<html>
<head>
	<title>angularJS入门小demo02-双向绑定</title>
	<script src="angular.min.js"></script>
</head>
<body ng-app>
请输入姓名:<input ng-model="name">
<input ng-model="name">
{{name}}
</body>
</html>
3. 初始化指令
<!DOCTYPE html>
<html>
<head>
	<title>angularJS入门小demo03-初始化指令</title>
	<script src="angular.min.js"></script>
</head>
<body ng-app ng-init="name='梁静茹'">
请输入姓名:<input ng-model="name">
<input ng-model="name">
{{name}}
</body>
</html>

也可以调用方法

4. 控制器
<!DOCTYPE html>
<html>
<head>
	<title>angularJS入门小demo04-控制器</title>
	<script src="angular.min.js"></script>
	<script>
		// 建立模块
		var app = angular.module("myApp",[]);
		// 创建控制器 $scope就是控制层与视图层之间交换数据的桥梁
		app.controller("myController",function($scope){

			$scope.add=function(){
				return parseInt($scope.x)+parseInt($scope.y);
			}
		});

	</script>
</head>
<body ng-app="myApp" ng-controller="myController">

第一个数:<input ng-model="x">
第二个数:<input ng-model="y">
{{add()}}
</body>
</html>
5. 事件指令
<!DOCTYPE html>
<html>
<head>
	<title>angularJS入门小demo05-事件指令</title>
	<script src="angular.min.js"></script>
	<script>
		// 建立模块
		var app = angular.module("myApp",[]);
		// 创建控制器 $scope就是控制层与视图层之间交换数据的桥梁
		app.controller("myController",function($scope){

			$scope.add=function(){
				$scope.z = parseInt($scope.x)+parseInt($scope.y);
			}
		});

	</script>
</head>
<body ng-app="myApp" ng-controller="myController">

第一个数:<input ng-model="x">
第二个数:<input ng-model="y">
<br/>
<button ng-click="add()">运算</button>
<br/>
运算结果:{{z}}
</body>
</html>
6. 循环数组
<!DOCTYPE html>
<html>
<head>
	<title>angularJS入门小demo06-循环数组</title>
	<script src="angular.min.js"></script>
	<script>
		// 建立模块
		var app = angular.module("myApp",[]);
		// 创建控制器 $scope就是控制层与视图层之间交换数据的桥梁
		app.controller("myController",function($scope){

			$scope.list = [1,2,3,4,55];
		});

	</script>
</head>
<body ng-app="myApp" ng-controller="myController">

<table>
	<tr ng-repeat="x in list">
		<td>{{x}}</td>
	</tr>
</table>
</body>
</html>
7.http请求
<!DOCTYPE html>
<html>
<head>
	<title>angularJS入门小demo08-内置服务$http</title>
	<script src="angular.min.js"></script>
	<script>
		// 建立模块
		var app = angular.module("myApp",[]);
		// 创建控制器 $scope就是控制层与视图层之间交换数据的桥梁
		app.controller("myController",function($scope,$http){

			$scope.findList = function () {
				$http.get("data.json").success(
						function (response) {
							$scope.list = response;
						}
				);
			}
		});



	</script>
</head>
<body ng-app="myApp" ng-controller="myController" ng-init="findList()">

<table>
	<tr>
		<td>姓名</td>
		<td>数学</td>
		<td>语文</td>
	</tr>
	<tr ng-repeat="entity in list">
		<td>{{entity.name}}</td>
		 <td>{{entity.shuxue}}</td>
		 <td>{{entity.yuwen}}</td>
	</tr>
</table>
</body>
</html>

2. 代码

1. 未分页

brand.html

	<script src="../plugins/angularjs/angular.min.js"></script>
	<script type="text/javascript">

		var app = angular.module('pinyougou',[]);
		app.controller('brandController',function ($scope, $http) {
			// 查询品牌列表
			$scope.findAll = function () {
				$http.get('../brand/findAll.do').success(
						function (response) {
							$scope.list = response;
						}
				);
			}
		});

	</script>
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="brandController" ng-init="findAll()">
  ...
  <tbody>
    <tr ng-repeat="entity in list">
      <td><input  type="checkbox" ></td>			                              
      <td>{{entity.id}}</td>
      <td>{{entity.name}}</td>
      <td>{{entity.firstChar}}</td>
      <td class="text-center">                                           
        <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal"  >修改</button>                                          
      </td>
    </tr>
  </tbody>

2. 分页

品牌分页:

前端给后端:当前页,每页记录数;

后端给前端:总记录数,当前页记录。

思路:

后端应该显示什么格式呢?

json,总记录数,当前页记录

{total:100,rows:[]}

方法1 :

Map map = new HashMap();
map.put('total',100);
map.put('rows',list);
return map;

方法2:

创建类,包含total和rows属性

1. 实体类

和具体业务无关,entity

public class PageResult implements Serializable {

    private Long total;//总记录数
    private List rows;// 当前页结果

    public PageResult(Long total, List rows) {
        this.total = total;
        this.rows = rows;
    }
//get set方法
2. 品牌分页的接口
public interface BrandService {
  PageResult findPage(int pageNum,int pageSize);
}
3. 实现类

用到了pageHelper插件

@Service
public class BrandServiceImpl implements BrandService {
  @Override
    public PageResult findPage(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        Page<TbBrand> page = (Page<TbBrand>) brandMapper.selectByExample(null);
        // 封装到PageResult中
        return new PageResult(page.getTotal(),page.getResult());
    }
}
4. 商家controller
@RestController
@RequestMapping("/brand")
public class BrandController {
  @RequestMapping("/findPage")
    public PageResult findPage(int page,int size){
        return brandService.findPage(page,size);
    }
}
5. 分页的前端实现

在body的table下边数据列表部分增加一行

<!--数据列表/-->                        
<tm-pagination conf="paginationConf"></tm-pagination>

head里引入分页的js和css

<!--分页组件开始-->
<script src="../plugins/angularjs/pagination.js"></script>
<link rel="stylesheet" href="../plugins/angularjs/pagination.css">
<!--分页组件结束-->

在script里增加分页的功能

<script type="text/javascript">

		var app = angular.module('pinyougou',['pagination']);
		app.controller('brandController',function ($scope, $http) {
			// 查询品牌列表
			$scope.findAll = function () {
				$http.get('../brand/findAll.do').success(
						function (response) {
							$scope.list = response;
						}
				);
			}
			
			// 分页控件配置 currentPage当前页 totalItems 总记录数 itemsPerPage 每页记录数
			// perPageOptions分页选项  onChange 当页码变更后自动触发的方法
			$scope.paginationConf = {
				currentPage:1,
				totalItems:10,
				itemsPerPage:10,
				perPageOptions:[10,20,30,40,50],
				onChange:function () {
					$scope.reloadList();
				}
			};

			// 刷新列表,之后会复用,提取为方法
			$scope.reloadList = function(){
				$scope.findPage($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage);
			};

			$scope.findPage = function (page, size) {
				$http.get('../brand/findPage.do?page='+page+'&size='+size).success(
						function (response) {
							$scope.list = response.rows;//显示当前页数据
							$scope.paginationConf.totalItems = response.total;//更新总记录数
						}
				)
			}
		});

	</script>
6. 品牌新增
1. 新建实体类

用于封装向前端返回的结果,成功与否。

public class Result implements Serializable {

    private boolean success; // 成功与否
    private String message; // 传输的具体信息

    public Result(boolean success, String message) {
        this.success = success;
        this.message = message;
    }
// ...
2. 接口
public interface BrandService {
  // 增加品牌
    void addBrand(TbBrand brand);
}
3. 实现类
@Service
public class BrandServiceImpl implements BrandService {
  @Override
    public void addBrand(TbBrand brand) {
        brandMapper.insert(brand);
    }
}
4. 商家的controller
    @RequestMapping("/add")
    public Result addBrand(@RequestBody TbBrand brand){
        try {
            brandService.addBrand(brand);
            return new Result(true,"增加品牌成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false,"增加品牌失败");
        }
    }
5. 前端

方法

// 新增品牌
$scope.add = function () {
  $http.post('../brand/add.do',$scope.entity).success(
    function (response) {
      if(response.success){
      	$scope.reloadList();// 刷新
      }else{
      	alert(response.message);
      }
    }
  );
}

body的编辑窗口

<tr>
	<td>品牌名称</td>
	<td><input  class="form-control" placeholder="品牌名称" ng-model="entity.name">  </td>
</tr>		      	
<tr>
	<td>首字母</td>
	<td><input  class="form-control" placeholder="首字母" ng-model="entity.firstChar">  </td>
  
  
// 保存按钮
  <button class="btn btn-success" data-dismiss="modal" aria-hidden="true" ng-click="add()">保存</button>

小瑕疵:每次新建都能看到前一次,不爽,如何修改?

修改新建按钮

<button type="button" class="btn btn-default" title="新建" data-toggle="modal" data-target="#editModal" ng-click="entity={}"><i class="fa fa-file-o" ></i> 新建</button>
7. 品牌修改

其实分两步:根据id查找和更新

1. 接口
    // 根据id查询
    TbBrand findOne(Long id);

    // 更新品牌
    void updateBrand(TbBrand brand);
2. 实现类
 	@Override
    public TbBrand findOne(Long id) {
        return brandMapper.selectByPrimaryKey(id);
    }

    @Override
    public void updateBrand(TbBrand brand) {
        brandMapper.updateByPrimaryKey(brand);
    }
3. 商家的controller
    @RequestMapping("/findOne")
    public TbBrand findOne(Long id){
        return brandService.findOne(id);
    }

    @RequestMapping("/update")
    public Result updateBrand(@RequestBody TbBrand brand){
        try {
            brandService.updateBrand(brand);
            return new Result(true,"品牌更新成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false,"品牌更新失败");
        }
    }
4. 前端

点击修改按钮,弹出的框和增加的框一样,然后修改,然后保存

<button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" ng-click="findOne(entity.id)" >修改</button>

方法

// 根据id查询品牌
$scope.findOne = function (id) {
  $http.get('../brand/findOne.do?id='+id).success(
    function (response) {
      $scope.entity = response;
    }
  );
};

编辑窗口的保存

<button class="btn btn-success" data-dismiss="modal" aria-hidden="true" ng-click="save()">保存</button>

方法

借用add方法

$scope.save = function () {
				var methodName = 'add'; //方法名
				if($scope.entity.id!=null){
					methodName = 'update';
				}

				$http.post('../brand/'+methodName+'.do',$scope.entity).success(
						function (response) {
							if(response.success){
								$scope.reloadList();// 刷新
							}else{
								alert(response.message);
							}
						}
				);
			}
8. 删除品牌

本项目采用复式删除,通过复选框删除

1. 接口
// 批量删除品牌
    void deleteBrands(Long[] ids);
2. 实现类
@Override
    public void deleteBrands(Long[] ids) {
        for (Long id : ids) {
            brandMapper.deleteByPrimaryKey(id);
        }
    }
3. 商家的controller
 @RequestMapping("/delete")
    public Result deleteBrands(Long[] ids){
        try {
            brandService.deleteBrands(ids);
            return new Result(true,"品牌删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false,"品牌删除失败");
        }
    }
4. 前端

需要定义一个集合存储勾选的复选框的id

方法

包含push添加,js原生的indexOf和splice

$scope.selectIds = [];// 用户勾选的ID集合

$scope.updateSelection = function ($event,id) {
  if($event.target.checked){
    $scope.selectIds.push(id);//push向集合中添加元素
  }else{
    // 删除元素
    var index = $scope.selectIds.indexOf(id);//查找值的位置
    $scope.selectIds.splice(index,1);// 参数1:值的位置 参数2:移除的个数
  }
}

body

<td><input  type="checkbox" ng-click="updateSelection($event,entity.id)"></td>
<td>{{entity.id}}</td>
<td>{{entity.name}}</td>
<td>{{entity.firstChar}}</td>

最好在后边添加个{{selectIds}}

删除

// 删除
			$scope.deleteSelection = function () {
				$http.get('../brand/delete.do?ids='+$scope.selectIds).success(
						function (response) {
							if(response.success){
								$scope.reloadList();//刷新
							}else{
								alert(response.message);
							}
						}
				);
			}

body

<button type="button" class="btn btn-default" title="删除" ng-click="deleteSelection()"><i class="fa fa-trash-o"></i> 删除</button>
9.条件查询

其实跟分页查询所有一样,只是

TODO 后端碰到问题,未解决!

后端问题为:invalid constant type,修改依赖的javassist版本即可。

1. 接口
    // 条件查询
    PageResult findPage(TbBrand brand, int pageNum,int pageSize);
2. 实现类
@Override
    public PageResult findPage(TbBrand brand, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum,pageSize);

        TbBrandExample example = new TbBrandExample();
        Criteria criteria = example.createCriteria();
        if(brand!=null){
            if(brand.getName()!=null && brand.getName().length()>0){
                criteria.andNameLike("%"+brand.getName()+"%");
            }
            if(brand.getFirstChar()!=null && brand.getFirstChar().length()>0){
                criteria.andFirstCharLike("%"+brand.getFirstChar()+"%");
            }
        }
        Page<TbBrand> page = (Page<TbBrand>) brandMapper.selectByExample(example);
        // 封装到PageResult中
        return new PageResult(page.getTotal(),page.getResult());
    }
3. controller
@RequestMapping("/search")
    public PageResult search(@RequestBody TbBrand brand,int page,int size){
        return brandService.findPage(brand,page,size);
    }
4. 前端

需要增加搜索框

<div class="box-tools pull-right">
   <div class="has-feedback">
		品牌名称:<input ng-model="searchEntity.name"> 品牌首字母:<input ng-model="searchEntity.firstChar">  <button class="btn btn-default" ng-click="reloadList()">查询</button>
   </div>

方法

$scope.searchEntity={};
// 条件查询
$scope.search = function (page,size) {
	// 混合提交
	$http.post('../brand/search.do?page='+page+'&size='+size,$scope.searchEntity).success(
		function (response) {
			$scope.list = response.rows;//显示当前页数据
			$scope.paginationConf.totalItems = response.total;//更新总记录数
			}
	);
};

修改reload

// 刷新列表
$scope.reloadList = function(){
	$scope.search($scope.paginationConf.currentPage,$scope.paginationConf.itemsPerPage);
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值