React vs Angular 2:誰才是最強(qiáng)王者

【原譯】:https://tech.evojam.com/2024/03/31/react-vs-angular2-the-fight-rages-on/

??google的Angular和Facebook的React是現(xiàn)在最流行(但不是只有兩個(gè))的瀏覽器端應(yīng)用開發(fā)工具,它們都是很優(yōu)秀的解決方案。愛掏網(wǎng) - it200.com然而angular 2仍然在beta版中,Google的一部分工程師已經(jīng)對它進(jìn)行測試了。愛掏網(wǎng) - it200.com使用react開發(fā)的應(yīng)用也很多,像instagram,netlfix,paypal等。愛掏網(wǎng) - it200.com

?殘忍的戰(zhàn)爭就要到來了。愛掏網(wǎng) - it200.com

第一滴血

已經(jīng)有一篇”血腥“的文章《Angular 2 versus React》(作者:Cory House)來比較angular2與react,它體現(xiàn)了兩者很多方面的亮點(diǎn),第一次對決已經(jīng)結(jié)束,但是大戰(zhàn)才剛剛開始。愛掏網(wǎng) - it200.com(譯者注:老外寫個(gè)文章真的一定要這么夸張嗎?哈哈~)

認(rèn)清你的對手

作為開發(fā)者,選擇angular還是react就像購買現(xiàn)成的電腦還是用現(xiàn)成的零件來組裝電腦一樣。愛掏網(wǎng) - it200.com

Cory House告訴我們:

angular 2 React
壓縮后764K 壓縮后151k
獨(dú)立的完整解決方案 簡單的視圖庫
很多angular特定的語法 javascript語法
很好的一致性(和typescript) 基本語法有點(diǎn)混淆
使用html和js jsx語法
綜合成熟穩(wěn)定的框架 發(fā)展迅速的開源庫
手動(dòng)debug,缺少完全的支持 jsx-很好的開發(fā)體驗(yàn)
對web components友好 有可能支持web componnets
靜態(tài)執(zhí)行 jsx-動(dòng)態(tài)執(zhí)行
我想補(bǔ)充的是react有很多優(yōu)秀的瀏覽器開發(fā)插件,然而并沒有看到angular 2的。愛掏網(wǎng) - it200.com

競技場

??為了比較這些前端的技術(shù),我做了一些TODO應(yīng)用。愛掏網(wǎng) - it200.com為了使問題更加簡單,我在兩個(gè)應(yīng)用中只使用了Redux core(受angular 2-introduction to Redux啟發(fā))。愛掏網(wǎng) - it200.com兩個(gè)都是使用typescript開發(fā)的,所以比較起來比較清晰些。愛掏網(wǎng) - it200.com你可以對比下代碼:

– Redux Core: https://github.com/evojam/redux-todo-lib – Angular2 App: https://github.com/evojam/angular2-redux-sample-app – React App: https://github.com/evojam/react-redux-sample-app

對抗

??兩者的核心都是一個(gè)component或是一個(gè)view單元。愛掏網(wǎng) - it200.com兩個(gè)都將你的app形成一個(gè)組件樹。愛掏網(wǎng) - it200.com它們都鼓勵(lì)將數(shù)據(jù)通過頂層傳遞給組件樹。愛掏網(wǎng) - it200.com根到葉子的數(shù)據(jù)流思路使我們開發(fā)的應(yīng)用”更靈活”,所以現(xiàn)在開始。愛掏網(wǎng) - it200.com

第一輪:功能組件

??在這個(gè)樹形結(jié)構(gòu)的基礎(chǔ)應(yīng)用中,每個(gè)頂層樹是一個(gè)組件,每個(gè)組件的特點(diǎn):

從父節(jié)點(diǎn)接受數(shù)據(jù)(稱之為輸入)
返回一個(gè)組件的子樹(視圖view)
??在angular2和React中,輸入都是通過子節(jié)點(diǎn)屬性(不是html屬性)從一個(gè)元素傳遞到它的子樹,兩種解決方案中,視圖view都可以理解為xml樹。愛掏網(wǎng) - it200.com

TodoList組件

