1. 程式人生 > >vue、react、angular的區別

vue、react、angular的區別

 

文件正在不停完善中,歡迎各位提建議和修改錯誤。

  vue2.0 react angular2 angular(官方不維護了)
基礎                       Vue.js 的目標是通過儘可能簡單的 API 實現響應的資料繫結和組合的檢視元件。
     
作者 尤雨溪 Facebook Google Google
官網 https://reactjs.org/ https://cn.vuejs.org/ https://www.angular.cn/  
框架 MVVM 不是一個MVC框架,只是其中一個層次(V)。 MVC MVVM
時間 2014 2013 2016 2009
大小 25k 151k 764k 143k
語言 JSX ES5 ES6 JSX ES5 ES6 TypeScript JavaScript
DOM Virtual Vitual    
Mobile Support Weex React Native Ionic Ionic
Designing Templates
JS Centric JS into HTML JS into HTML
資料繫結 雙向 單向 雙向 雙向
Rendering 伺服器端 伺服器端 伺服器端 客戶端
應用場景 對於不會持續的小型的 Web 應用,使用 Vue 能帶來短期內較高的開發效率。 React 配合嚴格的 Flux 架構,適合超大規模多人協作的複雜專案。 面向大型企業應用 適合 SPA,面向較小的應用程式。
優點 o 有完整的官方中文文件。
o 資料雙向繫結思路與 Angular 類似。
o 元件化與資料流則與 React 類似,不同元件間單項資料流可防止主模組資料被汙染。
o 使用腳手架工具 vue-cli 可以快速地構建專案:單檔案 Vue 元件,熱載入,儲存時檢查程式碼,單元測試等,優秀的元件化,配合 router 等大型專案也可以輕易拿下。
o Vue.js 中指令和元件分得更清晰。指令只封裝 DOM 操作,而元件代表一個自給自足的獨立單元(有自己的檢視和資料邏輯)。
o 採用 Virtual DOM 的思路,速度快,效能好。
o 可以直接使用 ES6 的語法,通過 webpack 編譯成瀏覽器相容的 ES5,可以提高開發效率。
o 狀態管理時,都是使用this.setData,簡單直觀。
o React 可以在伺服器上預渲染應用再發送到客戶端。它可以從預渲染的靜態內容中恢復一樣的記錄到動態應用程式中。搜尋引擎的爬蟲程式依賴的是服務端響應而不是 JavaScript 的執行,預渲染你的應用有助於搜尋引擎優化。
React更加關注UI的元件化,能較好的實現程式碼重用。

 
o 有 Angular 1.0 的優點。
o 可以使用 ES6 的語法。
o 可以通過懶載入來引入依賴注入。
o 是一套完整的框架,Angular 有自帶的資料繫結、render 渲染、AngularUI 庫,過濾器,directive(模板),服務 q(defer), http,inject(依賴注入), factory, provide 等等一系列工具。
o 整個框架充滿了 DI 的思路,耦合性非常低。
缺點 o 單項資料流,父子元件或平行元件間傳遞大量資料時需要基於 Vuex。
o 不內建例如 AJAX,Route 等功能到核心包,而是以外掛的方式載入。
o 社群/元件生態相對 Angular 和 React 來說不夠強大,現成的外掛和元件不夠完善。
o 大量資料時,首次渲染效能不如 React。
o 和 Angular 相比,React 的元件比較少,
o React 比較“輕”,只有一個 view 層,當業務比較複雜,需要較完整的框架時,要引入 Flux, Redux。
o 本身內容比較新,API 存在較大變化的風險。
o Angular 的 2.0 版本幾乎是推翻 1.0 版本重做的,要學習大量的東西,如模組、控制器、指令等,學習成本高。
o 新,資料少,缺乏開發經驗。
o 環境搭建耗時。
o 官方不在維護該框架。
腳手架 vue-clivue-iview-cli react-iview angular-cli
安裝:npm install -g @angular/clio React
 
