Strive for the first wheels in Angular 5

Github:github.com/OrangeXC/ud… Link: incompetent-plantation.surge.sh/

The latest wheel is more designed to give beginners a reference example, according to the current feedback, if the technology stack does not match, few people will click in to read, we can consider changing the blog type in the future.

I wrote a post about Angular2 from Build to development, which got 4th place in the Top Writer articles list for Q4 2016 on segmentFault, and now angular 5

The common perception is that big releases cause breaking change, because Angular goes from 1.x to 2.x with two frames.

Angular 1.x is angular.js, and angular 2.x will be angular, hosted on two Github repOs.

Js star is close to Angular double, and the community is thriving. This article is looking for components that work with Angular 5. The framework has just been updated, and the corresponding components have not been updated yet.

Angular 2 to 4 to 5, the number of components decreases exponentially, but the good news is that it can be easily extended backwards, so this project is completely understandable if you are familiar with Angular 2.

In fact, who can write wheels to see the document, I try to say more pits, let developers less pit.

Roll up your sleeves.

Setting up the development environment

NPM install - g @ presents/[email protected]Copy the code

Here you point the version directly to 1.5.0

ng new PROJECT-NAME
cd PROJECT-NAMECopy the code

At this point the dependency is installed. Run ng -v and you can see the following

ng serveCopy the code

By default, port 4200, you can see the initialization page.

The installation process may take a long time. You are advised to install YARN on the local PC first. During dependency installation, the CLI automatically uses YARN to install dependencies, which is much faster.

It’s ready to be developed here.

The development of

The public interface of udAO dictionary is deprecated, the interface presented here is unofficial and supports limited functionality

The UI library is ng-bootstrap, and ngx-loading is used

There will be a dependency version inconsistency warning during installation, as follows

Angular [some component] is an angular 1. X component named ng-ng2 -, Search NGX -[some component].

Ng-bootstrap supports only bootstrap4, which supports 3 and 4. In order to avoid version disputes, Ng-bootstrap is used directly.

Far from proving that Angular 5 can use the library, my criteria is Angular 4. If it supports Angular 4, then 90% support Angular 5, because the changes are really small.

routing

There are only four routes involved in this project so far.

  • /The home page
  • /translatetranslation
  • /searchFuzzy search
  • /detail/:wordDetails of the word

Define routes under app.module.ts

const routes: Routes = [
  {
    path: ' '.component: HomeComponent
  }, {
    path: 'translate'.component: TranslateComponent
  }, {
    path: 'search'.component: SearchComponent
  }, {
    path: 'detail/:word'.component: DetailComponent
  }
]Copy the code

Here’s the problem with routing jumps. Angular 5 still has a-tag jumps and JS jumps

  • A Label
@Directive({ selector: ':not(a)[routerLink]' })
class RouterLink {
  queryParams: {[k: string]: any}
  fragment: string
  queryParamsHandling: QueryParamsHandling
  preserveFragment: boolean
  skipLocationChange: boolean
  replaceUrl: boolean
  set routerLink: any[]|string
  set preserveQueryParams: boolean
  onClick(): boolean
  get urlTree: UrlTree
}Copy the code

Examples of this project:

<li class="nav-item">
  <a class="nav-link" routerLink="/" routerLinkActive="active" [routerLinkActiveOptions] ="{exact: true}">The home page</a>
</li>
<li class="nav-item">
  <a class="nav-link" routerLink="/translate" routerLinkActive="active">translation</a>
</li>
<li class="nav-item">
  <a class="nav-link" routerLink="/search" routerLinkActive="active">search</a>
</li>Copy the code

[routerLinkActiveOptions]=”{exact: true}”. [routerLinkActiveOptions]=”{exact: true}”.

  • Js writing
class Router {
  constructor(rootComponentType: Type<any>|null, urlSerializer: UrlSerializer, rootContexts: ChildrenOutletContexts, location: Location, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Routes)
  get events: Observable<Event>
  get routerState: RouterState
  errorHandler: ErrorHandler
  navigated: boolean
  urlHandlingStrategy: UrlHandlingStrategy
  routeReuseStrategy: RouteReuseStrategy
  onSameUrlNavigation: 'reload'|'ignore'
  config: Routes
  initialNavigation(): void
  setUpLocationChangeListener(): void
  get url: string
  resetConfig(config: Routes): void
  ngOnDestroy(): void
  dispose(): void
  createUrlTree(commands: any[], navigationExtras: NavigationExtras = {}): UrlTree
  navigateByUrl(url: string|UrlTree, extras: NavigationExtras = {skipLocationChange: false}) :Promise<boolean>
  navigate(commands: any[], extras: NavigationExtras = {skipLocationChange: false}) :Promise<boolean>
  serializeUrl(url: UrlTree): string
  parseUrl(url: string): UrlTree
  isActive(url: string|UrlTree, exact: boolean): boolean
}Copy the code

