vuejs angularjs 框架的一些比較(vue項目重構四)

使用Angularjs和Vue.js對比

首先須要說明的是:如今默認angularjs指angular1.0+版本,angular默認指2.0以上版本。本文的名詞也默認指定angular的1.0+版本。javascript

先讓咱們看一下 這兩個框架的設計上的一些不一樣。php

Angularjs

  • 1,MVC框架
  • 2,模塊化(Module)控制器(Contoller)依賴注入:這種模塊話的注入,其實在代碼層面上顯得並不夠整潔,好比我任何一個控制器controller 裏面其實要注入不少的服務。
  • 3,雙向數據綁定:界面的操做能實時反映到數據,數據的變動能實時展示到界面。
  • 4,指令(ng-click ng-bind ng-model ng-href ng-src ng-if/ng-show...),能夠自定義指令Directive,比jQuery插件要靈活,可是須要深刻了解Directive的一些特性,簡單的封裝容易,複雜一點官方沒有提供詳細的介紹文檔,咱們能夠經過閱讀源代碼來找到某些咱們須要的東西,如:在directive使用 $parse;
  • 5,服務Service($compile $filter $interval $timeout $http...)
  • 6,路由(ng-Route原生路由),ui-router(路由組件)
  • 7,Ajax封裝($http)
  • 8,使用於一些增刪改查的管理系統開發。

缺點:css

1:其中雙向數據綁定的實現使用了$scope變量的髒值檢測,使用$scope.$watch(視圖到模型),$scope.$apply(模型到視圖)檢測,內部調用的都是digest,固然也能夠直接調用$scope.$digest進行髒檢查。值得注意的是當數據變化十分頻繁時,髒檢測對瀏覽器性能的消耗將會很大,官方註明的最大檢測髒值爲2000個數據。html

2:ngView只能有一個,不能嵌套多個視圖,雖然有 angular-router解決,可是貌似ui-router 對於URL的控制不是很靈活,必須是嵌套式的。前端

3:ng提倡在控制器裏面不要有操做DOM的代碼,對於一些jQuery 插件的使用,若是想不破壞代碼的整潔性,須要寫一些directive去封裝插件。但其實咱們在tms裏,控制器對dom的操做仍是有很多的,其實按理說 這些操做應該被封裝爲指令去進行。vue

4:Angular 太笨重了,沒有讓用戶選擇一個輕量級的版本,固然1.2.X後,Angular也在作一些更改,好比把route,animate等模塊獨立出去,讓用戶本身去選擇。像animate 這個是一個動畫的插件,咱們在tms裏用的仍是比較少的。java

Vue

vue.js官網:是一套構建用戶界面的 漸進式框架。與其餘重量級框架不一樣的是,Vue 採用自底向上增量開發的設計。Vue 的核心庫只關注視圖層,而且很是容易學習,很是容易與其它庫或已有項目整合。另外一方面,Vue 徹底有能力驅動採用單文件組件和 Vue 生態系統支持的庫開發的複雜單頁應用。node

Vue.js 的目標是經過儘量簡單的 API 實現響應的數據綁定組合的視圖組件ios

  • (1)模塊化,目前最熱的方式是在項目中直接使用ES6的模塊化,結合Webpack進行項目打包 
  • (2)組件化,創造單個component後綴爲.vue的文件,包含template(html代碼),script(es6代碼),style(css樣式)
  • (3)雙向數據綁定:界面的操做能實時反映到數據,數據的變動能實時展示到界面。
  • (4)指令(v-html v-bind v-model v-if/v-show...)
  • (5)路由(vue-router)
  • (6)vuex 數據共享
  • (7)Ajax插件(vue-resource,axios)

vue很是小巧,壓縮後min源碼爲72.9kb,gzip壓縮後只有25.11kb,想比Angular爲144kb,能夠自駕搭配使用須要的庫插件,相似路由插件(Vue-router),Ajax插件(vue-resource,axios)等angularjs

模塊引入的對比:

//好比:angularjs  舉一個service服務的栗子