屬性繫結        
資料繫結        
通過分析選擇用vue的原因 通過分析框架的特點並結合專案分析對比後,最終決定選擇 Vue 框架來進行開發。 原因如下:
1. Vue 是通過 Virtual Dom 抽象層來實現頁面渲染,避免了高成本的常規 DOM 操作,儘管 Vue React 都使用了 Virtual Dom 實現這一點,但 Vue Virtual Dom 實現(復刻自 snabbdom)是更加輕量化的,所以在這裡給 Vue 續一秒(查水錶)
2. 對比 Vue React,它們都是 JavaScript 編寫的,聽起來這十分簡單和優雅。然而不幸的事實是,React JavaScript 內的 HTML CSS 會產生很多痛點。JSX vs TemplatesTemplates 可讀性,書寫優雅,邏輯清晰所以給 Vue 再續一秒(+1s)
3. Vue 的一些語法和 Angular 的很相似,但在 API 與設計兩方面上 Vue.js 都比 Angular 1 簡單得多,因此你可以快速地掌握它的全部特性並投入開發。所以 Vue + 1s
4. Angular 1 使用雙向繫結,Vue 在不同元件間強制使用單向資料流。這使應用中的資料流更加清晰易懂。所以 Vue++
5. Angular 2 的學習曲線是非常陡峭的。即使不包括 TypeScript,它的開始指南中所用的就有 ES2015 標準的 JavaScript18 NPM 依賴包,4 個檔案和超過 3 千多字的介紹,這一切都是為了完成個 Hello World。而Vue’s Hello World就非常簡單。甚至我們並不用花費一整個頁面去介紹它。所以如果專案經理選 Angular 2那也只好去學習(ci zhi)
6. jQuery Zepto 不在考慮範圍內。
     
基本構架 <div id="app">
  {{ message }}
</div>
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})
class HelloBox extends React.Component {
  render() {
    return (
      <div>
        Hello {this.props.name}
      </div>
    );
  }
}

ReactDOM.render(
  <HelloBox name="Taylor" />,
  mountNode
);
注意:
1.<script>標籤的type必須為 type="text/babel",因為需要browser.min.js來解析jsx的語法內容
2.MessageBox的首字母必須大寫,否則直接解析成一個標籤,並且不作顯示
3.所有標籤都要閉合
    <MessageBox/>的結束符“/”必須要有
    <br/>
