vue-ts学习笔记

TypeScript

官方地址

TypeScript

1. 下载

npm install -g typescript

查看是否安装成功

tsc -v Version 3.9.7

基本使用

helloworld.ts

console.log("ts hello world");

编译ts->js

tsc helloworld.ts 即可生成helloworld.js

配置自动编译

初始化tsconfig.json

tsc --init

找到tsconfig的outdir打开注释改成outDir:./js

然后终端--> 运行任务-->typescript-->tsc 监视

2. 基础类型

在编写ts的时候变量如果声明了是什么类型的,是允许修改的!尽管编译是通过的,但是不建议这么操作

2.1 布尔boolean

let isFlag:boolean = false;
console.log(isFlag)

2.2 数字类型number

let count:number = 0;
count++;
for(let i:number=0;i<10;i++){
    console.log(i)
}

2.3 字符串类型

let str:string = '123';
str = 'bob'
console.log(str)

2.4 数组类型

在声明数组的时候就已经限定好数组里面的每一个项的类型了,所以在进行数组的CRUD的时候,都必须要是相同的类型

定义数组的两种方式


let arr:number[] = [123,456]

let arr1:Array<string> = ['aaa','111']
let arr:number[] = [123,456]
let arr1:Array<string> = ['aaa','111']
arr.push(1111)
- 这种是不允许的
arr.push('a')
arr[0] = 45444;
console.log(arr,arr1)

2.5 元组类型

元组就是指定义数组的时候可以指定多种类型,但是指定的类型必须要和数组中的元素一一对应,不允许超出或者缺少

// 允许
let anyArray:[string,number,boolean] = ['1',1,false]

// 不允许
let anyArray:[string,number,boolean] = ['1',1,false,'aaaa']

// 不允许
let anyArray:[string,number,boolean] = ['1',1]

2.6 枚举类型

枚举就是定义一些常量供自己使用 待定

enum Status {
    success = 200,
    serverError = 500,
    noAuth = 403
}

let requestStatus:Status = Status.success;
console.log(requestStatus) // 200

2.7 any类型

定义一个变量为任意类型,你可以重新给他赋任意类型的值

也可以给一个变量指定多种类型

let num:string|boolean|undefined|null;


let a:any ;
a=123;
a=[123]
console.log(a)

let arr4:Array<any> = [1233,'aaa']
let arr5:any[] = ['aaaa',1]

console.log(arr4,arr5)

2.8 void类型

void一般用于函数 标识函数没有返回值

function foo():void{
    console.log('foo')
    // return 123;
}
// 标识函数的返回值是数字类型
function foo():number{
    console.log('foo')
    // return 123;
}
foo();

2.9 null和undefined

定义一个变量类型为null和undefined 其用处并不是很大

let u: undefined = undefined;
let n: null = null;

2.10 never

用来告知编译器某处代码永远不会执行,从而获得编译器提示, 以避免程序员在一个永远不会(或不应该)执行的地方编写代码.

function listen() : never{
    while(true){
        let conn = server.accept()
    }
}

listen()
console.log("!!!")  //Error: Unreachable code detected.ts(7027)
// 这里声明为never函数表示这个函数调用之后下面的代码不会执行 避免别人在下面继续写代码
function throwError(msg: string ) :never {
    throw new Error(msg)
}

throwError("some error")
// 程序报错 代码不会执行到着 所以在这里打印是没有用的
console.log("从这开始代码是不会执行的")  //Error: Unreachable code detected.ts(7027)

2.11 object

定义obj类型可能是用来限定函数传入的参数 待验真

let obj:Object ={a:123};
// obj.a = 456; // error
obj = {a:456}
console.log(obj)


declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error

3. 函数

3.1函数的两种定义方式

ts中的函数注意以下两点

  • 函数的返回值类型
  • 形参的数据类型
function foo1(a:string,b:number):string{
    return 'aaa'
}
const bar2 = function(bar:string):void{
    console.log(bar)
}

函数也可以返回一个Promise对象

   
async getList(payload?: any):Promise<object>{
        const res = await get_List()
        this.updateList(res)
        return Promise.resolve({a:123})
    }

3.2 可选参数和默认参数

可选参数一定要在必须参数的后面

const bar3 = function(bar:string,age?:number=15):void{
    if(age){
        console.log(age)
    }
    console.log(bar)
}

