参考网站:http://www.jspang.com/detailed?id=63#toc298
一.安装typescript
1.首先要安装Nodejs,然后用命令行查看node和npm是否安装成功
2.然后命令安装typescript
npm install -g typescript
3.输入tsc -v看看是否安装成功
注意:
如果安装成功,但tsc -v报错,有可能是环境变量的问题。
之前是这个方法解决的
二.运行第一个ts文件
在ts文件夹下建了个demo1.ts,如果直接用node demo1.js的命令会报错。需要转换一下,先tsc demo1.ts,这样ts文件夹会多一个对应的demo1.js文件,然后运行这个文件,node demo1.js.
1.运行的第一种方法:先转为js,再运行
先tsc demo1.ts,然后node deo1.js
2.另外一种方法,全局安装ts-node
npm install -g ts-node
本来可以直接起运行命令就可以的:ts-node demo1.ts
**注意:**但我这里命令跑起来的时候会报错,报一些关于node_module没找到关于@types/node这一类的错。
然后百度查了这两个命令:
npm i d3 @types/d3
npm install @types/node
然后再起就成功了
ts-node demo1.ts
三.语法
1.静态语法 static typing
1.1特点:
1)静态类型一旦声明了,类型就无法改变。
如下,声明了是数字,就不能改成字符串
2)自动携带相关类型的属性
3)如何自定义自定义静态类型
interface XiaoJieJie{
uname:string,
age:number
}
const xiaohong:XiaoJieJie={
uname:'小红',
age:18
}
console.log(xiaohong.age)
打印:
1.2.分类:
1.2.1基础静态类型
number,sring,boolean,null,undefined,void,symbol
const count : number = 98;
const myName : string ='jspang'
1.2.2对象静态类型
包括普通对象类型,数组类型,类类型,函数类型
//对象
const xiaoJieJie:{
name:string,
age:number
}={
name:'大脚',
age:18
}
//数组
//string []表示后面是数组,而且里面都是字符串
const xiaoJieJies : string []=['谢大脚','谢小脚','谢中脚']
//类
//表示有一个Person类,dajiao必须是person类的对象
class Person{}
const dajiao : Person = new Person()
//函数
//表示必须是函数,而且返回结果必须是字符串
const JianXiaoJieJie : ()=>string=()=>{return '大脚'}
2.类型注解和类型推断
2.1类型注解
鼠标悬停变量上,就会出现他的类型注解
2.2类型判断
没有写明类型,代码会自动分析type的类型
2.3工作使用问题(潜规则)
1)如果ts能够自动分析变量类型,我们就什么也不需要做了;
2)如果ts无法分析变量类型的话,我们就需要使用类型注解
示例:
这里one和two没有确定是什么类型的,所以total是any,也就是任何类型都可以。
这里确定了one和two的类型,所以total的类型是确定的,也是number
有一种函数变量参数的写法:
这样直接写会报错
需要这样写:
function add({one , two} : {one : number,two : number}){
return one + two
}
const total = add({one : 1 ,two : 2})
可以确定one和two这两个参数的类型
2.4函数返回类型的注解
2.4.1参数后面加类型
如下:如果在等式后面加了一个‘’,但要求最后的total是number类型的,就需要返回类型的注解。
function getTotal(one : number,two : number) {
return one + two + '';
}
const total = getTotal(1,2)
方法一,直接定义total的类型
方法二:在参数后面加类型
2.4.1 void
添加了void就不能有返回值,即使是空字符串也不可以。
2.4.2never
东西永远执行不完, 用never。比如:报错的代码,死循环
//报错
function errorFunction() :never {
throw new Error()
console.log('hello world')
}
//死循环
function forNever(): never {
while(true){}
console.log('hello world')
}
2.5数组类型注解的方法
const numberArr : number[] = [1,2,3]
const stringArr : string[] =['a','b','c']
const undefinedArr : undefined[] = [undefined,undefined]//这种后面就必须全部是undefiend,否则就报错
const arr :(string | number)[]=[1,'a',2]//这种就是字符串和数字都可以
const xiaoJieJie :{name:string,age:number}[]=[
{name:'六月',age:18},
{name:'刘洋',age:28}
]
对象数组还可以用类型别名的方法:
type Lady={name:string,age:number}
const xiaoJieJie :Lady[]=[
{name:'六月',age:18},
{name:'刘洋',age:28}
]
或者
class Madam{
name:string;
age:number
}
const xiaoJieJie :Madam[]=[
{name:'六月',age:18},
{name:'刘洋',age:28}
]
3.元组的使用和类型约束
元组的使用情况比较少
const xiaoJieJie : [string,string,number]=['a','b',12]
const xiaoJieJies :[string,string,number][]=[
['a','b',12],
['a','b',12],
['a','b',12],
]
4.接口interface
用法:参数有重复的时候,就定义一个接口的方式约束它的类型。
原始写法:
const screenResume=(name:string,age:number,bust:number)=>{
age < 24 && bust >= 90 && console.log(name + '进入面试')
age >= 24 || bust < 90 && console.log(name + '你被淘汰')
}
const getResume=(name:string,age:number,bust:number)=>{
console.log(name + '年龄是' + age)
console.log(name + '胸围是' + bust)
}
screenResume('大脚',18,94)
getResume('大脚',18,94)
4.1用接口的写法优化:
interface Girl{
name:string;
age:number;
bust:number;//注意这里使用分号结尾,为不是逗号
}
const girl={
name:'大脚',
age:18,
bust:94
}
//把girl传递进来,符合Girl接口的模式
const screenResume=(girl:Girl)=>{
girl.age < 24 && girl.bust >= 90 && console.log(girl.name + '进入面试')
girl.age >= 24 || girl.bust < 90 && console.log(girl.name + '你被淘汰')
}
const getResume=(girl:Girl)=>{
console.log(girl.name + '年龄是' + girl.age)
console.log(girl.name + '胸围是' + girl.bust)
}
screenResume(girl)
getResume(girl)
4.2 和类型别名的区别
其实这个和类型别名有点像,就是之前type的那个,他们之间的区别在于:类型别名后面可以跟着字符串也就是类型,但接口后面必须是个对象
4.3 ?表示可选值
interface Girl{
name:string;
age:number;
bust:number;
waistline?:number //表示可选参数
}
const girl={
name:'大脚',
age:18,
bust:94,
waistline:12//这里有值或没值都可以
}
//把girl传递进来,符合Girl接口的模式
const screenResume=(girl:Girl)=>{
girl.age < 24 && girl.bust >= 90 && console.log(girl.name + '进入面试')
girl.age >= 24 || girl.bust < 90 && console.log(girl.name + '你被淘汰')
}
const getResume=(girl:Girl)=>{
console.log(girl.name + '年龄是' + girl.age)
console.log(girl.name + '胸围是' + girl.bust)
girl.waistline&&console.log(girl.name+'腰围是'+girl.waistline)
}
screenResume(girl)
getResume(girl)
还有一种写法,就是所有类型都可以添加
4.4 [propname:string]:any表示名称是string类型,值是任何类型都可以
interface Girl{
name:string;
age:number;
bust:number;
waistline?:number; //表示可选参数,
[propname:string]:any
}
const girl={
name:'大脚',
age:18,
bust:94,
waistline:12,//这里有值或没值都可以
sex:'女'
}
//把girl传递进来,符合Girl接口的模式
const screenResume=(girl:Girl)=>{
girl.age < 24 && girl.bust >= 90 && console.log(girl.name + '进入面试')
girl.age >= 24 || girl.bust < 90 && console.log(girl.name + '你被淘汰')
}
const getResume=(girl:Girl)=>{
console.log(girl.name + '年龄是' + girl.age)
console.log(girl.name + '胸围是' + girl.bust)
girl.waistline&&console.log(girl.name+'腰围是'+girl.waistline)
girl.sex&&console.log(girl.name+'性别是'+girl.sex)
}
screenResume(girl)
getResume(girl)
4.5 类受接口的约束implements
接口不仅能限制对象,还可以限制类,类必须带着些属性。
interface Girl{
name:string;
age:number;
bust:number;
waistline?:number; //表示可选参数,
[propname:string]:any;
say():string;//必须有个say方法,返回值是string类型
}
class XiaoJieJie implements Girl{
name='六月';
age=18
bust=90
say(){
return '你好,洗浴'
}
}
4.6接口间的继承
interface Teacher extends Girl实现继承
interface Girl{
name:string;
age:number;
bust:number;
waistline?:number; //表示可选参数,
[propname:string]:any;
say():string;//必须有个say方法,返回值是string类型
}
//teacher继承Girl。teacher自带teach方法
interface Teacher extends Girl{
teach():string;
}
const girl={
name:'大脚',
age:18,
bust:94,
waistline:12,//这里有值或没值都可以
sex:'女',
say(){
return '欢迎光临,红浪漫洗浴'
},
teach(){
return '我来教你们做'
}
}
//把girl传递进来,符合Girl接口的模式
const screenResume=(girl:Girl)=>{
girl.age < 24 && girl.bust >= 90 && console.log(girl.name + '进入面试')
girl.age >= 24 || girl.bust < 90 && console.log(girl.name + '你被淘汰')
}
//这里girl要有teacher属性,就要在girl里面加teach方法
const getResume=(girl:Teacher)=>{
console.log(girl.name + '年龄是' + girl.age)
console.log(girl.name + '胸围是' + girl.bust)
girl.waistline&&console.log(girl.name+'腰围是'+girl.waistline)
girl.sex&&console.log(girl.name+'性别是'+girl.sex)
}
screenResume(girl)
getResume(girl)
5.类的概念和使用
5.1基本使用
跟es6差不多
class Lady{
content='帅哥'
sayHello(){
return this.content
}
}
class XiaoJieJie extends Lady{
sayLove(){
return 'I LOVE YOU'
}
}
console.log(new XiaoJieJie().sayHello())
console.log(new XiaoJieJie().sayLove())
5.2类的重写
把父类的方法或者属性拿出来重新定义
class Lady{
content='帅哥'
sayHello(){
return this.content
}
}
class XiaoJieJie extends Lady{
//重写
sayHello(){
return 'hi,honey'
}
sayLove(){
return 'I LOVE YOU'
}
}
console.log(new XiaoJieJie().sayHello())
console.log(new XiaoJieJie().sayLove())
5.3super关键字
super.取父级的方法
class Lady{
content='Hi,帅哥'
sayHello(){
return this.content
}
}
class XiaoJieJie extends Lady{
//super关键字点父级的方法,取父级的方法+值
sayHello(){
return super.sayHello()+'你好'
}
sayLove(){
return 'I LOVE YOU'
}
}
console.log(new XiaoJieJie().sayHello())
console.log(new XiaoJieJie().sayLove())
5.4类的访问类型
类的三种访问类型:private(私有的),protected(保护的),public(公有的)
类的内部和类的外包,大括号之内的是类的内部
5.4.1public共用的,在类的内部和类的外部都是允许调用的
Person不定义,默认定义成public类型的
class Person{
name : string = '';
sayHello(){
console.log(this.name+'say:hello')
}
}
const person = new Person()
person.name='jspang'
person.sayHello()
console.log(person.name)
相当于:
class Person{
public name : string = '';
public sayHello(){
console.log(this.name+'say:hello')
}
}
const person = new Person()
person.name='jspang'
person.sayHello()
console.log(person.name)
5.4.2private只允许类的内部使用
设置私有,外部调用就直接报错
5.4.3protected
protected不允许在类的外部使用,但在继承的时候运行在类的外部使用
5.5类的构造函数
构造函数中的特殊使用:
示例一:
constructor的简写
class Person{
//第一种写法:
// public name : string;
// constructor(name:string){
// this.name=name
// }
//第二种写法:
constructor(public name:string){}
}
const person = new Person('jspang')
console.log(person.name)
示例二:
只要子类中有constructor,就必须要通过super调父级,否则会报错
class Person{
//父类如果不写,这个constructor也是有的,就是为空constructor(){}
constructor(public name:string){}
}
class Teacher extends Person{
//子类也有自己的constructor的话,必须要通过super调父级的函数
constructor(public age:number){
super('jspang')
}
}
const teacher = new Teacher(18)
console.log(teacher.age)
console.log(teacher.name)
5.6private的使用
功能在于封装一个方法,然后通过getter或者setter的形式访问这个属性
如果直接访问会报错
使用方式:
get获取值
class xiaoJieJie{
constructor(private _age:number){}
get age(){
return this._age-10
}
}
const dajiao = new xiaoJieJie(28)
console.log(dajiao.age)
set进行赋值
class xiaoJieJie{
constructor(private _age:number){}
get age(){
return this._age-10
}
set age(age:number){
this._age=age+3
}
}
const dajiao = new xiaoJieJie(28)
dajiao.age=25
console.log(dajiao.age)
5.7静态类的使用
以前的写法:
class Girl{
sayLove(){
return 'I love you'
}
}
const girl =new Girl()
console.log(girl.sayLove())
使用static不需要实例,就可以直接调用方法
class Girl{
static sayLove(){
return 'I love you'
}
}
console.log(Girl.sayLove())
5.8只读属性
原本的类是可以修改的
class Person{
constructor (public name:string){}
}
const person =new Person('jspang')
person.name='谢广坤'
console.log(person.name)
只读属性的设置,局部可以修改,修改就会报错
5.9抽象类abstract
继承抽象类,子类就必须带抽象类的方法,否则就报错
abstract class Girl{
//抽象类的方法
abstract skill()
}
class Waiter extends Girl{
skill(){
console.log('大爷,喝水')
}
}
class BaseTeacher extends Girl{
skill(){
console.log('大爷,泰式按摩')
}
}
class seniorTeacher extends Girl{
skill(){
console.log('大爷,SPA按摩')
}
}
6.tsconfig.json文件
是ts的编译配置文件,也就是把ts编译成ts都靠这个文件
6.1怎么生成tsconfig.json文件
在终端输入:
tsc -init
就会在文件的根目录生成一个tsconfig.json文件
6.2如何让tsconfig.json生效
输入命令tsc demo1.ts虽然编译出来了一个demo1.js文件,但没有走tsconfig.json配置
而输入
tsc
是可以的,走了tsconfig.json的配置
ts-node demo1.ts会走tsconfig.json的配置
6.3分析tsconfig.json文件
6.3.1 include,exclude多个文件中编译指定文件
默认情况下是输入tsc命令,文件下的所以ts文件全部编译出来
但可以通过include[“demo1.ts”]这种指定编译的文件(和files的用法一样,也是包含的文件名字进行编译)
或者exclue[“demo2.ts”]排除指定文件,编译剩余的所有文件
6.3.2 strict代表js的编译和书写规范 。这个为true下面所有的都是true,设置也无用
strict下的其他配置:
1)noImplicitAny:设置为false表示允许你的注解any不用特意标明
默认为true的情况下这样直接写就会报错,必须要写清楚name : any才不报错
但设置noImplicitAny:false就不报错了
2)“strictNullChecks”: true
表示不允许有null只出现,出现就会报错
3)入口文件和编译文件
outDir:编译文件路径
"outDir": "./build",
rootDir:ts文件路径
"rootDir": "./src"
4)“sourceMap”: true开启就会生成一个.map文件
把源文件和生成的文件有了一个对应关系,生产文件错了,可以在ts文件上改错。
5)“noUnusedLocals”: true开启的话项目中没有使用的变量,编译打包的时候就会报错,提示你有无用变量。
“noUnusedParameters”: true, 没有用的方法在编译打包的时候就会提示出来
7.联合类型和类型保护(类型守护)
有联合类型存在的情况下才需要类型保护
参数有两种以上的方法叫联合类型
技师没有say方法的就会报错,这个时候就要用到类型保护。
第一种方式 as:
interface Waiter{
anjiao:boolean;
say:()=>{};
}
interface Teacher{
anjiao:boolean;
skill:()=>{};
}
function judgeWho(animal:Waiter | Teacher){
//会按脚就是服务可以调用say方法,不会按脚就是技师可以调用skill方法
if(animal.anjiao){
(animal as Teacher).skill()
}else{
(animal as Waiter).say()
}
}
第二种方法 in:
interface Waiter {
anjiao: boolean;
say: () => {};
}
interface Teacher {
anjiao: boolean;
skill: () => {};
}
function judgeWho(animal: Waiter | Teacher) {
//会按脚就是服务可以调用say方法,不会按脚就是技师可以调用skill方法
if("skill" in animal){
animal.skill();
}else{
animal.say()
}
}
第三种方法: typeof
如果是string方法,直接相加就会报错
这样写就不会报错:
function add(first :string | number,second :string |number){
if(typeof first ==='string'|| typeof second ==='string'){
return `${first}${second}`
}else{
return first + second;
}
}
第四种方法:instanceof 只能用于类
这个类可能是普通类,也可能是numberObj类
class NumberObj{
count:number;
}
function addObj(first :object | NumberObj,second :object |NumberObj){
if(first instanceof NumberObj && second instanceof NumberObj){
return first.count + second.count;
}
return 0;
}
8.Enum 枚举类型
初级程序员的写法:
function getServe(status : number){
if(status ===0){
return 'massage'
}else if(status ===1){
return 'SPA'
}else if(status ===2){
return 'dabaojian'
}
}
const result=getServe(0)
console.log(`我要去${result}`)
中级程序员的写法:
const Status={
MASSAGE:0,
SPA:1,
DABAOJIAN:2
}
function getServe(status : number){
if(status ===Status.MASSAGE){
return 'massage'
}else if(status ===Status.SPA){
return 'SPA'
}else if(status ===Status.DABAOJIAN){
return 'dabaojian'
}
}
const result=getServe(Status.SPA)
console.log(`我要去${result}`)
高级程序员的写法:
//因为枚举有个默认值,默认是从0,1,2,3这样的顺序
enum Status{
MASSAGE,
SPA,
DABAOJIAN,
}
function getServe(status : number){
if(status ===Status.MASSAGE){
return 'massage'
}else if(status ===Status.SPA){
return 'SPA'
}else if(status ===Status.DABAOJIAN){
return 'dabaojian'
}
}
const result=getServe(Status.SPA)
console.log(`我要去${result}`)
当然也可以修改默认值:
这样后面的数值也会按着顺序依次改
enum Status{
MASSAGE = 1,
SPA,
DABAOJIAN,
}
9.泛型
9.1方法中的泛型的使用
需求1:前面是字符串,后面也要求传字符串
function join<jsPang>(first:jsPang,second:jsPang){
return `${first}${second}`
}
//调用的时候指定类型
join<number>(1,2);
这里就在调用这个方法的时候定义参数类型,如果传入其他类型就会直接报错。
需求2:要求传入的参数是数组
params:ANY[]或者params:Array(ANY)都是可以的
function myFun<ANY>(params:ANY[]){
//function myFun<ANY>(params:Array(ANY)){
return params;
}
myFun<string>(["123","3456"])
传入是数组还有一种写法:
需求3:多个泛型的定义
一般泛型用字母T表示
function join<T,P>(first:T,second:P){
return `${first}${second}`
}
//调用的时候指定类型
join<string,number>('1',2);
需求4:泛型的继承
根据编号返回名字
class SelectGirl<T>{
constructor(private girls: T[]){}
getGirl(index :number):T{
return this.girls[index]
}
}
const selectGirl=new SelectGirl<string>(["大脚","刘颖","六月"])
console.log(selectGirl.getGirl(1))//"刘颖"
如果要求返回名字,就需要用单泛型的继承
interface Girl{
name:string
}
//继承了Girl接口,就必须要有一个name属性
class SelectGirl<T extends Girl>{
constructor(private girls: T[]){}
getGirl(index :number):string{
return this.girls[index].name
}
}
const selectGirl=new SelectGirl([
{name:"大脚"},
{name:"刘颖"},
{name:"六月"}
])
console.log(selectGirl.getGirl(1))//"刘颖"
需求5:泛型的约束
例如:在两个类型中选择一种,要么是number类型,要么是string类型
class SelectGirl<T extends number | string>{
constructor(private girls: T[]){}
getGirl(index :number):T{
return this.girls[index]
}
}
const selectGirl=new SelectGirl<string>(["大脚","刘颖","六月"])
console.log(selectGirl.getGirl(1))
10.ts的命名空间
10.1 搭环境
1.安装package.json
生成默认的文件
npm init -y
2.生成tsconfig.json
tsc -init
修改:
"outDir": "./build",
"rootDir": "./src",
3.目录结构
在src里面随便写了个demo.ts
html里面的script的src指向build的demo.js
<script src="./build/demo.js"></script>
浏览器打开html就可以看打印的内容,因为js在浏览器里面可以编译
10.2 感受命名空间的好处:减少不必要的全局变量
demo.ts:
class Header{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Header';
document.body.appendChild(elem)
}
}
class Body{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Body';
document.body.appendChild(elem)
}
}
class Footer{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Footer';
document.body.appendChild(elem)
}
}
class Page{
constructor(){
new Header();
new Body();
new Footer();
}
}
最后编译出来是这样的:
变量都是var定义的
"use strict";
var Header = /** @class */ (function () {
function Header() {
var elem = document.createElement('div');
elem.innerText = 'This is Header';
document.body.appendChild(elem);
}
return Header;
}());
var Body = /** @class */ (function () {
function Body() {
var elem = document.createElement('div');
elem.innerText = 'This is Body';
document.body.appendChild(elem);
}
return Body;
}());
var Footer = /** @class */ (function () {
function Footer() {
var elem = document.createElement('div');
elem.innerText = 'This is Footer';
document.body.appendChild(elem);
}
return Footer;
}());
var Page = /** @class */ (function () {
function Page() {
new Header();
new Body();
new Footer();
}
return Page;
}());
html里面调用这个js
<script>
new Page()
</script>
在浏览器里面也可以直接打印这些全局变量
使用命名空间的写法:
只有Home.page被暴露出去了,剩下的都是Home的方法
namespace Home{
class Header{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Header';
document.body.appendChild(elem)
}
}
class Body{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Body';
document.body.appendChild(elem)
}
}
class Footer{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Footer';
document.body.appendChild(elem)
}
}
export class Page{
constructor(){
new Header();
new Body();
new Footer();
}
}
}
编译后这样:
"use strict";
var Home;
(function (Home) {
var Header = /** @class */ (function () {
function Header() {
var elem = document.createElement('div');
elem.innerText = 'This is Header';
document.body.appendChild(elem);
}
return Header;
}());
var Body = /** @class */ (function () {
function Body() {
var elem = document.createElement('div');
elem.innerText = 'This is Body';
document.body.appendChild(elem);
}
return Body;
}());
var Footer = /** @class */ (function () {
function Footer() {
var elem = document.createElement('div');
elem.innerText = 'This is Footer';
document.body.appendChild(elem);
}
return Footer;
}());
var Page = /** @class */ (function () {
function Page() {
new Header();
new Body();
new Footer();
}
return Page;
}());
Home.Page = Page;
})(Home || (Home = {}));
html里面调用这个js,要改为命名空间下的Page
<script>
new Page()
</script>
浏览器打印不出来Headers
而是Home下面只有Page
10.3真正项目中的使用
1)components.ts:单独模块的ts文件
namespace Components{
export class Header{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Header';
document.body.appendChild(elem)
}
}
export class Body{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Body';
document.body.appendChild(elem)
}
}
export class Footer{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Footer';
document.body.appendChild(elem)
}
}
}
2)demo.ts:ts文件的出口
namespace Home{
export class Page{
constructor(){
//Components命名空间下的方法
new Components.Header();
new Components.Body();
new Components.Footer();
}
}
}
3)输入命令:tsc编译
4)demo.js文件这样:
"use strict";
var Home;
(function (Home) {
var Page = /** @class */ (function () {
function Page() {
//Components命名空间下的方法
new Components.Header();
new Components.Body();
new Components.Footer();
}
return Page;
}());
Home.Page = Page;
})(Home || (Home = {}));
5)html.js:
由于页面只引入了build/demo.js,而build/demo.js依赖于Components.js,所以会报错
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="./build/demo.js"></script>
<script>
new Home.Page()
</script>
</body>
</html>
6)针对这个情况可以在html页面引入Components.js,但比较麻烦。webpack编译一般指需要引入一个js文件,那怎么解决呢?
放开注释 -> 指明输出的文件:“outFile”: “./build/page.js”,
但这种情况下 module需要改成"amd"
"module": "amd",
"outFile": "./build/page.js", /* Concatenate and emit output to single file. */
"outDir": "./build", /* Redirect output structure to the directory. */
"rootDir": "./src",
7)html也改下js的路径:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="./build/page.js"></script>
<script>
new Home.Page()
</script>
</body>
</html>
10.4命名空间的嵌套
components.ts:
namespace Components{
export namespace SubComponents{
export class Test{
}
}
export class Header{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Header';
document.body.appendChild(elem)
}
}
export class Body{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Body';
document.body.appendChild(elem)
}
}
export class Footer{
constructor(){
const elem =document.createElement('div')
elem.innerText='This is Footer';
document.body.appendChild(elem)
}
}
}
重新编译以后,浏览器可以打印:
10.5import语法
components.ts:
export class Header {
constructor() {
const elem = document.createElement('div')
elem.innerText = 'This is Header';
document.body.appendChild(elem)
}
}
export class Body {
constructor() {
const elem = document.createElement('div')
elem.innerText = 'This is Body';
document.body.appendChild(elem)
}
}
export class Footer {
constructor() {
const elem = document.createElement('div')
elem.innerText = 'This is Footer';
document.body.appendChild(elem)
}
}
demo.ts:
import {Header,Body,Footer} from './components'
export default class Page {
constructor() {
//Components命名空间下的方法
new Header();
new Body();
new Footer();
}
}
编译后的page.js:
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.js"></script>
<script src="./build/page.js"></script>
<script>
require(["demo"], function (demo) {
new demo.default();
});
</script>
</body>
</html>