vue、react、angular的區別
阿新 • • 發佈:2018-11-19
文件正在不停完善中,歡迎各位提建議和修改錯誤。
vue2.0 | react | angular2 | angular(官方不維護了) | |
基礎 | Vue.js 的目標是通過儘可能簡單的 API 實現響應的資料繫結和組合的檢視元件。 |
|||
作者 | 尤雨溪 | |||
官網 | 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-cli,vue-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 Templates,Templates 可讀性,書寫優雅,邏輯清晰…所以給 Vue 再續一秒(+1s)。 3. Vue 的一些語法和 Angular 的很相似,但在 API 與設計兩方面上 Vue.js 都比 Angular 1 簡單得多,因此你可以快速地掌握它的全部特性並投入開發。所以 Vue + 1s。 4. Angular 1 使用雙向繫結,Vue 在不同元件間強制使用單向資料流。這使應用中的資料流更加清晰易懂。所以 Vue++。 5. Angular 2 的學習曲線是非常陡峭的。即使不包括 TypeScript,它的開始指南中所用的就有 ES2015 標準的 JavaScript,18個 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.activated:for keep-alive,元件被啟用時呼叫 8.deactivated:for 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)//返回{name:input裡輸入的值} 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 分為router2和router4 本處將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.0的Router*/} <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 afterEach:after 鉤子沒有 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方法。 路由元件:一個帶有RouterOutlet的Angular元件,它根據路由器的導航來顯示相應的檢視。 |
|
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 | |||