3.3 剩余参数

const bar4 = function(...rest:number[]):void{
    console.log(rest)
}
const bar5 = function(...rest:any[]):void{
    console.log(rest)
}
bar5(12,'aaa') // [12, "aaa"]

3.4 函数重载

同一个函数名,传入不同类型的函数

function hello(name: string): string;
function hello(age: number): number;
function hello(str: any): any {
    if (typeof str == 'string') {
        return str + 'str'
    } else {
        return str + 'number'
    }
}

hello(123)

snabbdom的列子

export declare function h(sel: string): VNode;
export declare function h(sel: string, data: VNodeData | null): VNode;
export declare function h(sel: string, children: VNodeChildren): VNode;
export declare function h(sel: string, data: VNodeData | null, children: VNodeChildren): VNode;

3.5 箭头函数

和普通函数是一样的

setTimeout(():void => {
    console.log('箭头函数')
}, 1000);

4. 类

ts中的类和ES6的类很相似

class Person {
    public name: string;
    public age: number;
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    work() {
        console.log(`${this.name}正在学习ts`)
    }
}

const per = new Person('liuxuan', 24)
console.log(per)
per.work(); // liuxuan正在学习ts

4.1 继承

class Person {
    public name: string;
    public age: number;
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    work() {
        console.log(`${this.name}正在学习ts`)
    }
}


class Son extends Person {
    public gender: number;
    constructor(name: string, age: number, gender: number) {
        super(name, age)
        this.gender = gender;
    }
    Console():void {
        if (this.gender == 0) {
            console.log('男')
        } else {
            console.log('女')
        }
    }
}

let son = new Son('刘德华', 15, 0)
son.work(); // 刘德华正在学习ts
son.Console(); // 男

4.2 修饰符

  • public 子类 类内部 类外部都可以访问
  • private 类内部可以访问
  • protected 子类和类内部可以访问

private

class Person {
    private name: string;
    public age: number;
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    work() {
        console.log(`${this.name}正在学习ts`)
    }

}
let son = new Son('刘德华', 15, 0)
子类和类外部无法访问
let p = new Person('liuxuan',24)
console.log(p.name)// 属性“name”为私有属性,只能在类“Person”中访问。
let son = new Son('刘德华', 15, 0)
console.log(son.name) // 属性“name”为私有属性,只能在类“Person”中访问。

protected

/*
 * @Description: 
 * @Author: 刘宣
 * @email: 1395380336@qq.com
 * @Date: 2021-05-11 23:17:18
 * @LastEditTime: 2021-05-11 23:41:39
 */

class Person {
    protected name: string;
    public age: number;
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    work():void{
        console.log(`{this.name}正在学习ts`)
    }
}
class Son extends Person {
    public gender: number;
    static address:string = '安徽省';
    constructor(name: string, age: number, gender: number) {
        super(name, age)
        this.gender = gender;
    }
    Console():void{
        if (this.gender == 0) {
            console.log('男')
        } else {
            console.log('女')
        }
    }
    static yourAddr(){
        console.log(Son.address)
    }
    work():void{
        console.log(`{this.name}正在学习ts`)
    }
}
let p = new Person('liuxuan',24)
p.work()
let son = new Son('刘德华', 15, 0)
son.work()  // 刘德华正在学习ts
在类的外部是无法访问的。
console.log(p.name)// 属性“name”受保护,只能在类“Person”及其子类中访问
 console.log(s.name)// 属性“name”受保护,只能在类“Person”及其子类中访问


4.3 静态属性和方法

类的静态属性和静态方法都是通过类名来调用的,也就是说有些方法我们不想实例化之后再调用,我们希望直接调用

class Son extends Person {
    public gender: number;
    static address:string = '安徽省';
    constructor(name: string, age: number, gender: number) {
        super(name, age)
        this.gender = gender;、
        
    }
    Console() {
        if (this.gender == 0) {
            console.log('男')
        } else {
            console.log('女')
        }
    }
    static yourAddr(){
        console.log(Son.address)
    }

}

Son.yourAddr(); // 安徽省

4.4 多态

就是指 父亲定义一个方法 子类都有这个方法 只是每个子类的表现(实现)不一样 这就是多态

例如 动物都有吃这个功能 但是狗喜欢吃骨头 猫喜欢吃老鼠 这就是多态

