使用typescript构建Vue应用的实现


Posted in Javascript onAugust 26, 2019

一、Vue项目初始化-引入typescript

使用typescript构建Vue应用和使用js一样,都是通过vue-cli去初始化并创建一个vue项目,只不过使用typescript构建的时候要在脚手架问卷操作的时候勾选上typescript选项。

二、typescript Vue项目比较

使用typescript构建的Vue项目发生了一些变化:
① main.js变成了main.ts,但是main.ts中的内容和main.js的内容是一模一样的。
② router.js变成了router.ts,但是router.ts中的内容和router.js中的内容也是一模一样的。
③ store.js变成了store.ts,但是store.ts中的内容和store.ts中的内容也是一模一样的。

因为typescript是javascript的超集,所以ts完全兼容js。

④ 新增了一个shims-vue.d.ts声明文件,这个文件的作用就是让typescript能够识别.vue文件,在引入"*.vue"文件的时候,会将其标识为一个Vue组件,才能对.vue文件进行类型校验,其具体内容如下:

declare module '*.vue' {
 import Vue from 'vue'
 export default Vue
}

⑤ 新增了一个shims-tsx.d.ts文件,其作用就是为了能够解析.tsx文件,对.tsx文件进行类型校验,其具体内容如下:

import Vue, { VNode } from 'vue'
declare global {
 namespace JSX {
  interface Element extends VNode {}
  interface ElementClass extends Vue {}
  interface IntrinsicElements {
   [elem: string]: any
  }
 }
}

⑥ 当然还会新增一个ts.config文件,这个是typescript的配置文件,具体内容这里不作解释,请参考tsconfig文件详解

三、.vue文件内容格式与写法

使用typescript来写Vue应用,最主要的就是.vue文件,.vue文件写法上与js有些不同并且新增了一些装饰器,接着一步一步分析。

① 虽然.vue文件的格式和写法上有了不同,但这不同只是<script></script>部分发生了变化,<template></template>和<style></style>和原来是一样的,一个最简单.vue文件仍然可以使用如下写法:

// HelloWorld.vue

<template>
  <div>
    hello world
  </div>
</template>

② 在写<script></script>部分,第一点不同就是,<script>标签上要加上lang语言属性,表示其中的内容为ts,如:

<script lang="ts">
</script>

③ 默认export上的不同,使用js的时候,我们是直接通过export default {}导出一个Vue组件对象即可,但是使用ts的时候,我们必须导出一个类class,类名为组件名,同时这个类必须继承Vue,如:

// import Vue from "vue";
import { Component, Vue } from 'vue-property-decorator'; // 引入Vue及一些装饰器
@Component
export default class App extends Vue { // 继承Vue并导出Vue组件

}

以上就是<sciprt>内容最基本的写法,上面继承的Vue不是直接从"vue"模块中引入,而是从"vue-property-decorator"即vue属性装饰器模块中引入,当然也可以通过vue模块引入import Vue from "vue",但是我们写.vue文件的时候通常要引入一些装饰器,同时这个装饰器类vue-property-decorator也提供了Vue,故可以直接从vue-property-decorator装饰器类上直接引入

④ 组件中data属性的写法,由于我们在.vue文件中声明了一个class,这个class就是Vue组件,我们可以直接在这个class中声明属性即可,这些声明的属性就是之前使用js写时的data属性中的数据,如:

export default class App extends Vue {
 public lists = [ // 这里就是之前Vue组件的data属性
  "Vue.js", "React.js", "Angular.js"
 ]
}

⑤ 组件中的computed计算属性的写法,同样我们可以在class中声明get和set方法即可变成对应的computed属性,如:

export default class App extends Vue {
 public lists = [ // 这里就是之前Vue组件的data属性
  "Vue.js", "React.js", "Angular.js"
 ]
 public get count() { // 通过get和set实现计算属性
  return this.lists.length;
 }
}

⑥ 组件中方法的声明更简单,直接在class中声明方法即可,如:

export default class App extends Vue {
  public say() {
    console.log("say");
  }
}

⑦ @Component装饰器的使用,@Component装饰器就是用来标识当前这个类是一个Vue组件,@Component装饰器还可以传递对象作为参数,这个传递的对象就是Vue组件实例,所以所有之前用js写法的时候,Vue组件支持的所有选项都可以传入,如:

