TypeScript都比《隐秘的角落》还火,而我却姗姗来迟的才研究他。现在来看看TS在Vue项目中的配置和一些简单的用法,我们在单独看TS语法的时候有些东西还是很好理解的但是在和框架(vue或react)一起使用的时候有些特殊的用法和障碍,查看框架提供的.d.ts的声明文件中一些复杂类型的定义、组件的书写方式等都要做出不小的调整。

  今天没有具体说TS是什么怎么用,只是简单的学习一下TS结合框架Vue中的一些j基本用法。

  Vue脚手架已经集成了TS所以在创建项目的时候可以像安装router和Vuex似的一样安装TS,安装好打开目录具体如下:

 1 |-- ts-vue
 2     |-- .browserslistrc     # browserslistrc 配置文件 (用于支持 Autoprefixer)
 3     |-- .eslintrc.js        # eslint 配置
 4     |-- .gitignore
 5     |-- babel.config.js     # babel-loader 配置
 6     |-- package-lock.json
 7     |-- package.json        # package.json 依赖
 8     |-- postcss.config.js   # postcss 配置
 9     |-- README.md
10     |-- tsconfig.json       # typescript 配置
11     |-- vue.config.js       # vue-cli 配置
12     |-- public              # 静态资源 (会被直接复制)
13     |   |-- favicon.ico     # favicon图标
14     |   |-- index.html      # html模板
15     |-- src
16     |   |-- App.vue         # 入口页面
17     |   |-- main.ts         # 入口文件 加载组件 初始化等
18     |   |-- shims-tsx.d.ts
19     |   |-- shims-vue.d.ts
20     |   |-- assets          # 主题 字体等静态资源 (由 webpack 处理加载)
21     |   |-- components      # 全局组件
22     |   |-- router          # 路由
23     |   |-- store           # 全局 vuex store
24     |   |-- styles          # 全局样式
25     |   |-- views           # 所有页面
26     |-- tests               # 测试

  其实对比我们js的项目区别不是很大,一些js后缀的文件被改成了ts,还多了几个文件

  ①tscinfig.json:配置文件,主要用于指定待编译的文件和定义编译选项,这个和脚手架2.x版本的congif.json一样的作用;

  ②shims-tsx.s.ts:允许.tsx 结尾的文件,在 Vue 项目中编写 jsx 代码;

  ③shims-vue.d.ts:由于TS默认不支持导入Vue文件,而这个文件就是用来识别Vue文件。

