• angular4.0


    angular4的安装

    1. 确保node和npm都是最新版的,我的是用nvm来管理node.
      所以用:
    nvm install stable #安装最新版node
    nvm install 8.4.0 # 安装8.4.0版本的node
    nvm ls #列出可使用的node
    nvm use 8.4.0 #使用8.4.0版本的node;
    
    1. 设置淘宝镜像
        npm configset registry https://registry.npm.taobao.org
    
    1. angular-cli是typescript写的,需要typescript的环境
        npm install -g typescript typings
    
    1. 安装angular-cli.angular-cli是angular4专属的命令工具
        npm install -g angular-cli@latest  //如果用bash安装失败的话,可以在桌面使用命令行工具cmd,来安装
    
    1. 安装好后,就多了一个命令ng.可以用来创建angular4项目
        ng new angulardemo
    
    1. 创建完成,就可以开启服务器,运行angular4项目了
        npm run start
    
    1. 如果要下载确定版本的angular-cli,比如1.0.0.可以用
        npm install -g angular-cli/@1.0.0
    
    1. angular官网文档
        https://www.angular.cn/
    

    在angular4中引入jquery库和bootstrap

    1. 在angular-cli.json文件中app下面的styles数组里面是引入的css文件.scripts数组是引入的js文件.比如要
      引入jquery库的话,就把jquery对应的地址写在scripts数组里,要引入bootstrap库的话,就把js文件加入到scripts数组中
      css文件加在styles数组中;
    2. 因为angular4是typescript环境,所以jquery和bootstrap要使用的话,需要下载对应的typescript解析器;

    jquery: npm install @types/jquery --save-dev

    bootstrap: npm install @types/bootstrap --save-dev

    路由

    子路由

    { path : "home", component: HomeComponent,
        children: [
            {path: "list", component: HomeList},
            {path: "create", component: HomeCreate},
        ]
    }
    

    主路由在跳路由时,路径是直接写的<a [routerLink]="['/product']">详情</a>

    如果是子路由在同级之间跳转,路径是以./开头的,比如product下面有create和list,路径不用写product/list,而是./list
    <a [routerLink]="['./list']">详情</a>

    路由对象

    路由的五个对象

    1. routes : 保存路由配置信息,就是angularJs里面的router文件
    2. RouterOutlet: 在html中标记路由内容呈现位置的占位符,就是标记路由控制的范围标记
    3. Router: 跳转路由链接用的,在controller里面用
    4. RouterLink: 跳转路由连接用和Router一个作用,区别是在html中的a标签上使用
    5. ActivatedRoute: 路由跳转时,从一个路由到另一个路由跳转时,保存的路由的参数信息和angularJs的$stateParams类似;

    这里面的路由,配置的是路径和组件的对应关系,而不是和模块的对应
    path:"user" (path不能以/开头) 如果path: "**",通配符匹配,必须放在最后面
    compoent:"A"

        <a [routerLink]="['/']">主页</a>
        <a [routerLink]="['/product']">详情</a>
        <router-outlet></router-outlet>
        [routerLink] 的[]表示属性绑定
        <button (click)="handler()"><button>事件绑定
    

    在 app.components.ts文件中的组件类函数中添加

    constructor(private router: Router) {}//导入router对象
    handler(){
          this.router.navigate(["/product"])
    }   //设置handler函数,路由跳转
    

    在路由中传递数据

    1. 在查询字符串中传递

    /product?id=1&name=2 => ActivatedRoute.queryParams[id]

    <a [routerLink] = "['/product']"  [queryParams]="{id: 1}"></a>
    
    export class ProductComponent implements Oninit {
        private productId: number;
        construct (private routeInfo: ActivatedRoute){}
        ngOnInit(){
            this.productId = this.routeInfo.snapshot.queryParams["id"];
        }
    }
    
    1. 在路径中传递数据

    {path: /product/:id} => /product/1 => ActivatedRoute.params[id]

    <a [routerLink] = "['/product', 1]"></a>
    
    this.id = this.routeInfo.params["_value"]["id"];
    
    1. 在路由配置中传递数据
      {path: /product, component: ProductComponent, data:[{isProd: true}]}
      => ActivatedRoute.data[0][isProd]

    依赖注入

    注入器和提供器

    1. 注入器
    //在组件类中的构造函数中,注入服务;
    constructor(private productService: ProductService){}
    
    1. 提供器
    //在
    providers: [{provide: ProductService, useClass: ProductService}]
    // 可以简写成
    providers: [ProductService]
    //useClass实例化方式,new谁. provide是token,就是在构造函数中声明的ProductService1;
    

    服务的创建,依赖注入

    1. 创建服务:
        ng g service shared/product
    

    在shared文件夹中创建一个product的服务;
    2. 声明提供器

    • 在主模块中声明. 在app.modules.ts文件的主模块装饰器中.
      所有的组件都可用.最常用.
    @ngModule({providers:[productService]})
    
    • 在单个组件中.在组件的装饰器中.只有该组件及其子组件可用.少用
    @Component({providers: [{provide: ProductService, useClass: AnotherProductService}]})
    
    1. 声明注入器
    export class productComponent implements Oninit{
        product: product; //声明变量
    
        //在构造函数中注入服务
        constructor(private productService: productService){}
        ngOnInit(){
            this.product = this.productService.getProduct();
        }
    }
    
    • 在服务中的装饰器@injectable()表示可以再注入其他的服务;

    数据绑定

    属性绑定

    angular4的属性绑定
    <img [src]="imgUrl">
    用[]把src属性包起来,[src]就是angular4的属性绑定,可以直接使用在此组件中定义的imgUrl的值;
    css类属性绑定
    <span *ngFor="let star of stars" class="btn" [class.primite] = "star">
    [class.promite] = "star"是说span标签有没有css类promite,取决于star是不是true。和ng-class类似;
    用[]把组件中的数据,绑定到模板上

    export class BindComponent implements OnInit{
        name: string;   //值
        constructor(){}
        ngOnInit()
    }
    
    <input [value]="name">
    
    //从组件到模板
    

    事件绑定

    用()把组件中的事件绑定到组件中的方法中

    <input (input)="doOnInput($event)">
    
    export class BindComponent implements OnInit{
        constructor(){}
        ngOnInit()
        doOnInput(event) {}
    }
     //单项绑定,从模板到控制器
    

    双向绑定

    <input [(ngModel)]="name">
    
    export class BindComponent implements OnInit{
        name: string;
        constructor(){}
        ngOnInit()
        doOnInput(event) {}
    }
    

    在标签中用[(ngModel)],在组件类中直接定义:name: string;不在contructor中,也不在哪个钩子中;

    表单验证

    模板式表单

    在装饰器中导入FormsModule

    @NgModule({
        imports: [
            FormsModule,
            HttpModule,
            ...
        ]
    })
    

    模板式表单只能用指令来定义数据模型,以下三个指令都来自FormsModule

    1. NgForm : 代表整个表单,自动的添加到form标签上。跟angular1一样;
      可以加在div上
      与form标签功能相同.
      如果不想要angular接管form标签可以加一个ngNoForm.
    2. NgModel : 双向数据绑定,标记一个标签成为数据模型的一部分
    3. NgModelGroup

    在表单用使用ngModel

     <input type="checkbox" ngModel #isHost="ngModel" name="isHost"> {{isHost.value}}
     <div class="form-group" *ngIf="isHost.value"> </div>
    

    在input标签中添加ngModel和name属性,把该标签的数据添加到表单数据模型中
    用#isHost="ngModel" 把标签的值暴露给页面模板,如果没有这个属性就没办法在html页面上用{{isHost}}显示出来;

    响应式表单,

    在装饰器中导入ReactiveFormsModule

    @NgModule({
        imports: [
            ReactiveFormsModule,
            HttpModule,
            ...
        ]
    })
    

    创建响应式表单需要两步

    1. 创建一个数据模型
    2. 在模板上链接这个数据模型;

    创建数据模型

    数据模型由FormControl, FormGroup,FormArray这三个类型组成;

    1. FromControl,对应指令FormGroup,FromGroupName
      代表一个表单元素的值和状态
    export class CdAppPublishComponent implements OnInit {
    	username: FormControl = new FormControl("aaa") //新建一个表单元素,初始值为"aaa"
    	formModel: FormGroup = new FormGroup({      //新建一个FormGroup
    	    form: new FromControl(),
    	    to: new FromControl(),
    	})
    	emails: FormArray = new FormArray([
    	    new FormControl("a@a.com"),
    	])
    
    }
    
    1. FormGroup,对应的指令 formControl, formControlName
      代表多个表单(FormControl)的集合,或整个表单;
    2. FormArray 对应的指令: formArrayName;
      代表一个可以增长的表单集合;只能通过序号来访问;
    3. 使用的指令与模板式表单不同
      formGroupName,FormControlName,formArrayName,都是通过表单的name属性来链接的;
    4. 响应式表单不能用"isHost"="ngModel"的方式在页面模板上使用,只能在代码中操作,
      而模板式表单只能再页面模板上使用不能在代码中操作;

    组件

    创建组件

    1. angular4的命令行工具angular-cli,可以帮助我们创建组件
    ng g component navbar
    

    创建一个navbar导航组件;会在app文件夹中直接创建一个navbar文件夹,里面是相应的文件;
    创建后会自动注入到appModules父组件中

    组件间的数据传递

    把父组件中的数据传递给子组件;
    <app-stars [rating] = "product.rating">
    app-stars这个组件的rating属性是由父组件的product.rating传递来的
    在app-stars组件的构造函数的钩子OnInit中设置
    @Input
    private rating: number = 0;
    rating变量是number类型,初始化值是0,私有数据,
    由父组件传入(@Input输入装饰器);
    也就是说装饰器是直接写在一个变量,构造函数的上面起作用的

    组件的输入属性

    输入属性是指被input装饰器注解的属性;用来从父组件接受数据.属性绑定是单向的,从父组件到子组件

    在子组件中

    //
    import { Component,ngOnInit, Input } from "@angular/forms";
    //引入Input装饰器,没错装饰器也需要引入;
    
    export class OrderComponent implements OnInit{
    
        //用输入装饰器修饰这两个变量,表示这两个值是从父组件传入的;
        @Input()
        storkCode: string;
    
        @Input()
        amount: number;
    
        constructor(){};
        ngOnInit(){}
    }
    
        <div>买{{amount}}个 {{storkCode}}</div>
    

    在父组件中

    export class AppComponent {
        stock = "";
    }
    
    <div>我是父组件</div>
    <input type="text" placeholder= "请输入股票代码" [(ngModel)]= "stock" >
    <app-order [stockCode]="stock" [amount]="100"></app-order>
    

    从父组件到子组件传递数据的两种方式

    1. 属性绑定
      只有形成了父子组件关系才能在标签上传递数据,在子组件中数据的是声明在组件类中作为自身的一个属性来获取的;
             storkCode: string;```
      
    2. 通过路由
      路由参数是通过构造函数来传递的;需要在构造函数中传入对象ActivatedRoute,
      用这个对象,再通过参数快照或参数订阅来获取到数据
    constructor(routeInfo: ActivatedRoute) {
    }
    ngOnInit(){
            this.productId = this.routeInfo.snapshot.queryParams["id"];
    }
    

    组件的各个部分的说明

    //js运行环境,引入要使用的组件(Component),钩子(ngOnInit),装饰器(Input)
    import { Component,ngOnInit, Input } from "@angular/forms";
    /*
    1. export导出,使外部可以使用这个对象
    2. class表示这是一个对象的类,里面的属性(比如title)都是this.title.
    里面的函数比如console(){console.log("123")}都是this.console;
    而上面的this(实际上并不存在)指的是用这个组件类实例化出来的组件
    3. 在export class OrderComponent implements OnInit{}是一个对象,不是函数。里面不能直接运行js.
    要运行js的话应该在constructor(){console.log("这里面")}或者是ngOnInit(){}里面;
    */
    export class OrderComponent implements OnInit{
        //这里面定义的变量,函数,都是可以爆露在组件实例的模板上的值;constructor是构造函数。
        //ngOnInit是当初始化是运行的函数钩子;
        //用输入装饰器修饰这两个变量,表示这两个值是从父组件传入的;
        @Input()
        storkCode: string;
        @Input()
        amount: number;
        constructor(){};
        ngOnInit(){}
    }
    

    组件中的OnChanges函数

    组件中的OnChanges函数,能监控自身组件的值的变化,也能监控父组件传入的值的变化。
    要被OnChanges函数监控,要满足下列条件

    1. 首先要在本身组件类函数中定义了变量;
    2. 由于某种方式发生了改变,或者有父组件传入,或者是再本组件中有input标签和双向数据绑定;
    3. 变量的值类型是简单数据类型,如果是复杂数据类型,比如对象。那么对象属性的改变了,这个变量本身的数据指向并没有发生改变。所以不会被OnChanges函数监控到;但是值依然会改变,因为组件还有监控机制;
    export class ChildComponent implements OnInit, OnChanges {
        greeting: string;
        user: {name: string};
        constructor(){}
        //changes是ngOnChanges的参数,监控到的变化信息存储在里面。SimpleChanges是
        //changes的数据类型;
        ngOnChanges(changes: SimpleChanges): void {
            console.log(changes);
        }
        //changes的数据模型如下所示
        {
            "greeting": {
                "previousValue": {},
                "currentValue": "Hello"
            }
        }
    }
    

    angular的变更检测机制和DoCheck钩子

    1. 要使用angular的变更检测需要在package.json的dependecies中添加zone.js
    2. 在angular应用中的任何改变,事件,异步都会触发变更检测;
    3. 变更检测有两种策略。
      • 一是默认的Default,在组件中的任何地方的变化都会引起整个应用的所有组件的检测
      • 还有OnPush策略。只有输入属性发生改变的时候才会进行自身和子组件的变更检测;
    4. 一个例子
    ngDoCheck(): void {
        if(this.user.name !== this.oldUser.name) {
            console.log("改变了“)
        }
    }
    
    1. 要注意的是ngDoCheck这个钩子的使用,要非常的小心,他的代码要非常的轻量级,
      逻辑需要非常的清晰。因为整个应用的任何一个组件的改变,事件等,都会触发所有组件的ngDoCheck钩子
      甚至鼠标在页面上随意点几下都会触发。很容易造成非常大的性能消耗;
    2. 在所有的钩子中,只要名字里有 Check 这个字段。都会有上门面第五条的性能问题
      包括: ngAfterContentChecked, ngAfterViewChecked,ngDoCheck;
    3. 综上ngDoCheck这个钩子不适合做三级联动

    组件的钩子ngAfterViewInit, ngAfterViewChecked

    1. ngAfterViewInit视图组装完成之后的初始化,ngAfterViewChecked视图组装后的检测
    2. ngAfterViewInit只会在初始化时调用一次,ngAfterViewChecked会在每次视图变更之后调用
    3. 这两个都是在视图组装完毕之后调用的;
    4. 如果一个组件有子组件,只有子组件的这两个钩子调用完之后,父组件的这两个钩子才会被调用
    5. angular不允许在一次变更流程中,在视图组装完毕后再去改变视图。
      简单的说就是不能再这两个钩子中去改变组件中挂载到视图中的值,否则会报错。如果一定要这么做
      可以把改变值的行为放在一个setTimeout里面;在异步流程中改变;
        message: string;
        ngAterViewInit(): void {
            setTimeout(() => {
                this.message = "hello";
            }, 0)
        }
    

    父组件使用子组件提供的方法;

    1. 子组件
    export class ChildComponent{
        greeting(name: string) {
            console.log(name)
        }
    }
    
    1. 父组件的模板
    <app-child #child1></app-child>
    <app-child #child2></app-child>
    
    1. 父组件的组件类
    export class ChildComponent{
        @ViewChild("child1")
        child1: ChildComponent;
        ngOnInit(): void {
            this.child1.greeting("tom")
        }
    }
    

    父子组件之间的投影,ng-content

    1. 子组件
    <div>
        我是子组件
        <ng-content select=".header"><ng-content>
        <ng-content select=".footer"><ng-content>
    </div>
    
    1. 父组件
    <div>
        我是父组件
        <app-child>
            <div class="header">这是页头,这个div时父组件投影到子组件中的内容,title: {{title}}</div>
            <div class="footer">这是页脚,这个div时父组件投影到子组件中的内容</div>
        </app-child>
    </div>
    <div [innerHTML] = 'divContent'> </div>
    
    export class AppComponent {
        title = "app works";
        divContent = "<div>慕课网;</div>"
    }
    
    1. 在父组件的模板中app-child里面的内容就会出现在子组件的标签的位置
      和angular1的置换指令ng-transclude类似;
    2. 如果子组件中有多个来自父组件的投影,那么可以用select="css选择器"来区分;
    3. 在本组件中,可以用[innerHTML]属性来把组件类中的html字符串,现式出来;

    组件的钩子ngOnDestroy

    1. 这个钩子会在路由变动导致页面上不再显示本组件时调用
    2. 一般用来销毁setTimeout,setInterval之类的;

    组件的生命周期;

    1. constructor,ngOnChanges, ngOnInit, ngDoCheck这四个函数依次执行,用来
      构建组件的属性。进行属性初始化
      • constructor实例化对象
      • ngOnChanges初始化输入属性;
      • ngOnInit初始化除了输入属性以外的其他所有的属性;
      • ngDoCheck做一次变更检查,进行到这里时组件的所有的属性都被赋值了;
    2. ngAfterContentInit, ngAfterContentChecked会在投影完成之后调用。是构建dom树,顺序是从父到子。类似angular1的compile阶段
      此时还可以对组件的值进行改变;
    3. ngAfterViewInit,ngAfterViewChecked,是视图构建完成之后调用。
      类似angular1的link阶段;此时就不能对组件的值进行改变了,如果非要改变就在setTimeout里面改;
    4. 在应用上的任何组件的任何行为不管是修改值,异步操作,事件,都会导致所有的组件
      的所有带有Check字段的钩子的执行;
    5. 如果应用的行为导致了组件输入属性的变化,会引发ngOnChanges的执行;
  • 相关阅读:
    6.Spark streaming技术内幕 : Job动态生成原理与源码解析
    5.Spark Streaming流计算框架的运行流程源码分析2
    4.Spark Streaming事务处理
    2.Spark Streaming运行机制和架构
    1.Spark Streaming另类实验与 Spark Streaming本质解析
    3.spark streaming Job 架构和容错解析
    35.Spark系统运行内幕机制循环流程
    unity3d 扩展NGUI Tweener —— TweenFillAmount
    unity3d 赛车游戏——复位点检测
    unity3d CarWaypoints插件
  • 原文地址:https://www.cnblogs.com/bridge7839/p/7484466.html
Copyright © 2020-2023  润新知