TypeScript趁早學(xué)習(xí)提高職場競爭力
Github來源: | 求星星 ? | 給個??關(guān)注,??點贊,??鼓勵一下作者
前言
希望可以通過這篇文章,能夠給你得到幫助。(感謝一鍵三連)

還不抓緊學(xué)TypeScript
TS:以JavaScript為基礎(chǔ)構(gòu)建的語言;可以在如何支持JavaScript的平臺中執(zhí)行;一個JavaScript的超集,TypeScript擴展了JavaScript,并添加了類型;TS不能被JS解析器直接執(zhí)行。
TypeScript增加了一些類型,支持ES的新特性,添加ES不具備的新特性,豐富的配置選項,強大的開發(fā)工具。
學(xué)習(xí)TS,記得下載Node.js哦~
使用npm全局安裝typescript,進入命令行,輸入:npm i -g typescript,創(chuàng)建一個ts文件,使用tsc對ts文件進行編譯:進入命令行,進入ts文件所在目錄,執(zhí)行命令:tsc xxx.ts。
基本類型:
類型聲明:
類型聲明是TS非常重要的一個特點 通過類型聲明可以指定TS中變量的類型 指定類型后,當(dāng)位變量賦值時,TS編譯器會自動檢查是否符合類型聲明,符合則賦值,否則報錯 簡而言之,類型聲明給變量設(shè)置了類型,使得變量只能存儲某種類型的值
語法:
let 變量: 類型;
let 變量: 類型 = 值;
function fn(參數(shù): 類型, 參數(shù): 類型):類型 {
...
}
自動類型判斷:
TS擁有自動的類型判斷機制 當(dāng)對變量的聲明和賦值是同時進行的,TS編譯器會自動判斷變量的類型 所以如果你的變量的聲明和賦值時同時進行的,可以省略掉類型聲明
| 類型 | 描述 |
|---|---|
| number | 任意數(shù)字 |
| string | 任意字符串 |
| boolean | 布爾值true或false |
| 字面量 | 限制變量的值就是該字面量的值 |
| any | 任意類型 |
| unknown | 類型安全的any |
| void | 沒有值或undefined |
| never | 沒有值 不能是任何值 |
| object | 任意的JS對象 |
| array | 任意JS數(shù)組 |
| tuple | 元素,TS新增類型,固定長度數(shù)組 |
| enum | 枚舉,TS中新增類型 |
number
let decimal: number = 6;
let hex: number = 0xf00d;
boolean
let isDone: boolean = false;
string
let color: striing = "blue"'
color = "red";
let fullName: string = "jeskson";
字面量
let color: 'red' | 'blue' | 'black';
any
let d: any = 3;
d = 'jeskson';
unknown
let notSure: unknown = 4;
void
let unusable: void = undefined;
never
function error(message: string): never {
throw new Error(message);
}
object
let obj: object = {}
array
let list: number[] = [1,2,3];
let list: Array<number> = [1,2,3];
tuple
let x: [string, number];
x = ["hello", 10];
類型斷言
有些情況下,變量的類型對于我們來說是很明確的,但是TS編譯器卻并不清楚,此時,可以通過類型斷言來告訴編譯器變量的類型,斷言有兩種形式:
第一種:
let someValue: unknown = "jeskson 1024bibi.com";
let strlength: number = (someValue as string).length;
第二種:
let someValue: unknown = "1024bibi.com";
編譯選項
自動編譯文件
編譯文件時,使用-w指令后,TS編譯器會自動監(jiān)視文件的變化,并在文件發(fā)生變化時對文件進行重新編譯。
tsc xxx.ts -w
自動編譯整個項目:
如果直接使用tsc指令,則可以自動將當(dāng)前項目下的所有ts文件編譯為js文件。
但是能直接使用tsc命令的前提時,要先在項目根目錄下創(chuàng)建一個ts的配置文件tsconfig.json。
tsconfig.json是一個JSON文件,添加配置文件后,只需tsc命令即可完成對整個項目的編譯。
配置選項:
include: 定義希望被編譯文件所在的目錄
// tsconfig.json
{
"include": [
"./src/**/*"
]
}
// ** 任意目錄
// * 任意文件
所有src目錄和tests目錄下的文件都會被編譯
"include": ["src/**/*", "tests/**/*"]
exclude
定義需要排除在外的目錄;默認值["node_modules","bower_components","jspm_package"]
"exclude": ["./src/hello/**/*"]
src下hello目錄下的文件都不會被編譯
extends:定義被繼承的配置文件
"extends": "./configs/base"
當(dāng)前配置文件中會自動包含config目錄下base.json中的所有配置信息
files
指定被編譯的列表,只有需要編譯的文件少時才會用到
示例:
"files": [
"type.ts",
"dada.ts"
]
compilerOptions
編譯選項是配置文件中非常重要也比較復(fù)雜的配置選項
在compilerOptions中包含多個子選項,用來完成對編譯的配置
項目選項:target
設(shè)置ts代碼編譯的目標(biāo)版本
示例:
"compilerOptions": {
"target": "ES6"
}
如上設(shè)置,我們所編寫的ts代碼將會被編譯為ES6版本的js代碼
lib
指定代碼運行時所包含的庫
"compilerOptions": {
"target": "ES6",
"lib": ["ES6", "DOM"],
"outDir": "dist",
"outFile": "dist/aa.js"
}
module
設(shè)置編譯后代碼使用的模塊化系統(tǒng)
// 配置
// 當(dāng)有錯誤時不生成編譯后的文件
"noEmitOnError": true,
// 用來設(shè)置編譯后的文件是否使用嚴格模式
"alwayStrict": true,
// 不允許隱式的any類型
"noImplicitAny": true,
// 不允許不明確類型的this
"noImplicitThis": true,
// 嚴格的檢查空值
"strictNullChecks": true
使用webpack打包代碼
使用命令:npm init -y
使用:cnpm i -D webpack webpack-cli typescript ts-loader
// webpack.config.js
// 引入一個包
const path = require('path');
// webpack中的所有的配置信息都應(yīng)該寫在module.exports中
module.exports = {
// 指定入口文件
entry: "./src/index.ts",
// 指定打包文件所在目錄
output: {
// 指定打包文件的目錄
path: path.resolve(__dirname, 'dist'),
// 打包后文件
filename: "bundle.js"
},
// 指定webpack打包時要使用模塊
module: {
// 指定要加載的規(guī)則
rules: [
{
// test指定的是規(guī)則生效的文件
test: /\.ts$/,
// 要使用的Loader
use: 'ts-loader',
// 要排除的文件
exclude: /node-modules/
}
]
}
};
// tsconfig.json
{
"compilerOptions": {
"module": "ES2015",
"target": "ES2015",
"strict" true
}
}
// package.json
"scripts": {
...
"bulid": "webpack"
}
使用命令行:npm run build
webpack
通常情況下,實際開發(fā)中我們都需要使用構(gòu)建工具對代碼進行打包,TS同樣也可以結(jié)合構(gòu)建工具一起使用,下邊以webpack為例介紹以下如何結(jié)合構(gòu)建工具使用TS。
步驟:
初始化項目
進入項目根目錄,執(zhí)行命令:npm init -y,主要作用:創(chuàng)建package.json文件。
下載構(gòu)建工具
npm i -D webpack webpack-cli webpack-dev-server typescript ts-loader clean-webpack-plugin
npm i -D webpack webpack-cli typescript ts-loader
webpack:構(gòu)建工具webpack webpack-cli: webpack的命令行工具 webpack-dev-server: webpack 的開發(fā)服務(wù)器 typescript: ts編譯器
// webpack.config.js
// 引入html插件
const HTMLWebpackPlugiin = require('html-webpack-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
// 配置webpack插件
plugins: [
new CleanWebpackPlugin(),
new HTMLWebpackPlugin({
title: "這是一個自定義title"
}), // 自動的生成html文件
]
// 用來設(shè)置引用模塊
resolve: {
extensions: ['.ts', '.js']
}
// package.json
"script": {
...
"start": "webpack serve --open chrome.exe"
},
使用命令:cnpm i -D @babel/core @babel/preset-env babel-loader core-js
// 指定webpack打包時要使用模塊
module: {
// 指定要加載的規(guī)則
rules: [
{
// test指定的是規(guī)則生效的文件
test: /\.ts$/,
// 要使用的Loader
use: [
{
loader: "babel-loader",
// 設(shè)置babel
options: {
presets: [
[
// 指定環(huán)境的插件
"@babel/preset-env",
// 配置信息
{
targets: {
"chrome":"88"
}
"corejs": "3",
// 使用corejs的方式 usage表示按需加載
"useBuiltIns":"usage"
}
]
]
}
}
'ts-loader'
]
// 要排除的文件
exclude: /node-modules/
}
]
}
面向?qū)ο?/span>
面向?qū)ο笫浅绦蛑幸粋€非常重要的思想,它被很多同學(xué)理解成了一個比較難,比較深奧的問題。其實,面向?qū)ο蠛芎唵?,程序之中所有的操作都需要通過對象來完成。
如:
操作瀏覽器要使用window對象 操作網(wǎng)頁要使用document對象 操作控制臺要使用console對象
一切操作都要通過對象,也就是所謂的面向?qū)ο?,那么對象到底是什么呢?這就要先說到程序是什么,計算機程序的本質(zhì)就是對現(xiàn)實事物的抽象,抽象的反義詞是具體,比如:照片是對一個具體的人的抽象,汽車模型是對具體汽車的抽象等等。程序也是對事物的抽象,在抽象中我們可以表示一個人,一條狗等。一個事物到了程序就變成了一個對象。
類
定義類:
class 類名 {
屬性名: 類型;
constructor(參數(shù): 類型){
this.屬性名 = 參數(shù);
}
方法名(){
...
}
}
示例:
class Person {
// 直接定義的屬性是實例屬性,需要通過對象的實例去訪問:
// const per = new Person();
// per.name
// 使用static開頭的屬性是靜態(tài)屬性(類屬性),可以直接通過類去訪問
// Person.age
// readonly開頭的屬性表示一個只讀的屬性
// 定義實例屬性
name: string = 'jeskson';
// 在屬性前使用static 關(guān)鍵字可以定義類屬性(靜態(tài)屬性)
static age: number = 18;
}
const per = new Person();
// console.log(per);
// console.log(per.name, per.age);
sayHello(){
console.log('hello');
}
// 不加static,實例對象調(diào)用
// 定義static,類方法或?qū)傩?br>構(gòu)造函數(shù)
class Dog{
name = 'j';
age = 1;
bark(){
alert('j');
}
}
const dog = new Dog();
const dog2 = new Dog();
console.log(dog);
console.log(dog2);
改造:
class Dog {
name: string;
age: number;
// constructor 被稱為構(gòu)造函數(shù)
// 構(gòu)造函數(shù)會在對象創(chuàng)建時調(diào)用
constructor(name: string, age: number) {
// 在實例方法中,this就表示當(dāng)前的實例
// 在構(gòu)造函數(shù)中當(dāng)前對象就是當(dāng)前新建的那個對象
// 可以通過this向新建的對象中添加屬性
this.name = name;
this.age = age;
}
bark() {
alert('1024bibi.com');
// 在方法中可以通過this來表示當(dāng)前調(diào)用方法的對象
console.log(this.name);
}
}
const dog = new Dog('dadaqianduan.cn', age: 1);
const dog2 = new Dog('1024bibi.com', age: 2);
console.log(dog);
console.log(dog2);
dog2.bark();
繼承
(function(){
// 定義一個表示狗的類
class Dog{
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHello() {
console.log('dadaqianduan.cn')'
}
}
const dog = new Dog('dada', 1);
console.log(dog);
dog.sayHello();
})();
使用繼承后,子類將會擁有父類所有的方法和屬性
使用繼承可以將多個類中公有的代碼寫在一個父類中,這樣只需要寫一次即可讓所有的子類都同時擁有父類中的屬性和方法。
子類覆蓋掉父類方法的形式,稱為方法重寫。
class Dog extends Animal{
run() {
console.log();
}
sayHello() {
console.log();
}
}
super-父類還有一個名字叫做超類
(function(){
class Animal{
name: string;
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log('動物叫');
}
}
class Dog extends Animal{
sayHello() {
// 在類的方法中 super 就表示當(dāng)前類的父類
super.sayHello();
}
}
const dog = new Dog('1024bibi.com');
dog.sayHello();
})();
class Dog extends Animal{
age: number,
constructor(name: string, age: number){
// 如果在子類中寫了構(gòu)造函數(shù),在子類構(gòu)造函數(shù)中必須對父類引用
super(name); // 調(diào)用父類的構(gòu)造函數(shù)
this.age = age;
}
sayHello() {
// 在類的方法中 super 就表示當(dāng)前類的父類
// super.sayHello();
}
}
const dog = new Dog('dadaqianduan.cn');
抽象類
以abstract開頭的類是抽象類,不希望這個類創(chuàng)建對象的時候
抽象類中可以添加抽象方法,抽象方法只能定義在抽象類中,子類必須對抽象方法進行重寫
abstract class Animal{
name: string;
constructor(name: string) {
this.name = name;
}
// 定義一個抽象方法
// 抽象方法使用abstract開頭,沒有方法體
// 抽象方法只能定義在抽象類中,子類必須對抽象方法進行重寫
abstract sayHello():void;
}
接口
(function(){
// 描述一個對象的類型
type myType = {
name: string,
age: number
};
// 接口用來定義一個類結(jié)構(gòu)
// 用來定義一個類中應(yīng)該包含哪些屬性和方法
// 同時接口也可以當(dāng)成類型聲明去使用
interface myInterface{
name: string;
age: number;
}
interface myInterface{
gender: string;
}
const obj: myType = {
name: 'dada',
age: 1
};
const obj1: myInterface = {
name: 'dada',
age: 1,
gender: '男'
};
})();
接口可以在定義類的時候去限制類的結(jié)構(gòu)
接口中的所有的屬性都不能有實際的值
接口只定義對象的結(jié)構(gòu),而不考慮實際值
在接口中所有的方法都是抽象方法
interface myInter{
name: string;
sayHello(): void;
}
// 定義類時,可以使類去實現(xiàn)一個接口
// 實現(xiàn)接口就是使類滿足接口的要求
class MyClass implements myInter {
name: string;
constructor(name: stirng) {
this.name = name;
}
sayHello(){
// 接口就是就類的限制,定義規(guī)范
}
}
封裝
(function(){
// 定義一個表示人的類
class Person{
private _name: string;
private _age: number;
// public 修飾的屬性可以在任意位置訪問(修改)默認值
// private 私有屬性,私有屬性只能在類內(nèi)部進行訪問修改
// 通過在類中添加方法使得私有屬性可以被外部訪問
constructor(name: string, age: number) {
this._name = name;
this._age = age;
}
// 定義方法,用來獲取name屬性
getName() {
return this._name;
}
// 定義方法,用來設(shè)置name屬性
setName(value: string) {
if(value>=0) {
this._name = value;
}
}
// TS中設(shè)置getter方法的法方式
get name() {
console.log('get name()執(zhí)行了');
return this._name;
}
set age(value) {
if(value>=0){
this._age = value;
}
}
}
}
const per = new Person('jeskson', 18);
console.log(per);
// per.name = 'dadaqianduan.cn';
// per.age = 12;
// console.log(per.getName());
// per.setName('jeskson');
// per.age = 2
})();
get name() {
return this._name;
}
set name(value) {
this._name = value;
}
public
class A {
public num: number;
// private num: number;
// protected 受保護的屬性,只能在當(dāng)前類和子類中使用
constructor(num: number){
this.num = num;
}
}
class B extends A {
test() {
console.log(this.num);
}
}
語法糖
class C{
// 可以直接將屬性定義在構(gòu)造函數(shù)中
constructor(public name: string, public age: number){
}
}
泛型
在定義函數(shù)或是類時,如果遇到類型不明確就可以使用泛型
function fn(a: number): number{
return a;
}
此時泛型便能夠發(fā)揮作用;
舉個例子:
function test(arg: any): any{
return arg;
}
any會關(guān)閉掉類型的檢查,任意類型
使用any會關(guān)閉TS的類型檢查,其次這樣設(shè)置也不能體現(xiàn)出參數(shù)和返回值是相同的類型。
創(chuàng)建泛型函數(shù)
// 類型不明確時,使用泛型
function fn<T>(a: T): T{
return a;
}
// T只有在函數(shù)的執(zhí)行的時候,才能定義
這里的<T>就是泛型,不一定非叫T
可以直接調(diào)用具有泛型的函數(shù)
fn(10); // 不指定泛型,ts可以自動對類型進行推斷
fn<string>('jeskson'); // 指定泛型
function fn2<T,k>(a: T, b: K): T {
console.log(b);
return a;
}
fn2<number, string>(123, 'dadaqianduan.cn');
// 限制泛型的類型
interface Inter {
length: number;
}
function fn3<T extends Inter>(a: T): number{
return a.length;
}
fn3('123');
fn3({length: 12);
泛型可以同時指定多個,T extends Inter表示泛型必須時Inter實現(xiàn)類(子類)
泛型類
class MyClass<T> {
name: T;
constructor(name: T) {
this.name = name;
}
}
const mc = new MyClass<string>('jeskson');
typescript打包
webpack整合,通常情況下,實際開發(fā)中我們都需要使用構(gòu)建工具對代碼進行打包;TS同樣也可以結(jié)合構(gòu)建工具一起使用,下邊以webpack為例介紹一下如何構(gòu)建工具使用TS:
初始化項目,進入項目根目錄執(zhí)行命令:npm init -y,創(chuàng)建package.json文件。
下載構(gòu)建工具,命令如下:
npm i -D webpack webpack-cli webpack-dev-server typescript ts-loader clean-webpack-plugin
webpack:構(gòu)建工具webpackwebpack-cli:webpack的命令行工具webpack-dev-server:webpack的開發(fā)服務(wù)器typescript:ts編譯器ts-loader:ts加載器,用于在webpack中編譯ts文件html-webpack-plugin:webpack中html插件,用來自動創(chuàng)建html文件clean-webpack-plugin:webpack中的清除插件,每次構(gòu)建都會先清除目錄
配置webpack
根目錄下創(chuàng)建webpack的配置文件webpack.config.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
optimization:{
minimize: false // 關(guān)閉代碼壓縮,可選
},
entry: "./src/index.ts",
devtool: "inline-source-map",
devServer: {
contentBase: './dist'
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
environment: {
arrowFunction: false // 關(guān)閉webpack的箭頭函數(shù),可選
}
},
resolve: {
extensions: [".ts", ".js"]
},
module: {
rules: [
{
test: /\.ts$/,
use: {
loader: "ts-loader"
},
exclude: /node_modules/
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title:'TS測試'
}),
]
}
配置TS編譯選項
根目錄下創(chuàng)建tsconfig.json,配置可以根據(jù)自己需要
{
"compilerOptions": {
"target": "ES2015",
"module": "ES2015",
"strict": true
}
}
修改package.json配置
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"start": "webpack serve --open chrome.exe"
},
項目使用
在src下創(chuàng)建ts文件,并在并命令行執(zhí)行npm run build對代碼進行編譯;
或者執(zhí)行npm start來啟動開發(fā)服務(wù)器;
Babel
除了webpack,開發(fā)中還經(jīng)常需要結(jié)合babel來對代碼進行轉(zhuǎn)換;以使其可以兼容到更多的瀏覽器,在上述步驟的基礎(chǔ)上,通過以下步驟再將babel引入到項目中。
Promise等ES6特性,TS無法直接轉(zhuǎn)換,這時還要用到babel來做轉(zhuǎn)換。
安裝依賴包:
npm i -D @babel/core @babel/preset-env babel-loader core-js
共安裝了4個包,分別是:
@babel/core:babel的核心工具
@babel/preset-env:babel的預(yù)定義環(huán)境
@babel-loader:babel在webpack中的加載器
core-js:core-js用來使老版本的瀏覽器支持新版ES語法
修改webpack.config.js配置文件
module: {
rules: [
{
test: /\.ts$/,
use: [
{
loader: "babel-loader",
options:{
presets: [
[
"@babel/preset-env",
{
"targets":{
"chrome": "58",
"ie": "11"
},
"corejs":"3",
"useBuiltIns": "usage"
}
]
]
}
},
{
loader: "ts-loader",
}
],
exclude: /node_modules/
}
]
}
使用ts編譯后的文件將會再次被babel處理;使得代碼可以在大部分瀏覽器中直接使用;同時可以在配置選項的targets中指定要兼容的瀏覽器版本
編譯選項
自動編譯文件
tsc xxx.ts -w
自動編譯整個項目
如果直接使用tsc指令,則可以自動將當(dāng)前項目下的所有ts文件編譯為js文件。
但是能直接使用tsc命令的前提時,要先在項目根目錄下創(chuàng)建一個ts的配置文件 tsconfig.json
tsconfig.json是一個JSON文件,添加配置文件后,只需只需 tsc 命令即可完成對整個項目的編譯
include
定義希望被編譯文件所在的目錄
默認值:["**/*"]
示例:
"include":["src/**/*", "tests/**/*"]
exclude
定義需要排除在外的目錄
默認值:["node_modules", "bower_components", "jspm_packages"]
示例:
"exclude": ["./src/hello/**/*"]
extends
定義被繼承的配置文件
示例:
"extends": "./configs/base"
files
指定被編譯文件的列表,只有需要編譯的文件少時才會用到
compilerOptions
編譯選項是配置文件中非常重要也比較復(fù)雜的配置選項
"compilerOptions": {
"target": "ES6"
}
// 設(shè)置ts代碼編譯的目標(biāo)版本
// 可選值:
ES3(默認)、ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext
lib
指定代碼運行時所包含的庫(宿主環(huán)境)
"compilerOptions": {
"target": "ES6",
"lib": ["ES6", "DOM"],
"outDir": "dist",
"outFile": "dist/aa.js"
}
// 可選值:
ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext、DOM、WebWorker、ScriptHost ......
module
設(shè)置編譯后代碼使用的模塊化系統(tǒng)
"compilerOptions": {
"module": "CommonJS"
}
outDir
編譯后文件的所在目錄
"compilerOptions": {
"outDir": "dist"
}
outFile
將所有的文件編譯為一個js文件
默認會將所有的編寫在全局作用域中的代碼合并為一個js文件,如果module制定了None、System或AMD則會將模塊一起合并到文件之中
"compilerOptions": {
"outFile": "dist/app.js"
}
rootDir
指定代碼的根目錄,默認情況下編譯后文件的目錄結(jié)構(gòu)會以最長的公共目錄為根目錄
// 通過rootDir可以手動指定根目錄
"compilerOptions": {
"rootDir": "./src"
}
allowJs
是否對js文件編譯
checkJs
是否對js文件進行檢查
"compilerOptions": {
"allowJs": true,
"checkJs": true
}
removeComments
是否刪除注釋 默認值:false
noEmit
不對代碼進行編譯 默認值:false
sourceMap
是否生成 sourceMap默認值: false
嚴格檢查
strict
啟用所有的嚴格檢查,默認值為true,設(shè)置后相當(dāng)于開啟了所有的嚴格檢查
alwaysStrict
總是以嚴格模式對代碼進行編譯
noImplicitAny
禁止隱式的any類型
noImplicitThis
禁止類型不明確的this
strictBindCallApply
嚴格檢查bind、call和apply的參數(shù)列表
strictFunctionTypes
嚴格檢查函數(shù)的類型
strictNullChecks
嚴格的空值檢查
strictPropertyInitialization
嚴格檢查屬性是否初始化
額外檢查
noFallthroughCasesInSwitch
檢查switch語句包含正確的break
noImplicitReturns
檢查函數(shù)沒有隱式的返回值
noUnusedLocals
檢查未使用的局部變量
noUnusedParameters
檢查未使用的參數(shù)
allowUnreachableCode
檢查不可達代碼
可選值:true,忽略不可達代碼 false,不可達代碼將引起錯誤
noEmitOnError
有錯誤的情況下不進行編譯,默認值:false
npm i -D less less-loader css-loader style-loader
問題:request to https://registry.cnpmjs.org/ts-loader failed, reason: Hostname/IP does not match certificate's altnames: Host: registry.cnpmjs.org. is not in the cert's altnames: DNS:r.cnpmjs.org
命令行下執(zhí)行:
關(guān)閉npm的https(取消npm的https認證)
npm config set strict-ssl false
npm ERR! code ERR_TLS_CERT_ALTNAME_INVALID
npm ERR! errno ERR_TLS_CERT_ALTNAME_INVALID
npm ERR! request to https://registry.cnpmjs.org/cnpm failed, reason: Hostname/IP does not match certificate's altnames: Host: registry.cnpmjs.org. is not in the cert's altnames: DNS:r.cnpmjs.org
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\41586\AppData\Roaming\npm-cache\_logs\2020-08-23T00_26_46_591Z-debug.log
解決辦法:
npm config set registry http://registry.npmjs.org/
使用TypeScript + Webpack + Less項目依賴:
TypeScript:
typescript;
ts-loader;
Webpack:
webpack;
webpack-cli;
webpack-dev-server;
html-webpack-plugin;
clean-webpack-plugin;
Babel:
core-js;
babel-loader;
@babel/core;
@babel/preset-env;
Less & CSS資源:
style-loader;
css-loader;
less;
less-loader;
postcss;
postcss-loader;
postcss-preset-env;
分別執(zhí)行下面的命令安裝依賴并編譯項目:
# 安裝依賴
npm i
# 編譯打包
npm run build
使用npm run start進入開發(fā)模式。
問題:
Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.output has an unknown property 'environment'. These properties are valid:
object { auxiliaryComment?, chunkCallbackName?, chunkFilename?, chunkLoadTimeout?, crossOriginLoading?, devtoolFallbackModuleFilen
ameTemplate?, devtoolLineToLine?, devtoolModuleFilenameTemplate?, devtoolNamespace?, filename?, futureEmitAssets?, globalObject?, has
hDigest?, hashDigestLength?, hashFunction?, hashSalt?, hotUpdateChunkFilename?, hotUpdateFunction?, hotUpdateMainFilename?, jsonpFunc
tion?, jsonpScriptType?, library?, libraryExport?, libraryTarget?, path?, pathinfo?, publicPath?, sourceMapFilename?, sourcePrefix?,
strictModuleExceptionHandling?, umdNamedDefine?, webassemblyModuleFilename? }
-> Options affecting the output of the compilation. `output` options tell webpack how to write the compiled files to disk.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `webpack`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
Mode模式(Mode)
提供 mode 配置選項,告知 webpack 使用相應(yīng)模式的內(nèi)置優(yōu)化。
Providing the mode configuration option tells webpack to use its built-in optimizations accordingly.
string = 'production': 'none' | 'development' | 'production'
用法
只需在配置對象中提供 mode 選項:
module.exports = {
mode: 'development',
};
或者從 CLI 參數(shù)中傳遞:
webpack --mode=development
Mode: development
// webpack.development.config.js
module.exports = {
mode: 'development'
Mode: production
// webpack.production.config.js
module.exports = {
mode: 'production',
Mode: none
// webpack.custom.config.js
module.exports = {
mode: 'none',
如果要根據(jù) webpack.config.js 中的 mode 變量更改打包行為,則必須將配置導(dǎo)出為函數(shù),而不是導(dǎo)出對象:
var config = {
entry: './app.js',
//...
};
module.exports = (env, argv) => {
if (argv.mode === 'development') {
config.devtool = 'source-map';
}
if (argv.mode === 'production') {
//...
}
return config;
};
css
// 清除默認樣式
* {
margin: 0;
padding: 0;
// 改變盒子模型的計算方式
box-sizing: border-box;
}
box-sizing屬性用于更改用于計算元素的寬度和高度默認的CSS盒子模型,可以使用此屬性來模擬不正確支持CSS盒子模型規(guī)范的瀏覽器行為。
框?qū)傩缘幕疽?guī)范:

width和height設(shè)置內(nèi)容框的寬度和高度。內(nèi)容框是框內(nèi)容顯示的區(qū)域,包括框內(nèi)的文本內(nèi)容。padding表示一個css框內(nèi)邊距,這一層位于內(nèi)容框的外邊緣與邊界的內(nèi)邊緣之間。border即css框的邊界是一個分隔層。margin即外邊距代表css框周圍的外部區(qū)域。
box-sizing:border-box屬性
運用box-sizing:border-box屬性下,框模型的變化

width=content+padding+border
采用的是flex布局的方式,為了自適應(yīng),寬度width采用的是百分比%的形式,border,padding,margin采用的是px尺寸,所有外層的盒子運用了box-sizing:border-box,屬性來改變盒子的結(jié)構(gòu)。
背景裁剪(Background clip)屬性
background-clip: border-box:背景被裁剪到邊框盒

#div {
padding: 25px;
border:10px dotted #000;
background-color: yellow;
background-clip: border-box;
}
background-cilp: padding-box;背景被裁剪到內(nèi)邊距框;