@Component({
  // 这里可以配置Vue组件支持的各种选项
  components: {
    HelloWorld
  },
  data() {
    return {
     a:1
    }
  },
  methods: {
    say(){
     console.log("say");
    }
  }
})
export default class App extends Vue {
}

@Component内容使用的是Vue.extend()方法,用于扩展Vue Component并生成Vue组件,这里需要注意的就是,Vue最终会将class中定义的属性和@Component中定义的属性进行合并,如果二者中定义了同名的属性,那么class中的优先级更高,即class中定义的会覆盖掉@Component中定义的同名属性,但是data除外,@Component中定义的同名的data数据会覆盖掉class中定义的同名data属性,如:

@Component({
  data() {
    bar: 1
  },
  methods: {
    say(){
     console.log("say::@Component");
    }
  }
})
export default class App extends Vue {
  public bar: number = 2; // 这里的bar会被@Component中定义的bar覆盖掉
  public say() { // 这里的say()方法会覆盖掉@Component中定义的say方法
    console.log("say::class");
  }
}

还有一点要注意的是,@Component装饰器千万不要漏写,必须在组件类class前修饰

⑧ props属性的写法,使用ts写Vue组件的时候,如果要在组件上定义props属性,那么必须通过@Prop()装饰器,其实就是在定义组件data属性的时候用@Prop()装饰器进行修饰,如果没有通过@Propp()进行修饰,那么定义的属性就是组件的data属性,可以给@Prop()传递一个配置对象,可以定义传递属性的default、required、type等属性,如:

import { Component, Vue, Prop } from 'vue-property-decorator';
@Component // 不要忘了用@Component修饰组件class哟
export default class HelloWorld extends Vue {
  @Prop() public bar!: string; // 这里定义的是props属性
  public foo = "foo"; // 这里定义的是data属性
  @Prop({type: String, default:"foo", required: true}) public foo!: string;
}
</script>

需要注意的是,public foo!: string,这里声明的string类型是不起作用的,要限定父组件传入的foo属性的数据类型,必须在@Prop()装饰器内限定数据类型,否则无效

⑨ @Emit()装饰器的使用,在子组件发射自定义事件的时候通常会通过this.$emit("say")的方式,但是typescript提供了一个@Emit()装饰器,用于修饰一个方法,当这个方法被执行的时候,就会在方法执行完成后发射一个同方法名的事件出去,当然,这是在没有给@Emit()传递参数的情况下,如果给@Emit()传递了参数,那么就会发射指定参数的事件,如:

export default class HelloWorld extends Vue {
  @Emit() // 在say()方法执行完成后会发射一个同方法名的say事件
  public say() {
  }
  @Emit("speak") // 这里给@Emit()传递了参数,则会发射speak事件
  public say() {
  }
}

⑩ @Watch()装饰器的使用,其拥有监听组件中数据的变化,就相当于$watch,需要给其传递一个字符串参数,表示其监听的是哪个数据的变化,如:

@Watch("foo") // 监听this.foo的变化
public add(newValue: number, oldValue: number) {
 console.log(`newValue is ${newValue}, oldValue is ${oldValue}`);
}

四、vuex中的变化

vuex中的数据是存放在state属性上的,如果要限定state中数据的属性和类型,那么我们必须在创建store对象的时候定义一个接口限定一下数据类型,如:

interface IState {
 lists: string[]
}
export default new Vuex.Store<IState>({
  state: {
    lists: ["vue"] // 定义了state的数据结构,必须要有lists属性,并且属性值为string[]
  }
});

获取vuex中的数据时候,还是可以通过this.$store.state.lists获取到,但是我们也可以通过装饰器获取到,要使用vuex的装饰器,我们需要安装vuex-class,如:

import {State, Mutation, Action} from "vuex-class";
export default class App extends Vue {
  // 将从vuex中获取到的lists数据保存到组件的lists属性上
  @State("lists") public lists!: string[];
  @Mutation("say") // 在say()方法前修饰,当say()方法执行的时候就会提交一个say mutation
  public say() {
   console.log("say1");
  }
  @Action("speak") // 在speak()方法前修饰,当speak()方法执行的时候就会提交一个speak action
  public speak(){
  }
  public mounted () {
   this.say();
   this.speak();
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Stop SQL Server
Jun 21 Javascript
js+JQuery返回顶部功能如何实现
Dec 03 Javascript
node.js WEB开发中图片验证码的实现方法
Jun 03 Javascript
js实现仿阿里巴巴城市选择框效果实例
Jun 24 Javascript
JQuery点击行tr实现checkBox选中的简单实例
May 26 Javascript
Javascript 5种方法实现过滤删除前后所有空格
Jun 22 Javascript
第一次接触神奇的Bootstrap表单
Jul 27 Javascript
jQuery选择器之基本选择器用法实例分析
Feb 19 jQuery
TypeScript之调用栈的实现
Dec 31 Javascript
Vue跨域请求问题解决方案过程解析
Aug 07 Javascript
vue在图片上传的时候压缩图片
Nov 18 Vue.js
在JavaScript中查找字符串中最长单词的三种方法(推荐)
Jan 18 Javascript
微信小程序实现手势滑动卡片效果
Aug 26 #Javascript
微信小程序实现左侧滑栏过程解析
Aug 26 #Javascript
vue柱状进度条图像的完美实现方案
Aug 26 #Javascript
React传值 组件传值 之间的关系详解
Aug 26 #Javascript
js实现指定时间倒计时效果
Aug 26 #Javascript
Vue.use()在new Vue() 之前使用的原因浅析
Aug 26 #Javascript
微信小程序事件 bindtap bindinput代码实例
Aug 26 #Javascript
You might like
发一个php简单的伪原创程序,配合商城采集用的
2010/10/12 PHP
支持中文、字母、数字的PHP验证码
2015/05/04 PHP
PHP基于正则批量替换Img中src内容实现获取缩略图的功能示例
2017/06/07 PHP
php 自定义函数实现将数据 以excel 表格形式导出示例
2019/11/13 PHP
Document对象内容集合(比较全)
2010/09/06 Javascript
javascript full screen 全屏显示页面元素的方法
2013/09/27 Javascript
浏览器缩放检测的js代码
2014/09/28 Javascript
nodejs简单实现中英文翻译
2015/05/04 NodeJs
基于jQuery通过jQuery.form.js插件实现异步上传
2015/12/13 Javascript
js如何判断输入字符串长度
2015/12/16 Javascript
JS插件overlib用法实例详解
2015/12/26 Javascript
Bootstrap3 input输入框插入glyphicon图标的方法
2016/05/16 Javascript
jQuery限制图片大小的方法
2016/05/25 Javascript
通过nodejs 服务器读取HTML文件渲染到页面的方法
2018/05/17 NodeJs
async/await优雅的错误处理方法总结
2019/01/30 Javascript
了解JavaScript表单操作和表单域
2019/05/27 Javascript
Jquery Fade用法详解
2020/11/06 jQuery
[00:33]2018DOTA2亚洲邀请赛TNC出场
2018/04/04 DOTA
[00:56]PWL开团时刻DAY8——追追追追追!
2020/11/09 DOTA
Python自定义scrapy中间模块避免重复采集的方法
2015/04/07 Python
python 迭代器和iter()函数详解及实例
2017/03/21 Python
Python数据预处理之数据规范化(归一化)示例
2019/01/08 Python
利用anaconda作为python的依赖库管理方法
2019/08/13 Python
python文字转语音的实例代码分析
2019/11/12 Python
windows中安装Python3.8.0的实现方法
2019/11/19 Python
python实现二分类的卡方分箱示例
2019/11/22 Python
在python中修改.properties文件的操作
2020/04/08 Python
Pytorch数据拼接与拆分操作实现图解
2020/04/30 Python
详解Python多线程下的list
2020/07/03 Python
Python爬虫防封ip的一些技巧
2020/08/06 Python
Ever New美国:澳大利亚领先的女装时尚品牌
2019/11/28 全球购物
Tomcat中怎么使用log4j输出所有的log
2016/07/07 面试题
自我评价范文
2013/12/22 职场文书
车队司机自我鉴定
2014/03/02 职场文书
2014市国税局对照检查材料思想汇报
2014/09/23 职场文书
2016教师学习党章心得体会
2016/01/15 职场文书