在组件中使用TS

  1.TypeScript写组件的时候有俩种方式:Vue.extend or Vue-class-component

  ①Vue.extend():使用基础 Vue 构造器,创建一个“子类”。此种写法与 Vue 单文件组件标准形式最为接近,唯一不同仅是组件选项需要被包裹在 Vue.extend() 中。
  ②vue-class-component:通常与 vue-property-decorator 一起使用,提供一系列装饰器,能让我们书写类风格的 Vue 组件。
  两种形式输出结果一致,同是创建一个 Vue 子类,但在书写组件选项如 props,mixin 时,有些不同。特别是当你使用 Vue.extend() 时,为了让 TypeScript 正确推断类型,你将不得不做一些额外的处理。所以更推荐使用vue-class-component。

  vue-property-decorator社区出品,但是完全依赖于vue-class-component(推荐使用这个哦)  

  vue-class-component官方出品,提供了Vue、Component等;  

   2.使用vue-property-decorator

   当我们在vue单文件中使用TypeScript时,引入vue-property-decorator之后,script中的标签就变为这样:

 1 <script lang="ts">
 2 import {Component, Prop, Vue} from 'vue-property-decorator'
 3 
 4 @Component({})
 5 export default class App extends Vue {
 6   name:string = 'yingaxiang'
 7 
 8   // computed
 9   get MyName():string {
10     return `My name is ${this.name}`
11   }
12 
13   // methods
14   sayHello():void {
15     alert(`Hello ${this.name}`)
16   }
17 
18   mounted() {
19     this.sayHello();
20   }
21 }
22 </script>

   等同于js中的

 1 <script lang="es6">
 2 export default {
 3   data () {
 4     return {
 5       name: 'yingaxiang'
 6     }
 7   },
 8 
 9   mounted () {
10     this.sayHello()
11   },
12 
13   computed: {
14     MyName() {
15       return `My name is ${this.name}`
16     }
17   },
18 
19   methods: {
20     sayHello() {
21       alert(`Hello ${this.name}`)
22     },
23   }
24 }
25 </script>

  小结:

  ①@component声明成一个vue的组件实例,如果不使用则不能得到一个vue组件,所以这个无论有没有引入自定义组件都要声明,和js的components有些区别;

  ②vue中的计算属性,我们只需要将该计算属性名定义为为一个函数,并在在函数之前加上get关键字就可,所以原本写在computed中的计算属性现在只要在前边加上get。

  3.在vue-class-decorator中还有其他属性下边详解

   ①@Emit:在Vue的事件监听与触发子父传参中都要用到$emit和$on,那么在 vue-property-decorator中提供了@Emit

 1 <script lang="ts">
 2     import {Vue, Component, Emit} from 'vue-property-decorator';
 3 
 4     @Component({})
 5     export default class "组件名" extends Vue{
 6         mounted(){
 7             this.$on('emit-todo', function(n) {
 8                 console.log(n)
 9             })
10 
11             this.emitTodo('yingaxiang');
12         }
13 
14             @Emit()
15         emitTodo(n: string){
16             console.log('yingaxiang');
17         }
18     }
19 </script>

  等同于js中:

 1 <script lang="es6">
 2     import Vue from 'vue';
 3 
 4     export default {
 5         mounted(){
 6             this.$on('emit-todo', function(n) {
 7                 console.log(n)
 8             })
 9 
10             this.emitTodo('yingaxiang');
11         },
12         methods: {
13             emitTodo(n){
14                 console.log('yingaxiang');
15                 this.$emit('emit-todo', n);
16             }
17         }
18     }
19 </script>

  小结:

  在Vue中我们是使用$emit触发事件,使用vue-property-decorator时,可以借助@Emit装饰器来实现.@Emit修饰的函数所接受的参数会在运行之后触发事件的时候传递过去。@Emit触发事件有俩种写法:

  @Emit()不传参数,那么它触发的事件名就是它所修饰的函数名.

  @Emit(name: string),里面传递一个字符串,该字符串为要触发的事件名.

  ②利用vue-property-decorator提供的@Watch装饰器来替换Vue中的watch属性,以此来监听值的变化.

 1 <script lang="ts">
 2 import {Vue, Component, Watch} from 'vue-property-decorator';、
 3 @Watch('child')
 4 onChangeValue(newVal: string, oldVal: string){
 5     // todo...
 6 }
 7 
 8 @Watch('person', {immediate: true, deep: true})
 9 onChangeValue(newVal: Person, oldVal: Person){
10     // todo...
11 }
12 </script>

  等同于js中

 1 export default{
 2     watch: {
 3         'child': this.onChangeValue
 4             // 这种写法默认 `immediate`和`deep`为`false`
 5         ,
 6         'person': {
 7             handler: 'onChangeValue',
 8             immediate: true,
 9             deep: true
10         }
11     },
12     methods: {
13         onChangeValue(newVal, oldVal){
14             // todo...
15         }
16     }
17 }

  ③@prop属性子组件接收父组件传递来的参数.我们需要定义Prop属性.

 1 <script lang="ts">
 2     import {Vue, Component, Prop} from 'vue-property-decorator';
 3 
 4     @Component({})
 5     export default class "组件名" extends Vue{
 6         @Prop(Number) propA!: number;
 7         @Prop({default: 'default value'}) propB!: string;
 8         @propC([String, Boolean]) propC: string | boolean;
 9     }
10 </script>

  等同于js的:

 1 export default {
 2   props: {
 3     propA: {
 4       type: Number
 5     },
 6     propB: {
 7       default: 'default value'
 8     },
 9     propC: {
10       type: [String, Boolean]
11     },
12   }
13 }

  这里需要特别强调:

  !: 表示一定存在,?: 表示可能不存在。这两种在语法上叫赋值断言

 

 

  以上介绍应该是TS在vue中最基本的使用方式,持续学习中......

 

posted on 2020-06-30 17:42  前端幼儿园_影啊翔  阅读(492)  评论(1编辑  收藏  举报