4.
標籤內的class屬性必須寫出className,因為他可能和createClass可能產生衝突
5.樣式必須是駝峰式寫法(fontSize
6.render裡的標籤尤其只有一個分結點(即最外層只能有一個標籤包含其他的標籤)
   
迴圈 v-for
  <div id="app-4">
  <ol>
    <li v-for="todo in todos">
      {{ todo.text }}
    </li>
  </ol>
</div>
.map/for迴圈  ,沒有自己的迴圈語句
<script type="text/babel"> 
        var arr = ["
張三","李四","王五"]; 
        ReactDOM.render( 
            <ul> 
                { 
                    arr.map(function(name){ 
                        return <li>{name}</li> <span style="color:#ff0000;">//
必須要return出來否則在dom中不會顯示</span> 
                    }) 
                }    
            </ul>, 
            document.querySelector("#example") 
        ) 
    </script>  
ngFor
<li *ngFor="let hero of heroes">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
 
鉤子函式(生命週期) 1.beforeCreate 元件例項剛被建立,元件屬性計算之前,如data屬性等(可以在這加個loading事件)
 2.created:元件例項建立完成,屬性已繫結,但DOM還未生成,$el屬性還不存在(在這結束loading,還做一些初始化,實現函式自執行)
3.beforeMount:模板編譯/掛載之前(完成了 el data 初始化)
4.mounted:模板編譯/掛載之後(ajax獲取資料階段。在這發起後端請求,拿回資料,配合路由鉤子做一些事情)
5.beforeUpdate:元件更新之前(指view層的資料變化前,不是data中的資料改變前觸發)
6.updated:元件更新之後(data裡的值被修改後觸發)
7.activatedfor keep-alive,元件被啟用時呼叫
8.deactivatedfor keep-alive,元件被移除時呼叫
9.beforeDestory:元件銷燬前呼叫(你確認刪除XX嗎?)
10.destoryed:元件銷燬後呼叫(Vue例項銷燬。當前元件已被刪除,清空相關內容)
一、Mounted階段:載入階段或者說初始化階段,這個階段元件由jsx轉換成真實的Dom
1.getDefaultProps:設定預設屬性
2.getInitialState:設定預設狀態
3.componentWillMount:元件即將載入時候執行的函式(通常在這裡執行ajax等操作)
4.render:必不可少
5.componentDidMount:元件載入完畢時候執行的函式。

二、Update階段:元件執行中階段,當元件修改自身狀態或者父元件修改子元件屬性時候發生的階段。
1.componentWillReceiveProps:元件將要接受新元件
2.shouldComponentUpdate:元件是否更新
    //元件進行效能提升的時候就是靠 shouldComponentUpdate這個函式
    shouldComponentUpdate:function(nextProps){//是一個問句,要不要隨父元件更新,如果寫了這個函式,即使裡面沒有設定return false/true,都不會隨父元件更新,即預設是return false
        // console.log(nextProps)//
返回{nameinput裡輸入的值}
        console.log('b.shouldComponentUpdate')
        // return false;//
表示子元件不隨父元件不更新,只執行a.b.cde函式都不執行,執行順序為1234d54ab4ab4ab...
        return true;//
表示子元件隨父元件的更新而更新,abcde都執行,執行順序為1234d54abcdeabcde...
    },

3.componentWillUpdate: 元件即將更新
4.render:必不可少
5.componentDidUpdate:元件更新完畢時候執行的函式。

三、Unmount階段:元件解除安裝階段,這個一般是元件被瀏覽器回收的階段。(一般不需要關注的階段)
1.componentWillUnmount:開發者需要來銷燬(元件真正刪除之前呼叫,比如計時器和事件監聽器)
ngOnChanges當被繫結的輸入屬性的值發生變化時呼叫,首次呼叫一定會發生在 ngOnInit之前。(介面:OnChanges)(範圍:指令和元件)
ngOnInit在第一輪 ngOnChanges 完成之後呼叫。 ( 譯註:也就是說當每個輸入屬性的值都被觸發了一次 ngOnChanges 之後才會呼叫 ngOnInit ,此時所有輸入屬性都已經有了正確的初始繫結值 )(介面:OnInit)(範圍:指令和元件)
ngDoCheck在每個 Angular 變更檢測週期中呼叫。(介面:DoCheck)(範圍:指令和元件)
ngAfterContentInit當把內容投影進元件之後呼叫。(介面:AfterContentInit)(範圍:元件)
ngAfterContentChecked每次完成被投影元件內容的變更檢測之後呼叫。(介面:AfterContentChecked)(範圍:元件)
ngAfterViewInit初始化完元件檢視及其子檢視之後呼叫。after initializing the component’s views and child views.(介面:AfterViewInit)(範圍:元件)
ngAfterViewChecked每次做完元件檢視和子檢視的變更檢測之後呼叫。(介面:AfterViewChecked)(範圍:元件)
ngOnDestroy Angular 每次銷燬指令 / 元件之前呼叫。(介面:OnDestroy)(範圍:指令和元件)
 
路由 vue-router
官網:https://router.vuejs.org/zh-cn/
routes.js
1.引入模組
    import Home from './components/Home.vue';
    import User from './components/user/User.vue';
2.
定義路由並暴露介面
    export const routes = [     {path:'/',component:Home,name:'home'},//name給路由設定名字,為了方便router-link的時候不用拼接字串,方便些     {path:'/user',component:User,children:[// /user      user下的模組
            {path:"",component:UserStart},// /user/
            {path:":id",component:UserDetail},// /user/:id           {path:":id/edit",component:UserEdit,name:'userEdit'}// /user/:id/edit
        ]}
]
    Notice:url
設參(/:id)
   
接參:在對應的component後的.vue中,本處為User.vue

