注:Demo源码地址:https://github.com/smk108/react-angular
React和Angular都是主流的前端框架,我参与的前端项目通常都是使用react开发,因为要在自己开发的项目中使用一个由angular开发的开源项目,因此开始尝试两大主流框架的集成。
React文档中讲到了react可以与第三方库整合,是以jQuery 和Backbone为例讲解了将其他应用添加到react 项目里。本文以一个测试demo为例介绍一下如何将angularJS集成到react 项目里。
首先,是在react的render方法中声明一个div容器,这个div容器可以简单设置一些静态的属性,但是不能设置会触发react更新这个容器的属性或子元素,这样保证react不会更新这个div容器。
render() {
return (
<div className="main">
<Timer
time={this.state.time}
firstName={this.state.firstName}
lastName={this.state.lastName}
handleNameChange={this.handleNameChange}/>
<div ng-app="app" ng-controller="myCtrl" ref={ref => this.angularDiv = ref}>
<angular-div></angular-div>
</div>
</div>
);
}
然后,编写html模板,例如:
<div>angular中显示名: <input type="text" ng-model="firstName"></div>
<div>angular中显示姓: <input type="text" ng-model="lastName"></div>
</div>angular中显示姓名: {{firstName + "." + lastName}}</div>
最后,在angular控制器中声明自定义指令angularDiv:
let appComponent = {
restrict: 'E',
template: require('./test.html'),
};
angular.module('app', [])
.directive('angularDiv',function(){
return appComponent
})
.controller('myCtrl',['$scope',function($scope){
$scope.firstName= "John";
$scope.lastName= "Doe";
$scope.update = function (attr, value) {
$scope[attr] = value;
$scope.$apply();
}
}]);
我在控制器中定义了update方法,用以在外部更新$scope中的值。
在外部获取$scope的方法为:
angular.element(this.angularDiv).scope()
更新$scope值的方式为:
angular.element(this.angularDiv).scope().update('firstName', test)
这样,就简单实现了将angular项目集成到react项目中的需求。最终demo显示效果如下:
当修改react组件中的input框内容时,angularJs中显示的内容会与之同步更新,当然,angularJs的input框可以自己修改。该demo的功能非常简单,在开发中应该根据实际需求进行开发扩展。
在集成过程中还有几个问题需要注意:
- 可以不在$scope中定义update方法,在外部获取到$scope后直接赋值,但是必须要调用$scope.$apply()才能生效;
- 控制器的定义不管是放在生命周期componentDidMount中,还是在单独js文件中定义然后通过import导入,控制器的定义都比react生命周期componentDidMount的执行有延迟。因此,如果再页面渲染完成立即使用代码获取$scope会得到undefined,提供参考的解决方法有:
- setTimeout()设置一定延时;
- 在控制器的定义代码末尾抛出一个事件,在react中监听该事件,监听到事件后再通过代码获取$scope,然后实现需要的功能;
- 循环查询控制器的定义是否完成或获取到的$scope是否已经定义,满足一定条件后再进行相关操作
这是我在测试框架集成过程中遇到的问题,如果有更友好的方式解决这个问题,还请不吝指教。