class Animal{
    name:string ;
    constructor(name:string){
        this.name = name
    }
    eat(){
        
    }
}
class Dog extends Animal{
    constructor(name:string){
        super(name)
    }
    eat():void{
        console.log(this.name+'吃肉')
    }
}
var dog = new Dog('金毛')
dog.eat();

4.5 抽象类

ts中的抽象类:它是提供其他类型继承的基类,不能被实例化

用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中的实现

抽象方法只能出现在抽象类中

抽象类和抽象方法用来定义标准 标准:Animal这个类要求它的子类必须包含eat方法 (也就是说抽象类的抽象方法必须在子类中进行重写

// 定义一个Animal1抽象类
abstract class Animal1{
    abstract foo():any;
}
// Dog1继承Animal1抽象类 并重写Animal1的抽象方法eat
// 不重写父类方法ts就会编译报错
class Dog1 extends Animal1{
    constructor(){
        super();
    }
    foo():number{
        console.log('抽象方法的抽象类必须要被重写')
        return 123;
    }
}
console.log(new Dog1().foo())

5.接口 interface

接口:主要就是用来对行为和属性的规范 以及对批量方法的约束

使用:函数的参数(key:interface)

属性和行为的规范

接口的写法与类的写法不同 接口是{}

接口与类的关系:类实现这个接口

不使用接口进行约束实现,是无法实现对批量方法进行约束的

// printLabel 函数规定传入一个对象 对象上必须有一个label属性且必须是字符串类型
function printLabel(labelledObj: { label: string }) {
    console.log(labelledObj.label);
}
// 我们传入的对象参数实际上会包含很多属性,但是编译器只会检查那些必需的属性是否存在,并且其类型是否匹配
let myObj = { size: 10, label: "Size 10 Object" }; 
printLabel(myObj);

//   并且同时是无法实现批量方法的约束
// printLabel2 和 printLabel对形参的约束是一样的 但是我们需要重新写一下
function printLabel2(labelledObj: { label: string }) {
    console.log(labelledObj.label);
}

换成interface

interface Print{
    label:string;
}
printLabel3/printLabel4都是被Print接口约束的
function printLabel3(labelledObj: Print) {
    console.log(labelledObj.label);
}
printLabel3(myObj)

function printLabel4(labelledObj: Print) {
    console.log(labelledObj.label);
}
printLabel4(myObj)

5.1 可选参数?/只读参数 readonly

// 可选参数/只读属性
// 和函数的可选一样 在名字的后面加上?
interface Print2{
    label:string;
    age?:number;
    readonly gender:number;
}

function printLabel5(labelledObj: Print2) {
    console.log(labelledObj)
    labelledObj.gender = 45; // 无法分配到 "gender" ,因为它是只读属性
}

printLabel5({label:'111',gender:123,age:24}) // {label: "111", gender: 123}
printLabel5({label:'111',gender:123,age:24}) // {label: "111", gender: 123,age:24}

5.2 接口小案例

/*
 * @Description: 
 * @Author: 刘宣
 * @email: 1395380336@qq.com
 * @Date: 2021-05-12 11:27:18
 * @LastEditTime: 2021-05-12 13:53:30
 */
interface AjaxConfig {
    type: string;
    url: string;
    data?: any;
    dataType: string;
    header?: object
}

function Ajax(obj: AjaxConfig) {
    var xhr:any = null;
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest()
    } else {
        xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xhr.open(obj.type,obj.url)
    xhr.send(obj.data)
    xhr.onreadystatechange = ():void=>{
        if(xhr.readyState!=4)return;
        console.log(xhr.responseText
            )
    }
}

Ajax({
    type:"GET",
    url:"AAA",
    dataType:"1111"
})

5.3 对函数进行限制

对函数进行限定 可实现对函数的批量限定,规定被限定的函数必须符合我的接口规范

限定函数的name属性为string类型,age为number类型 返回值为空

interface Func {
    (name: string, age: number): void;
}

// 批量对func和func1进行限定
var func: Func = function (name: string, age: number): void {
    console.log(name + "==" + age)
}
func(12,22) // Error
func('12',22) // Success


var func1: Func = function (name: string, age: number): void {
    console.log(name + "==" + age)
}
func1(12,22) // Error
func1('12',22) // Success

5.4 对类类型进行限定

对类的类型进行限定。类和类之间叫实现 implements

规定:凡是实现我这个类的 必须存在存在name为string 和eat方法 且这两个方法的类型必须要和我接口保持一致

interface Animal {
    name: string;
    eat(name: string): number;
}

class Dog3 implements Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    eat() {
        console.log(name + "===吃")
        return 123;
    }
}