main.js
3.1引用下載的VueRouter和配置的路由(routes.js
    import VueRouter from 'vue-router';//1.引用路由模組
    import {routes} from './routes';//3.引用路由配置變數
3.2使用
    Vue.use(VueRouter);//2.
3.3
建立router例項,然後傳routes配置引數
    const router=new VueRouter({//4.建立例項
    routes//routes:routes的簡寫  //5.將路由變數例項化成路由物件
    })
3.4
new Vue中例項化router
    new Vue({
      el: '#app',
      router,
      render: h => h(App)
    })


app.vue裡的html裡顯示路由
<router-view></router-view>      
   

 知識點:     
app.vue主元件中顯示路由內容需要用<router-view></router-view> 來進行渲染
在路由中設定
name屬性後可以利用router-link來設定:to引數,以便跳轉到指定的元件模組
react-router
官網:https://github.com/ReactTraining/react-router2
分為router2router4
本處將router2
index.js(入口檔案)
var React = require('react');
var ReactDOM = require('react-dom');

//
引入路由部分
var Router = require('react-router').Router;//路由的模組
var Route = require('react-router').Route;//路由
var hashHistory = require('react-router').hashHistory;

//
引入模組
var App = require('./modules/App')
var About = require('./modules/About')
var Repos = require('./modules/Repos')

var Index = React.createClass({
    render:function(){
        return(
            <Router history = {hashHistory}>
                <Route path="/" component={App}/>
                <Route path="/about" component={About}/>
                <Route path="/repos" component={Repos}/>               
            </Router>
        )
    }
})
ReactDOM.render(<Index/>,document.getElementById('app'))


App.js
1.引入連結
var Link = require('react-router').Link;
2.render
下的div標籤內寫點選連結跳轉的程式碼
<ul>
    <li><Link to="/about">About</Link></li>
    <li><Link to="/repos">Repos</Link></li>                   
</ul>
 
 router4
3.App.js裡面直接引用
3.1引用
import {Home} from './Components'
3.2div
裡換成
    ReactDOM.render(
    <BrowserRouter>{/*BrowserRouter
相當於2.0Router*/}
        <div>
            <ul>
                <li><NavLink to="/" activeClassName="active">Home</NavLink></li>
            </ul>
            <Route path="/" component={Home} exact={true}/>{/*Route
4.0是拿來渲染的,相當於2.0{this.props.children}。在2.0是拿來設定路由的。*/}
        </div>
    </BrowserRouter>,
document.getElementById('app')
)
angular/router二函式。
官網:
https://www.angular.cn/guide/router
案例:
index.html
<base href="/">
.module.ts(import)
import { RouterModule, Routes } from '@angular/router';
.module.ts(except)
const appRoutes: Routes = [
  { path: 'crisis-center', component: CrisisListComponent },
  { path: 'hero/:id',      component: HeroDetailComponent },
  {
    path: 'heroes',
    component: HeroListComponent,
    data: { title: 'Heroes List' }
  },
  { path: '',
    redirectTo: '/heroes',
    pathMatch: 'full'
  },
  { path: '**', component: PageNotFoundComponent }
];

@NgModule({
  imports: [
    RouterModule.forRoot(
      appRoutes,
      { enableTracing: true } // <-- debugging purposes only
    )
    // other imports here
  ],
  ...
})
export class AppModule { }

.compontent.ts(template)//實現點選跳轉
  <h1>Angular Router</h1>
  <nav>
    <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
    <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
  </nav>
  <router-outlet></router-outlet>

注意:path不能以斜槓(/)開頭
 
路由的鉤子函式 全域性鉤子函式:
before each:意思是在 每次每一個路由改變的時候都得執行一遍。
它的三個引數:

to: (Route路由物件即將要進入的目標 路由物件    to物件下面的屬性: path   params  query   hash   fullPath    matched   name    meta(在matched下,但是本例可以直接用)
from: (Route路由物件當前導航正要離開的路由
next: (Function函式)   一定要呼叫該方法來 resolve 這個鉤子。  呼叫方法:next(引數或者空)   ***必須呼叫
next(無引數的時候):  進行管道中的下一個鉤子,如果走到最後一個鉤子函式,那麼  導航的狀態就是 confirm

afterEachafter 鉤子沒有 next 方法,不能改變導航,代表已經確定好了導航怎麼去執行後,附帶的一個執行鉤子函式

元件內的鉤子函式:(
beforeRouteEnter beforeRouteLeave 再加一個 watch函式
每個路由都有Enter和Leave鉤子,使用者進入或離開該路由時觸發。
1.onEnter鉤子函式
<Route path="inbox" component={Inbox}>
  <Route
    path="messages/:id"
    onEnter={
      ({params}, replace) => replace(`/messages/${params.id}`)
    }
  />
</Route>
 

2.setRouteLeaveHook方法為Leave鉤子指定routerWillLeave函式   
componentDidMount() {
        this.props.router.setRouteLeaveHook(
            this.props.route,
            this.routerWillLeave
        )
    }

    routerWillLeave(nextLocation) {
        return '
確認要離開?';
    }
Router Event路由器事件(即鉤子函式)
NavigationStart本事件會在導航開始時觸發。
RoutesRecognized本事件會在路由器解析完URL,並識別出了相應的路由時觸發
RouteConfigLoadStart 本事件會在Router對一個路由配置進行惰性載入之前觸發。
RouteConfigLoadEnd本事件會在路由被惰性載入之後觸發。
NavigationEnd本事件會在導航成功結束之後觸發。
NavigationCancel本事件會在導航被取消之後觸發。 這可能是因為在導航期間某個路由守衛返回了false
NavigationError這個事件會在導航由於意料之外的錯誤而失敗時觸發。

路由器部件
Router(路由器):為啟用的URL顯示應用元件。管理從一個元件到另一個元件的導航
RouterModule(路由器模組):一個獨立的Angular模組,用於提供所需的服務提供商,以及用來在應用檢視之間進行導航的指令。
Routes(路由陣列):定義了一個路由陣列,每一個都會把一個URL路徑對映到一個元件。
Route(路由):定義路由器該如何根據URL模式(pattern)來導航到元件。大多數路由都由路徑和元件類構成。
RouterOutlet(路由出口):該指令(<router-outlet>)用來標記出路由器該在哪裡顯示檢視。
RouterLink(路由連結):該指令用來把一個可點選的HTML元素繫結到路由。 點選帶有繫結到字串或連結引數陣列的routerLink指令的元素就會觸發一次導航。
RouterLinkActive(活動路由連結):當HTML元素上或元素內的routerLink變為啟用或非啟用狀態時,該指令為這個HTML元素新增或移除CSS類。
ActivatedRoute(啟用的路由):為每個路由元件提供提供的一個服務,它包含特定於路由的資訊,比如路由引數、靜態資料、解析資料、全域性查詢引數和全域性碎片(fragment)。
RouterState(路由器狀態):路由器的當前狀態包含了一棵由程式中啟用的路由構成的樹。它包含一些用於遍歷路由樹的快捷方法。
連結引數陣列:這個陣列會被路由器解釋成一個路由操作指南。我們可以把一個RouterLink繫結到該陣列,或者把它作為引數傳給Router.navigate方法。
路由元件:一個帶有RouterOutletAngular元件,它根據路由器的導航來顯示相應的檢視。
 
ajax資料請求 axios,resource      
ref傳值       
 1.傳值
 <input type="text" value="除錯 vuejs 2.0" ref="input1">  
 
 2.
接參
this.$refs.input1可以訪問到該元件例項,其實就是dom元素節點。
1.傳值
<input ref="myInput" />
 
 2.
接參
var input = this.refs.myInput;
 0
 0 0
 0 0
 0 0
 0 0
 0
 
url傳參 方法一:
this.$router.push({
                        name: 'routePage',
                        query/params: {
                            routeParams: params
                        }

方法二:
兩種方式
<a v-link="{ name: 'history', params: { deviceId: deviceId, dataId: dataId }}">history</a>
學習網址:http://blog.csdn.net/qq_23158083/article/details/68488831
 

.props.params 
 傳一個物件:
 1.在路由設定裡
    <Route path='/user/:data' component={UserPage}></Route>
2.在跳轉檔案裡
import {Link,hashHistory} from 'react-router';
var data = {id:3,name:sam,age:36};
data = JSON.stringify(data);
var path = `/user/${data}`;

方法一:<Link to={path}>使用者</Link>>
 
方法二:ashHistory.push(path);
3.
在跳轉到的檔案裡:
接參:var data = JSON.parse(this.props.params.data);
var {id,name,age} = data;

傳一個值:
 1.在路由設定裡
    <Route path='/user/:name' component={UserPage}></Route>
2.
在跳轉檔案裡
import {Link,hashHistory} from 'react-router';
方法一:<Link to="/user/sam">使用者</Link>
 
方法二:hashHistory.push("/user/sam");
3.
在跳轉到的檔案裡:
接參:
this.props.params.name
 
 
二、query
 1.在路由設定裡
    <Route path='/user' component={UserPage}></Route> 
2.
在跳轉檔案裡
import {Link,hashHistory} from 'react-router';
 var data = {id:3,name:sam,age:36};
var path = {
  pathname:'/user',
  query:data,
}

方法一:<Link to={path}>使用者</Link>
 
方法二:hashHistory.push(path);
3.
在跳轉到的檔案裡:
接參:
var data = this.props.location.query;
var {id,name,age} = data;
 

.state
 1.在路由設定裡
    <Route path='/user' component={UserPage}></Route>
2.
在跳轉檔案裡
import {Link,hashHistory} from 'react-router';
var data = {id:3,name:sam,age:36};
var path = {
  pathname:'/user',
  state:data,
}

方法一:<Link to={path}>使用者</Link>
 
方法二:hashHistory.push(path);
3.
在跳轉到的檔案裡:
接參:
var data = this.props.location.query;
var {id,name,age} = data;
state
方式依然可以傳遞任意型別的資料,而且可以不以明文方式傳輸。
   
url引數的獲取方法  this.$route.params
例如:
ready: function(){
        console.log('deviceid: ' + this.$route.params.deviceId);
        console.log('dataId: ' + this.$route.params.dataId);
    }
  this.props.
例如:
router4的獲取引數值方式
       { this.props.match.params.id }
   
router2的獲取方式
      參考網址:http://blog.csdn.net/starwmx520/article/details/50772943
      //
通過this.props.params.XX
     //
通過this.props.location.query.XX
   
         
  vuex redux    
含義 Vue中,多元件的開發給我們帶來了很多的方便,但同時當專案規模變大的時候,多個元件間的資料通訊和狀態管理就顯得難以維護。而Vuex就此應運而生。將狀態管理單獨拎出來,應用統一的方式進行處理,在後期維護的過程中資料的修改和維護就變得簡單而清晰了。Vuex採用和Redux類似的單向資料流的方式來管理資料。使用者介面負責觸發動作(Action)進而改變對應狀態(State),從而反映到檢視(View)上      
  State設定狀態,但它不會進行直接狀態的修改。負責儲存整個應用的狀態資料,一般需要在使用的時候在跟節點注入store物件,後期就可以使用this.$store.state直接獲取狀態  
  
mapState 輔助函式。當一個元件需要獲取多個狀態時候,將這些狀態都宣告為計算屬性會有些重複和冗餘。為了解決這個問題,我們可以使用 mapState 輔助函式幫助我們生成計算屬性,讓你少按幾次鍵
    ...mapState使用物件展開運算子將此物件混入到外部物件中

 Getter  只獲取狀態,不做任何修改
 mapGetters 輔助函式
   
Mutation   
    }    }   }   
   commit
:提交載荷、】store.commit('increment', 10)  
    }    }   }
Action   
    }    }   }   
    }    }   }
Module   
    }    }   }   
    }    }   }
   
    }    }   }
   
    }    }   }
   
    }    }   }
   
    }    }   }
   
    }
     http://blog.csdn.net/sinat_17775997/article/details/54943797
    }   }
   
    }
   }
   
    }   }
   
    }   }
   
    }   }
   
    }   }
   
    }   }
   
    }
   
  State
Getter
Mutation
Action
Module
     
angular2       MVC