如何使用 vue + typescript 编写页面 ( 基础装饰器部分 )

7,944 阅读5分钟

关于 Vue

Vue是一款前端的库,用来快速生成页面,是一款MVVM理念的框架。

关于 Typescript

Typescript是一款ECMAScript/Javascript的超集,提供了更丰富的语法

选择 vue 的理由

简单。推荐指数:3.7 。

扣分主要是我不太喜欢 script,css,template放在一个文件里面。当然了css还可以剔除到单独文件,但是script就没法剔除了,否则语法器会报找不到

开发相关准备

  • 开发平台 Windows 10
  • 开发工具使用的微软旗下的 Visual Studio Code ,以下简称 vscode
    • 安装vue插件 Vetur
    • 安装 Beautify css/less/scss 插件
    • 有需要可以安装一个中文语言包
  • 环境安装
    • node 用来运行环境和使用npm下载相关的开发包
    • git 部分包源码需要使用git下载安装
    • python 安装py是使用 node-sass 需要使用到,使用其他css预编译可以忽略
    • 以上工具准备好后接下来安装 vue-cli 3.0 使用 npm install -g @vue/cli (习惯使用yarn的人可以使用yarn global add @vue/cli
  • 使用 vue-cli 创建项目
    • vue create demo ,demo就是创建项目的名称
    • 提示选择预设,选择 Manually select features 回车确认
    • 选择typescript vuex router babel css pre-processors,不使用linter,不选单元测试[有需要另说]
    • 回车后按照需要选择合适的选项
    • 选择完毕后回车等待资源准备
  • 使用 vue-ui管理项目
    • 运行 vue ui
    • 成功后访问提供的 url
    • Vue 项目管理器导入创建的项目
    • 在插件、依赖、配置可以做相应调整,也可以添加需要的插件、依赖

编码开始

打开 vscode ,文件-打开文件夹,选择刚才创建好的项目文件夹,导入项目,使用CTRL + ~ 召唤控制台。 输入npm run serve运行开发模式,按住CTRL点击链接,打开项目地址。初次使用ts时,需了解以下ts的基本语法,并且在使用ts编写vue时,需要了解vue相关的基础知识。以下介绍默认已经熟悉并了解相关内容,但是不知如何整合。 打开src/views/Home.vue 作为参照,进行讲解:

熟悉几个vue的装饰器 vue-property-decorator

以下的装饰器的功能和原js编写的功能相同/相似,可以参照官方文档类比解读。

import { Vue, Component, Inject, Provide, Prop, Model, Watch, Emit, Mixins } from 'vue-property-decorator'

1. Vue 实际上就是 Vue 本身,继承vue相关属性和函数

class MyComponent extends Vue { }

2. @Component 声明成一个vue的组件实例,如果不使用,则不能得到一个vue组件

第一种方式,不需要定义额外内容

@Component
class MyComponent extends Vue { }

第二种方式,定义相关内容

@Component({
    /* 这里和js版本编写的 vue 组件内容相同,
     * 凡是不能在ts里面完成的都可以在这里完成 
     * 最终会被合并到一个实例中。
     * 在这里定义的内容,不会被语法器获取到,因此必须要同步在class中声明
     */
    data(){
        return { myname:"",age:18 }
    }
})
class MyComponent extends Vue {
    private myname:string;
    mounted(){
        this.myname;    
        this.age;// 语法器报错,当前类找不到age属性
    }
}

3. @Provide 向任意层级的子组件提供可访问的属性,默认为当前属性的名称,可以指定名称

@Component
class ParentComponent extends Vue { 
    @Provide() private info!:string;
    @Provide("next") private infoNext!:string;
}

4. @Inject 获取父级由Provide提供的属性,默认为当前属性的名称,可以指定名称,多个父级提供相同名称属性时,获取最近父级的名称属性

@Component
class MyComponent extends Vue { 
    @Inject() private info!:string;
    @Inject("next") private infoNext!:string;
}

5. @Prop 由标签属性注入,获取对应标签属性上值,可配置具体prop内容,参照js版本props内容

@Component
class MyComponent extends Vue { 
   @Prop() age!:number;
   @Prop({default:1}) sex!:number;
}
<template>
    <MyComponent :age="16" />
</template>

<script lang="ts">  
import MyComponent from './MyComponent.vue';

@Component({
    components:{ MyComponent }
})
class PComponent extends Vue { }
</script>

6. @Model 是v-model的装饰器,当自定义组件想使用v-model时,可以使用这种方式,配合emit可以双向传递属性值

<template>
    <input type="checkbox" :checked="checked" @change="changed"/>
</template>

<script lang="ts">
@Component
class MyComponent extends Vue { 
   @Model("change") checked!:number;
   changed(event:any){ /* 这里是偷懒写的any,在实际项目中需要避免 */
       this.$emit("change",event.target.value)
   }
}
</script>
<template>
    <MyComponent :age="16" v-model="mycheck" />
</template>

<script lang="ts"> 
import MyComponent from './MyComponent.vue';

@Component({
    components:{ MyComponent }
})
class PComponent extends Vue {
    private mycheck:boolean = false;
}
</script>

7. @Watch 观察某个属性更新

@Component
class MyComponent extends Vue { 
   @Prop() age!:number;
   @Watch("age")
   ageChange(newVal:number,oldVal:number){
       /*age属性更新时,处理相关内容*/
   }
}

8. @Emit this.$emit 的装饰器,如果没有指定名称,默认使用函数名称。有返回值时,使用返回值,没有则使用

@Component
class MyComponent extends Vue { 
   private myname = "";
   
   @Emit()
   ageChangeA(){ /* 仅发送 this.$emit('ageChangeA') */   }
   
   @Emit()
   ageChangeB(age:number){ /* 发送 age  this.$emit('ageChangeB',age) */   }
   
   @Emit()
   ageChangeC(age:number){  return 1 /* this.$emit('ageChangeC',1) 发送return 结果*/ }
}

9. Mixins

// MyMixin.ts
@Component
export default class MyMixin extends Vue { 
   /* 如果使用private 修饰,则两个相同的 私有属性混入时,会产生冲突 */
   protected myname = "张三";
   created(){  /* 混入对象有自己的 生命周期函数*/ }
   getMyName(){ console.log("张三混入") }
}
// OtherMixin.ts
@Component
export default class OtherMixin extends Vue { 
   /* 如果使用private 修饰,则两个相同的 私有属性混入时,会产生冲突 */
   protected myname = "李四";
   created(){  /* 混入对象有自己的 生命周期函数*/ }
   getMyName(){ console.log("李四混入") }
}
@Component
class MyComponent extends Mixins(MyMixin,OtherMixin) { 
   private myname = ""; /* 混入对象已经定义,这里产生属性冲突 */
   mounted(){
       this.getMyName() // 李四混入
   }
}

装饰器可以参照 vue-property-decorator

没有filters,没有指令相关装饰器,有需要可以在@Component里面补充,或者可以直接定义函数调用计算返回值 在class里定义的属性即data属性,需要赋值初始值。

对于computed,使用 get 替代

@Component
class MyComponent extends Vue { 
   private myname = ""; /* 混入对象已经定义,这里产生属性冲突 */
   get upperName(){
       return "A" + this.myname
   }
}