剑客
关注科技互联网

Angular1.5 入门之常用指令使用

Angular使用了应该有一个月了,一直想总结来着,但是比较懒,所以一直拖着。这次正好趁着分享,写一篇相关内容的文章,来总结下Angular的基本使用和常用指令。本来打算写的是入门教程,发现入门教程怎么写都感觉不如官网,所以放弃了,可以把这一篇当做入门教程的补充版。如果大家要看入门教程可以看官方的 angular tutorial
,中文版的话1.5版本的没找到,大家可以看 angular 1.4
angular 教程

这里以一个简单的图片列表应用为demo,查看效果可以点击: http://www.liuchungui.com/example/angularExample/01/
查看,github地址是 angularExample 01

现在跟着我一步一步来吧!

一、使用npm管理器搭建环境

我们使用npm包管理器来搭建环境,因为它易于安装和管理。我们先创建一个文件夹,初始化工程。

$ mkdir angularExample
$ cd angularExample
$ npm init

初始化的时候,会让你填入项目的一些信息,之后我们输入 yes
之后,会在当前目录下生成一个 package.json
,里面是我们填入的信息。

之后,我们安装 angularJS
jquery
bootstrap

#安装angular
$ npm install --save angular
#安装jquery
$ npm install --save jquery
#安装bootstrap
$ npm install --save bootstrap

这时,我们的项目工程文件下多了个 node_modules
文件夹, node_modules
下有 angular
jquery
,这就说明我们安装成功了。

查看 package.json
,如下:

{
 "name": "learning",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
 "test": "echo /"Error: no test specified/" && exit 1"
 },
 "author": "",
 "license": "ISC",
 "dependencies": {
 "angular": "^1.5.8",
 "bootstrap": "^3.3.7",
 "jquery": "^3.1.1"
 }
}

看到 dependencies
那一块,这里说明我们项目依赖的是 angular 1.5.8
jquery 3.1.1
bootstrap 3.3.7

在安装完依赖之后,我们需要将我们的工程放入一个web环境下,例如apache等等。如果你没有对应的web环境,我们可以使用npm快速搭建一个,这里可参考 快速搭建静态服务器的几种方法

到此,我们的环境算是搭建好了,现在开启我们的旅程吧!

二、图片列表应用

1、导入文件

克隆或下载 angularExample
,将工程下面的 demoApp.css
样式文件、 image
文件夹和 resource
文件夹copy到你的工程目录下,这是我们所需要样式、图片和资源。

创建 index.html
demoApp.js
,在 index.html
文件中,导入 angular
jquery
bootstrap
这三个框架,然后导入 demoApp.css
demoApp.js

下面是index.html文件内容:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Hello World</title>
 <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.css">
 <link rel="stylesheet" href="demoApp.css">
 <script src="node_modules/angular/angular.js"></script>
 <script src="node_modules/jquery/dist/jquery.js"></script>
 <script src="demoApp.js"></script>
</head>
<body>
</body>
</html>

2、添加列表展示页面

下面是添加列表展示页之后index.html的内容:

<!DOCTYPE html>
<html lang="en" ng-app="demoApp">
<head>
 <meta charset="UTF-8">
 <title>Hello World</title>
 <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.css">
 <link rel="stylesheet" href="demoApp.css">
 <script src="node_modules/angular/angular.js"></script>
 <script src="node_modules/jquery/dist/jquery.js"></script>
 <script src="demoApp.js"></script>
</head>
<body ng-controller="demoController">
<div class="photos">
 <div class="photoItem" ng-repeat="info in imageList">
 <img ng-src="{{info.imageUrl}}" ng-style="imageStyle(info.width)"/>
 </div>
</div>
</body>
</html>

demoApp.js中的内容:

'use strict';

var demoApp = angular.module('demoApp', []);

demoApp.controller('demoController', function ($scope, $http) {
 /**
 * 获取imageList.json文件中的json数据
 */
 $http.get('resource/imageList.json').success(function (data) {
 console.log(data);
 //绑定到scope当中的图片列表中
 $scope.imageList = data;
 }).error(function (error) {
 console.log(error);
 });

 /**
 * 设置图片的宽和高
 */
 $scope.imageStyle = function(width) {
 var windowWidth = window.document.body.clientWidth;
 var scale = windowWidth/1932;
 return {
 'height': parseInt(352*scale) + 'px',
 'width': parseInt((windowWidth-36)/4) + 'px'
 };
 };

 /**
 * jquery事件
 * resize是当窗口变化时,会触发resize事件
 */
 $(window).resize(function(){
 /**
 * angular 事件, 重新更新界面, 做手动刷新
 */
 $scope.$apply(function(){
 //do something to update current scope based on the new innerWidth and let angular update the view.
 });
 });

});

上面的代码,我们实现了一个简单展示图片的列表,而且做到了响应式布局,你可以在浏览器里面看到效果。这是怎么做到的?

首先,创建 demoApp
应用

我们在 index.html
文件中 <html lang="en" ng-app="demoApp">
中使用了 ng-app
指令,这个指令指定了 angular
demoApp
模块作为它的根模块,也指定了 html
标签作为我们angular应用的作用域。

