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

相关文章
相关标签/搜索