Typescript之从零开始学习笔记,涵盖常用基本类型实操案例

Typescript之从零开始学习笔记

文章目录

  • Typescript之从零开始学习笔记
  • 1.环境搭建
    • [1. 安装node.js](#1. 安装node.js)
    • [2. 安装typescript](#2. 安装typescript)
    • [3. 使用tsc对ts进行编译](#3. 使用tsc对ts进行编译)
  • [2. TS 配置](#2. TS 配置)
    • [1 编译器配置](#1 编译器配置)
      • [1. 生成配置文件](#1. 生成配置文件)
      • [2. 自动编译](#2. 自动编译)
      • [3. 发生错误](#3. 发生错误)
  • [3. 基本语法](#3. 基本语法)
    • [1. 静态类型检查](#1. 静态类型检查)
    • 2.基本数据类型
    • [3. 数组类型](#3. 数组类型)
    • [4. any类型](#4. any类型)
    • [5. 函数的参数类型](#5. 函数的参数类型)
    • 6.函数形参为对象类型
    • [7. 联合类型](#7. 联合类型)
    • [8 类型别名](#8 类型别名)
    • [9. 类类型](#9. 类类型)
    • 10.接口类型
    • [11. 类型断言](#11. 类型断言)
    • [12. 模板文字类型(Template Literal Types)](#12. 模板文字类型(Template Literal Types))
    • [13. TS特殊符号用法](#13. TS特殊符号用法)
  • [4. type与接口扩展字段类型区别](#4. type与接口扩展字段类型区别)

官网:https://www.typescriptlang.org/

官网文档:https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html

1.环境搭建

1. 安装node.js

官网下载直接安装即可(安装过程略)

2. 安装typescript

  1. 安装
sh 复制代码
# npm i -g typescript
C:\Users\infodba>npm i -g typescript
D:\Program Files\nodejs\node_global\tsc -> D:\Program Files\nodejs\node_global\node_modules\typescript\bin\tsc
D:\Program Files\nodejs\node_global\tsserver -> D:\Program Files\nodejs\node_global\node_modules\typescript\bin\tsserver
+ typescript@4.5.4
added 1 package from 1 contributor in 5.696s
  1. 查看typescript版本
shell 复制代码
# tsc -v
C:\Users\infodba>tsc -v
Version 4.5.4

3. 使用tsc对ts进行编译

typescript 复制代码
tsc xxx.ts

2. TS 配置

1 编译器配置

1. 生成配置文件

shell 复制代码
# 1. 生成配置文件
tsc --init 
PS F:\2022WebStudy\yuan-ts-study\yuan-ts-study> tsc --init
Created a new tsconfig.json with:                                                                                  TS 
  target: es2016
  module: commonjs
  strict: true
  esModuleInterop: true
  skipLibCheck: true
  forceConsistentCasingInFileNames: true
You can learn more at https://aka.ms/tsconfig.json
#tsc --init 命令执行完后默认会在当前目录下生成tsconfig.json文件
  • tsconfig.json配置文件内容如下:
json 复制代码
{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */

    /* Projects */
    // "incremental": true,                              /* Enable incremental compilation */
    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
    // "tsBuildInfoFile": "./",                          /* Specify the folder for .tsbuildinfo incremental compilation files. */
    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects */
    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */

    /* Language and Environment 默认加载的是es2016也即es7,可以配置es3|es5|es6|es7等来兼容低版本浏览器的js支持 */
    "target": "es2016",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
    // "jsx": "preserve",                                /* Specify what JSX code is generated. */
    // "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */
    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
    // "reactNamespace": "",                             /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */

    /* Modules */
    "module": "commonjs",                                /* Specify what module code is generated. */
    // "rootDir": "./",                                  /* Specify the root folder within your source files. */
    //指定ts源文件目录
    "rootDir":"./src",
    // "moduleResolution": "node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
    // "typeRoots": [],                                  /* Specify multiple folders that act like `./node_modules/@types`. */
    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
    // "resolveJsonModule": true,                        /* Enable importing .json files */
    // "noResolve": true,                                /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */

    /* JavaScript Support */
    // "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */

    /* Emit */
    // "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
    // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
       //指定编译后的ts输出目录
      "outFile": "./dist",     
      // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
    // "outDir": "./",                                   /* Specify an output folder for all emitted files. */
    // "removeComments": true,                           /* Disable emitting comments. */
    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types */
    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
    // "newLine": "crlf",                                /* Set the newline character for emitting files. */
    // "stripInternal": true,                            /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like `__extends` in compiled output. */
    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
    // "preserveConstEnums": true,                       /* Disable erasing `const enum` declarations in generated code. */
    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */

    /* Interop Constraints */
    // "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */

    /* Type Checking 强制语法检查, */
    "strict": true,                                      /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied `any` type.. */
    // "strictNullChecks": true,                         /* When type checking, take into account `null` and `undefined`. */
    // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
    // "strictBindCallApply": true,                      /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
    // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
    // "noImplicitThis": true,                           /* Enable error reporting when `this` is given the type `any`. */
    // "useUnknownInCatchVariables": true,               /* Type catch clause variables as 'unknown' instead of 'any'. */
    // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
    // "noUnusedLocals": true,                           /* Enable error reporting when a local variables aren't read. */
    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read */
    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
    // "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
    // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
    // "noUncheckedIndexedAccess": true,                 /* Include 'undefined' in index signature results */
    // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type */
    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
    // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */

    /* Completeness */
    // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
  }
}

2. 自动编译

在vscode工具中使用下面命令会开启自动编译监听,当xxx.ts编写完成后会自动触发编译器并编译成xxx.js文件

shell 复制代码
# 2. 自动编译
tsc --watch

3. 发生错误

如果ts中写了编译成js文件运行时异常的代码,ts在编译成js时默认会编译通过,而执行js时才会报错,如果想要再编译时直接抛出异常,则使用下面命令

shell 复制代码
# 3. 发出错误
tsc -onEmitOnError hello.ts

3. 基本语法

1. 静态类型检查

2static-typecheck.ts内容如下:

ts 复制代码
/**静态类型检查 */
const msg = "hello"
msg()
/**
编译会出现如下错误:
2.static-typecheck.ts:4:1 - error TS2349: This expression is not callable.
  Type 'String' has no call signatures.
4 msg()
*/

2.基本数据类型

3datatype-base.ts内容如下

ts 复制代码
/** 数据类型---基本数据类型*/
let age: number = 20;
let userName: string = 'jinshengyuan'
let gender: boolean = true
let person: any = { 
    "name":"jinshengyuan",
    "code":"001"
}
let date: Date = new Date()

console.log(`${age} type is ${typeof age}`)
console.log(`${userName} type is ${typeof userName}`)
console.log(`${gender} type is ${typeof gender}`)
console.log(`${person} type is ${typeof person}`)
console.log(person.name,"=============="+person.code)
console.log(`${date} type is ${typeof date}`)
# 执行结果如下:
PS F:\2022WebStudy\yuan-ts-study\yuan-ts-study\dist> node .\3datatype-base.js
20 type is number
jinshengyuan type is string
true type is boolean
[object Object] type is object
jinshengyuan ==============001
Sat Jan 15 2022 16:18:50 GMT+0800 (中国标准时间) type is object

3. 数组类型

数组定义有两种方式:

  • 普通方式:let v:dataType [] = []
  • 泛型方式:let v:Array = []
ts 复制代码
/** 
 * 数据类型-数组
 * 有两种方式:
 * 1.普通方式
 * let v:dataType [] = []
 * 2.泛型方式
 * let v:Array<dataType> = []
 *  */

//1. variable:dataType []
let numArr: number[] = [1, 3, 34, 904]

numArr.forEach(num => {
    console.log(num);
});
console.log("=======================")
// 2.泛型方式
let strArr: Array<string> = ['a', 'b', 'c']

strArr.forEach(str => {
    console.log(str)
})
/*** 执行结果如下:
 1
3
34
34
=======================
a
b
c
*/

4. any类型

不希望某个特定值导致类型检查错误时可以使用any类型

ts 复制代码
/** 数据类型-any */
let obj: any = {
    userName: 'jinshengyuan',
    gender: true,
    age: 27,
    birthday: 'xxxx-xx-xx'
}

console.log(obj.userName)
//jinshengyuan

/** 数据类型-any */
let obj: any = {
    userName: 'jinshengyuan',
    gender: true,
    age: 27,
    birthday: 'xxxx-xx-xx'
}

console.log(obj.userName)
//jinshengyuan

//objOne后面不跟数据类型,ts会根据属性的值自动推断具体的类型
let objOne = {
    userName: 'jinshengyuan',
    gender: true,
    age: 27,
    birthday: 'xxxx-xx-xx'
}

5. 函数的参数类型

6datatype-funcation.ts如下

ts 复制代码
/** 数据类型-函数形参类型定义 */
// 1.函数形参指定类型
let f1 = (name: string, age: number) => {
    console.log(`${name}已经${age}岁了`);

}
f1('jinshengyuan', 22)

//2.函数无返回值类型指定
function f2(a: number, b: number): void {
    console.log(`${a}+${b}=${a + b}`)
}
f2(2, 33)

//3.函数有返回值类型指定
function f3(a: number, b: number): number {
    return a + b;
}
let f3_result = f3(3, 4)
console.log("f3_result:" + f3_result)

//4.类型推断

const names = ['zhangsan', 'lisi', '王五']
names.forEach(function (name) {
    //这里虽然name没有显示的指定类型,但ts将names中每一个元素自动推断为string类型,就可以直接调用string类型的方法
    console.log(name.toUpperCase())
})
//或使用箭头函数
names.forEach(name => {
    console.log(name.toUpperCase())
})

6.函数形参为对象类型

  1. 函数形参中是一个对象,则对象的每个属性的类型后用分割;

  2. 若对象参数中某个属性的值可选,则属性后需要跟表示此属性值可指定也可不指定,否则必须指定值

  3. 若对象参数中某个属性的值可选且为string类型,则此时调用spring类型的方式时必须也跟上?,否则ts编译报错

ts 复制代码
/**数据类型-对象类型指定 */

//1.函数形参中是一个对象,则对象的每个属性的类型后用,或;分割
// , 分割
function myAxisA(pt: { x: number, y: number }) {
    console.log("坐标A:" + pt.x, pt.y)
}

// ; 分割
function myAxisB(pt: { x: number; y: number }) {
    console.log("坐标B:" + pt.x, pt.y)
}

const pointDataA = {
    x: 22,
    y: 33
}
myAxisA(pointDataA);

const pointDataB = {
    x: 100,
    y: 300
}
myAxisB(pointDataB);

/***
坐标A:22 33
坐标B:100 300
 */

//2.若对象参数中某个属性的值可选,则属性后需要跟`?`表示此属性值可指定也可不指定,否则必须指定值
function printName(person: { name: string, age?: number }) {
    console.log(person.name)
}
//不传age属性也能编译通过及正常打印
printName({
    name: 'jinshengyuan'
})
//传age属性能编译通过及正常打印
printName({
    name: 'jinshengyuan',
    age: 33
})

//3. 若对象参数中某个属性的值可选且为string类型,则此时调用spring类型的方式时必须也跟上`?`,否则ts编译报错
function printName1(obj: { name: string, code?: string }) {
    //新式优雅写法,在对象的属性名后加入`?`
    console.log(obj.code?.toUpperCase())
    //原始写法
    if (obj.code != undefined) {
        console.log(obj.code.toUpperCase())
    }
}
printName1({
    name: '张三',
    code: 'zangSan'
})

7. 联合类型

联合类型中间使用管道符|进行分割

ts 复制代码
/** 数据类型-联合类型  let v:numver|string|boolean */
// 联合类型中间使用管道符`|`进行分割
//1.printInfo函数的id属性类型可以为数值、字符串、数组三种类型
function printInfo(id: number | string | Array<string>) {
    console.log("只为:" + id + "类型为:" + typeof id)
}
printInfo(222)
printInfo('aaa')
printInfo(['a', 'b', 'c'])
/*
222类型为:number
aaa类型为:string
a,b,c类型为:object
*/

//2.如果v传入的是数组,则在后面追加z,否则输出hello
function hello(v: string[] | string) {
    if (Array.isArray(v)) {
        console.log(v.join("z"))
    } else {
        console.log("hello")
    }
}
hello(['x', 'y'])
hello("hi")
/*
xzy
hello
*/
//3. 多种类型共有的方法,如数字素组与字符窜都有截取元素的方法`slice()`
function publicM(x: number[] | string) {
    //截取前三个元素
    console.log(x.slice(0, 3))
}

publicM([1, 3, 34, 46, 4, 67, 90, 7, 5])
publicM('helloword')
/*
[ 1, 3, 34 ]
hel
*/

8 类型别名

  1. ts中定义参数类型时都是变量名在前而数据类型在后,类型别名就是将类型放在变量名称前边,类似与Java中声明变量的方式

  2. 类型别名使用 type关键字指定,且给变量赋值的是具体的数据类型,如type id = string|number,可以是时任何类型;

  3. type 关键字后边如果如果是一个对象类型,则对象的属性指定类型有三种写法,区别在于属性之间用 ,|;|\n进行分割

  4. 作用目的:可以时同一类型多次重复使用

ts 复制代码
/** 数据类型-类型别名 语法: type x = string|number */
// 类型别名为pointType的类型为string 或 number
type pointType = string | number

// 类型为 point 的类型是对象,对象中的属性类型=别名为pointType的类型  
//[注意:下面指定类型别名的方式等价,即:point=pointA=pointB,区别在于 `,`|`;`|`\n`]
//1.属性指定用`,`隔开
type point = {
    x: pointType,
    y: pointType
}
// 2. 属性之间用`;`隔开
type pointA = {
    x: pointType;
    y: pointType
}
// 3. 属性之间换行,写在一行是不行的
type pointB = {
    x: pointType
    y: pointType
}

function getPoint(pt: point) {
    console.log("坐标:" + pt.x + "," + pt.y)
}
getPoint({
    x: '220',
    y: 333
})

getPoint({
    x: 100,
    y: 200
})
/*
坐标:220,333
坐标:100,200
*/

9. 类类型

ts 复制代码
class Demo {
  a: number;
  b: number;
  constructor(a: number, b: number) {
    this.a = a;
    this.b = b;
  }
  getDemo() {
    return `(${this.a}, ${this.b})`;
  }
}

const demo = new Point(5, 7);
demo.getDemo()   // (5, 7)

10.接口类型

  1. 接口以interface关键字开头,且变量名大写;
  2. 接口可以继承接口
ts 复制代码
/** 数据类型-接口 */
//1. 定义一个动物接口
interface Animals {
    name: string;
    age: number;
}
//dog函数形参指定为接口类型
function dog(dog: Animals) {
    console.log(dog.name, dog.age);
}
dog({ name: '小狗', age: 4 })

//2. 接口继承接口类型,Ant继承Animals
interface Ant extends Animals {
    like: string;
    day: number;
}

function ant(ant: Ant) {
    console.log(`小蚂蚁${ant.name} ${ant.age}岁了,${ant.like}每${ant.day}天搬家一次`)
}
// 继承自父接口的属性必须指定全,否则编译不通过
ant({ name: '土豆', age: 4, like: "喜欢", day: 5 })

// 3. 向现有类型中添加字段,可以多次声明后直接将属性合并到一起
interface MyInfo {
    name: string;
}
interface MyInfo {
    age: number;
}
interface MyInfo {
    gender: boolean;
}

const myinfo: MyInfo = {
    name: "张三",
    age: 33,
    gender: true
}
//===========type 扩展字段类型==============
// 1. 声明对象类型
type Animal = {
    name: string;
}
//2.扩展字段类型
type Tigger = Animal & {
    hobby: string
}
const tigger: Tigger = {
    name: "老虎",
    hobby: "吃肉"
}

//3. type声明的类型对象是不可更改的,所以不能添加类型字段

11. 类型断言

语法:就是在获得的某个DOM元素后,在元素前面加泛型或在元素之后通过as 关键字指定元素的具体类型

有两种写法:

  • const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement
  • const myCanvas = document.getElementById("main_canvas")
ts 复制代码
/** 数据类型-类型断言 */
const myCanvas1 = document.getElementById("main_canvas") as HTMLCanvasElement
const myCanvas2 = <HTMLCanvasElement>document.getElementById("main_canvas") 
// 
const x = ('hello' as any) as string
// unknow 未知类型
const y = ('22' as unknown) as number
          

12. 模板文字类型(Template Literal Types)

13. TS特殊符号用法

  1. 属性或参数中使用 ?:表示该属性或参数为可选项
  2. 属性或参数中使用 !:表示强制解析(告诉typescript编译器,这里一定有值),常用于vue-decorator中的@Prop
  3. 变量后使用 !:表示类型推断排除null、undefined

4. type与接口扩展字段类型区别

相同点:

  1. 都可以定义对象属性的类型
  2. 都可以扩展字段类型,type 通过 & 符合扩展字段类型,interface通过extends关键字来扩展字段类型

不同点:

接口支持向已有类型对象中添加属性,而type不支持

  1. 扩展字段方式不同
ts 复制代码
//1. 接口-通过`extends`关键字继承父接口来扩展字段
interface Animals {
    name: string;
    age: number;
}
//接口继承接口类型,Ant继承Animals
interface Ant extends Animals {
    like: string;
    day: number;
}
//dog函数形参指定为接口类型
function dog(dog: Animals) {
    console.log(dog.name, dog.age);
}
dog({ name: '小狗', age: 4 })

//2. type-通过 `&` 符合来扩展字段
type Animal = {
    name: string;
}
// type 扩展字段类型
type Tigger = Animal & {
    hobby: string
}
const tigger: Tigger = {
    name: "老虎",
    hobby: "吃肉"
}
  1. 向现有的对象类型中添加字段
  • 接口通过多次声明同名的接口方式来添加字段,使用时会将属性合并到一起;
  • type一旦声明了字段类型是不可更改的,所以不支持添加字段
ts 复制代码
// 1.interface-向现有类型中添加字段,可以多次声明同名的接口后直接将属性合并到一起
interface MyInfo {
    name: string;
}
interface MyInfo {
    age: number;
}
interface MyInfo {
    gender: boolean;
}

const myinfo: MyInfo = {
    name: "张三",
    age: 33,
    gender: true
}
// 2.type-不支持向现有类型对象中添加字段
相关推荐
胡西风_foxww6 分钟前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_748254888 分钟前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
星就前端叭1 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234521 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js
Web阿成1 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript
jwensh2 小时前
【Jenkins】Declarative和Scripted两种脚本模式有什么具体的区别
运维·前端·jenkins
关你西红柿子2 小时前
小程序app封装公用顶部筛选区uv-drop-down
前端·javascript·vue.js·小程序·uv
益达是我2 小时前
【Chrome】浏览器提示警告Chrome is moving towards a new experience
前端·chrome
济南小草根2 小时前
把一个Vue项目的页面打包后再另一个项目中使用
前端·javascript·vue.js
聪小陈2 小时前
圣诞节:记一次掘友让我感动的时刻
前端·程序员