随后,我们在 demoApp.js
文件中注册了 demoApp
模块,名称与上一步 ng-app
指定的名称对应,注册模块的模式是固定的,如下:

'use strict';

/**
 * 注册模块, []是依赖的模块
 * @type {angular.Module}
 */
var demoApp = angular.module("demoApp", []);

所使用的 angular.module
中有两个参数,第一个参数是注册的模块名称,第二个参数是这个注册模块依赖的模块。

然后、创建控制器

创建控制器,在html中只需要使用 ng-controller
指定一下就行了,如 <body ng-controller="demoController">
,那这个body标签就成为控制器的作用域了。而在js中,需要创建一个对应的控制器,样式如下面:

demoApp.controller("demoController", function ($scope, $http) {
 });

最后,创建图片列表

图片列表中模块 index.html
中的代码如下:

<div class="photos">
 <div class="photoItem" ng-repeat="info in imageList">
 <img ng-src="{{info.imageUrl}}" ng-style="imageStyle(info.width)" />
 </div>
</div>

它首先使用 ng-repeat
指令,遍历了 imageList
的内容,然后实例化了多个 <img>

在说 ng-repeat
命令之前,我们先来看看这个 imageList
是怎么来的。我们在 demoApp.js
中看到下面一段代码:

/**
 * 获取imageList.json文件中的json数据
 */
$http.get('resource/imageList.json').success(function (data) {
 console.log(data);
 //绑定到scope当中的图片列表中
 $scope.imageList = data;
}).error(function (error) {
 console.log(error);
});

这段代码注释很清楚,就是我们通过 $http
进行http请求,获取本地的资源文件 imageList.json
中的内容,然后将这个json数据赋值给$scope.imageList,这样模板 index.html
中的 imageList
就有内容了。

这整个过程用到了angular两个核心概念:

  • 依赖注入:通过依赖注入,我们可以很方便的获取所需要的东西。这个 $scope
    $http
    就是通过依赖注入的机制获得的,我们并不需要创建它们,只需要在 demoController
    获取就行了。
  • 数据绑定:当我们获取数据赋值给当前作用域下的某个值后,例如$scope.imageList,模板 index.html
    中的imageList也发生了变化。

imageList
有值后, ng-repeat
遍历这个 imageList
,然后多次实例化 img
元素,用法就和PHP中的for-in类似,只是少了for。

在实例化 img
时,使用了 ng-src
ng-style
指令。

其中, ng-src
src
一样,指定图片的地址。

ng-style
则对应的是 style
,指定的是样式,但是它与style不同的是,它传递的是对象,而且可以通过函数获取一个对象。例如上面实现响应式布局,就是通过 imageStyle
返回了对应的高和宽。

不过,这种通过js设置样式的代码是不推荐的,因为在angular使用的是MVC的开发模式,M就是绑定的数据;V就是DOM,也就是我们的index.html模板;C则是控制器。上面,我们相当于在控制器做模板的事情,我们应该保持js纯洁性,详情可参考: 细说Angular ng-class

3、添加分类、搜索和删除功能

当我们在显示列表的时候,也许想拥有菜单分类、搜索和删除的功能,这个时候在前面的代码基础上,如何实现呢?

这里是实现之后的 index.html

<body ng-controller="demoController">
<div class="row">
 <div class="col-sm-4 col-xs-12">
 <div class="btn-group pull-left">
 <button type="button" class="btn btn-default" ng-class="{'btn-primary': !search.type}" ng-click="selectType()">全部</button>
 <button type="button" class="btn btn-default" ng-class="{'btn-primary': search.type == 1}" ng-click="selectType(1)">人物</button>
 <button type="button" class="btn btn-default" ng-class="{'btn-primary': search.type == 2}" ng-click="selectType(2)">动物</button>
 <button type="button" class="btn btn-default" ng-class="{'btn-primary': search.type == 3}" ng-click="selectType(3)">风景</button>
 </div>
 </div>
 <div class="col-sm-4 col-xs-12" style="margin: 10px 0; height: 40px">
 <input class="form-control" ng-model="search.keyword" placeholder="搜索内容"/>
 </div>
 <div class="col-sm-4 col-xs-12" style="line-height: 50px">
 搜索:{{search.keyword}}
 </div>
</div>

<div class="photos">
 <div class="photoItem" ng-repeat="info in imageList | filter:search" ng-if="!info.is_hide">
 <img ng-src="{{info.imageUrl}}" ng-style="imageStyle(info.width)"/>
 <div class="block">
 <button class="btn btn-default gap" ng-click="removePhoto(info)"><span>删除</span></button>
 </div>
 </div>
</div>
</body>

在demoApp.js文件中的demoController添加了下面一些内容:

$scope.search = {};
/**
 * 删除图片
 * @param index
 */
$scope.removePhoto = function (info) {
 info.is_hide = true;
};

/**
 * 按钮点击选择类型的事件
 * @param type
 */
$scope.selectType = function (type) {
 $scope.search.type = type;
};

