zoukankan      html  css  js  c++  java
  • 关于angular1与angular2的应用区别

    angular1.0的这些繁杂的api,还有它的执行速度,运行效率,学习曲线,都被人吐槽,最近一直在用ng1,实在很想吐槽。

    最近写ng2的项目,写了一些ng2基础的应用(包括angular-cli,路由,表单验证,组件通信,ajax,服务/指令,lazyload)demo,地址在->点我

    学了一下angular2,看它有什么区别呢?

    我就不复述网上一堆的对比言论了,我仅仅对我项目里用到的一个点来进行阐述。

    有个需求就是一个radio对应一个input标签,比如有两对。

    我需要选中1的时候传输1的value,选中2的时候传2的vaule。当选中1,2的input必须置空,选中2的时候1可以有值。还需要拿到数据以后还能显示回这个页面。

    ng1做的时候要radio俩ngModel,input俩ngModel,你需要判断radio是不是被选中。input的ngModel就不用管了。(好的办法是用事件代理,这样在传输数据没问题,很简单,数据回显的时候就要根据数据推radio的选中情况了,不操作dom的情况下还需要加ngModel,不过也是没办法的事,不然改交互好了)

    重要的一点是你必须$watch radio对应ngModel,如果没被选中,那2框置空。。坑的是如果我有好几个表单,我需要循环表单$watch!!!!坑死了。性能超差。(因为可能在代码里修改radio对应的ngModel来手动完成radio的唯一性,不然也不需要watch,事件代理也一样坑,回显的时候也必须手动维护一个数组来模拟radio的原生特性,但是可以避免$watch,因为发送请求数据不需要radio的状态,所以正在强烈建议重构这个页面)

    开始ng2-----------------------------------------------------------------

    ng2一个好的点就是ngModel的转变,它做的很棒的一点是单项绑定和双向绑定的选择,ngModel也是。()是数据到模板的绑定,[ngModel]是模板到数据的绑定。

    ng2有Attribute, Class, and Style 绑定,Event Binding。而且都是可以拼接字符串或者在binding里面写表达式,甚至是函数,比如:

      ckass(){
          return " abc dec"
      }

    <input type="text"  #spy1 [ngClass]="'hahaha'+ckass()" />

    想用的心已经蠢蠢欲动了。。

    普通的双向绑定如ng1是这样写

    <input type="text" [(ngModel)]="input" />

    重要的是它可以拆开:

    <input type="checkbox" [ngModel]="input" (ngModelChange)="handleChange()"/>
     {{ input }}

    (ngModelChange)是啥,它里面可以随便写吗?

    答案是不能。借用雪狼大叔的翻译:安利一下angular.live

    ngModelChange并不是<input>元素的事件。 它实际上是一个来自ngModel指令的事件属性。 当Angular在表单中看到一个[(x)]的绑定目标时, 它会期待这个x指令有一个名为x的输入属性,和一个名为xChange的输出属性。

    双向绑定的指令都会有一个xxChange的属性,它可以修改绑定。比如我们给它加个条件,如果radio选中了,就可以绑定啦, 不然你就是空吧。

    <button class="batton" (click)="handleClick($event)"> click me</button>
    <input type="checkbox" [ngModel]="input" (ngModelChange)="handleChange()"/>
    <input type="text" [(ngModel)]="input" [disabled]="!check" />
      {{ input }}
    export class AppComponent {
      check = false;
      handleChange(){
        this.check = !this.check;
        if(!this.check) {
          this.input = "";
        }
      }
      handleClick(e: any) { 
         this.check = false;
      }
    }

    这里留一个button来解决程序修改radio状态的问题。可以看到,我们的handleChange其实就做了一个手动绑定的工作。如果没选中给置空。

    运行你会发现,点击click me,input的内容并木有置空,因为radio的修改不是模板到数据的过程,是数据到模板的过程。

    没关系,[ngModel]的单项绑定仍然可以自己控制,比如:

    @Component({
        selector: 'my-app',
        template: `
      <button class="batton" (click)="handleClick($event)"> click me</button>
    
      <input type="checkbox" [ngModel]="handleCheck()" (ngModelChange)="handleChange()"/>
      <input type="text" [(ngModel)]="input" [disabled]="!check" />
      {{ input }}
      `,
        styles: [``]
    })

    又来了个handleCheck,这是ng1的ngModel不能搞定的。反正不支持处理函数。

    那ng2咋写:

    export class AppComponent {
      check = false;
      handleCheck(){
        if (!this.check) {
          this.input = "";
        }
      }
      handleChange(){
        this.check = !this.check;
        if(!this.check) {
          this.input = "";
        }
      }
      handleClick(e: any) { 
         this.check = false;
      }
    }

    我们在数据到模板的绑定只需要判断是否选中就可以了,这样就避免了$watch。

    还有一些表达方式的不一样,主要是因为都换成ts了,一些类似es6的语法都开始发挥作用。

    1.模块注入

     因为es6的语法,去掉了ng1的依赖注入,改为模块化的注入,import语法

    import { Component } from '@angular/core';
    export class AppModule { }

    2.模块化

    由于ng2的模块化,原本模块化不那么明显的ng1的语法要改变很多,模块都作类,新增了注解语法,

    @Component({
      selector: 'hero',
      templateUrl: 'component.html'
    })
    export class HeroFormComponent {
       ...  
    }

    Component注解规定了这个模块的selector,和模板template,然后把这个类做控制器。

    3.数据展示

    基本类似ng1,双花括号的展示方式

    import { Component } from '@angular/core';
    @Component({
      selector: 'my-app',
      template: `
        <h1>{{title}}</h1>
        <h2>My favorite hero is: {{myHero}}</h2>
        `
    })
    export class AppComponent {
      title = 'Tour of Heroes';
      myHero = 'Windstorm';
    }

    只是模板选择器写在了注解里,控制器为此类。

    然后这个类就可以做为一个模块使用,其实就是ng1的组件型指令

    <my-app>loading...</my-app>

    另外,template里的一些自带指令也是类似ng1,只是写法不同,除了上面写的绑定意外,再说一个ngFor

    template: `
        <h1>{{title}}</h1>
        <h2>My favorite hero is: {{myHero}}</h2>
        <p>Heroes:</p>
        <ul>
          <li *ngFor="let hero of heroes">
            {{ hero }}
          </li>
        </ul>
      `

    就是类似ng-repeat的作用了。只是换了个语法,看文档就好了。

    4.dom事件

    为了使键盘事件比较方便,然后自己封装进了ng2,vue已做此工作

    <input #box
          (keyup.enter)="update(box.value)"
          (blur)="update(box.value)">

    其余的事件都是类似的,带有()括号的单向绑定。

    5.服务

    服务也有点差距,注入和声明有点不同,此为声明

    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class HeroService {
    ... }

    当 TypeScript 看到@Injectable()装饰器时,就会记下本服务的元数据。 如果 Angular 需要往这个服务中注入其它依赖,就会使用这些元数据。

    使用服务首先引入服务

    import { HeroService } from './hero.service';

    然后需要在注解里注册一下

     providers: [HeroService]

    然后在这个类中就可以使用这个服务了

    export class AppComponent implements OnInit {
      title = 'Tour of Heroes';
      heroes: Hero[];
    
      constructor(private heroService: HeroService) { }
      getHeroes(): void {
        this.heroService.getHeroes().then(heroes => this.heroes = heroes);
      }
      ngOnInit(): void {
        this.getHeroes();
      }
    }

    6,生命周期

    ng2增加了很多生命周期,如上面的ngOnInit等等,都是ng1没有的,就不介绍了

    7,http

    跟ng1类似ng2也是封装了ajax到http,不同的是现在的ng2可以用rxjs了。。rxjs好像贵族的东西,用的人很少,学习成本不低,但是好用。ng2的http不是封装的promise了,而是简化的rx的Observable,需要subscribe来执行他的请求。也可以引入rx的toPromise,然后then下去就可以了。有点强破推销的意思。

    8.管道

    其实就是ng1的filter。

    import { Pipe, PipeTransform } from '@angular/core';
    /*
     * Raise the value exponentially
     * Takes an exponent argument that defaults to 1.
     * Usage:
     *   value | exponentialStrength:exponent
     * Example:
     *   {{ 2 |  exponentialStrength:10}}
     *   formats to: 1024
    */
    @Pipe({name: 'exponentialStrength'})
    export class ExponentialStrengthPipe implements PipeTransform {
      transform(value: number, exponent: string): number {
        let exp = parseFloat(exponent);
        return Math.pow(value, isNaN(exp) ? 1 : exp);
      }
    }

    @Pipe装饰器告诉Angular:这是一个管道,管道类实现了PipeTransform接口的transform方法,该方法接受一个输入值和一些可选参数,并返回转换后的值。transform方法返回就处理后的值。

    9.路由

    路由配置没什么说的,跟着文档一步步来就好了,由于是import的引入,不存在ng1包含路由很大的情况,根据配置来就好了。这种框架的路由都是类似的。

    10. 组件交互

    ng1现在都忘记了,主要说一下ng2的组件交互。

    父传子的交互方式是靠props来传递的,这点跟react一样了,子组件的状态是纯靠输入,这是material的分页组件,在子组件里需要用装饰器来取,@input。下面例子就有

    <md-paginator #paginator
                                [length]="xxx"
                                [pageIndex]="0"
                                [pageSize]="10"
                                [pageSizeOptions]="[10]">
                </md-paginator>
    

     子传父组件是不建议的,但也有很多需求,比如打开一个子组件做modal,然后modal关闭的时候回传给父组件数据,对于react的方案一个是redux,另一个包括ng1也在用的就是事件系统。都有各自的事件系统,

    但是ng2的事件系统最为强大,因为它是rxjs。

    这里给一个例子:subject就是rxjs的对象。关于rxjs的介绍另有博文:rxjs-流式编程

    @Component({
      selector: 'wap',
      template: '<app-add-warp [subject]="subject" ></app-add-warp>'
    })
    export class addWarpComponent {
      
        subject = new Subject();
        constructor() {
          this.subject.subscribe({
            next: (v) => console.log(v)
          });
        };
    }
    @Component({
      selector: 'app-add',
      templateUrl: './add.component.html',
      styleUrls: ['./add.component.scss']
    })
    export class AddComponent implements OnInit {
        @Input('subject') cbSubject:Subject<any>;
         constructor() {
        }
        ngOnInit() {
              this.cbSubject.next(this.user);   
        }    
      }
    }    

    subscribe就是触发事件要执行的东西,next方法就是触发事件的点。

  • 相关阅读:
    【转载】总结一下Android中主题(Theme)的正确玩法
    Android获唯一标识
    AS问题解决系列3—iCCP: Not recognizing known sRGB profile
    AS问题解决系列1—Unable to execute DX错误
    Android Studio Error2
    Android Error
    NAT简单介绍
    redis缓存工具Jedis进行跨jvm加锁(分布式应用)--不幸暂弃用--能够做第三方锁使用
    工作总结1.怎样高效跟客户确定需求?
    Sqoop处理Clob与Blob字段
  • 原文地址:https://www.cnblogs.com/dh-dh/p/5535323.html
Copyright © 2011-2022 走看看