# angularjs
**Repository Path**: tHero/angularjs
## Basic Information
- **Project Name**: angularjs
- **Description**: 学习angularjs内容
- **Primary Language**: JavaScript
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2016-05-23
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
### angualr js 视频学习内容
#### dot 的重要
代码示例:
> 在`html`页面中,定义了3个输入框,每一个输入框对应这个一个输出;
index.html
```html
```
javascript内容
```javascript
function FirstCtrl($scope) {
}
function SecondCtrl($scope){
}
```

代码总结
---
* 在上述的`HTML`页面中,使用了`ng-model`用来映射对象,名称都一致;通过运行代码可以发现,修改任意的
input内容页面的值都会随着更改,由此可知,`使用data.messsage定义的模型,他们的作用域是相同的`
进阶
---
> 现在我们将上面的`html`代码修改一下,不在使用`data.message`的方式,将所有的`data.message`修改
为message,那么在执行命令
```html
{{message}}
{{message}}
{{message}}
```

代码总结
---
* 当`FirstCtrl`和`SecondCtrl`的值没有输入时,仅输入第一个表单`input`内容,下面2个输入框将会随着
第一个表单的值变化而变化
* 当`FirstCtrl`和`SecondCtrl`的值开始输入时,对应的`h1`的内容将会改变,但是在修改input表单1时,
下面的两个表单将不会随着改变;
总结:
> 在同一个`ng-app`中`message`是个全局变量,在`controller`没有该属性的时候,会向上查找,
`message`属于全局变量,将会查找到该对象;同一个`controller`定义的属性只能被对应的controller引用,
其他`controller`不能相互访问
* 当`Firstctrl`与`SecondCtrl`对应的`model`被实例化后(即:`message`),就成为了他们私有的属性外界将
不允许被访问
### angularjs 两个controller如何传递参数
在两个controller中如何进行参数的传递?一般通过注册服务,通过服务对象,来存储数据代码示例:
> `html` 定义两个`controler`用于调用在`js`中定义的`controller`
```html
```
> controller 传递参数问题
```
var myApp = angular.module('myApp',[]);
myApp.factory('userData',[function () {
var data = {
userame:'123'
}
return data;
}]);
myApp.controller('FirstCtrl',['userData','$scope',function(userData,$scope){
userData = {
username:'23'
}
console.log("First输出内容");
console.log(userData);
}]);
myApp.controller('SecCtrl',['userData',function (userData) {
console.log("SecCtrl 输出内容");
console.log(userData);
}]);
```
**代码说明**
```
myApp.factory('userData',[function () {
var data = {
userame:'123'
}
return data;
}]);
```
注册一个服务,`userData`表示定义对象的名称,通过该对象可以在各个controller之间进行传递参数,通过该对象,其他controller
也可以修改该值,格式如下;
`app.factory('对象名称',[function(){
//代码内容
}]);`定义这样的对象时需要有返回值;即含有`return`语句
controller 如何引用定义的对象,通过注入的方式来完成,在下方通过`['userData',function(userData){}]`来完成对象的
注入,在`contoller`中是可以修改`userData`中的值的,但是仅对该作用域有效;
```
myApp.controller('SecCtrl',['userData',function (userData) {
console.log("SecCtrl 输出内容");
console.log(userData);
}]);
```

**?如何修改定义`factory`定义的全局变量**
遗留
### 在`controller`中定义`functon`
通过$scope来绑定参数,在{{}}中定义方法,并传递`message`的对象,controller便可以进行修改内容
```html
{{reversedMessage(message)}}
```
也没传递的参数可以直接通过$scope.message来获得,需要注意的时候,使用split方法时需要将该对象进行初始化
```javascript
myApp.controller('ThrCtrl',['$scope',function ($scope) {
$scope.message = "";
$scope.reversedMessage = function (message) {
return $scope.message.split("").reverse().join("");
}
}]);
```

从上述图中可以看出随着字符的输入,输出部分会逆向输出内容
### 通过`filter`来控制字符串的倒序输出
`filter`的是使用方法:通过调用`{{message|filter方法名称}}`来完成字符串的倒序输出,需要注意的是,filter调用的方法
名称是不需要传递参数,同时也不需要含有`()`
```html
{{message|revers}}
```
`filter`定义的方法`app.filter('方法名称',function)` 调用该方法必须含有相应的返回值,一次来达到页面的输出
```javascript
//定义filter
myApp.filter('revers',function(){
return function(text){
return text.split("").reverse().join("");
}
})
```
运行方式

