Angular中集成Script脚本你还不会?看这篇就够了

背景:

     最近在做angular项目时,需要集成一个控件,其中需要引入最新的js文件,所以我们要使用:

 <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>

像这样的方式,并需要写一些初始化的逻辑显示此控件。

先看看效果:

分析:

angular中使用的是ts语言(es6+),html里也舍去了script脚本。那到底html和script有什么关系呢?

  • 首先,在Angular2框架之中实际使用的是ES6,全称ECMAScript6,是Javascript的下一个版本。官方的例子则是基本采用TS,全称TypeScript,是JS的一个超集。
  • 为什么采用新的语言,而不是沿用当前的ES5,官网和社区已经有了很多解释了,新语言当然有新语言的优势,比如定义变量,可以指定类型,而在程序中用错类型,则会在编译过程中就给出警告,不至于等到上线了才发现BUG。
  • 既然采用了新的语言,为了跟当前的浏览器系统兼容,当然就有一个翻译过程,准确的说,甭管是TS还是ES6,甚至将来可能的ES7,在当下,都要翻译成ES5,才能在当前流行的浏览器之中运行。这个翻译,行话上讲,也就是“编译”。
  • 事实上,编译不仅仅干这么一点事,很多的优化工作、查错工作,也是在这个阶段完成的,比如你使用了没有定义的变量、函数;比如你用错了函数类型;比如你使用了某个函数库但只是用了其中一小部分,那么多没用的部分应当排除掉避免占用宝贵的下载带宽,这些都是在编译过程做到的。
  • 好了,既然经过了这么复杂的动作,这个编译也必不可少,那么实际上答案已经出来了:那就是,很多原有理所应当存在的东西,就比如你在HTML中定义的JS对象、变量、函数,那些都是在执行环节,浏览器中才存在的。而在编译阶段,那些东西还只是停留在字符状态,Angular当然并不知道他们存在,也就无法直接的、像原来我们使用HTML-JS一样来使用它们了,这就如同上面那张图,看上去海天一色,互相映衬,但在根本上,它们是在两个世界。

解释:

你肯定早看到了,大量的第三方模块和代码库,通过NPM的管理,共存于这个架构中,彼此友好的相处。你原有的工作,完全可以用同样的方式来工作。
你也可能会说,可我有很多代码没有做到那么好的面向对象化包装,也不想做那么复杂,该怎么办呢?AngularJS也提供了至少2个方法,来完成两个世界的打通工作。

代码实现:

1.通过declare方式引入

在最外层的index.html中嵌入:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Demo</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
  <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
  <script src="https://promotions.newegg.com/Newegg/Survey/newegg-feedback.min.js" type="text/javascript"></script>
  <!-- include the script -->
  <script type="text/javascript">
    var test = 'test'
  </script>
</head>
<body>
  <app-root></app-root>
</body>

</html>

<script type="text/javascript">

    var test = 'test'

  </script>是我嵌入的一脚本,并且设置了一个变量

在ts代码里直接定义 :

import { Component, OnChanges, OnInit, OnDestroy, ViewChild, AfterViewInit, AfterViewChecked, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
declare let test: string;
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.less']
})
export class AppComponent implements OnInit {
  constructor() {
    // webGlObject.init();
    // console.log(window)
    // console.log(test)
  }
  ngOnInit(): void {
    console.log(test)

如上,AppComponent 不会去管理test,在编译或者运行时,会去script里寻找test,如果没有则打印undfiend。相当于ts代码和script完全是独立的两部分,只是在运行时候才会有关联

2.通过window方式引入(不推荐,angular也许不再浏览器执行)

import { Component, OnChanges, OnInit, OnDestroy, ViewChild, AfterViewInit, AfterViewChecked, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
declare let test: string;
declare let window: any;
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.less']
})
export class AppComponent implements OnInit {
  constructor() {
    // webGlObject.init();
    // console.log(window)
    // console.log(test)
  }
  ngOnInit(): void {
    console.log(window.test)

这种方式也会输出test的值。

思考:既然直接能访问到window对象,那很多属性都能直接用吧?

如果将来这段Angular代码,很可能不是运行在一个浏览器,其中可能根本没有window/document对象,那时候,这段代码就出错了。当然你可能会说,不不不,我就是在浏览器运行,不考虑别的。OK,我也不较劲,你当我没说,你完全可以就这么用。
但是比较规范的办法,应当是把window对象以及你需要的其它类似对象,写成一个服务,然后注入到app.component之中,这样,即便将来运行环境有变化,只修改服务部分代码,你的主程序完全可以不用修改。

猜你喜欢

转载自blog.csdn.net/qq_40677590/article/details/105579855