(function() {
  ydCreditApp.factory('myCarService', function($resource, configuration, $http) {  // 其實可以在這裏看到,$resource 等的依賴注入了。
      var myCarList=$resource(configuration.apiBaseUrl+'/api/tms/car/listCars',{
      },{
          get:{
              method:'GET'
          }
      });
      var carDetail=$resource(configuration.apiBaseUrl+'/api/tms/car/getCar',{
      },{
          get:{
              method:'GET'
          }
      });
 return {
          myCarList:myCarList,
          carDetail:carDetail

    })
})()
// 在這個栗子中,咱們啓用了一個名爲myCarService的服務。而後在須要的地方,好比myCarCtr.js文件裏,即控制器裏,調用這個myCarService模塊時:

(function() {
    ydCreditApp.controller('myCarController', function($scope,myCarService) { 
     myCarService.myCarList.get({ params },function(data) {
               console.log(data) // 後臺返回的數據
           }
 }
});

// vue 好比我想把vue裏的一個組件 或者說某個單獨的js文件裏的一些信息給輸出,想在別的地方調用 。舉一個api文件栗子 文件位置是:api/index.js

export default {

  //報銷主體
  getCompany(params) {
    return fetchGet('/api/oa/reimburse/getAllCompanyName', params)
  },
    //用戶登陸
  Login(params) {
    return fetchPost('/api/oa/login', params)
  },
    ...
}

// 在想引入的文件裏這樣寫

import API from 'api文件的路徑'

// 這樣在欲使用這個api文件裏 就可使用 API.getCompany() API.Login() 等方法            

固然 至於 export與import的寫法並不止這一個,能夠在須要的時候,看看其餘文件 好比 mian.js文件 ,或者是router下的indexjs文件,項目裏不少文件也都會有這種寫法 可以看懂 而且將想要的模塊引入便可。

另外:對於前端模塊化的解釋 是這樣的:

前端模塊化其實就是將一個完整的單一的功能整合起來造成單獨的一個功能組件,當須要用的的時候只須要加載這個組件,而後即可以經過該組件惟一的名稱去使用其中的內容。 像咱們的angularjs裏的myCarService  myCarCtr 其實都是一個模塊。vue裏的那個Api/index.js 也是一個模塊。其實關於前端模塊化 還有幾個模塊化框架的 好比:commomJs AMD CMD ES6規範。像剛纔介紹的angularjs的那種 包含 依賴 回調 特徵的 採用的是異步模塊定義 (AMD) 像咱們的vue 採用的就是如今最新的ES6模塊化。

Vue與 Angular 雙向數據綁定原理

angular.js :髒值檢查

angular.js 是經過髒值檢測的方式比對數據是否有變動,來決定是否更新視圖,咱們知道,更新頁面最簡單的方法莫過於設置一個定時器,規定多久時間以後去進行更新頁面,angularjs做爲一個google開發的框架,確定也不會這樣作,angular實現雙向綁定,是在一些特定的事件觸發下進行的,好比

  • DOM事件,譬如用戶輸入文本,點擊按鈕等。( ng-click )
  • XHR響應事件 ( $http )
  • 瀏覽器Location變動事件 ( $location )
  • Timer事件( $timeout , $interval )
  • 執行 $digest() 或 $apply()

vue :數據劫持

vue.js 則是採用數據劫持結合發佈者-訂閱者模式的方式,經過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變更時發佈消息給訂閱者,觸發相應的監聽回調。

寫法上的一些比較

首先固然是Hello World了

1:數據的綁定 

在數據的綁定層面 均可以使用 {{  }} 這個特殊的字符來表明某個要被綁定的數據 這個像jsp裏的 ${ messgae }

vue

<div id="app">
  {{ message }}
</div>

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})

Angularjs

<div ng-app="myApp" ng-controller="myCtrl">
 {{message}}
</div>

var app = angular.module('myApp', []);  // 在咱們的tms裏 這個app  就是 咱們的 ydapp
app.controller('myCtrl', function($scope) {
    $scope.message = "Hello world";
});

 

相比較來看,vue採用了json的數據格式進行dom和data的編寫,編寫風格更加靠進js的數據編碼格式,通俗易懂。

2:數據的雙向綁定

兩者在實現的原理上是有差距的,剛纔也已經介紹

vue的雙向數據綁定

<div id="app">
  <p>{{ message }}</p>
  <input v-model="message">
</div>

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})

 

Angularjs的雙向數據綁定

<div ng-app="myApp" ng-controller="myCtrl">
  <p>{{message}}</p>
  <input ng-model="message">
</div>

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
    $scope.message = "Hello world!";
});

 

在雙向綁定這一個層面上,其實也是差很少的,只是,angularjs須要引入一個$scope 做用域,全部的數據都綁定在$scope這一個特殊的符號上。

3:事件綁定方面

咱們知道 在angular裏,官方提供的指令的形式都是形如 ng-事件的形式,但vue裏,支持一些簡寫的方式