#div {
padding: 25px;
border:10px dotted #000;
background-color: yellow;
background-clip: padding-box;
}
background-clip: content-box;背景被裁剪到內(nèi)容框。

#div {
padding: 25px;
border:10px dotted #000;
background-color: yellow;
background-clip: content-box;
}
塊級盒子和內(nèi)聯(lián)盒子
塊級盒子
一個被定義成塊級的(block)盒子會表現(xiàn)出以下行為:
盒子會在內(nèi)聯(lián)的方向上擴展并占據(jù)父容器在該方向上的所有可用空間,在絕大數(shù)情況下意味著盒子會和父容器一樣寬
每個盒子都會換行
width 和 height屬性可以發(fā)揮作用內(nèi)邊距(
padding), 外邊距(margin) 和 邊框(border) 會將其他元素從當(dāng)前盒子周圍“推開”內(nèi)聯(lián)盒子
一個被定義成內(nèi)聯(lián)的(inline box)盒子會表現(xiàn)出以下行為:
盒子不會產(chǎn)生換行。 width 和 height屬性將不起作用。垂直方向的內(nèi)邊距、外邊距以及邊框會被應(yīng)用但是不會把其他處于 inline狀態(tài)的盒子推開。水平方向的內(nèi)邊距、外邊距以及邊框會被應(yīng)用且會把其他處于 inline狀態(tài)的盒子推開。
CSS中組成一個塊級盒子需要:
Content box: 這個區(qū)域是用來顯示內(nèi)容,大小可以通過設(shè)置 width 和 height.
Padding box: 包圍在內(nèi)容區(qū)域外部的空白區(qū)域;大小通過 padding 相關(guān)屬性設(shè)置。
Border box: 邊框盒包裹內(nèi)容和內(nèi)邊距。大小通過 border 相關(guān)屬性設(shè)置。
Margin box: 這是最外面的區(qū)域,是盒子和其他元素之間的空白區(qū)域。大小通過 margin 相關(guān)屬性設(shè)置。

