献给 Angular1 小伙伴的 react 学习教程

很幸运刚毕业到公司,领导就给我选择了前端开发这个行当,而接触的第一个框架就是Angular1,和大部分人同样,一本大漠老师的《使用AngularJS开发下一代WEB应用》带我入门,也照着写了一些代码,看书的时候也以为大部分理解了,可是一到实际项目开发彻底找不到北了,我想这也是不少人的写照。css

就本身的体会,前端开发水平能够大概分为三个层次,每个层次都是一个质的跨越,第一层是入门级的(从Angular1来看就是ng-controller党,这样更形象一点),诚然这种模式已经比当年有了极大进步,可是一样的,现在的前端复杂程度大增,这种进步只能算不拖后腿,第二层是进阶级的,组件化开发已经在心中打下烙印,这些人看到的不是页面,而是一颗组件树(说的好玄啊^ ^),对于通常的团队,我认为能达到这个水平就够用了,每一个成员打好基本功,这个团队是很不错的了。第三层,是我想象的,我认为在他们眼中都是数据,没有UI,数据就是UI,经过精妙的架构体系控制着数据的流动,同时掌控着数据在每个环节的变化。这里的角度更可能是按一个偏产品的前端开发团队来分析的,本身的视野有限欢迎你们讨论。我认为若是达到了第二层就算是脱离贫困奔小康甚至过上小资生活,对于生活(工做)遇到的困难都能比较轻松的应对。我认为一个框架的熟练度达到相似第二层是很重要的,不然盲目的追新是很难达到质的提高,因此但愿你们共勉不要盲从,至少要在团队中技术能hold住,再去想技能树更新,这才会事半功倍的。html

回到原题,因为项目演进的缘由下半年会由Angular1转为React,所以本身是从一个Angular1的开发视角来学习react,有人会问为啥要用视角来学习,为啥要对比,我本身也不知道这是否是一个好的方式,但我我的以为用一个更熟悉的视角,新知识会记得更深入,也许文中的一些对比有误,请你们指正,go~前端

开始

Angular1做为一门09年的颠覆性技术,为前端开发带来了一场革命,但因为那时候没有成熟的模块化方案,没有ES6标准的推进,致使这场革命不是那么完全。确实Angular1不够组件化,但Angular1带给其余框架的影响是巨大的,react,Vue的出现没有达到Angular1当年的颠覆,react和Vue的核心技术也都有着Angular1的影子(或者说变了形态的影子),所以这篇教程就是带你们在react上找寻Angular1熟悉的味道。react

对比哪些

固然是angular.directive和angular.component,这也是Angular1最能体现组件化特征的地方。通常来讲一个组件会对外暴露属性事件方法jquery

属性

  • angular

在angular1中属性有三种@,<,=,@表示不可修改的属性,最多见的id都会用@来表示,若是@对应的值会变化时,要加上{{}},架构

<my-comp text={{::someText}}></my-comp>复制代码

修饰符<的样子就体现了单向数据流的特征,它相似Vue中watch的形式,在$onChanges中能够watch到属性的变化,不用再本身一个一个添加$watch*之类的东东了,框架

=这个样子也很是形象,父做用域和隔离做用域的属性都指向同一个地址空间,所以隔离做用域也能够修改父做用域的属性,这每每使得问题难以定位。dom

  • react

react的属性很js,没有angular那么多修饰符或者继承、隔离这些东西,react很开放,它告诉你属性应该像@同样是不可变的,可是它就是一个js对象,你能够改变它,可是你要本身承担所可能带来的后果,那么想一想@改怎么写,react的props就该怎么用,想象一下咱们在写一个指令叫MyProps,它目前只有一个{id:'@', width: '@'}ide

angular版模块化

angular.directive('myProps', function(){
    return {
        restrict: 'E',
        scope: {
            id:'@',
            width: '@'
        },
        controller:function($scope){
            scope.width = scope.width || 200
        },
        template: `<button id='{{::id}}' width='{{::width}}'></button>`
    }
})复制代码

react版

class MyProps extends React.Component {
  render() {
    return (
      <button id={this.props.id} style={{ width: this.props.width + 'px' }}> idButton </button>
    )
  }
}
MyProps.defaultProps = { width: 200 }复制代码

react很js很class吧,其实思路是否是很类似,this.props就和scope同样,只不过react经过jsx实现了表达式计算。

事件

  • angular

在angular里事件通常用&来修饰,若是你但愿对响应参数作定制也可使用=

angular版

angular.directive('myProps', function(){
    return {
        restrict: 'E',
        scope: {
            id:'@',
            width: '@',
            click: '&'
        },
        controller:function($scope){
            scope.width = scope.width || 200
        },
        template: `<button id='{{::id}}' width='{{::width}}' ng-click='click()'></button>`
    }
})复制代码

react版