需求,通过在表单输入input内容来过滤表格中的值;
`ng-model`定义要过滤的对象,在`filter`中来过滤要输入的内容
* 如果`ng-model`定义要查询的对象`A`(search),那么`filter`中定义的A对象与`ng-model`一致(search),那么表格中的内容将会全部进行过滤(name和character)
* 如果`ng-model`定义要查询的内容`A.a` (search.name),那么`filter`过滤时只会过滤出`a`中字段(names);
* 如果`ng-model`定义要查询的内容`A.$`,那么`filter`过滤时将会过滤所有内容
### filter 内容
```html
```
定义`javascript`的时候需要注意,想在也没使用`controller`定义的对象,需要在`controller`定义
```javascript
var myApp = angular.module('myApp',[]);
myApp.factory('avenger',function () {
var avengers = {};
avengers.cast = [{
name:'Robert Down',
character:'Tony Task'
},{
name:'chris',
character:'stevent'
},{
name:'mark Down',
character:'Bruce Task'
},{
name:'Scaret',
character:'Natsa'
},{
name:'Robert Down',
character:'Tony Task'
}]
return avengers;
})
myApp.controller('avenger',['avenger','$scope',function (avenger,$scope) {
$scope.avengers = avenger;
}]);
```

### `scope`相关问题
注意几个问题;
* 1、 `angularjs` 提供了`ng-click`来对`dom`元素添加绑定事件;
* 2、 `ng-click` 是可以直接调用定义在`controller`中的函数的;可以传递参数;
也可以传递`model`对象;
* 3、 绑定到`input`表单上的`model`对象是个字符串;不能够直接进行加减;在计算时
会当成字符串进行拼接输出;
```
例如:
并在:加法
controller: $scop.counter += amount;
计算结果:{{counter}}
流程: input 输入1 计算结果输出的为01;
```
* 4、 在`contoller`中可以定义属性;譬如 `$scope.counter = 0` ;
同时可以定义函数,譬如:
```
$scope.add = function(amount){
$scope.counter += amount;
}
有意思的是,在html中,不用添加$scope就可以访问到属性已经方法;
```
* 5、`javascript` 在操作的时候可以使用对象的方式来创建对象;并在`html`页面中
显示
```html
//在controller中定义一个对象
$scope.person = {
name:"thero",
age :12
}
//再页面直接使用对象【.】属性的方式,就可以展示用户的信息了
用户姓名{{person.name}}
用户年龄{{person.age}}
```
### `scope`的继承关系
> `scope`中的继承关系有些类似与dom层级;子集可以继承来自父类定义的属性和对象;
例如:
app.js
```javascript
var app = angular.module('myApp',[]);
app.controller('parentController',function ($scope) {
$scope.person = {
name :''
}
$scope.person.name = "chen";
});
app.controller('childController', function ($scope) {
console.log($scope.person.name);
$scope.person.name="thero";
});
```
extends.html
```html
{{name}}
父级对象内容{{person.name}}
子级对象内容{{person.name}}
```
注意事项
====
* 在controller定义的对象,需要先声明后使用;下面的代码中,如果不定义`$scope.person`
对象,而是直接使用` $scope.person.name`时,是无法直接使用的,会报出下面的错误
;
先定义后使用的原则
```javascript
app.controller('parentController',function ($scope) {
$scope.person = {
name :''
}
$scope.person.name = "chen";
});
```
当时由于集成的关系,在下面的代码中,没有定义name属性,却可以直接使用,这就集成的关系
```javascript
app.controller('childController', function ($scope) {
console.log($scope.person.name);
$scope.person.name="thero";
});
```
* 如果在`dom`层级中,不存在这种父基本的关系,`$scope`是否还有集成关系呢?
```html
{{name}}
父级对象内容{{person.name}}
子级对象内容{{person.name}}
```
上述的代码中,我们打破了层级关系,js代码不变;在访问页面的时候,`{{person.name}}`
该属性已经不存在了;由此我们可以发现,`controller`中属性的继承关系来源于`dom`层;
控制器的使用规范
====
* 1、在`controller`中尽量不要对`dom`进行操作;
* 2、可以将复杂的逻辑放到指令和服务中;
### `expression`表达式处理
可以利用一个示例来完成表达式的处理
```html
{{parseValue}}
```
expressoin.js
```javascript
var app = angular.module('myApp',[]);
app.controller('MyController',function ($scope,$parse) {
$scope.$watch('expr',function (newVal,oldVal,scope) {
if(newVal!=oldVal){
var parseFun = $parse(newVal);
$scope.parseValue = parseFun(scope);
}
});
});
```
代码解释
---
* 当我们在页面的表单中输入任何值的时候,下面的h2标签会对应显示值,如下图
;
* 和其他不同`expression`是,在表单`model`定义的`expr`名称 ,在表达式中`{{}}`我们
绑定了另一个值`parseValue`我们通过下面的代码,将`expr`和`parseValue`进行了关联起
来,来动态修改绑定的值;
* 如果angularjs没能加载完所有的页面,在页面显示时将会出现`{{}}`字符串,我们可以使用
`
` `name`为`anguarjs`定义的`ng-model`内容
```javascript
var app = angular.module('myApp',[]);
app.controller('MyController',function ($scope,$parse) {
$scope.$watch('expr',function (newVal,oldVal,scope) {
if(newVal!=oldVal){
var parseFun = $parse(newVal);
$scope.parseValue = parseFun(scope);
}
});
});
```
* 在`js`的文件中,可以通过`$watch`方法来监控`expr(model)`值的变化;该方法需要传递
2个参数,`model`对象以及回调函数,回调函数提供了3个参数(`newVal`,`oldVla`,scope);
* `newVal` 修改`model`后的值,
* `oldVal` 历史数值;
* `scope` 上下文对象;
* 在该`js`文件中定义的`$scope`与回调函数的scope是同一个对象;如下图
* `$parse` `angularjs`方法,用于格式化数据等;如下图;
* `app.controller('MyController',function ($scope,$parse){} `左侧的代码中,提供了
2个参数,angularjs会自动注入这些参数;
### filter 过滤器
angularjs提供2中过滤的方式。可以退数字进行格式化,大小转小写;对数进行排序
* 使用`expression`来过滤数据,格式为`{{|}}` 其中`|` 左侧为值,右侧为表达式;
* 使用`$filter`对象来进行过滤数据;
各类过滤器
----
1. `currency` 货币转换`50.035`,使用`{{50.035|currency:"RMB"}}`的形式就可以转换了
```html
currency 货币转换
53.035
{{50.035|currency:"RMB"}}
```
在下面的运行结果我们可以发现,不仅将货币进行了转换,同时还进行了四舍五入;进行了数字的格式化