这个实现之后就是我们的最终效果,当点击类型时,可以获取对应类型的图片,当输入关键字,可以搜索到相关的图片,还可以进行删除,这是怎么做到的呢?

首先,我们在左上角添加一排按钮,添加类型选择的功能,如下:

<div class="col-sm-4 col-xs-12">
 <div class="btn-group pull-left">
 <button type="button" class="btn btn-default" ng-class="{'btn-primary': !search.type}" ng-click="selectType()">全部</button>
 <button type="button" class="btn btn-default" ng-class="{'btn-primary': search.type == 1}" ng-click="selectType(1)">人物</button>
 <button type="button" class="btn btn-default" ng-class="{'btn-primary': search.type == 2}" ng-click="selectType(2)">动物</button>
 <button type="button" class="btn btn-default" ng-class="{'btn-primary': search.type == 3}" ng-click="selectType(3)">风景</button>
 </div>
</div>

对应的demoApp.js文件的内容有:

 /**
 * 按钮点击选择类型的事件
 * @param type
 */
$scope.selectType = function (type) {
 $scope.search.type = type;
};

我们在按钮上通过 ng-click
指令添加了事件监听,当点击按钮的时候,触发了 selectType
事件,随后就将 search.type
的值改变成了事件传递过来的值。

search.type
值改变之后,由于按钮中我们添加了 ng-class
指令,从而enable了当前点击按钮的 btn-primary
类,这样就实现了选中效果。

ng-class
是用来实现样式的,它有两种用法(通过函数传递就不说了):

  • 传递类名, 例如 <a ng-class="active selected" />
    ,这样a标签就相当于给了两个样式类的效果,和 <a class="active selected">
    一样
  • 通过true和false来控制,例如 <button ng-class="{'btn-primary': search.type == 1}">
    ,当search.type为1时,button就拥有了btn-primary这个类的样式;否则就不拥有。

相比与 ng-style
ng-class
它更能实现js与html代码的分离,保持js的纯洁,详情可参考: 细说Angular ng-class

当我们点击类型按钮的时候,如何显示出对应类型的图片?这用到了 ng-repeat的过滤器
,具体代码在这里:

<div class="photoItem" ng-repeat="info in imageList | filter:search">
</div>

当使用ng-repeat遍历时,如果 info
中的数据与 search
中的数据不匹配,则 ng-repeat
会忽略,不会实例化元素。

这个匹配规则默认是这样的,当 search
是一个数字或字符串时,它会匹配 info
对象所有的值,例如,search=6,那么info={id: 6, type:2}和info={id:7, type:6}都会匹配到;而当search是个对象时,它就会将对应的键值进行匹配,例如search={type:2},它只会匹配info={id: 6, type:2}的对象,而不会匹配info={id: 2, type:7}。

当然,上面是 ng-repeat
的过滤器的默认匹配规则,我们可以后面添加第三个参数,详情可以参考 filter

同样原理,我们实现搜索是通过 ng-model
filter
实现的,这里就说说 ng-model
,代码如下:

<div class="col-sm-4 col-xs-12" style="margin: 10px 0; height: 40px">
 <input class="form-control" ng-model="search.keyword" placeholder="搜索内容"/>
</div>
<div class="col-sm-4 col-xs-12" style="line-height: 50px">
 搜索:{{search.keyword}}
</div>

这段代码通过 ng-model
,我们实现了 双向绑定
,当我们输入值之后,我们可以看到界面中 搜索:
后面的内容随着我们输入变化而变化,我们不需要在js中做任何事情就可以做到这些,这是一个特别棒的特性。

最后,我们来看看是如何实现删除的?

对应的index.html中的代码:

 <div class="photoItem" ng-repeat="info in imageList | filter:search" ng-if="!info.is_hide">
 <img ng-src="{{info.imageUrl}}" ng-style="imageStyle(info.width)"/>
 <div class="block">
 <button class="btn btn-default gap" ng-click="removePhoto(info)"><span>删除</span></button>
 </div>
</div>

对应的demoApp.js中的代码:

 /**
 * 删除图片
 * @param index
 */
$scope.removePhoto = function (info) {
 info.is_hide = true;
};

操作主要是在按钮上添加一个removePhoto事件,当点击按钮的时候,将数据中的 is_hide
设置true,而在模板有 ng-if="!info.is_hide"
,当is_hide为true时,表达式为false, 从而通过 ng-if
指令实现了删除功能。

除了, ng-if
可以隐藏元素之外,还有 ng-show
ng-hide
,它们用法差不多,都是传递一个bool值进行控制。但是,它们之间是有些区别的:

  • ng-if 它实现隐藏的功能,是将元素从dom中删除,使用ng-if会创建子作用域。
  • ng-show 它实现隐藏的功能,是将元素中的display设置为none,它不会创建子作用域。
  • ng-hide 它实现隐藏的功能和ng-show一样,是设置元素样式中的display为none来实现的,它不会创建子作用域。
    到此,我们就实现了简单的图片列表应用。

三、指令补充

1、 ng-app

这个指令指定了angular中 demoApp
模块作为它的根模块。使用ng-app指令时,需要注意的是,它一般都放在页面的根元素当中,例如

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址