class MyButton extends React.Component {
  render() {
    return (
      <div> <div id={this.props.id + '_btn'} style={{ width: this.props.w + 'px', height: this.props.h + 'px', backgroundColor: this.props.bgColor }} onClick={this.props.click}>clickMe</div> </div>
    )
  }
}

class MyEvent extends React.Component {
  constructor(props) {
    super(props)
  }
  clickHandler() {
    console.log('My Button Clicked')
  }
  render() {
    return (
      <MyButton id="event" click={this.clickHandler.bind(this)} w="200" h="40" bgColor="green" /> ) } } ReactDOM.render( <MyEvent />, document.getElementById('root'))复制代码

你也能够对响应参数作定制,就像angular中把事件修饰&变为=那样,这里就不上angular的了

react版本

class MyButton extends React.Component {
  constructor(props) {
    super(props)
  }
  clickHandler() {
    this.props.click(this.props.bgColor)
  }
  render() {
    return (
      <div> <div id={this.props.id + '_btn'} style={{ width: this.props.w + 'px', height: this.props.h + 'px', backgroundColor: this.props.bgColor }} onClick={this.clickHandler.bind(this)}>clickMe</div> </div>
    )
  }
}

class MyEvent extends React.Component {
  constructor(props) {
    super(props)
  }
  clickHandler(color) {
    console.log('My Button color: ' + color)
  }
  render() {
    return (
      <MyButton id="event" click={this.clickHandler.bind(this)} w="200" h="40" bgColor="green" /> ) } } ReactDOM.render( <MyEvent />, document.getElementById('root'))复制代码

方法

其实方法并非angular所包含的一个概念,angular提倡数据状态影响UI的理念,除了angular提供的一些ng-内置指令,咱们要写一大堆双向绑定属性(伴随着一大堆$watch),性能堪忧,更重要的是你会发现定位问题很难(脏数据校验)。所以在咱们项目除了disable、display之类会使用<,界面变动都采用方法,将指令的UI变动方法绑定到$scope.$parent上,这样父指令就能够经过这些方法来操做子指令的UI变动了。

angular版

angular.module('myApp',[]);  
myApp.controller('listCtrl',function($scope){    var display = false
   $scope.showOrHide=function(){  
      $scope.btn.setDisplay(display?'block':'none')
     display =!display
   };  
});  

myApp.directive('kid',function(){  
    return {  
        'restrict':'E',  
        scope:{id: '@'},
        template:'<div><button>click</button></div>',
        link: function(scope, elem) {
        scope.$parent[scope.id] = {
           setDisplay: function(display){
             elem.css('display', display)
           }
         }
      }
    }  
});复制代码

按照这个思路咱们在react上也试试。

class MyButton extends React.Component {
  constructor(props) {
    super(props)
  }
  setDisplay(display) {
    this.refs.myButton_ref.style.display = display
  }
  render() {
    return (
      <div ref="myButton_ref"> <div id={this.props.id + '_btn'} style={{ width: this.props.w + 'px', height: this.props.h + 'px', backgroundColor: this.props.bgColor }}>clickMe</div> </div>
    )
  }
}

class MyEvent extends React.Component {
  constructor(props) {
    super(props)
    this.display = false
  }
  showOrHide() {
    this.child.setDisplay(this.display ? 'block' : 'none')
    this.display = !this.display
  }
  render() {
    return (
      <div> <MyButton id="event" w="200" h="40" bgColor="green" ref={(instance) => { this.child = instance }} /> <button onClick={this.showOrHide.bind(this)}>showOrHide</button> </div> ) } }复制代码

代码中ref="myButton_ref"很是别扭,由于直接对dom的操做让咱们感受回到了jquery时代,所以这里咱们应该使用一直未提到的state,那state像angular的什么呢,和指令中的controller很像,你能够在controller里对$scope里增长新的属性(这里也包含了父指令传进来的属性),所以angular里的$scope包含了react中的props和state,react把它分开会让使用者更加清楚,让使用者知道props是不能变的,state才是可变的。所以咱们把代码中的MyButton稍做修改。

class MyButton extends React.Component {
  constructor(props) {
    super(props)
    this.state = { display: 'block' } // 初始值
  }
  setDisplay(display) {
    this.setState({ display })
  }
  render() {
    return (
      <div style={{ display: this.state.display }}> <div id={this.props.id + '_btn'} style={{ width: this.props.w + 'px', height: this.props.h + 'px', backgroundColor: this.props.bgColor }}>clickMe</div> </div>
    )
  }
}复制代码

最后

这篇教程主要从本身这个Angular1使用者的的视角来看react,我以为对于Angular开发人员来讲是一个不错的学习react的思路,本人也是刚刚接触react,文中若有错误也请及时指正。下一篇将对Angular1指令的生命周期和react组件生命周期作以对比,谢谢你们。

相关文章
相关标签/搜索