??一個(gè)可復(fù)用、可選擇、簡單的todo list需要做到兩點(diǎn)–todos數(shù)組(我做的數(shù)組)和過濾的方式(要展示的數(shù)組)。愛掏網(wǎng) - it200.com所以我們的組件輸入可以是這樣的:

interface ITodoListProps {
todos: ITodo[];
filter: FilterType;
}
??而組件在任何地方都可以這樣使用:

– React


–Angular 2

    下面是React組件的定義:

    // src/components/todo-list.tsx

    import { Todo } from './todo';

    export function TodoList(props: ITodoListProps): JSX.Element {
    return (


      {todosFilter(props.todoList, props.filter)
      .map(todo => (

      ))}

    );
    }
    下面是Angulart2組件定義的版本:

    // src/components/todo-list.ts

    import { Todo } from './todo';

    @Component({
    changeDetection: ChangeDetectionStrategy.OnPush,
    directives: [Todo],
    host: {'class':'todo-list'},
    pipes: [TodosFilter],
    selector: '[todoList]',
    templateUrl: '/src/components/todo-list.html'
    })
    export class TodoList implements ITodoListProps {
    @Input() todoList: ITodo[];
    @Input() filter: FilterType;
    }
    // src/components/todo-list.html


    ??毫無疑問,React版本是沒有狀態(tài),更純正,更簡單,它使用data并返回dom,很好。愛掏網(wǎng) - it200.com

    ??這里可以運(yùn)行但是不能正確編譯,我不知道它是不是typescript支持性的原因或者React編碼輸入的錯(cuò)誤(如果知道錯(cuò)誤請給issue)。愛掏網(wǎng) - it200.com無論怎樣,它失敗了,我不得不在React組件基礎(chǔ)上切換成一個(gè)class。愛掏網(wǎng) - it200.comReact保存了狀態(tài)–就是組件成員的屬性–但是屬性仍然可以被當(dāng)做immutable的數(shù)據(jù)輸入:

    // src/components/todo-list.tsx

    import { Todo } from './todo';

    export class TodoList extends Component {
    render(): JSX.Element {
    return (


      {todosFilter(this.props.todoList, this.props.filter)
      .map(todo => )}

    );
    }
    }
    ??angular2 版本需要多得多的配置,對于這個(gè)簡單的應(yīng)用要干的事情太多了。愛掏網(wǎng) - it200.com這是因?yàn)閍ngular沒有將js和html混合在一起(directives,host,pipes,selector,templateUrl)和更多復(fù)雜的數(shù)據(jù)修改檢測機(jī)制(數(shù)據(jù)監(jiān)聽)。愛掏網(wǎng) - it200.com

    selector是一種將組件js定義和模板元素綁定起來的方法–而在React它不需要因?yàn)閖s組件就是jsx組件元素。愛掏網(wǎng) - it200.com
    pipes和directives用于通知組件哪些其它的組件、directives和pipes(內(nèi)置html filter)將要在模板中使用,而React中的js組件是直接在jsx模板中使用的。愛掏網(wǎng) - it200.comReact不提供任何無模板的directive(對我來說這是個(gè)問題,我后面會(huì)提到)或者內(nèi)聯(lián)的pipes(因?yàn)槲覀兛梢允褂眉僯s功能)。愛掏網(wǎng) - it200.com
    templateUrl是大家都明白的,對吧?它被因?yàn)槭蔷€下引用的,但是我確實(shí)覺得從組件文件中分離出更大的模板是比較合理的做法。愛掏網(wǎng) - it200.com缺少實(shí)時(shí)編譯的模板檢查確實(shí)是angular的劣勢。愛掏網(wǎng) - it200.com
    而host的出現(xiàn)是因?yàn)槟0邃秩局羞^程不大一樣
    ??React的組件功能(或是渲染方法)返回整個(gè)頂層模板包含的組件樹。愛掏網(wǎng) - it200.com

    return (


      { todoList.map( todo => ) }

    );
    ??在angular中,組件是與組件的根元素綁定的(通過上面提到的選擇器selector),這個(gè)組件的根元素就被稱為host,所以在angular模板中,我們只放入根元素的內(nèi)容:

    // src/components/todo-list.html


  • ??如果我們想添加一下東西(例如css的class,屬性值)給host元素,我們稱之為host定義,例如 {'class':'todo-list'} 會(huì)添加 todo-list類到
      元素中。愛掏網(wǎng) - it200.com我們也可以通過typescript的裝飾器功能綁定動(dòng)態(tài)值和監(jiān)聽器給host元素。愛掏網(wǎng) - it200.com

      Todo 組件

      ??所以我們現(xiàn)在開始綁定一些事件處理器。愛掏網(wǎng) - it200.comangular todo組件就像這樣:

      // src/components/todo.ts

      interface ITodoProps {
      todo: ITodo;
      }

      @Component({
      host: {'class': 'todo'},
      selector: '[todo]',
      templateUrl: '/src/components/todo.html'
      })
      export class Todo implements ITodoProps {
      constructor(private todoActions: TodoActions) {}

      @Input() todo: ITodo;
      
      @HostBinding('class.done')
      private get isCompleted() {
          return this.todo.completed;
      }

      }
      // src/components/todo.html



      ??我們把ITodo實(shí)例當(dāng)做一個(gè)輸入值。愛掏網(wǎng) - it200.com輸出為帶有兩個(gè)按鈕的host元素。愛掏網(wǎng) - it200.com我們也綁定了靜態(tài)todo和條件的"done"css類到host元素中。愛掏網(wǎng) - it200.com按鈕點(diǎn)擊觸發(fā)組件的todoActions成員相應(yīng)的方法。愛掏網(wǎng) - it200.com沒什么亮點(diǎn),只有(click)=...或許會(huì)引起我們的注意。愛掏網(wǎng) - it200.com我們也可以”加點(diǎn)糖“并使用

      ??而React版本:

      interface ITodoProps {
      todo: ITodo;
      key: string;
      }

      export class Todo extends Component {
      private getToggleAction(todo: ITodo) {
      return () => {
      todoActions.toggleTodo(todo.id);
      }
      }

      private removeTodo(todo: ITodo) {
          todoActions.removeTodo(this.props.todo.id);
      }
      
      public render(): JSX.Element {
          return (
          
    • ); }

      }
      ??我們把ITodo實(shí)例當(dāng)做一個(gè)輸入值。愛掏網(wǎng) - it200.com輸出為帶有兩個(gè)按鈕的一個(gè)元素。愛掏網(wǎng) - it200.comXML樹返回的根元素也綁定了靜態(tài)todo和條件的"done"css類。愛掏網(wǎng) - it200.com目前為止都基本相似。愛掏網(wǎng) - it200.com但是我們看到這里兩個(gè)React令人失望的特點(diǎn):

      在onClick處理中this的上下文丟失了–我們必須做下修改(綁定或添加)
      class屬性必須和整個(gè)元素一起保存–沒有css類管理機(jī)制
      ??我也不喜歡className和htmlFor屬性,但是他們必須要使用,因?yàn)閏lass和For都是js的保留字,就像我們必須將html和js混合在一起一樣。愛掏網(wǎng) - it200.com

      組合:React

      Todo





    • TodoList


        { todoList.map( todo => ) }

      對于對象更深的結(jié)構(gòu):


      輸出為:








      組合:Angular2

      Todo

      @Component({ host: {'class': 'todo'}, selector: '[todo]', … })
      export class Todo … {

      @HostBinding('class.done')
      private get isCompleted() { … }
      }


      TodoList

      @Component({ host: {'class':'todo-list'}, selector: '[todoList]', … })
      export class TodoList … { … }

      對于對象更深的結(jié)構(gòu):


        輸出為:








        第一輪結(jié)果

        ??React在開發(fā)輕量級(jí)單一組件場景下具有絕對優(yōu)勢。愛掏網(wǎng) - it200.com如果你的應(yīng)用可以用數(shù)據(jù)視圖簡單描述清楚的話React似乎是最佳的解決方案。愛掏網(wǎng) - it200.com而且無疑是我們見過的最靈活的視圖渲染框架。愛掏網(wǎng) - it200.com但是事件處理邏輯越多,UI渲染越復(fù)雜,angular2就越具有優(yōu)勢。愛掏網(wǎng) - it200.com事實(shí)上,angular2的組件配置和綁定聲明復(fù)雜度和組件的復(fù)雜性成反比。愛掏網(wǎng) - it200.com此外,它還有靈活的使用方式(從數(shù)據(jù)到視圖的綁定)。愛掏網(wǎng) - it200.com可能某一天Reactangular或者Angulareact框架能讓我們高效的在一個(gè)應(yīng)用中使用兩種實(shí)現(xiàn)方式。愛掏網(wǎng) - it200.com但現(xiàn)在我們必須要選擇。愛掏網(wǎng) - it200.com

        ??靈活與否,都應(yīng)該以減輕開發(fā)者的痛苦來作為考量。愛掏網(wǎng) - it200.com代碼的可讀性也是一方面,但目前html在這里是很重要的判斷。愛掏網(wǎng) - it200.com

        第二輪:視圖美學(xué)

        ??讓我們來準(zhǔn)備一個(gè)新的組件來處理更復(fù)雜的結(jié)構(gòu)–列表結(jié)構(gòu)。愛掏網(wǎng) - it200.com

        angular2

      • ngFor="#todoList of lists trackBy _byId"
        [class.active]="isCurrent(todoList)"
        class="todo-lists-list-item">

          ngIf="!isCurrent(todoList)" class="todo-list">
        • class="todo-preview"
          [class.done]="todo.completed">
              


      • React


          {this.props.lists.map(list => (
        • className={this.listClassName(list)}>

          {list.id !== this.props.currentId ? (

            {list.todos.map(todo => (
          • className={this.todoClassName(todo)}>
            {todo.text}

          • ))}

          ) : (

          )}

        • ))}

        第二輪結(jié)果

        ??有什么好說的嗎?選擇你喜歡的就好了~

        ??ok,我認(rèn)為

      • ngFor="#item in list trackBy fn">…
      • ngFor="#item in list trackBy fn">…
      • 相比{list.map((item, index) => (
      • ))}更具有可讀性,在某些地方,將js和xml混合起來就比較混亂。愛掏網(wǎng) - it200.com當(dāng)然,只是個(gè)人觀點(diǎn)。愛掏網(wǎng) - it200.com

        第三輪:數(shù)據(jù)修改監(jiān)聽

        ??我們在此聲明一件重要的事情–Dom修改(在修改被檢測到以后)在兩種框架中處理方式是類似的。愛掏網(wǎng) - it200.com它們只修改確實(shí)需要改變的部分。愛掏網(wǎng) - it200.com我們來看下如果發(fā)生數(shù)據(jù)變化,處理的方式有什么不同;

        React

        ??React的基本處理方式很簡單。愛掏網(wǎng) - it200.com如果組件的state或者props發(fā)生改變,就會(huì)調(diào)用修改處理函數(shù):

        state在setState()被調(diào)用時(shí)觸發(fā)
        props在父組件重新渲染時(shí)發(fā)生變化
        ??當(dāng)然也可以通過調(diào)用forceUpdate()來觸發(fā)改變,修改監(jiān)聽器只在子樹發(fā)生改變的地方觸發(fā)。愛掏網(wǎng) - it200.com簡單便捷,唯一不好的地方是我們必須在頂層元素里手動(dòng)調(diào)用setState()方法。愛掏網(wǎng) - it200.com

        ??你可能會(huì)注意到例子里面的key={todo.id},這里是來列表元素檢測改變的機(jī)制必須的,如果一個(gè)key上面的值修改了–html相對應(yīng)的元素就會(huì)重新渲染。愛掏網(wǎng) - it200.com有點(diǎn)啰嗦,但是有必要。愛掏網(wǎng) - it200.com另外在項(xiàng)目中使用嚴(yán)格模式編程是,你必須在你的列表組件中額外定義一個(gè)key:string。愛掏網(wǎng) - it200.com

        Angular

        ??angular 團(tuán)隊(duì)決定使用稍微不同的方式。愛掏網(wǎng) - it200.com他們包含了zone.js到瀏覽器異步回調(diào)中(例如:setTimeout,setInterval,事件處理和xhr請求事件)。愛掏網(wǎng) - it200.com當(dāng)他們當(dāng)中任意一個(gè)被調(diào)用,就會(huì)運(yùn)行修改檢測。愛掏網(wǎng) - it200.com你可參考下great in-depth explanation,更有趣的是,你可以在你任意一個(gè)組件樹上選擇使用的檢測策略。愛掏網(wǎng) - it200.com

        ??在樣例中,我使用了onPush策略,所以所有的組件修改檢測只在他們@input()屬性發(fā)生變化時(shí)才會(huì)觸發(fā)。愛掏網(wǎng) - it200.com所以angular里的修改檢測可以在任何合適的時(shí)候觸發(fā),而react只在一個(gè)時(shí)候觸發(fā)。愛掏網(wǎng) - it200.com當(dāng)然angular還有更多的觸發(fā)策略:CheckOnce, Checked, CheckAlways, Detached, OnPush, Default。愛掏網(wǎng) - it200.com跟多信息可以參考:ChangeDetectionStrategy docs。愛掏網(wǎng) - it200.com

        ??就像React的key={…}一樣,angular有自己的方式來處理列表的變化–NgFor.ngForTrackBy。愛掏網(wǎng) - it200.com在代碼里就是

      • 愛掏網(wǎng) - it200.com這里傳遞的_byId是list => list.id的一個(gè)函數(shù)。愛掏網(wǎng) - it200.com所以很像React–我們必須給列表里的每個(gè)元素創(chuàng)建唯一的標(biāo)識(shí)來辨別當(dāng)修改觸發(fā)是是不是發(fā)生在同一個(gè)元素上面。愛掏網(wǎng) - it200.com可能稍微比React優(yōu)雅一點(diǎn),但是你必須學(xué)習(xí)更多框架里面特定的語法。愛掏網(wǎng) - it200.com

        第三輪結(jié)論

        ??兩種解決方案都提供了一個(gè)相對健全的途徑,然而React的默認(rèn)修改檢測無疑更優(yōu)一些。愛掏網(wǎng) - it200.com另一方面,angular這種在底層的檢測相當(dāng)于一個(gè)瀏覽器開發(fā)玩家使用的因?yàn)樗褭z測插入到瀏覽器一些異步調(diào)用層,所以廣播檢測的職責(zé)對開發(fā)者來說不可控。愛掏網(wǎng) - it200.com當(dāng)然每種方案都有他們不盡人意的地方。愛掏網(wǎng) - it200.comReact的組件檢測如果數(shù)據(jù)不是來自屬性的話必須通過手動(dòng)調(diào)用觸發(fā),如果使用了其它存儲(chǔ)方式會(huì)直接觸發(fā)(Flux 框架)。愛掏網(wǎng) - it200.com如果你想讓angular變得靈活些,你必須在每個(gè)單一的組件定義他們的數(shù)據(jù)檢測觸發(fā)策略。愛掏網(wǎng) - it200.com

        ??不過兩種方式都很好。愛掏網(wǎng) - it200.comangular使用簡潔的配置工具實(shí)現(xiàn)了更多的擴(kuò)展性,這點(diǎn)React就沒做到。愛掏網(wǎng) - it200.com

        第四輪:擴(kuò)展html

        ??做什么?就是像html添加一些功能,讓它在更多的元素中被復(fù)用。愛掏網(wǎng) - it200.com

        Angular

        @Directive({selector: '[inp-alerter]'})
        export class InpAlerter {

        @Input('inp-alerter') inpAlerter: string; 
        
        @HostBinding() placeholder = 'Write something here';
        
        @HostListener('keyup.enter', ['$event.target.value'])
        onInput(val: string): void { … }

        }
        ??上面的例子展示了我們怎樣從一個(gè)輸入屬性中獲取值、綁定一些其他值給元素屬性或給元素添加監(jiān)聽事件。愛掏網(wǎng) - it200.com而且它可以用inp-alerter屬性應(yīng)用到其它任意一個(gè)html元素中。愛掏網(wǎng) - it200.com而且這只是我們能做的很小的一部分,實(shí)際上@Directive定義的類可以作為絕大多數(shù)功能用于@components,但是沒有模板。愛掏網(wǎng) - it200.com簡單強(qiáng)大。愛掏網(wǎng) - it200.com

        React

        ??有一種可能是使用React mixins的方式來實(shí)現(xiàn)相同的功能,但是有點(diǎn)過度設(shè)計(jì)的傾向而且容易出錯(cuò)。愛掏網(wǎng) - it200.com無論怎樣,開發(fā)者必須為應(yīng)用中使用的每個(gè)元素功能創(chuàng)建一個(gè)組件。愛掏網(wǎng) - it200.com

        K.O.

        ??最后一輪決出了勝負(fù),React被戰(zhàn)勝了。愛掏網(wǎng) - it200.com

        ??感謝上帝,這只是個(gè)比喻。愛掏網(wǎng) - it200.com

        ??總之,這是一個(gè)angular 1.x統(tǒng)治的世界,而且也正準(zhǔn)備走向html擴(kuò)展元素web components的世界。愛掏網(wǎng) - it200.comangular 2贏的了這一輪。愛掏網(wǎng) - it200.com但是我確定React不會(huì)就此放棄。愛掏網(wǎng) - it200.com

        落幕

        ??顯然,React和Angular 2有很多共同點(diǎn),他們在處理應(yīng)用框架和數(shù)據(jù)上使用了相似的原理。愛掏網(wǎng) - it200.com另一方面,每個(gè)功能的實(shí)現(xiàn)都使用了不同的方式(好吧,組件調(diào)用的生命周期還是完全一致的)。愛掏網(wǎng) - it200.com這些不同點(diǎn)并不意味著應(yīng)用開發(fā)時(shí)的難度,每種方案都提供了足夠完善的工具來開發(fā)一個(gè)大型、嚴(yán)謹(jǐn)、靈活的應(yīng)用核心。愛掏網(wǎng) - it200.com

        ??當(dāng)然React更小并且只涵蓋view/component的操作–這是我這里要對比的。愛掏網(wǎng) - it200.com缺少向html的擴(kuò)展機(jī)制無疑是React唯一不足的地方。愛掏網(wǎng) - it200.com

        ??Angular2則更加穩(wěn)定、可擴(kuò)展和更加完善。愛掏網(wǎng) - it200.com但是它仍然在beta階段–并且相對對手具有優(yōu)勢因?yàn)闊o論相比angular1還是React的經(jīng)歷來看它具有更加優(yōu)秀的合并思想。愛掏網(wǎng) - it200.com

        原文作者:JAKUB STROJEWSKI

        參考文章:

        Comparison of Angular 2 and React

        State Management in Angular 2 and React

        Choosing between React vs. Angular 2

        聲明:所有內(nèi)容來自互聯(lián)網(wǎng)搜索結(jié)果,不保證100%準(zhǔn)確性,僅供參考。如若本站內(nèi)容侵犯了原著者的合法權(quán)益,可聯(lián)系我們進(jìn)行處理。
        發(fā)表評(píng)論
        更多 網(wǎng)友評(píng)論0 條評(píng)論)
        暫無評(píng)論

        返回頂部

        主站蜘蛛池模板: 欧美精品国产综合久久| 亚洲精品国产高清不卡在线| 国产乱码一区二区三区爽爽爽| 国产精品黄大片观看| 国模视频一区二区| 国产高清一级伦理| 国产经典一区二区三区蜜芽| 在线精品国产一区二区三区| 无码精品日韩中文字幕| 日本猛妇色xxxxx在线| 日韩人妻一区二区三区免费| 欧美亚洲欧美日韩中文二区| 欧美边吃奶边爱边做视频| 激情亚洲的在线观看| 波多野结衣中文字幕一区二区三区| 狠狠ady精品| 秋霞鲁丝片无码av| 精品一区二区三区四区| 福利网址在线观看| 浪潮AV色综合久久天堂| 污污视频在线免费看| 欧美美女与野兽免费看电影| 欧美牲交a欧美牲交aⅴ免费真 | 美女胸又大又黄又www的网站 | 国产美女一级特黄毛片| 国产色无码精品视频免费| 国产精品自产拍在线观看| 国产真实乱了全集mp4| 国产小视频你懂的| 四虎影永久在线观看精品| 公和我在厨房好爽中文字幕 | 色哟哟www网站| 男攻在开会男受在桌子底下 | 欧美成年黄网站色视频| 日韩精品视频免费观看| 无码日韩精品一区二区免费| 巨大挺进她的花茎| 在线观看黄日本高清视频| 国产福利小视频| 国产91精品久久久久久久| 人妻中文字幕无码专区|