千锋教育前端Vue3.0全套视频教程(Kerwin2023版,Vue.js零基础

组合式和选项式不同,
选项式vue3向下兼容vue2的大部分,除了过滤器,还有两个钩子函数(名称修改了),
组合式中没有了vue2中的created和beforecreated,改为了setup
v-if比v-for有更高优先级
vue3中可以绑定多个事件一定要添加小括号() ,方法中间使用逗号, 隔开即可
事件中使用下列方法可以事件和值同时传
vue2和vue3都支持,传值设置多个类型
vue可以将clas样式传给子组件
reactive 定义响应式数据
reactive它也是定义响应式数据的
ref 它可以定义任意类型,ref定义的对象调用是一定要加.value
reactive 它只能定义引用类型[对象],调用reactive对象中的属性不需要加.value的
reactive可以理解为是对ref在引用对象定义的一个简化方案,不用写.value
把值转为ref对象 1 对 1
批量转换 把reactive中的所有的数据对转为ref对象
shallowReactive,isReactive,readonly
shallowReactive 浅层响应式,只对对象的第1层进行响应式处理
isReactive 工具函数,检查当前的变量是否是由 reactive 或 shallowReactive 创建
ref reactive toRefs => 重点记牢 ref
多事件绑定
1.以逗号隔开
2.写数组 可以写成数组方式,亲测发现还是需要写小括号
defineComponent 和 customRef
defineComponent 如果你在选项式方案用ts,写此方案为多,可以有类型推导
defineComponent 此方案还有更好的语法提示
customRef 创建一个自定义的 ref,显式声明对其依赖追踪和更新触发的控制方式
customRef 想着自主的去处理ref响应数据过程控制就可以用到它
setup
1.setup它是vue3提供的compositionApi配置入口,所有的组合api都只能写在此配置中
2.此方法它不能使用this,this它是一个undefined
3.此方法默认只能返回json对象,不能返回其他类型
4.如果使用async/await则必须要和Suspense组件进行集合才可以使用
5.setup它有两个参数,此参数可以让我们在写代码调用props或相关方法
6.setup中包含了数据,方法,计算属性,侦听器等
注:如果你写的是一个选项式写法,data和setup等是可以共存的
在vue3中自定义的函数,如果是以use开头的,一般叫它为 hooks函数
自定义hooks函数
为何返回值用数组不用对象?
在解构时,它更加灵活方便,可以随意的去起解构变量名称
provide和inject
- provide是提供一个值,可以被后代组件注入。
provide() 接受两个参数:第一个参数是要注入的 key,可以是一个字符串或者一个 symbol,第二个 参数是要注入的值。
- inject注入一个由祖先组件或整个应用 (通过 app.provide()) 提供的值。
第一个参数是注入的 key。第二个参数是可选的,即在没有匹配到 key 时使用的默认值。
需要注意的是只有响应式的才能被子组件所接收实现响应式,即ref或reactive定义的
dev (Development environment) : 开发环境,外部用户无法访问,开发人员使用,版本变动很大。
sit (System Integration Test ) : 系统集成测试,开发人员自己测试流程是否走通。
test :测试环境,外部用户无法访问,专门给测试人员使用的,版本相对稳定。
fat (Feature Acceptance Test environment) : 功能验收测试环境,用于软件测试者测试使用
uat (User Acceptance Test environment) : 用户验收测试环境,用于生产环境下的软件测试者测试使用。
pre :灰度环境,外部用户可以访问,但是服务器配置相对低,其它和生产一样,外部用户可以访问,版本发布初期,正式版本发布前。
pro(Production e
ts基础
一、基本类型
1. string 类型
let firstName: string = "张三"; let message: string = `Hello ${firstName}, age is ${age}`;
2. number 类型
let age: number = 18;
3. boolean 类型
let isDone: boolean = false;
4. bigInt 类型
let oneHundred: bigint = BigInt(100);
5. symbol 类型
let s: symbol = Symbol();
6. void类型
let s: void
7. null类型
let s: null
8. undefined类型
let s: undefined
9. never类型
let s: never
二、Array 与 Tuple
1. Array 类型
// 第一种定义数组类型的方式: type[] let arr1: number[] = [1, 2, 3, 4]; // 第二种定义数组类型的方式(数组泛型):Array<type> let arr2: Array<number> = [1, 2, 3, 4];
2. Tuple 类型
数组一般由同种类型的值组成,但有时我们需要在数组中储存不同类型的值,这时候我们就可以使用元组。
元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。
let x: [string, number]; x = ["hello", 1]; // OK x = [1, "hello"]; // Error console.log(x[0]); // 输出 hello
三、Any 与 Unknown
1. Any 类型
在 TypeScript 中,任何类型都可以被归为 any
类型。这让 any
类型成为了类型系统的顶级类型(也被称为全局超级类型)
作为开发者,any
类型给了我们很大的自由:TypeScript 允许我们对 any
类型的值执行任何操作,而无需事先执行任何形式的检查:
// 声明一个 any 类型的变量 let notSure: any = 4; // 可以给它赋值为 其他任何类型 notSure = "maybe it is a string"; // OK notSure = true; // OK // 调用它不存在的属性or方法 notSure.myName; // Ok notSure.getName(); // OK // 将它赋值给任意类型的 let num: number = notSure // OK
在许多情况下,这太宽松了。使用 any
类型,可以很容易编写类型正确但在运行时可能有问题的代码。如果我们使用 any
类型,就无法使用 TypeScript 提供的大量的保护机制。为了解决 any 带来的问题,TypeScript 3.0 引入了类型安全的 unknown
类型。
2. noImplicitAny 配置
如果未指定类型,并且 TypeScript 无法从上下文推断出类型,则编译器通常默认为:any
通常希望避免这种情况,可以在tsconfig.json
文件中配置:
"noImplicitAny": true
3. Unknown 类型
就像所有类型都可以赋值给 any
, 所有类型也都可以赋值给 unknown
。这使得 unknown
成为 TypeScript 类型系统的另一种顶级类型(另一种是 any
)
let value: unknown; value = true; // ok value = 40; // ok value = "hello world"; // ok value = []; // ok value = {}; // ok value = null; // ok value = undefined; // ok value = new TypeError(); // ok value = Symbol(); // ok
只能将 unknown
类型分配给 any
类型和 unknown
类型。
let value: unknown; let value1: unknown = value; // ok let value2: any = value; // ok let value3: number = value; // Error let value4: string = value; // Error
对 unknown
类型的值做一些操作时,这些操作将不再被认为是类型正确的。
// 声明一个 unknown 类型的变量 let notSure: unknown = 4; // 可以给它赋值为 其他任何类型 notSure = "maybe it is a string"; notSure = true; // 调用它不存在的属性or方法 notSure.myName; // Error notSure.getName(); // Error // 将它赋值给任意类型 let num: number = notSure; // Error
any不挑剔,也很受人喜欢
unknown不挑剔,只有any和unknown两个朋友
四、类型推导
TypeScript 能根据一些简单的规则推断(检查)变量的类型。故大部分情况下我们无需手动标注类型。
let foo = 123; // foo 是 'number' let bar = 'hello'; // bar 是 'string' foo = bar; // Error: 不能将 'string' 赋值给 `number`
五、函数
函数是在 JavaScript 中传递数据的主要方式。 TypeScript 允许您指定函数的输入和输出值的类型。
1. 参数类型标注
function greet(name: string) { console.log("Hello, " + name.toUpperCase() + "!!"); } greet("hello"); // OK greet(42); // Error 类型“number”的参数不能赋给类型“string”的参数。
2. 可选参数
/** * 通过在 参数名称后面写一个 ? 号,表示该参数可选。 * 这时 name 的类型为 string | undefined 的一个联合类型 */ function greet(name?: string) { // TODO } greet("hello"); // OK greet(); // OK greet(42); // Error 类型“number”的参数不能赋给类型“string”的参数
3. 返回类型标注
function getFavoriteNumber(): number { // return 26; // OK return "hello"; // Error 不能将类型“string”分配给类型“number”。 }
4. 匿名函数自动推断类型
const names = ["Alice", "Bob", "Eve"]; names.forEach(function (s) { console.log(s.toUppercase()); // Error 属性“toUppercase”在类型“string”上不存在。你是否指的是“toUpperCase”? }); names.forEach((s) => { console.log(s.toUppercase()); // Error 属性“toUppercase”在类型“string”上不存在。你是否指的是“toUpperCase”? });
六、对象类型
要定义对象类型,我们只需列出其属性及其类型
function printCoord(pt: { x: number; y: number }) { console.log("The coordinate's x value is " + pt.x); console.log("The coordinate's y value is " + pt.y); } printCoord({ x: 3, y: 7 }); // OK printCoord({ x: "3", y: "8" }); // Error 不能将类型“string”分配给类型“number”
1. 可选属性
对象类型还可以指定其部分或全部属性是可选的。 只需要在属性名称后添加 ?
号即可。
function printName(obj: { first: string; last?: string }) { // ... } printName({ first: "Bob" }); // OK printName({ first: "Alice", last: "Alisson" }); // OK
2. 可选属性检查
当您从可选属性读取时,您必须在使用之前进行检查。
function printName(obj: { first: string; last?: string }) { console.log(obj.last.toUpperCase()); // Error 对象可能为“未定义” if (obj.last !== undefined) { // OK console.log(obj.last.toUpperCase()); } // OK console.log(obj.last?.toUpperCase()); }
3. 只读属性
对象类型还可以指定其部分或全部属性是只读的。只需要在属性名称前添加 readonly
即可。
function printName(obj: { readonly first: string; last?: string }) { obj.first = "hello"; // Error 无法分配到 "first" ,因为它是只读属性。 }
七、交叉类型(&)
交叉类型:将多个类型合并为一个类型,使用&
符号连接,如:
type AProps = { a: string } type BProps = { b: number } type allProps = AProps & BProps const Info: allProps = { a: '小杜杜', b: 7 }
八、联合类型 |
联合类型是由两个或多个其他类型组成的类型,通常使用 | 联合。
1. 定义联合类型
function printId(id: number | string) { console.log("Your ID is: " + id); } printId(100); // OK printId("200"); // OK printId(true); // Error 类型“boolean”的参数不能赋给类型“string | number”的参数 let isOk: 0 | 1 = 2; // 不能将类型“2”分配给类型“0 | 1”
2. 使用联合类型
在 TypeScript 中,若一个变量使用了联合类型,那么当我们使用该变量时必不可少的会去明确的限制该变量的具体类型,这称为类型缩小。
function printId(id: number | string) { console.log(id.toUpperCase()); // Error // 类型缩小 if (typeof id === "string") { // In this branch, id is of type 'string' console.log(id.toUpperCase()); } else { // Here, id is of type 'number' console.log(id); } }
九、类型别名
将现有的一些类型取个别名,方便后续复用。
1. 描述对象
type Point = { x: number; y: number; }; function printCoord(pt: Point) { console.log("The coordinate's x value is " + pt.x); console.log("The coordinate's y value is " + pt.y); } printCoord({ x: 100, y: 100 });
十、接口
接口声明是命名对象类型的另一种方法:
1. 描述对象
interface Point { x: number; y: number; } function printCoord(pt: Point) { console.log("The coordinate's x value is " + pt.x); console.log("The coordinate's y value is " + pt.y); } printCoord({ x: 100, y: 100 });
2. 描述函数
interface SetPoint { (x: number, y: number): void; }
十一、type 和 interface
1. 相同点
- 类型别名和接口都可以用来描述对象或函数
- 类型别名和接口都支持扩展
2. 不同点
- 类型别名可以为基本类型、联合类型或元组类型定义别名,而接口不行。
- 同名接口会自动合并,而类型别名不会。
3. 使用场景
- 使用类型别名的场景:
- 定义基本类型的别名时,使用 type
- 定义元组类型时,使用 type
- 定义函数类型时,使用 type
- 定义联合类型时,使用 type
- 定义映射类型时,使用 type
- 使用接口的场景:
- 需要利用接口自动合并特性的时候,使用 interface
- 定义对象类型且无需使用 type 的时候,使用 interface
十二、TypeScript 断言
1. 类型断言
有时候你会遇到这样的情况,你会比 TypeScript 更了解某个值的详细信息。通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方法可以告诉编译器,”相信我,我知道自己在干什么“。类型断言好比其他语言里的类型转换,但是不进行特殊的数据检查和解构。它没有运行时的影响,只是在编译阶段起作用。
类型断言有两种方式:
1. 尖括号<> 语法
let someValue: any = "this is a string"; let strLength: number = (<string>someValue).length;
2. as 语法
let someValue: any = "this is a string"; let strLength: number = (someValue as string).length;
vue中一般使用as
2. 非空断言
非空断言使用一个后缀表达式操作符!
表示。可以用于断言操作对象是非 null 和 非 undefined 类型的。
1. 忽略 null 和 undefined 类型
function myFunc(maybeString: string | null | undefined) { const str: string = maybeString; // 不能将类型“string | null | undefined”分配给类型“string”。不能将类型“undefined”分配给类型“string” const str1: string = maybeString!; // OK console.log(str); console.log(str1); }
2. 调用函数时忽略 undefined 类型
type CallbackType = () => number; function myFunc(callback: CallbackType | undefined) { const num1 = callback(); // Error 不能调用可能是“未定义”的对象。 const num2 = callback!(); // Ok }
十三、文本类型 git merge 分支名
除了一般类型之外,我们还可以在类型位置引用特定的字符串
和数字
let isOk: 0 | 1 = 2; // 不能将类型“2”分配给类型“0 | 1” let string: "hello" = ""; // Error 不能将类型“""”分配给类型“"hello"”
十四、Null 和 Undefined 类型
TypeScript 中,undefined
和 null
两者都有各自的类型分别为 undefined
和 null
。
let u: undefined = undefined; let n: null = null;
十五、Enum 类型
使用枚举我们可以定义一些带名字的常量。使用枚举可以清晰地表达意图或创建一组有区别的用例。
TypeScript 支持数字和字符串的枚举。
1. 数字枚举
enum Direction { Up, Down, Left, Right, } let dir: Direction = Direction.Up; /** * 默认情况下,Up 的值为 0, 其余成员会按顺序自增。 * Up 0 * Down 1 * Left 2 * Right 3 */ enum Direction { Up = 1, Down, Left, Right, } let dir: Direction = Direction.Up; /** * 也可以给成员设置初始值。 * Up 1 * Down 2 * Left 3 * Right 4 */ enum Direction { Up = 1, Down, Left, Right, } let dir: Direction = Direction.Up; /** * 也可以给成员设置初始值。 * Up 1 * Down 2 * Left 3 * Right 4 */
编译生成的 JS 代码如下示例:
var Direction; (function (Direction) { Direction[Direction["Up"] = 1] = "Up"; Direction[Direction["Down"] = 2] = "Down"; Direction[Direction["Left"] = 3] = "Left"; Direction[Direction["Right"] = 4] = "Right"; })(Direction || (Direction = {})); var dir = Direction.Up;
2. 字符串枚举
在 TypeScript 2.4 版本,允许我们使用字符串枚举。在一个字符串枚举里,每个成员都必须用字符串字面量。
enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT", } let dir: Direction = Direction.Up;
编译生成的 JS 代码如下示例:
var Direction; (function (Direction) { Direction["Up"] = "UP"; Direction["Down"] = "DOWN"; Direction["Left"] = "LEFT"; Direction["Right"] = "RIGHT"; })(Direction || (Direction = {})); var dir = Direction.Up;
反向映射:
通过观察数字枚举和字符串枚举的编译结果,我们可以知道数字枚举除了支持 从成员名称到成员值 的普通映射之外,它还支持 从成员值到成员名称 的反向映射:
enum Direction { Up, Down, Left, Right, } let dirName = Direction[0]; // Up let dirValue = Direction.Up; // 0
3. 常量枚举
除了数字枚举和字符串枚举之外,还有一种特殊的枚举 -- 常量枚举。它是使用 const
关键字修饰的枚举,常量枚举会使用内联语法,不会为枚举类型编译生产任何 JavaScript 。
const enum Direction { Up, Down, Left, Right, } let dir: Direction = Direction.Up;
编译生成的 JS 代码如下:
var dir = 0 /* Direction.Up */;
4. 异构枚举
异构枚举的成员值是数字和字符串的混合
enum BooleanLikeHeterogeneousEnum { No = 0, Yes = "YES", }
十六、 Void 类型 与 Never 类型
1. Void 类型
某种程度上来说,void
类型像是与 any
类型相反,它表示没有任何类型。
当一个函数没有返回值时,这时它的返回值类型是 void
// 返回没有返回值时,hello 返回值类型为 void function hello(name: string) { console.log(`Hello ${name}`); } // 但当你主动返回 undefined 时,返回值类型为 undefined function world(name: string) { console.log(`Hello ${name}`); return undefined; }
2. Never 类型
never
类型表示的是那些永不存在的类型。
// 返回 never 的函数必须存在无法达到的终点 function error(message: string): never { // 1. 通过抛出异常实现 返回值类型为 never throw new Error(message); } function infiniteLoop(): never { // 2. 通过死循环实现 返回值类型为 never while (true) {} } // 类型别名 a 是一个 never 类型。因为不存在一个类型既是 string 又是 number type a = string & number