Examples of this project:

gotoDetail ({ entry }) {
  this.router.navigate([`/detail/${entry}`])}Copy the code

Both examples are the easiest to use compared to an overview of the documentation, so you can look at other methods if you need to, and basically cover all routing requirements.

request

Unlike Vue and React, Angular provides a front-end full stack solution that includes HTTP modules and only needs to be introduced in app.module.ts

import { HttpClientModule } from '@angular/common/http'

// ...
imports: [
  HttpClientModule
]
// ...Copy the code

The syntax of the request is also very simple, you can go to Github to see the code.

The ngOnInit hook does not trigger the request for update when the route is changed.

The following code

ngOnInit () {
  this.route.params.subscribe((params) = > {
    this.loading = true

    const apiURL = `https://dict.youdao.com/jsonapi?q=${params['word']}`

    this.http.get(` /? url=The ${encodeURIComponent(apiURL)}`)
    .subscribe(res= > {
      // set component data

      this.loading = false})})}Copy the code

Invalid because there are no written before this. The route. Params. Subscribe ((params) = > {}), so every time not trigger monitor

Subscribe listens for this.route.params all the time.

Request path

As with Axios’ baseURL, we don’t want to write the full path for each request at request time, and need to configure the global baseURL to keep the request path short.

Angular needs @Injectable. Dependency injection is a familiar concept. We’ve written about it in articles

@Injectable()
export class ExampleInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const url = 'https://proxy-oagpwnbkpe.now.sh'

    req = req.clone({
      url: url + req.url
    })

    return next.handle(req)
  }
}
// ...
providers: [
  AppComponent,
  { provide: HTTP_INTERCEPTORS, useClass: ExampleInterceptor, multi: true}]// ...Copy the code

This code solves the baseURL problem.

Forward requests

Notice here in the previous section that const URL = ‘https://proxy-oagpwnbkpe.now.sh’, the root path is not the path to dao.

A layer of Node proxy processing is still done. Cross-domain issues still need to be addressed.

The code for the Node service is also very simple, using fly for node side requests

The following code

const express = require('express')
const fly = require('flyio')
const app = express()

app.use('/'.async (req, res) => {
  const data = await fly.get(req.query.url).then(res= > res.data)

  res.set('Access-Control-Allow-Origin'.The '*')

  res.send(data)
})

app.listen(process.env.PORT || 3001)Copy the code

The key is to set an access-Control-allow-Origin: * in the return header so that the browser does not block the request.

The data flow

On the detail page, five subcomponents are split, and of course the parent component is a very simple one-way data flow

Example: The HTML of the parent component is as follows

<app-detail-phrs-list-tab [simple] ="simple" [ec] ="ec"></app-detail-phrs-list-tab>Copy the code

The component.ts of the child component looks like this

export class DetailPhrsListTabComponent {
  @Input() simple
  @Input() ec
}Copy the code

I can use @input to get the value that the parent component passed in. So how do I manage global state, depending on the complexity of the project

Simple global state management can create a global.ts and then dependency injection, as follows

// globals.ts
import { Injectable } from '@angular/core';

@Injectable()
export class Globals {
  role: string = 'test';
}Copy the code

This can be called in a component

// hello.component.ts
import { Component } from '@angular/core';
import { Globals } from './globals';

@Component({
  selector: 'hello'.template: 'The global role is {{globals.role}}'.providers: [Globals]
})

export class HelloComponent {
  constructor(private globals: Globals) {}
}Copy the code

Another approach is the global state management libraries familiar to SPA developers, such as Flex, Redux

Angular also provides Angular-Redux, recommended for use in complex applications.

Package online

The package command provides several configuration parameters around ng build, which will not be described here.

The deployment uses surge

A word of caution: Do not deploy private projects to such public services; there are many drawbacks.

conclusion

Either front-end framework has its advantages. Since the project is small and there is no chance of unleashing the power of RXJS, angular-CLI has installed this library by default and is very efficient in handling complex asynchronous data flows.

The related documents

The documentation for this Angular 5 update is as follows

IO /docs: blog.angular. IO /version-5-0… Official CLI: github.com/angular/ang…

Go over the wall as far as you can. The domestic angular.cn/ documentation hasn’t been updated yet.