let d = new Dog3('金毛');
d.eat();

5.5 可索引接口

指的是对对象和数组进行限定

索引为number类型就是对数组的限定,索引为字符串类型就是对对象进行限定

数组:


interface Arrays {
    // 限定数组的索引为number 且数组项为数字
    [index: number]: number
}
let newArr: Arrays = [123, 'aa'] // 不能将类型“string”分配给类型“number”
let newArr1: Arrays = [123]


对象

interface Objects {
    // 限定对象的索引为string 对象的key限定为string
    [index: string]: string 
}
let obj1: Objects = {
    'name': 'zs',
     age: 18, // 这里的key应该为字符串
}

5.5 接口的扩展(接口继承接口)

接口继承接口 并且实现了类

City类必须要同时符合Area和Province接口规范,

interface Area {
    area: string;
}
// 接口继承接口
interface Province extends Area {
    province: string;
}
class China {
    country: string;
    constructor(country: string) {
        this.country = country;
    }
}
// City类继承China类并实现了Province接口
class City extends China implements Province {
    province: string;
    area: string;
    constructor(province: string, area: string, country: string) {
        super(country)
        this.province = province
        this.area = area
    }
    hello(){
        console.log(this.province,this.area,this.country)
    }
}

let C = new City("安徽省", "华东", "china")
C.hello(); // 安徽省 华东 china

6 泛型

泛型:可以支持不特定的数据类型 要求:传入的参数和返回的参数是一致的

具体的类型 T由传入时候的数据类型来决定

泛型就是解决类 接口 方法 的复用性 以及对不特定数据类型的支持

回顾之前 我们在定义函数或者类或者接口的时候 我们都是直接把它们的数据类型写死了 ,这导致他们无法进行一个复用,使用泛型可以有效的解决这类问题

6.1 泛型函数

// 不使用泛型
function foo(name: string): string {
    console.log(name)
    return name;
}
foo('123')
// 如果我们想传入数字怎么办(可以设置为any类型,但是这样就失去了类型校验的价值)?  再写一份 

function foo1(name: number): number {
    console.log(name)
    return name;
}
foo1(123)

// 到此发现 这显然是很冗余的
// 使用泛型 

function foo4<T>(name: T): T {
    console.log(name)
    return name;
}
foo4('123')
foo4(456)

// 使用泛型之后 foo4函数被重用了

6.2 泛型类

// 普通类

class Foo7 {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    printName() {
        console.log(this.name)
    }
}

let foo7 = new Foo7('liuxuan');
foo7.printName(); // liuxuan

let foo8 = new Foo7(123); // 类型“number”的参数不能赋给类型“string”的参数。

// 到此发现这个类也是存在局限的 因为我们在初始化的时候 只能传入string类型的

泛型类

// 泛型类

class Foo8<T>{
    name: T;
    constructor(name: T) {
        this.name = name;
    }
    printName(): void {
        console.log(this.name, 'printName')
    }
}

let foo9 = new Foo8('foo8')
let foo10 = new Foo8(10)
foo9.printName()
foo10.printName()

// 使用泛型类之后,这个Foo8类 显然可以支持更多的类型了 减少了代码的冗余

6.3 泛型接口

// 泛型接口


// 普通接口
interface Bar1 {
    name: string;
    eat(name: string, food: string): void;
}

class Bar2 implements Bar1 {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    eat(): void {
        console.log(this.name) // 杨训鹏
    }
}

let bar10 = new Bar2('杨训鹏')
bar10.eat();

// 这个接口也是存在局限性的,因为这个接口只支持string类型的
new Bar2(10) // 类型“number”的参数不能赋给类型“string”的参数。

泛型接口

// 使用泛型接口对函数和属性进行泛型限定

interface Bar99<T> {
    name: T;
    eat(name: T, food: T): void;
}

