angularjs ng-if妙用,ng-if解决父子组件异步传值
壹 ❀ 引
angularjs开发中,组件件相互通信传值是再普遍不过的操作了,比如我在父作用域中获取了一个数据,想要传递给子组件使用,做简单的做法就是通过scope传递,比如这样:
<body ng-controller="myCtrl as vm"> <echo-demo data='vm.echo'></echo-demo> </body>
angular.module('myApp', []) .controller('myCtrl', function ($timeout) { let vm = this; vm.echo = { name: '听风是风' }; }).directive('echoDemo', function () { return { restrict: 'EA', template: '<div>{{$ctrl.name.name}}</div>', replace: true, scope: { data: '<' }, controllerAs: '$ctrl', controller: function ($scope) { let self = this; self.$onInit = function () { self.name = $scope.data; }; } } });
拷贝,正常子组件会显示 听风是风。
我们将问题升级,假设父获取的数据为异步操作,比如我们将上方代码中父控制器的变量外层添加定时器模拟异步操作,其它不变:
$timeout(() => { vm.echo = { name: '听风是风' }; }, 3000);
你会发现这样子组件就拿不到数据了,因为异步的问题,子组件初始化会先执行,此时数据为undefined。那么怎么解决呢?
贰 ❀ 解决异步通信
第一种最常见,直接不用scope传递了,改用事件通信,父什么时候拿到值,就开始派发事件,子组件内响应监听。
// 父作用域 利用定制器模拟异步请求 $timeout(() => { $scope.$broadcast('传数据啦',data); }, 3000); // 子作用域 $scope.$on('传数据啦', function (event, data) { // 拿到data了... });
有没有更简单的办法,有,给组件名上添加一个ng-if就好了,像这样:
<echo-demo data='vm.echo' ng-if="vm.echo"></echo-demo>
添加了ng-if后你会发现即便父作用域初始化数据外层有$timeout也没关系,这是因为ng-if的本意就是,当ng-if后的数据什么时候不为false才加载dom,所以这里就成了什么时候父作用域拿到数据,组件才开始渲染加载。
真的是很巧妙的借用了ng-if的特性,解决了异步传值的问题。大家如果对于angularjs事件通信有疑问可以阅读 angularjs事件通信$on,$emit,$broadcast详解 这篇文章。
那么本文结束。