angularjs

<a ng-click = 'greet(param) '></a> 

vue:

<a v-on: click="fn"></a> 簡寫方式: <a @click="fn"></a>

 

不過在vue裏,咱們須要知道一個vue的周期函數 ,好比這個方法greet要被寫在一個名爲methods的實例屬性。就像上面的data屬性寫法同樣。

 
 
<div id="example-2">
<!-- `greet` 是在下面定義的方法名 -->
<button v-on:click="greet">Greet</button>
</div>

//
example2 就是一個實例
var example2 = new Vue({
  el: '#example-2',
  data: {
    name: 'Vue.js'
  },
  // 在 `methods` 對象中定義方法
  methods: {
    greet: function (event) {
      // `this` 在方法裏指向當前 Vue 實例
      alert('Hello ' + this.name + '!')
      // `event` 是原生 DOM 事件
      if (event) {
        alert(event.target.tagName)
      }
    }
  }
})

// 也能夠用 JavaScript 直接調用方法
example2.greet() // => 'Hello Vue.js!

 

固然 vue裏面還有其餘不少的簡寫方式,可是基本上也能像angularjs裏面的同樣 , 將 ng- 改成 v- 也就好了。

自定義指令:

angularjs
angular.module('app', []).directive('myDirective', function() {
    return {
    restrict:String,                
    priority:Number,
    terminal:Boolean,
    template:String or Template Function,
    templateUrl:String or Template Function,
    replace:Boolean or String,
    transclude:Boolean,
    scope:Boolean or Object,
    controller:String or function(scope, element, attrs, transclude, otherInjectables) { ... },
    controllerAs:String,
    require:String,
    link: function(scope, iElement, iAttrs) {
        //進行一些時間的綁定渲染等
    },
    compile:function(tElement, tAttrs, transclude) {
        return {
            pre: function(scope, iElement, iAttrs, controller) { ... },
            post: function(scope, iElement, iAttrs, controller) { ... }
           }
        return function postLink(...) { ... }
        }
    };
    
vuejs
// 註冊一個全局自定義指令 `v-focus`
Vue.directive('focus', {
  // 當被綁定的元素插入到 DOM 中時……
  inserted: function (el) {
    // 事件
  }
})

 

4:渲染列表的寫法

vue.渲染列表

<div id="app">
  <ul>
    <li v-for="name in names">
      {{ name.first }}
    </li>
  </ul>
</div>

new Vue({
  el: '#app',
  data: {
    names: [
      { first: 'summer', last: '7310' },
      { first: 'David', last:'666' },
      { first: 'Json', last:'888' }
    ]
  }
})

Angularjs渲染列表

<div ng-app="myApp" ng-controller="myCtrl">
  <li ng-repeat="name in names">{{name.first}}</li>
</div>

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
    $scope.names = [
      { first: 'summer', last: '7310' },
      { first: 'David', last:'666' },
      { first: 'Json', last:'888' }
    ]
});

看的出來 其實也是沒有多大的區別的

5:循環寫法

vue的循環

<ul>
    <li v-for="item in list">
        <a :href="item.url">{{item.title}}</a>
    </li>
</ul>

angularjs循環

<div class="item" ng-repeat="item in list">
    <a ng-href="{{item.url}}">{{news.title}}</a>
</div>

vue和Angular處理用戶輸入

<div id="app">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">Reverse Message</button>
</div>

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
})

 


<div ng-app="myApp" ng-controller="myCtrl">
 <p>{{ message }}</p>
 <button ng-click="reverseMessage()">Reverse Message</button>
</div>

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
    $scope.message = "Hello world!";
    $scope.reverseMessage = function() {
        this.message = this.message.split('').reverse().join('')
    }
});

 以上也基本上是一些寫法上的比較。

6:路由

angularjs

angularjs自帶的路由是ngRouter 可是這個路由不能完成多視圖 與 嵌套視圖 。緣由是在於,ngRouter的每一個視圖 不能有惟一的標誌,當視圖發生變化時,全部的視圖都會變爲同樣的視圖。

後來有了ui.router 幫助來完成這些功能。

多視圖:頁面能夠顯示多個動態變化的不一樣區塊。

  <div ui-view></div>
  <div ui-view="main"></div>