> 格式 {{数值|currency:'货币格式'}}
2. `date`日期格式化,这里只展示常用的日期格式化;
```html
date 日期转换
{{today}}
{{today|date:'yyyy'}} 或
{{today|date:'MM'}} 或
{{today|date:'dd'}}
{{today|date:'HH'}}
{{today|date:'mm'}}
{{today|date:'ss'}}
{{today|date:'yyyy-MM-dd HH:mm:ss'}}
```

其中
* 'yyyy' 年
* 'MM' 月
* 'dd' 日
* 'HH' 小时
* 'mm' 分钟
* 'ss' 秒
* 'yyyy-MM-dd HH:mm:ss' 时间格式
> 格式:{{date|date:'时间格式'}}
3. `数组格式化`
```html
数组内容:['a','lerner','to','eat','pizza']
按照含有e的字符串进行过滤
{{['a','lerner','to','eat','pizza']| filter:'e'}}
```
> 格式:{{数组|filter:要过滤的字符串}}
4. 对对象的过滤
```html
[{
'name':'Ari',
'city':'san Francisco',
'favorite food':'pizza'
},{
'name':'Nate',
'city':'san Francisco',
'favorite food':'india food'
}]
可以对对象进行过滤
{{
[{
'name':'Ari',
'city':'san Francisco',
'favorite food':'pizza'
},{
'name':'Nate',
'city':'san Francisco',
'favorite food':'india food'
}]
| filter:{'favorite food':'pizza'}
}}
```