class Bar999<T> implements Bar99<T> {
    name: T;
    constructor(name: T) {
        this.name = name;
    }
    eat(name: T, food: T): void {
        console.log(name,food,"name-food") 
    }
}
new Bar999<string>('helloWorld').eat('name','food') // helloWorld
new Bar999<number>(123).eat(1,2) // 123

6.4 把类当作泛型

用来限定传入的类型是我类的实例

案例:封装一个数据库操作类

数据库DBI接口

interface DBI<T> {
    add(info: T): boolean;
    update(info: T, id: number): boolean;
    delete(id: number): boolean;
    get(id: number): any[];
}

定义MSsql类

实现泛型接口的类也必须是一个泛型类

class MSSQL<T> implements DBI<T>{
    add(info: T): boolean {
        console.log(info) // User {username: "wgy", password: 91129}
        throw new Error("Method not implemented.");
    }
    update(info: T, id: number): boolean {
        throw new Error("Method not implemented.");
    }
    delete(id: number): boolean {
        throw new Error("Method not implemented.");
    }
    get(id: number): any[] {
        throw new Error("Method not implemented.");
    }
}

定义一个MYSQL类

class MYSQL<T> implements DBI<T>{
    add(info: T): boolean {
        console.log(info) // User {username: "wgy", password: 91129}
        throw new Error("Method not implemented.");
    }
    update(info: T, id: number): boolean {
        throw new Error("Method not implemented.");
    }
    delete(id: number): boolean {
        throw new Error("Method not implemented.");
    }
    get(id: number): any[] {
        throw new Error("Method not implemented.");
    }

}

我们要向数据库添加用户 所以要限定传入的数据必须要限定为User类的实例

class User{
    username:string;
    password:any;
    constructor(username:string,password:any){
        this.username = username;
        this.password = password;
    }
}

操作

// 像数据库中插入用户信息
let user = new User('wgy',91129);
// 使用类泛型 来限定传入我数据的数据必须是User的实例
let ms = new MSSQL<User>();
ms.add(user)
// ms.add(123) // 类型“number”的参数不能赋给类型“User”的参数。

7.模块

ts中的模块封装遵循的是ES6的 export/import语法

对上面的DB案例进行封装

新建DB-interface.ts用来保存接口

interface DBI<T> {
    add(info: T): boolean;
    update(info: T, id: number): boolean;
    delete(id: number): boolean;
    get(id: number): any[];
}

export default DBI;

新建MYSQL类 操作mysql

import DBI from "./DB-interface"
export default class MYSQL<T> implements DBI<T>{
    add(info: T): boolean {
        console.log(info) // User {username: "wgy", password: 91129}
        throw new Error("Method not implemented.");
    }
    update(info: T, id: number): boolean {
        throw new Error("Method not implemented.");
    }
    delete(id: number): boolean {
        throw new Error("Method not implemented.");
    }
    get(id: number): any[] {
        throw new Error("Method not implemented.");
    }

}

新建MSSQL类 操作微软的sql

import DBI from "./DB-interface"
export default class MSSQL<T> implements DBI<T>{
    add(info: T): boolean {
        console.log(info) // User {username: "wgy", password: 91129}
        throw new Error("Method not implemented.");
    }
    update(info: T, id: number): boolean {
        throw new Error("Method not implemented.");
    }
    delete(id: number): boolean {
        throw new Error("Method not implemented.");
    }
    get(id: number): any[] {
        throw new Error("Method not implemented.");
    }

}

新建User类 操作用户信息

export default class User{
    username:string;
    password:any;
    constructor(username:string,password:any){
        this.username = username;
        this.password = password;
    }
}

demo.ts中使用

导入

import MSSQL from "./modules/MSSQL-DB";
import MYSQL from "./modules/MYSQL-DB";
import User from "./modules/User";

使用

// 像数据库中插入用户信息
let user = new User('wgy',91129);
// 使用类泛型 来限定传入我数据的数据必须是User的实例
let ms = new MSSQL<User>();
ms.add(user)
// ms.add(123) // 类型“number”的参数不能赋给类型“User”的参数。

到此就完成了模块话

----demo.ts
----modules
------DB-interface.ts
------MYSQL-DB.TS
------MSSQL-DB.TS
------User.ts

8.命名空间

9.装饰器

9.1 类装饰器

9.2 属性装饰器

10.ts在vue中的使用

