【问题标题】:How to transition an angularJS application to angular如何将 angularJS 应用程序转换为 angular
【发布时间】:2018-06-22 01:57:13
【问题描述】:

我目前在 AngularJS (https://next.plnkr.co/edit/qpyvZuvI8vw8q6on?open=lib%2Fscript.js&preview) 中定义了一个简单的搜索功能,但我希望将此功能迁移到现有的 Angular 应用程序中。我创建了一个新的 Angular 应用程序并将视图移动到 app.component.html

  <head>
    <script src="./script.js"></script>
  </head>

  <h1> Search Feature </h1>

  <body ng-app="search" ng-cloak>
     <div id="content" ng-controller="MainCtrl">
        <input type='text' ng-model='searchText' placeholder=" Enter Query Here  " />  
          <ul>
            <li class="angular-with-newlines" ng-repeat="course in courses | filter:searchText"> 
              {{course.course_number}}: {{course.title}}
              <button ng-click="course.showDesc=!course.showDesc">See More</button> 
              <div ng-if="course.showDesc"> Description: {{course.description}} </div>
         </li>
      </ul>
    </div>
  </body>

然后我将控制器代码移动到一个名为script.js的javascript文件中

import angular from 'angular';

angular.module('search', []).controller('MainCtrl', function($scope) {

  $scope.courses = [
        {
            id: 1,
      course_number: '54 Mathematics',
      title: 'Linear Algebra and Differential Equations',
      description: 'Basic linear algebra; matrix arithmetic and determinants. Vector spaces; inner product as spaces.',
      keywords: 'determinants, linear, equations, inner, basic, spaces, partial, order'
        },
        {
            id: 2,
      course_number: '110 Mathematics',
      title: 'Linear Algebra',
      description: "Matrices, vector spaces, linear transformations, inner products, determinants.",
      keywords: "determinants, forms, products, eigenvectors, linear"
        },
        {
           id: 3,
      course_number: '89A Statistics',
      title: 'Linear Algebra for Data Science',
      description: 'An introduction to linear algebra for data science.',
      keywords: 'ranking, prob, network, document, algebra, basics, model, matrices,'
        }

    ];
});

但是,我无法访问控制器中定义的任何数据,并且应用程序无法运行。我对 Web 开发比较陌生,所以这不起作用,因为我需要将我的 javascript 代码转换为 typescript 吗?还是我需要以不同的方式导入我的代码?

感谢任何输入!谢谢!

【问题讨论】:

  • 如果您是 Angular 新手,您应该知道 AngularJS (version=2) 只是名称相似。没有一种语法是兼容的。当时很多批评是他们应该使用一个新名称,而不是试图利用 AngularJS 的流行度来搭便车。但我想这对他们有用。 HTML 模板有些相似,如果您搜索“如何在 Angular 2 中使用ng-something”之类的内容,通常会找到等价的模板。我猜那个过滤器不好。声明模块、控制器和注入范围都是不同的。
  • 两者有很大不同。您可能必须重写所有内容......即使 Angular 与它的 alpha 版本相比也发生了很大变化,而 1.5 年前,无论是否使用 Angular,开发人员都非常沮丧,因为每次更新都会发生如此迅速的变化。但是感谢上帝,当前的框架非常稳定。新事物总是有可能出现,但这不会影响已经编写的代码,因为 Angular 团队还担心向后兼容性。
  • 是的,即使您看到“angular 2, 4, 5, 6”,也只是因为semver,它们在大多数情况下几乎相同并且向后兼容。只是 1.x 是完全不同的野兽。

标签: javascript angularjs angular typescript angular-controller


【解决方案1】:

我需要学习一些角度,所以我尝试将其转换为学习努力。一步一步:

  1. 创建新项目ng new test
  2. Angular 中有管道函数,但没有管道过滤器,所以我们必须创建一个。 (cd 测试)ng generate pipe search(我通过列出所有可生成的 ng generate --help 来发现这一点。
  3. 经过一番搜索,我了解到要使用“ng-model”,您需要将“FormsModule”添加到您的应用程序中。在 app.module.ts 中:import { FormsModule } from "@angular/forms"; 并更新 @NgModule 导入:... imports: [ BrowserModule, FormsModule ], ...
  4. 更新了app.component.html 以使用我们的模板:

<div id="content"> <input type='text' [(ngModel)]='searchText' placeholder=" Enter Query Here" /> <ul> <li class="angular-with-newlines" *ngFor="let course of courses | Search:searchText"> {{course.course_number}}: {{course.title}} <button (click)="course.showDesc=!course.showDesc">See More</button> <div *ngIf="course.showDesc"> Description: {{course.description}} </div> </li> </ul> </div>

如果您知道旧模板的工作原理,那么我认为这些更改是不言自明的。这需要一点研究,但几乎所有东西都与 AngularJS 相同,并且只对语法进行了一些更改。

  1. 控制器也是如此。没有更多的范围,只需在控制器中直接声明一个变量。当然还要添加搜索输入模型:

import { Component } from "@angular/core"; @Component({ selector: "app-root", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"] }) export class AppComponent { title = "app"; searchText = "Math"; // Just a default value courses = [{ id: 1, course_number: ...}, ...]; // Snip for readability }

  1. 最后实现我们的搜索过滤器。您需要在此处投入最多的工作(如果您想完全模仿旧过滤器的话。

search.pipe.ts:

import { Pipe, PipeTransform } from "@angular/core";
@Pipe({
  name: "Search",
  pure: false
})
export class SearchPipe implements PipeTransform {
  transform(items: any[], searchValue: string, filter: Object): any {
    return items.filter(item => {
      return item.title.indexOf(searchValue) > -1 ||
             item.course_number.indexOf(searchValue) > -1;
    });
  }
}

我使用 indexOf 和 es6 过滤器创建了一些简单的东西 - 这里只查看两个字段,它不区分大小写。我必须将pure 设置为false 才能正确更新。这向我表明,管道可能不是做事的最佳方式。也许由模型更改(带去抖动)触发的控制器函数并创建结果数组会是一个更好的主意。

附加说明:使用 NgModel 可能有点过头了,因为它以两种方式绑定值(从控制器到模板以及从模板到控制器),但我们从不更改值(除了设置默认值) ),因此跳过 ngModel 并使用 (change)="doSearch()" 将少一个导入,并且可能更清洁,但我想比过滤器更模块化。

【讨论】:

    【解决方案2】:

    我在stackblitz 上创建了一个工作示例。查看 app.component.tsapp.component.htmlapp.module.tscourse-filter.pipe。 ts

    在 Angular 中有一个叫做 Pipes 的东西。管道将数据作为输入并将其转换为所需的输出。有一些built in pipes,您也可以创建自己的custom pipes。对于您的场景,我们必须创建一个自定义管道。

    您的大部分 html 都可以重复使用。但是你必须用 Angular pipe 替换 filter 功能。

    您必须像这样创建一个管道并将其声明为ngModule

    import { Pipe, PipeTransform } from '@angular/core';
    import { Course } from './app.component';
    
    @Pipe({
      name: 'courseFilter'
    })
    export class CourseFilter implements PipeTransform {
      transform(courses: Course[], keyword: string): Course[] {
        debugger;
        if (!keyword || keyword === '') {
          return courses;
        }
        return courses.filter((course: Course) => {
          return course.course_number.toString().includes(keyword) ||
            course.description.includes(keyword) || 
            course.keywords.includes(keyword) || 
            course.title.includes(keyword)
        });
      }
    }
    

    app.module.ts

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { FormsModule } from '@angular/forms';
    
    import { AppComponent } from './app.component';
    import { HelloComponent } from './hello.component';
    import { CourseFilter } from './course-filter.pipe';
    
    @NgModule({
      imports:      [ BrowserModule, FormsModule ],
      declarations: [ AppComponent, HelloComponent, CourseFilter ],
      bootstrap:    [ AppComponent ]
    })
    export class AppModule { }
    

    您将 FormsModule 添加到 @NgModule 装饰器中定义的导入列表中。这使应用程序可以访问所有模板驱动的表单功能,包括 ngModel。

    BrowserModule 是一个模块,它提供了人们通常希望在 ngIf 等 Angular2 应用程序中使用的各种服务和指令。

    你的模板应该是这样的。

      <h1> Search Feature </h1>
    
     <input type='text' [(ngModel)]='searchText' placeholder=" Search a Topic, Subject, or a Course!" >
    
    <div>
        <ul>
            <li *ngFor="let course of courses | courseFilter: searchText">
           {{course.course_number}} :      {{course.title}} <br>
           <button (click)="course.showDescription = !course.showDescription">See More</button>
           <div *ngIf="course.showDescription">
             {{course.description}}
           </div>
            </li>
        </ul>
    </div>
    

    【讨论】:

    • 不错。因为我只是尝试实现相同的(只是注意到差异很有趣)。我想我会提出一些问题。 CommonModule 在这里做什么?快速搜索一下,它适用于 ngFor 和 ngIF 等基础知识,但如果没有它似乎运行良好,那么展示您正在使用的内容是否只是最佳实践?
    • @ippi 实际上我们不需要在这里导入CommonModule。但是我们需要导入Formsmodule,因为我们在应用程序中使用[(ngModule)]。我将用描述更新答案。任何方式感谢您指出
    • 为了清楚我理解,我添加了另一个管道来突出显示课程标题、描述和关键字中的搜索结果,但它似乎不起作用。 (stackblitz.com/edit/angular-course-filter-pipe-cjqrbc) 如果我想在插值上使用管道会有什么不同吗?从这里突出显示过滤器 (gist.github.com/adamrecsko/…) 谢谢!
    • 它工作正常.. 添加一些CSS,它应该工作。你完美地用&lt;span class="highlight"&gt;letter or word&lt;/span&gt;替换了这些字母。检查元素并查看。我认为问题在于样式。添加一些 CSS。
    猜你喜欢
    • 2015-09-29
    • 2021-09-27
    • 2019-01-23
    • 1970-01-01
    • 2017-06-06
    • 2017-09-13
    • 1970-01-01
    • 2020-06-13
    • 2017-01-02
    相关资源
    最近更新 更多