獻給 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組件生命週期作以對比,謝謝你們。

相關文章
相關標籤/搜索