整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          秒懂ReactJS

          秒懂ReactJS

          篇文章是為ReactJs小白準備的,希望他們快速抓住ReactJs的要點并能在實踐中隨機應變。

          兩句話版本

          • ReactJs把視圖更新簡化為一個render函數
          • render函數接收兩個參數,分別是配置項和狀態

          長版本

          ReactJs是一個專注于View的Web前端框架。Web前端的View就是瀏覽器中的Dom元素,改變View的唯一途徑就是修改瀏覽器中的Dom元素,因此ReactJs的核心任務就是如何修改Dom元素,作為一個成功的框架,ReactJs使修改Dom元素變得高效而又簡單。

          ReactJs把修改Dom的操作簡化成一個函數renderInto(parentDom, props, states)=>htmlString,這個函數的意圖就是根據props,states計算出視圖對應的html字符串并添加為parentDom的子節點。props和states就是普通的javascript對象,這個函數的核心邏輯就是計算html元素的機構及元素屬性然后拼接成字符串返回。作為框架,ReactJs用JSX形式的DSL解決了拼接html的任務并接管了更新到parentDom的職責。看一個例子,理解這個函數并理解ReactJs怎么使用這個函數你就可以一個人開始ReactJs之旅了。

          var props={name: 'myname'};  
          var states={amount: 1000};  
          
          
          function render(props, states) {  
            var title=’Hello, ' + props.name;  
            var description='You have ' + states.amount + ' score now.';  
          
          
            return (  
              <div className="score-board">  
                 <h1>{title}</h1>  
                 <p>{description}</p>  
              </div>  
            );  
          }
          

          函數第一行根據props計算title,第二行根據states計算description,最后以JSX形式返回拼接好的html字符串。

          如果你用過AngularJs,EmberJs等類似的前端框架,你可能會覺得沒什么了不起,不就是把模板和邏輯放到一起嗎?是的,沒錯,但這不僅僅是組織形式上的改變,而是編程隱喻的轉變—從復雜的MVC或MVVM模式到簡單的render函數。還有一點不同是JSX最終編譯成調用react-dom的javascript語句,而不是直接生成字符串。

          render函數還只是ReactJs這座冰山的一角,”React”會在render函數的輸入變化時再次調用這個函數。再看一個例子。

          var props={name: 'myname'};  
          var states={amount: 1000};  
          
          
          function handleClickAdd() {  
            states={amount: states.amount + 1};  
          }  
          
          
          function render(props, states) {  
            var title=’Hello, ' + props.name;  
            var description='You have ' + states.amount + ' score now.';  
          
          
            return (  
              <div className="score-board">  
                 <h1>{title}</h1>  
                 <p>{description}</p>  
                 <button onClick={handleClickAdd}>+1</button>  
              </div>  
            );  
          }
          

          這個例子增加了一個”+1”按鈕,當用戶點擊按鈕時會修改states,ReactJs在states變化時的”React”就是再次調用render函數,然后用新輸出更新瀏覽器的dom。

          可能你會問,props和states不就是Model嗎?是的,可以理解成Model,但此Model非彼Model,props和states都是為View服務的而非和View平起平坐。

          可能你還會問,為啥不把props和states合并成一個對象?要回答這個問題,就涉及到復雜視圖的場景。想想看,當視圖內的元素不斷增加時,代碼上如何處理,還要在一個render函數里折騰嗎?肯定不會。我猜你已經想到了,要把大問題拆小。ReactJs給出的解決方法就是把大視圖拆成若干個小視圖,每個視圖都有自己的render函數,在JSX中可以直接使用視圖標簽。看一個例子。

          var Score=React.createClass({  
            initialState: function() {  
              return {amount: 1000};  
            },  
          
          
            function handleClickAdd() {  
              this.setState({amount: this.states.amount + 1});  
            }  
          
          
            render: function() {  
              var title=’Hello, ' + this.props.name;  
              var description='You have ' + this.states.amount + ' score now.';  
          
          
              return (  
                <div className="score-board">  
                   <h1>{title}</h1>  
                   <p>{description}</p>  
                   <button onClick={handleClickAdd}>+1</button>  
                </div>  
              );  
            }  
          });  
          
          
          var ScoreList=React.createClass({  
            render() {  
              return (  
                <ul className="score-list">  
                  <li><Score name="Tom" /></li>  
                  <li><Score name="Jerry" /></li>  
                </ul>  
              );  
            }  
          });  
          
          
          ReactDOM.render(  
            <ScoreList />,  
            document.getElementById('content')  
          );
          

          這個例子中有兩類View,分別是Score和ScoreList。ScoreList的render函數中使用Score標簽并給出配置項name的值。詳細看一下Score,ReactJs提供createClass方法定義視圖,在render函數中通過this.props訪問外部傳入的配置項,通過this.states訪問視圖內部的狀態。從意圖上看,props外部傳入視圖的配置項,擁有者是父視圖,視圖內部只能讀取配置項,states的擁有者是視圖自身。

          區分props和states的結果就是,子視圖沒辦法直接改變父視圖,視圖改變一定是自觸發改變的視圖開始向子視圖傳播。對上面的例子,當Tom的Score改變時,ScoreList其他部分一定不會改變,所以視圖更新從Tom的Score視圖開始就可以,這就保證了能更高效地計算視圖變化,再加上VirtualDom的使用,使ReactJs的效率大大超過其他框架。

          當子視圖需要改變父視圖時,也一定是從父視圖開始向下更新。假如上面的例子中ScoreList還有平均分的視圖,當Tom的分數改變時,需要更新ScoreList中的平均分。這就需要Score視圖在處理”+1”輸入時把變化通知到ScoreList,做法時給Score增加配置項,ScoreList中定義更新平均分的函數并把函數作為配置項傳給Score。當ScoreList更新時,因為Jerry的props和states都沒變化,所以Jerry的Score視圖不需要更新。

          這就是ReactJs的全部秘密了(不過Web前端本身是一個復雜系統,你還需要了解更多其他內容)。

          ngularJS的主要組成部分是:

          • 啟動(startup) - 展示“hello world!”
          • 執行期(runtime) - AngularJS 執行期概覽
          • 作用域(scope) - 視圖和控制器的集合區
          • 控制器(controller) - 應用的行為
          • 模型(model) - 應用的數據
          • 視圖(view) - 用戶能看到的
          • 指令(directives) - 擴展HTML語法
          • 過濾器(filters) - 數據本地化
          • 注入器(injector) - 聚合你的應用
          • 模塊(module) - 配置注入器
          • $ - AngularJS的命名空間(namespace)

          啟動

          我們通過一個例子來講解啟動這個部分

          <!doctype html>

          <html ng-app>

          <head>

          <script src="http://code.angularjs.org/angular-1.1.0.min.js"></script>

          </head>

          <body>

          <p ng-init=" name='World' ">Hello {{name}}!</p>

          </body>

          </html>

          1. 瀏覽器載入HTML,然后把它解析成DOM樹。
          2. 瀏覽器載入angular.js腳本。
          3. AngularJS等到DOMContentLoaded事件觸發執行。
          4. AngularJS尋找ng-app指令,這個指令指示了應用程序的邊界。
          5. 使用ng-app中指定的模塊來配置注入器($injector)。
          6. 注入器($injector)是用來創建“編譯服務($compile service)”和“根作用域($rootScope)”的。
          7. 編譯服務($compile service)是用來編譯DOM樹并把它鏈接到根作用域($rootScope)的,這里的根作用域就是html。
          8. ng-init指令將“World”賦給作用域里的name這個變量。
          9. 作用域中的name與頁面上的{{name}}綁定,整個表達式變成了“Hello World”。

          執行期

          瀏覽器的事件機制:

          1. 瀏覽器的Event loop等待事件的觸發。所謂事件包括用戶的交互操作、定時事件、或者網絡事件(服務器的響應)。
          2. 事件觸發后,如果有綁定事件回調函數,那么此函數就會被執行。此時會進入Javascript上下文。通常回調用來修改DOM結構。
          3. 一旦回調執行完畢,瀏覽器就會離開Javascript上下文,并且根據DOM的修改重新渲染視圖。

          而AngularJS通過使用自己的Event loop,改變了傳統的Javascript工作流。這使得Javascript的執行被分成原生部分和擁有AngularJS執行上下文的部分。只有在AngularJS執行上下文中運行的操作,才能享受到AngularJS提供的數據綁定,異常處理,資源管理等功能和服務。你可以使用 $apply()方法,從普通Javascript上下文進入AngularJS執行上下文。記住,大部分情況下(如在控制器,服務中),$apply都已經被執行過了。只有當你使用自定義的事件回調或者是使用第三方類庫的回調時,才需要自己執行$apply。

          下面通過一個例子來講解如何實現“將用戶輸入綁定到視圖上”的效果。

          <!doctype html>

          <html ng-app>

          <head>

          <script src="http://code.angularjs.org/angular-1.1.0.min.js"></script>

          </head>

          <body>

          <input ng-model="name">

          <p>Hello {{name}}!</p>

          </body>

          </html>

          在編譯階段:

          input元素上的ng-model指令會給<input>輸入框綁定keydown事件;

          {{name}}這個變量替換表達式建立了一個 $watch ,來接受 name 變量改變的通知。

          在執行期階段:

          按下任何一個鍵(以X鍵為例),都會觸發一個 input 輸入框的keydown事件;

          input 上的指令捕捉到 input 內容的改變,然后調用 $apply("name='X';")來更新處于AngularJS執行上下文中的模型;

          AngularJS將 name='X'應用到模型上;

          $digest 循環開始;這個循環是由兩個小循環組成的,這兩個小循環用來處理$evalAsync隊列和$watch列表。這個$digest循環直到模型“穩定”前會一直迭代。這個穩定具體指的是$evalAsync列表為空,并且$watch列表中檢測不到任何改變了。這個$evalAsync隊列是用來管理那些“視圖渲染前需要在當前棧外執行的操作”。這通常使用 setTimeout(0)來完成的。并且,因為瀏覽器會根據事件隊列按順序渲染視圖,這時還會造成視圖的抖動。$watch列表是一個表達式的集合,這些表達式可能是自上次迭代后發生了改變的。如果檢測到了有改變,那么$watch函數就會被調用,它通常會把新的值更新到DOM中。

          $watch 列表檢測到了name值的變化,然后通知 {{name}}變量替換的表達式,這個表達式負責將DOM進行更新;

          AngularJS退出執行上下文,然后退出Javascript上下文中的keydown事件;

          瀏覽器以更新的文本重新渲染視圖。

          作用域(Scope)

          作用域是用來檢測模型的改變和為表達式提供執行上下文的。它是分層組織起來的,并且層級關系是緊跟著DOM的結構的。

          下面這個例子演示了{{name}}表達式在不同的作用域下被解析成了不同的值

          <!doctype html>

          <html ng-app>

          <head>

          <script src="http://code.angularjs.org/angular-1.1.0.min.js"></script>

          <script>

          function GreetCtrl($scope) {

                $scope.name='World';

               }

               function ListCtrl($scope) {

                $scope.names=['Igor', 'Misko', 'Vojta'];

               }

          </script>

          </head>

          <body>

          <div ng-controller="GreetCtrl">

          Hello {{name}}!

          </div>

          <div ng-controller="ListCtrl">

          <ol>

          <li ng-repeat="name in names">{{name}}</li>

          </ol>

          </div>

          </body>

          </html>

          在GreetCtrl控制器中的name等于'World'。在ListCtrl控制器中的name等于'Igor', 'Misko', 'Vojta'。因為它們的作用域不一樣。

          控制器

          視圖背后的控制代碼就是控制器。它的主要工作內容是構造模型和回調方法,并把模型和回調方法一起發送到視圖。 視圖可以看做是作用域在模板(HTML)上的投影。而作用域是一個中間地帶,它把模型整理好傳遞給視圖,把瀏覽器事件傳遞給控制器。控制器和視圖的分離非常重要,因為:

          (1)控制器是由Javascript寫的。Javascript是命令式的,命令式的語言適合用來編寫應用的行為。控制器不應該包含任何關于渲染代碼(DOM引用或者片段)。

          (2)視圖模板是用HTML寫的。HTML是聲明是的,聲明式的語言適合用來編寫UI。視圖不應該包含任何行為。

          (3)因為控制器和視圖沒有直接的調用關系,所以可以使多個視圖對應同一個控制器。這對“換膚(re-skinning)”、適配不同設備(比如移動設備和臺式機)、測試,都非常重要。

          模型

          模型就是用來和模板結合生成視圖的數據。模型在作用域中可以被引用,這樣才能被渲染生成視圖。和其他框架不一樣的是,Angularjs對模型本身沒有任何限制和要求。你不需要繼承任何類也不需要實現指定的方法。 模型可以是哈希形式的原生對象,也可以是完整對象類型。簡而言之,模型可以是原生的Javascript對象。

          視圖

          所謂視圖,就是指用戶所看見的。 視圖的生命周期由作為一個模板開始,它將和模型合并,并最終渲染到瀏覽器的DOM中。與其他模板系統不同的是,AngularJS使用一種獨特的形式來渲染視圖。

          其他模板 - 大部分模板系統工作原理,都是一開始獲取一個帶有特殊標記的HTML形式字符串。通常情況下模板的特殊標記破壞了HTML的語法,以至于模板是不能用HTML編輯器編輯的。然后這個字符串會被送到模板引擎那里解析,并和數據合并。合并的結果是一個可以被瀏覽器解析的HTML字符串。這個字符串會被.innerHTML方法寫到DOM中。使用innerHTML會造成瀏覽器的重新渲染。當模型改變時,這整個流程又要重復一遍。模板的生存周期就是DOM的更新周期。這里我想強調是,這些模板的基礎是字符串。

          AngularJS - AngularJS和其它模板系統不同。它使用的是DOM而不是字符串。模板仍然是用HTML字符串寫的,并且它仍然是HTML。瀏覽器將它解析成DOM, 然后這個DOM會作為輸入傳遞給模板引擎,也就是我們的編譯器。編譯器查看其中的指令,找到的指令后,會開始監視指令內容中相應的模型。 這樣做,就使得視圖能“連續地”更新,不需要模板和數據的重新合并。你的模型也就成了你視圖變化的唯一原因。

          指令

          一個指令 就是一種“由某個屬性、元素名稱、css類名出現而導致的行為,或者說是DOM的變化”。指令能讓你以一種聲明式的方法來擴展HTML表示能力。

          Filters過濾器

          過濾器扮演著數據翻譯的角色。一般他們主要用在數據需要格式化為本地格式的時候。它參照了UNIX過濾的規則,并且也實現了“|”(管道)語法。

          模塊和注入器

          每個AngularJS應用都有一個唯一的注入器。注入器提供一個通過名字查找對象實例的方法。它將所有對象緩存在內部,所以如果重復調用同一名稱的對象,每次調用都會得到同一個實例。如果調用的對象不存在,那么注入器就會讓實例的工廠(instance factory)函數創建一個新的實例。

          一個模塊就是一種配置注入器的實例的工廠函數的方式,我們也稱它為“提供者(provider)”。

          var myModule=angular.module('myModule', [])

          myModule.factory('serviceA', function() { //定義serviceA的工廠函數,myModule模塊就是提供serviceA實例的工廠函數的提供者

          return {

          ......

          };

          });

          // create an injector and configure it from 'myModule'

          var $injector=angular.injector('myModule');

          // retrieve an object from the injector by name

          var serviceA=$injector.get('serviceA'); //從注入器查找serviceA對象,這時注入器會讓實例serviceA的工廠函數factory創建一個新的實例serviceA返回

          // always true because of instance cache

          $injector.get('serviceA')===$injector.get('serviceA');

          注入器真正強大之處在于讓方法和類型能夠通過注入器,請求到他們依賴的組件,而不需要自己加載依賴。

          我們看看下面動態時間的這個例子:

          <!doctype html>

          <html ng-app="timeExampleModule">

          <head>

          <script src="http://code.angularjs.org/angular-1.1.0.min.js"></script>

          <script">

            angular.module('timeExampleModule', []).

                factory('time', function($timeout) {

                 var time={};

                (function tick() {

                time.now=new Date().toString();

                $timeout(tick, 1000);

                })();

                return time;

               });

              function ClockCtrl($scope, time) {

               $scope.time=time;

              }

          </script>

          </head>

          <body>

          <div ng-controller="ClockCtrl">

          Current time is: {{ time.now }}

          </div>

          </body>

          </html>

          你只要把需要的依賴寫在函數參數里。當AngularJS調用這個函數時,它會自動填充好需要的參數。這個例子中,當ng-controller實例化構造器ClockCtrl的時候,它自動提供了指明的依賴time實例對象。

          AngularJS 命名空間

          為了防止意外的命名沖突, AngularJS為可能沖突的對象名加以前綴"$"。所以請不要在你自己的代碼里用"$"做前綴,以免和AngularJS代碼發生沖突。

          于一個Web前端工程師而言,框架知識非常重要,它對你項目的成功有著相當大的影響。專業的鄭州Web前端課程都會涵蓋JS框架知識,比如Angular和React,今天千鋒鄭州老師就給大家講解一下AngularJS與ReactJS的區別,以便同學們理解記憶。

          AngularJS:框架領域的冠軍

          Angular.js是一個開源的Web應用程序框架,具有由Google提供的Model-View-Controller(MVC)架構(Angular 1)和Model-View-ViewModel(MVVM)架構(Angular 2)。Angular.js通過使用指令擴展HTML的功能來解決開發SPA(單頁應用程序)的問題,此框架強調讓你的app快速完成和運行。目前Angular是最受歡迎的JS框架,你可以一站式使用,它是大型企業的首選框架。

          ReactJS:在塊上的新生兒

          ReactJS是一個開源的JavaScript庫,用于構建高性能的用戶界面,專注于由Facebook引入和提供的驚人的渲染性能。React專注于模型視圖控制器(Model View Controller)架構中的“V”,它是為了解決與其他JavaScript框架的常見問題——大數據集的高效渲染而創建的。React是最輕量級的JS框架,如果你需要逐漸現代化現有的代碼庫,那么這是一個合適的選擇。

          Angular和React功能比較:

          動態UI綁定:Angular允許在純對象或甚至屬性級別使用UI綁定。可以同時更新多個綁定,而不需要耗時的DOM更新;ReactJS直截了當地將狀態直接鏈接到UI。狀態參數作為對象傳遞,并合并到React組件的內部參考狀態。

          可重復使用的組件:Angular組件稱為“指令”,它們比Ember組件強大得多。它們能夠創建你自己語義的和可重用的HTML語法;React在視圖和控制器級別使用mixin,因此組件不必UI相關,并且可能只包含一些實用程序或甚至復雜的程序邏輯。

          路由:Angular需要模板或控制器到其路由器配置,必須手動管理;React不處理路由,但是有很多模塊用于路由,如react-router,flow-router。

          意見:Angular和React都是靈活的意見,給出一點靈活性來實現你自己的客戶端堆棧。

          數據綁定:Angular是雙向綁定,React是單向綁定。

          要選擇哪個框架,需要評估應用程序的需求以及每個框架的優勢,需要深入了解所考慮的每個框架的優點和缺點,以及它們如何在不同用例下競爭。如果你正在決策創建一個Web app,對于長期支持和活躍的社區,Angular、React都是安全的。

          如果你想了解更多Web前端課程內容,可以關注“千鋒鄭州校區”微信公眾號。如果你想參加專業的鄭州Web前端培訓班,可以來千鋒申請長達兩周的免費試聽,親身體驗教學效果!


          主站蜘蛛池模板: 亚洲一区免费视频| 日本一区二区三区在线看| 丰满人妻一区二区三区免费视频| 亚洲av色香蕉一区二区三区| 无码日韩精品一区二区三区免费| 国产成人无码一区二区三区在线| 亚洲AV综合色一区二区三区 | 亚洲乱码日产一区三区| 韩日午夜在线资源一区二区| 色国产精品一区在线观看| 日韩中文字幕一区| 国产在线一区二区视频| 黑人大战亚洲人精品一区| 亚洲狠狠狠一区二区三区| 日韩精品一区二区三区国语自制| 亚洲国产精品一区二区九九| 综合久久一区二区三区 | 男女久久久国产一区二区三区| 99精品一区二区三区| 精品国产日韩一区三区| 国产成人无码AV一区二区 | 国产日本亚洲一区二区三区| 日本一区二区三区久久| 国产免费无码一区二区| 国产香蕉一区二区三区在线视频| 久久精品中文字幕一区| 中文字幕一区在线观看视频| 久久久国产一区二区三区| 精品无码av一区二区三区| 男人的天堂精品国产一区| 一区二区在线观看视频| 国产精品一区二区在线观看| 亚洲A∨无码一区二区三区| 男人的天堂av亚洲一区2区| 国产内射999视频一区| 精品乱码一区内射人妻无码| 蜜桃视频一区二区三区在线观看| 无码人妻一区二区三区在线水卜樱| 无码人妻精品一区二区三区夜夜嗨 | 丝袜美腿一区二区三区| 国产一区二区在线观看app|