$stateProvider
    .state('home', {
        url: '/',
        views: {
            '': {
                templateUrl: 'views/home'
            },
            'main': {
                template: 'views/main'
            }
        }

嵌套視圖:在main視圖裏,繼續添加其餘的視圖,該視圖是一個獨立的區域。

  <div ui-view></div>
  <div ui-view="main">
    我是父視圖
    <div ui-view='home'></home>
  </div>
$stateProvider
    .state('main', {
        abstract: true,
        url: '/main',
        templateUrl: 'views/main.html'
    })
    .state('main.home', {
        url: '/home',
        templateUrl: 'views/home.html'
    });

傳參:

.state('main.myWork', {
                        url: '/myWork/:page/:mobile/:name/:sendCity/:arriveCity',
                        params: { page: null, mobile: null,name:null,arriveCity:null,sendCity:null},
                        templateUrl: 'views/myWork/myWorkList.html',
                        controller: 'myWorkController',
                        ncyBreadcrumb: {
                            label: '審批待辦',
                            parent: 'main'
                        },
                        data: {
                            requiredLogin: true
                        }
                    })

在ui.router裏面,經過 parent.child 肯定父子視圖的關係。

vue

vue所提倡的官方路由是:vue-route,也能夠本身選擇本身的路由。

首先來看這個圖片,這個圖片 包括了 三個同級的視圖。在內容部分 也有三個視圖組件被引入。能夠說 是體現出了vue的視圖的嵌套與多視圖的特性。

多視圖:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-view class="view two" name="a"></router-view>
    <router-view class="view one"></router-view>
    <router-view class="view three" name="b"></router-view>

  </div>
</template>
App.vue
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
const Data = () => import('../components/Data.vue')

const Bar = { template: '<div>子路由<router-view /></div>' };
const car = { template: '<div>孫子路由</div>' };
const d = { template: '<div>我是頭部</div>' };
const f = { template: '<div>我是底部</div>' };
Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name:'首頁',
      components: {
        default: HelloWorld,
        a:d,
        b:f
      }
    }
    ,{
      path:'/content',
      name:'數據',
      component:Data,
      children:[{
        path:'h',
        component:Bar
      }]
    }
  ]
})
router/index.js
<template>
  <div class="hello" style="border:1px solid red">
    我是內容
    <div style="background-color: green">
      <p>我是內容引入的組件部分</p>
      <head-top></head-top>
      <content-view></content-view>
      <footer-view></footer-view>
    </div>

  </div>
</template>

<script>
  import headTop from './headTop'
  import footerView from './footer'
  import contentView from './content.vue'
 export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  components:{
    headTop,
    contentView,
    footerView
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
內容部分的vue文件

路由的嵌套

通常來講 

就拿上面的代碼來講 ,其中的name屬性是路由的名稱,path:‘h’  指定的是路由地址 /content/h  component 就是你註冊引入的組件模塊

 

 

7:與服務器的通訊

angularjs

 angularjs提供了對ajax請求的封裝 $http 服務  固然 這個params能夠傳遞的參數有不少,能夠根據須要去定義一些傳值。

好比:

<script>
var app = angular.module('myApp', []);
app.controller('siteCtrl', function($scope, $http) {
  $http.get("http://www.runoob.com/try/angularjs/data/sites.php",{params})
  .then(function (response) {$scope.names = response.data.sites;});
});
</script>

咱們在tms裏,大多數使用的是$resource服務,這個是引入的一個模塊

<script type="text/javascript" src="/javascripts/angular-resource.js">

咱們在如今的tms實際的打包時,也常常會因爲這個包拉不下來 致使打包失敗,這個咱們也已經有了優化的方案。這裏也再也不細說。

 下面時$resource在tms系統裏使用的一個栗子

var myCarList=$resource(configuration.apiBaseUrl+'/api/tms/car/listCars',{
    params },{ get:{ method:
'GET' } });

vue

vue跟服務端的通訊 有 vue-resource插件,可是在vue2.0以後 就再也不維護這個插件,官方也推薦使用axios。一款基於promise(‘承諾於將來發生’的一個對象)的http請求客戶端,可同時在瀏覽器和nodejs中使用。

一樣 咱們也須要引入這個插件模塊。

// 安裝 axios
$ npm install axios
// 在要使用的文件中引入axios
import axios from 'axios'

 看一下axios的寫法把 一個基於promise的新寫法:

axios.get('/user', {
// params也能夠不要的
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

 

 

 固然 對應的還有post請求 都是相似的寫法。

vuex 是vue的一個狀態管理工具

爲何vue 須要一個這樣的工具

 

這個工具怎麼使用

待續...

父子組件之間的通訊

 vue

 

angularjs

相關文章
相關標籤/搜索