> 格式:{{对象数组|filter:对象}}
5. 自定义数组过滤
```html
--
['a','A','b']
可以对对象进行过滤
{{
['a','A','b']
| isCapitalized
}}
```
```javascript
app.filter('isCapitalized',function () {
return function (str) {
var filterArray = new Array();
for(var i=0;i 格式:{{要过滤内容|方法名称}}
**`注意:`**在自定义的方法中,不需要添加filter:也不用在方法后面添加括号
自定义filter的方式:
```javascript
var app = angular.module('myApp',[]);
app.filter('方法名称',function(){
return function(XXX){
return XXX;
}
});
```
xxx就是`要过滤内容`,如果是数组需要添加遍历来完成操作;最终要有返回值
6. `json` 格式化转换
```html
{{ {name:"chen"} | json }}
```
> 格式{{ 对象或json | json }}
7. `limitto ` 截取数据
```html
{{ 'San francisco is very cloudy' | limitTo:3}}
{{ 'San francisco is very cloudy' | limitTo:-6}}
{{ ['a','b','c'] | limitTo:1 }}
```
> 格式{{ 对象或数组 | limitTo:3 }}
8. `orderby` 过滤内容
```html
{{
[{
"name":"Ari",
"status":"awake"
},{
"name":"Q",
"status":"sleeping"
},{
"name":"Nate",
"status":"awake"
}] |orderBy:'name':true
}}
```
> 格式:{{数组|orderBy:属性:boolean}}
属性,要排序的对象中的一个属性,boolean倒序还是正序
9. `lowercase`转小写
```html
{{ 'aAc' | lowercase}}
```
> 格式:{{字符串|lowercase}}
10. 数字转换
```html
{{ 123456 | number}}
{{ 123456 | number:2}}
```
> 格式 {{数字|number:2}} 当有数字的时候表示保留的个数
### directive 指令
```html
```
```javascript
var myApp = angular.module("myApp",[]);
//E 表示dom元素
myApp.directive("superMane",function(){
return {
restrict:'E',
template:'Here I am to save day
'
}
});
//A表示属性 ,注意在定义指令的时候是有大小写区分的,但是在html中没有大小写区分了
//定义时保持都为小写即可
myApp.directive("superalert",function () {
return {
restrict:'A',
link:function(){
alert("hello wolrd by directive");
}
}
});
myApp.directive('superclass',function () {
return {
restrict:'EC',
template:'myclass'
}
});
```

> 注意:
* A 处定义的名称中,如果含有大写字符,那么在html需要在大写字符前添加“-”即(`superMan`)--> ``
* B 处,表示该指令可以存在的地方,只表示该元素可以可以出现的位置
* `E`表示`dom`元素
* `A`表示属性位置
* `C`表示`class`位置
* `M`表示注释位置
* C 处表示dom元素的内容,可以为函数,也可以直接为link:function
### `directive`通过指令来修改class内容
`html`定义了2个属性,`enter`和`leave`属性,在js文件中定义相关的指令,通过指令的方式来添加绑定事件,当
鼠标`over`在点我的div上时,控制台将会输出`I'am in side`;离开时控制台输出`I'am leave`

```html
点我
```
`javascript`代码示例,下面的代码中我们定义了`enter`和`leave`两个指令,通过这两个指令,来绑定鼠标事件;
```javascript
myApp.directive('enter',function () {
return function (scope,element,attrs) {
console.log(scope);
console.log(element);
console.log(attrs);
element.bind("mouseenter",function () {
console.log("I'am in side ");
element.addClass("myclass");
});
}
});
myApp.directive("leave",function () {
return function(scope,element,attrs){
element.bind("mouseleave",function () {
console.log("I'am leave");
element.removeClass(attrs.enter);
});
}
});
myApp.directive("leave",function () {
return function(scope,element,attrs){
element.bind("mouseleave",function () {
console.log("I'am leave");
element.removeClass(attrs.leave);
});
}
});
```
在`return function`中有3个参数
* scope作用域对象;**指令中返回的scope与全局的区别,当指令中定义了scope{}时,scope和$scope将不在是同一个对象**
* 在指令中定义的`function(scope,element,attrs)` 这三个参数他们的重要,有占位符的概念,即对象和定义的名称无关;如果scope和element
的位置互换,为`function(element,scope,attrs)`在控制台输出时可以发现element为scope对象,由此可知对象与顺序有关,与定义的名称无关,如下图所示
;
* 上述代码中`controller`定义的`$scope`很重要,如下图:

如果该对象的名称被修改了,那么将会出现错误,如下图,这里注入的对象与顺序无关,但与名称有关:

但是我们可以通过另外一种方式来解决`$scope`名称注入错误的问题,如图,通过使用[]的方式就可以解决掉该问题

此时我们发现a和b的顺序将会影响到注入对象,如下图

在将A、B对应的别名修改后,发现他们与顺序发生着密切的关系
* elementdom元素对象
* attrs对象属性内容;我们可以在控制台进行输出这3个对象,以此来查看内容

通过控制台输出的内容,我们发现attrs是一个对象,其中有`enter`和`leave`两个属性,我们可以通过
`attrs.enter` 或者`attrs.leave`来获取定义在div中的属性内容
### 使用指令调用controller方法
如果想在指令中调用controller的方法,**该指令也需要在controller的作用域中,否则无法调用到该指令**
```html
```
与console和修改div颜色的指令写法类似,不同的是,在调用方法的地方,有3中形式可以调用;
* `scope.functionName` `scope`.方法名称;该方法不推荐使用,我们不能很容易的知道在该作用域中,是否有该方法;
* `scope.$apply("methodName")` `methodName`方法名称 注意的是,这里要填写的是字符串;在`html`页面中也需要加
如指令="方法名称"
* `scope.$apply(attrs.directive);` `attrs`表示属性对象;`directiveName` 指令名称
```javascript
myApp.directive('enterMessage',function () {
return function (scope,element,attrs) {
element.bind("mouseenter",function () {
console.log("123456");
scope.$apply(attrs.enterMessage);//scope.$apply("enterMessage()");
})
}
});
```
### `directive` 中`templateUrl`使用方法
在上的指令中我们将div的信息都写了`template`中,这样识别度太低,我们可以使用`templateUrl`来完成
```html
The content is {{content}}
```
```javascript
var myApp = angular.module("myApp",[]);
myApp.directive("zippy",function () {
return{
restrict:'E',
transclude:true,
scope:{
title:'@'
},
templateUrl:'zippy.html',
link:function (scope,element,attrs) {
scope.isContentVisible = false;
scope.toggleContent = function () {
scope.isContentVisible = !scope.isContentVisible;
};
}
}
});
```
代码说明:
====
使用`templateUrl`可以将模板定义到指定的`html`文件中,如果不想创建新的`html`模块,可以在上面的`html`代码片段中加上
```html
```
注意的问题:
* `template`更改为`templateUrl`;
* 在`html`页面中需要定义`script`标签,该标签需要在`html` `ng-app`的作用域范围内;定义的`scripe`的`type`为`text/ng-template`
* 也可以直接创建该文件,只需将dom内容添加到html页面中即可
**注意**
* 模板信息的内容是被添加到缓存中的,可以通过下面的代码来获取缓存内容
`templateUrl:$templateCache.get('zippy.html')`,`$templateCache`需要定义在指令的function中,如下图:
;
### `directive`之间的交互
>指令之间的交互内容
```html
superMan
superman2
```

* A处定义的指令名称,将会在其他指令中通过`require`的方式进行调用
* C处调用在`superhero`中定义的`controler` 即`指令名称+ctrl`来作为对象进行注入
* D通过C定义的`controller`来调用在`superhero`中定义的方法;
* B注意这里的`scope`,如果该处没用定义,那么他们的作用域都来自于父类的`scope`,如果定义了,他们讲拥有各自的作用域如下图
> 定义了`scope`对象后输出内容

> 未定义`scope`对象后输出的内容,只想`superman`和`superman2`在控制台输出的内容一致;表明他们拥有相同的作用域

> 在指令中定义一个`controller`该方法中可以定义函数;在其他的指令中,可以注入`superhero`+Ctrl
```javascript
myApp.directive('superhero',function () {
return {
restrict: 'E',
scope:{},
controller:function ($scope) {
$scope.abilities = [];
this.addStrength = function () {
$scope.abilities.push("addStrength");
};
this.addSpeed =function () {
$scope.abilities.push("speed");
}
this.addFlight = function () {
$scope.abilities.push("addFlight");
}
},
link: function (scope, element) {
element.addClass("button");
element.bind("mouseenter",function () {
console.log(scope.abilities);
});
}
};
});
myApp.directive("strength",function () {
return {
require: "superhero",
link:function (scope,element,attrs,superHeroCtrl) {
superHeroCtrl.addStrength();
console.log(superHeroCtrl.abilities);
}
};
});
myApp.directive("speed",function () {
return {
require: "superhero",
link:function (scope,element,attrs,superHeroCtrl) {
superHeroCtrl.addSpeed();
console.log(superHeroCtrl.abilities);
}
};
});
myApp.directive("flight",function () {
return {
require: "superhero",
link:function (scope,element,attrs,superHeroCtrl) {
superHeroCtrl.addFlight();
console.log(superHeroCtrl.abilities);
}
};
});
```
### scope中作用域内容
`@`
这是一个单项绑定的前缀标识符
使用方法:在元素中使用属性,好比这样`
`,注意,
属性的名字要用-将两个单词连接,因为是数据的单项绑定所以要通过使用{{}}来绑定数据。
> 如果在`return`当中没用使用`scope`的时候,如果想获得定义在`dom`中的属性内容,则需要下面的方式进行获取
```javascipt
myApp.directive("eat",function(){
return {
template:"{{love}}
",
link:function(scope,element,attrs){
scope.love = attrs.love;
}
}
});
```
通过调用`link`当中提供的`scope`方法来获取内容
```html
```
使用`@`的符号,可以来解决复杂的参数绑定内容
```javascript
myApp.directive("drink",function () {
return {
scope:{
flavor:"@"
},
template:'{{flavor}}
'
}
});
```
通过@符号,我们可以很轻松的获取到定义在`dom`中的值
```html
```
`=`
这是一个双向数据绑定前缀标识符
使用方法:在元素中使用属性,好比这样``,注意,数据的双向绑定要通过=前缀标识符实现,
所以不可以使用`{{}}`。
代码示例
===
```html
```
在指令中的socpe定义未`=`时,同事在dom层添加的内容为`flavor="{{ctrlFlavor }}"`,此时控制将会抛出
`angularjs.js:9503 Error: [$parse:syntax] Syntax Error: Token 'ctrlFlavor' is unexpected, expecting [:] at column 3 of the expression [{{ctrlFlavor }}] starting at [ctrlFlavor }}].`

**解决方式**
将dom层中内容为`flavor="{{ctrlFlavor }}"`更改为`flavor="ctrlFlavor"`
```javascript
var myApp = angular.module('drinkApp',[]);
myApp.controller("AppCtrl",['$scope',function ($scope) {
$scope.ctrlFlavor = "blackBerry";
}]);
myApp.directive("drink",function () {
return {
scope:{
flavor:"="
},
template:'{{flavor}}
'
}
});
```
`&`
这是一个绑定函数方法的前缀标识符
使用方法:在元素中使用属性,好比这样``,注意,属性的名字要用-将多个个单词连接。
> `&`通过该方法可以获取到定义在`controller`中的方法

代码说明:
====
* `A` 在controller中定义一个`method`
* `B` 在指令的作用域中使用&方法来表示代替一个方法,其中定义的done属性,提供`template(C处)`使用,类似于指针的概念;
* `C` 定义`ng-click`方法,来绑定定义在`scope`作用域中的方法,注意的是在`html`页面中仍然要使用定义在`controller`
定义的函数;`done`只是用来做指令和`controller`的桥梁
### `transclusion`的使用
```html
这是个面板
```
```javascript
var myApp = angular.module("myApp",[]);
myApp.directive("eat",function () {
return{
restrict:'E',
template:'hello World
'
}
});
```
上述的代码中,定义了eat个指令,刷新html页面后,可以发现,在原来定义的html被替换调用,如果不想将
原来已经存在的html页面替换掉,可以使用`transclusion`属性
```javascript
var myApp = angular.module("myApp",[]);
myApp.directive("eat",function () {
return{
restrict:'ECA',
transclusion:true,
template:'hello World
'
}
});
```
`**注意**`
> 该配置只用当dom元素定义在指令元素之间时才会起到作用;
> 如果上述条件没有满足,那么将会报错,内容为:
`angularjs.js:9503 Error: [ngTransclude:orphan] Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element: `
[translusion参考资料](http://www.ngnice.com/posts/28116df4d6f938)
### 另外一种方式来定义`controller`
```html
```
```javascript
var app = angular.module('myApp',[]);
var phoneAppStuff = {}
phoneAppStuff.controllers= {};
phoneAppStuff.controllers.AppCtrl = function ($scope) {
this.sayHi = function () {
alert("Hi");
}
return $scope.Appctrl = this;
}
phoneAppStuff.directivies = {};
phoneAppStuff.directivies.panel = function () {
return {
restrict:'E'
}
}
app.directive(phoneAppStuff.directivies);
app.controller(phoneAppStuff.controllers);
```
除了传统的方法来定义`controller`,我们还可以通过上面的代码,来完成对`controller`和`directive`来定义,
在` return $scope.Appctrl = this;`需要 注意的是,这里定义的`Appctrl`才是在`controller`定义使用的关键,
他影响了了`ng-click="Appctrl.sayHi()" ` 中定义的`Appctrl`的使用,这里是受影响大小写的;
> 步骤与方法
1. `phoneAppStuff.controllers= {};`先声明一个变量;
2. 为该变量添加一个属性
```javascript
phoneAppStuff.controllers.AppCtrl = function ($scope) {
this.sayHi = function () {
alert("Hi");
}
return $scope.Appctrl = this;
}
```
3. 与`angularjs`进行关联,这里注意的是,进行关联的是声明的变量即在第一步定义的`controller`
```javascript
app.controller(phoneAppStuff.controllers);
```
### 指令replace属性
> 该属性的作用,为true将会替换自定义标签的内容,且不在dom渲染该标签;
```html
```
在下面的代码中我们讲replace:true 注释掉了,默认情况下为false,在浏览器渲染dom的时候会发现该指令
也作为了一个元素节点添加的html中了,
```javascript
var app = angular.module("myApp",[]);
app.directive("dumbPassword",function () {
return{
restrict:'E',
//replace:true,
template:'this is dumpPassword
'
}
});
```
`定义replace:true`时,含有指令内容

`定义replace:false`时指令的内容被删除了

### 点击`div`折叠内容 `ng-show`控制页面显示与隐藏
定义两个div,用户输入的时候,在下方显示出来;当点击第一个第一个div时,第二个div显示出来
```html
The content is {{content}}
```
```javascript
var myApp = angular.module("myApp",[]);
myApp.directive("zippy",function () {
return{
restrict:'E',
transclude:true,
scope:{
title:'@'
},
template:'',
link:function (scope,element,attrs) {
scope.isContentVisible = false;
scope.toggleContent = function () {
scope.isContentVisible = !scope.isContentVisible;
};
}
}
});
```

代码说明
---
* 上述代码中,我们定义了`isContentVisible`该属性可以用来控制点击第一个div时,第二个div显示与隐藏;
* `ng-show`指令,用来控制`dom`的隐藏与显示
### `angularjs` `watch`监听`ng-model`
`watch`方法可以用来监听ng-model输入的值,如果我们讲ng-model定义到
input表单中,我们可以发现当我们更改值时该值function都会被调用;
下面我们设计一个情况,用户在表单输入内容,当输入的内容等于password时
我们修改输入的内容,将字体的背景更改为红色
```html
```
```javascript
var app = angular.module("myApp",[]);
app.directive("dumbPassword",function () {
return{
restrict:'E',
replace:true,
template:'',
link:function (scope,element,attrs) {
console.log("哈哈")
//通过输出element内容我们可以知道页面这里的节点元素 指的是div template的整个内容
console.log(element);
//设置当前输出文本中的内容
scope.$watch("model.input",function (value) {
if(value=="password"){
console.log(element);
element.find("div").toggleClass("alert");
}else{
element.find("div").toggleClass();
}
});
}
}
});
```
代码解释
===

* A处输出的element元素,这个元素在link function含有的参数;通过控制台的输出,我们可以观察到A与B输出的element对象
是相同的,如下图

* C处,angular提供的wacth方法可以用来监控model当中的值,在上述的案例中我们可以得知,当用户修改了表单中的值时
$watch方法 都可以实时监控到内容
* 
#### 使用compile 来处理动态的元素内容
在上述的案例中我们使用了link提供的element参数来修改input表单中的值,我们还可以使用compile来,完成上的代码
```javascipt
app.directive("dumbspassword",function () {
var validElment = angular.element("{{model.input}}
");
this.link = function(scope,element,attrs){
scope.$watch("model.input",function (value) {
if(value=="password"){
element.find("div").toggleClass("alert");
}
});
}
return {
restrict:'E',
repalce:true,
template:' \n \n
',
compile:function (tElem) {
tElem.append(validElment);
return link;
}
}
});
```
[1]: ./images/1471683881029.jpg "1471683881029.jpg"