angularjs通信以及postmessage与iframe通信

这篇文章是用 markdown工具写的,有需要的可以使用 vscode打开
 
# angularjs 控制器、组件之间的通信

## 一、基于事件的方式

此方式下,主要通过 angularjs 内置指令`$on`,`$emit`,`$broadcast`来实现

- $on:表示事件监听
- $emit:表示向父级以上的作用域触发事件
- $broadcast:表示向子级以下的作用域广播事件

### 1. 向下广播事件

```js
//父控制器
function father($scope) {
$scope.toChildren = function() {
$scope.$broadcast('toChildren', 'father to children');
}
}
//子控制器
function children($scope) {
$scope.$on('toChildren', function(e, data) {
console.log('父传过来的值', data);
});
}
```

### 2. 向上传播事件

```javascript
//子控制器
function children($scope) {
$scope.$emit('toFather', 'children to father');
}
//父控制器
function father($scope) {
$scope.$on('toFather', function(e, data) {
console.log('子传过来的值', data);
});
}
```

### 3. 同级作用域之间传播

一个子控制中向父作用域触发一个事件,然后在父作用域中监听事件,再广播给另一子作用域,这样通过事件携带参数,实现了数据经过父作用域,在同级作用域之间传播。

**注意:** 通过父元素作为中介进行传递,同级元素用的事件名不能一样,否则会进入死循环。

```js
//子控制器1
function children1($scope) {
$scope.toChildren2 = function() {
$scope.$emit('toChildren2', 'children1 to children2');
}
}
//父控制器
function father($scope) {
$scope.$on('toChildren2', function(e, data) {
$scope.$broadcast('toChildren', data);
});
}
//子控制器2
function children2($scope) {
$scope.$on('toChildren', function(e, data) {
console.log('children1传过来的值', data);
});
}
```

## 二、angularjs服务的方式

在 angularjs 中服务是一个单例,所以在服务中生成一个对象,该对象就可以利用依赖注入的方式在所有的控制器中共享

```js
var app = angular.module('myApp', []);
//服务
app.factory('instance', function(){
return {};
});
//控制器1
app.controller('MainCtrl', function($scope, instance) {
$scope.change = function() {
instance.name = $scope.test;
};
});
//控制器2
app.controller('sideCtrl', function($scope, instance) {
$scope.add = function() {
$scope.name = instance.name;
};
});
```

## 三、component中的bindings对象

官方并不推荐我们使用 "=" 进行数据绑定, 因为 "=" 是一种双向的数据绑定,这就意味着我们在 component 中去修改数据的时候,在它的父组件中的值也会被修改。

```js
bindings: {
hero: '<', //'<'单向数据绑定,'='双向数据绑定
comment: '@', //'@'字符串绑定,特别是在绑定的值不会更改的时候
onClick: '&' //函数,绑定的函数将作为component事件的回调函数
}
```

### 1. component与父组件数据之间的绑定

父组件

```html
<body ng-controller="MainCtrl as ctrl">
<h3>hero</h3>
<br>
<hero-detail hero='ctrl.hero'></hero-detail>
</body>
```

```js
angular.module('ComponentTestApp',[])
.controller('MainCtrl',function(){
this.hero = {
name:'Sunday'
}
});
```

子组件

```HTML
<h1>HeroName: {{$ctrl.hero.name}}</h1>
```

```javascript
angular.module('ComponentTestApp')
.component('heroDetail',{
templateUrl:'',
controller:HeroDetailController,
bindings:{
hero:'<'
}
});
```

### 2. component与父组件方法之间的绑定

父组件

```html
<body ng-controller="MainCtrl as ctrl">
<hero-detail on-log="ctrl.log(text)"></hero-detail>
</body>
```

```js
angular.module('ComponentTestApp',[])
.controller('MainCtrl',function(){
this.log = function(text){
console.log("输出的内容为: " + text);
}
});
```

子组件

```html
<input type="text" placeholder="被输出的内容" ng-model="text">
<br>
<button ng-click="onLog()">outputLog</button>
```

```js
function HeroDetailController($scope){
$scope.text = '';
var ctrl = this;
$scope.onLog = function(){
ctrl.onLog({text: $scope.text});
}
}
angular.module('ComponentTestApp')
.component('heroDetail',{
templateUrl:'',
controller:HeroDetailController,
bindings:{
onLog:'&'
}
});
```

**注意:** 在代码中我们通过 "&" 符号去绑定了一个方法 `onLog()`,该方法接收一个 `text` 参数,在参数进行传递的时候,是以 json 的形式进行传递的,这样我们在点击 `outputLog` 按钮的时候,就会输出我们在 `input` 中输入的内容。

# postMessage、iframe通信

## iframe通信

通常我们使用iframe直接在页面嵌套iframe标签指定的src就可以了

```html
<iframe name="myiframe" id="myiframe" src="external_file.html" frameborder="0" width="200" height="200" scrolling="no">
```

- name:规定 `iframe` 的名称。
- width:规定 `iframe` 的宽度。
- height:规定 `iframe` 的高度。
- src:规定在 `iframe` 中显示的文档的URL。
- frameborder:规定是否显示 `iframe` 周围的边框。 (0 为无边框,1 位有边框)。
- align:规定如何根据周围的元素来对齐 `iframe`。 (left,right,top,middle,bottom)。
- scrolling:规定是否在 `iframe` 中显示滚动条。 (yes,no,auto)

通常我们需要从URL获取相关字段,可以通过下面方法,然后做相关业务处理

```js
$scope.urlData = $location.search();
```

## postMessage通信

### 1. 父页面发送数据给子页面

```js
//获取iframe元素
iFrame = document.getElementById('myiframe')
//iframe加载完毕后再发送消息,否则子页面接收不到message
iFrame.onload = function(){
//iframe加载完立即发送一条消息
iFrame.contentWindow.postMessage('MessageFromIndex1','*');
}
```

```js
//回调函数
function receiveMessage ( event ) {
console.log( 'receiveMessage', event )
}
//监听message事件
window.addEventListener("message", receiveMessage, false);
```

- postMessage是挂载在window对象上的,所以等iframe加载完毕后,用iFrame.contentWindow获取到iframe的window对象,然后调用postMessage方法,相当于给子页面发送了一条消息
- postMessage方法第一个参数是要发送的数据,可以是任何原始类型的数据。
- postMessage方法第二个参数可以设置要发送到哪个url,如果当前子页面的url和设置的不一致,则会发送失败,我们设置为*,代表所有url都允许发送。

### 2. 子页面发送数据给父页面

```js
//给父页面发送消息,data为对象
window.parent.postMessage( {msg: 'MessageFromIframePage'}, '*');
```

```js
//回调函数
function receiveMessageFromIframePage (event) {
console.log('receiveMessageFromIframePage', event)
}
//监听message事件
window.addEventListener("message", receiveMessageFromIframePage, false);
```

转载于:https://www.cnblogs.com/wzq201607/p/angularjs_communication.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值