在標(biāo)準模型中,如果你給盒設(shè)置 width 和 height,實際設(shè)置的是 content box。
padding 和 border 再加上設(shè)置的寬高一起決定整個盒子的大小。
示例:
.box {
width: 350px;
height: 150px;
margin: 25px;
padding: 25px;
border: 5px solid black;
}
如果使用標(biāo)準模型寬度 = 410px (350 + 25 + 25 + 5 + 5),高度 = 210px (150 + 25 + 25 + 5 + 5),padding 加 border 再加 content box。

替代(IE)盒模型
默認瀏覽器會使用標(biāo)準模型。如果需要使用替代模型,您可以通過為其設(shè)置 box-sizing: border-box 來實現(xiàn)。
示例:
.box {
box-sizing: border-box;
}

回看筆者往期高贊文章,也許能收獲更多喔!
一個合格的初級前端工程師需要掌握的模塊筆記 前端模擬面試字數(shù)過23477萬內(nèi)容 Vue.js筆試題解決業(yè)務(wù)中常見問題 【初級】個人分享Vue前端開發(fā)教程筆記 長篇總結(jié)之JavaScript,鞏固前端基礎(chǔ) 前端面試必備ES6全方位總結(jié) 達達前端個人web分享92道JavaScript面試題附加回答 【圖文并茂,點贊收藏哦!】重學(xué)鞏固你的Vuejs知識體系 【思維導(dǎo)圖】前端開發(fā)-鞏固你的JavaScript知識體系 14期-連肝7個晚上,總結(jié)了計算機網(wǎng)絡(luò)的知識點?。ü?6條) 這是我的第一次JavaScript初級技巧 localStorage和sessionStorage本地存儲 HTML5中的拖放功能 挑戰(zhàn)前端知識點HTTP/ECMAScript 必學(xué)必會-音頻和視頻 前端170面試題+答案學(xué)習(xí)整理(良心制作) 前端HTML5面試官和應(yīng)試者一問一答 哪吒鬧海,席卷圖文學(xué)習(xí)前端Flex布局 騰訊位置服務(wù)開發(fā)應(yīng)用 【進階】面試官問我Chrome瀏覽器的渲染原理(6000字長文) 面試官一上來就問我Chrome底層原理和HTTP協(xié)議(萬字長文) 熬夜總結(jié)了 “HTML5畫布” 的知識點 this/call/apply/bind(萬字長文) HTTP/HTTPS/HTTP2/DNS/TCP/經(jīng)典題 執(zhí)行上下文/作用域鏈/閉包/一等公民 Web頁面制作基礎(chǔ) 學(xué)習(xí)總結(jié)之HTML5劍指前端(建議收藏,圖文并茂)
??關(guān)注+點贊+收藏+評論+轉(zhuǎn)發(fā)??
點贊、收藏和評論
我是Jeskson(達達前端),感謝各位人才的:點贊、收藏和評論,我們下期見!(如本文內(nèi)容有地方講解有誤,歡迎指出?謝謝,一起學(xué)習(xí)了)
我們下期見!
文章持續(xù)更新,可以微信搜一搜「 程序員哆啦A夢 」第一時間閱讀,回復(fù)【資料】有我準備的一線大廠資料,本文 http://www.dadaqianduan.cn/#/ 已經(jīng)收錄
github收錄,歡迎Star:https://github.com/webVueBlog/WebFamily