前言:在写法上 只有js的部分写法变了 ,主要是以下两个包(装饰器)

vue-property-decorator

vuex-module-decorators

首先先创建一个ts的项目,然后装包(一个是vue的一个是)

cnpm i vue-property-decorator vuex-module-decorators -S

10.1与Vue 写法上的区别

注意:下面的写法都是在export default class About extends Vue {}写的

首先最基本的我们需要引入两个函数吧

import { Component, Vue} from "vue-property-decorator";

@Component声明组件

https://segmentfault.com/a/1190000019906321

@Component 装饰器可以接收一个对象作为参数,可以在对象中声明 components ,filters,directives等未提供装饰器的选项,也可以声明computed,watch等 ,目前我还没用到,用到了写

@Component({
  name: "About",
  components: {
    User
  }
})

以前的写法

name:"About",
components:{
    User
}
10.1.1.vue文件的写法区别

react

class Test extends React.Component{}

ts-vue

export default class About extends Vue {}

js-vue

export default {}
10.1.2.data
// 定义一个User接口 用来约束UserList的数据类型
interface IUser {
  name: string;
  age: number;
  sex?: number;
  id: number;
}

private firstName: string = "liu";
  private lastName: string = "xuan";
  private CPC: any = "v-model自定义组件";
  private obj: any = {
    names: "zs",
    age: 20,
    sex: 1,
    id: 123
  };
  userList: IUser[] = [
    {
      name: "zs",
      age: 20,
      sex: 1,
      id: 123
    },
    {
      name: "wu",
      // age: '18', // 受到interface接口的约束
      age: 15,
      sex: 0,
      id: 456
    }
  ];

vue

  data(){
    return {
      firstName:"liu",
     lastName:xuan
  },
10.1.3 computed
private get fullName():string{
    return this.firstName + this.lastName;
}
 computed:{
      fullName(){
        return this.firstName+this.lastName
      }
 },
10.1.4 watch
import {Watch} from "vue-property-decorator"
@Watch("firstName",{immediate:true,deep:true})
 // 这里的名字是随便写的 不固定的
private firstNameChange(newVal: any, oldVal: any): void {
    console.log(newVal, oldVal, "我相当于Vue的Watch监听");
  }
watch(){
   firstName:{
       handler:(newval,oldval){
       
        },
        deep:true,
        immediate:true
   }
}
10.1.5 生命周期函数

生命周期函数的写法还是和之前是一样的

  public created() {
    this.lastName = "wgy";
    this.getList();
    console.log("我是声明周期函数 我的写法还是和之前是一样的");
  }
  public mounted() {
    console.log("我是声明周期函数 我的写法还是和之前是一样的");
  }

10.1.6 普通函数

写法也是和之前一样的 真要说区别的话 多了一些方法的修饰符

  private addCount():void {
    AboutStore.updateCount(11);
  }

  private getList():void{
     AboutStore.getList().then(res=>{
       console.log(res) // {a:123}
     })
  }

子组件

    <User
      v-for="(userItem, index) in userList"
      :sex="userItem.sex"
      :age="userItem.age"
      :id="userItem.id"
      :name="userItem.name"
      :key="index"
      :userItem="userItem"
      v-model="CPC"
    ></User>
10.1.7 prop
  import { Prop } from "vue-property-decorator";
  @Prop(Number) private id!: number; // id后面加上! 表示属性断言 表示这个属性在ts里面一定会有的
  @Prop({ type: Number, required:true }) private age!: number;
  @Prop({ type: String }) private name!: string;
  @Prop({ type: Number }) private sex!: number;
prop:{
    age:{
        type:Number,
        required:true
    }
}
10.1.8 emit
 @Emit("changeCPCtocpc")
  clickHandle(): string {
    //这里return得会作为参数传递给父组件
    return "cpc-vue1";
  }
  clickHandleJs(): void {
    this.$emit('changeCPCtocpc','cpc-vue1')
  }
10.1.9 model
  @Model("changeCPCtocpc", { type: String }) private vmodel!: any;
model:{
    event:"changeCPCtocpc",
    prop: vmodel
}

10.2 Vuex的使用

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,042评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,996评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,674评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,340评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,404评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,749评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,902评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,662评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,110评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,577评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,258评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,848评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,726评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,952评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,271评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,452评论 2 348

推荐阅读更多精彩内容