在Vue中使用TypeScript(简单上手)(一)

1、环境安装

  • npm install vue-class-component vue-property-decorator -S
  • npm install -g typescript

2、组件使用

  • Vue中有三大组件:类组件 + 扩展式组件 + 函数式组件
  • 扩展式组件中使用 TypeScript 语法时,方法与 Vue + JavaScript 开发时相似,而类组件中使用 TypeScript 语法与 Vue + JavaScript 开发时则相差较大。而函数式组件,只能接受父级传递的数据进行渲染。

3、Vue项目中使用三种组件

App.vue

<template>
  <div>
    <ClassComponent proid="pro1"/>
    <ExtendComponent proid="pro1" />
    <FunctionComponent a = "1" b="你好"/>
  </div>
</template>

<script lang="ts">
// 类组件 + 扩展式组件 + 函数式组件
import { Vue, Component } from 'vue-property-decorator'
import ClassComponent from './components/ClassComponent.vue'
import ExtendComponent from './components/ExtendComponent.vue'
import FunctionComponent from './components/FunctionComponent.vue'
// 使用装饰器去装饰该组件
@Component({
  components: {
    ClassComponent, ExtendComponent, FunctionComponent
  }
})
export default class App extends Vue {

}
</script>

(1)扩展式组件

<template>
  <div>
    <h2>扩展式组件</h2>
    <p>{{ msg }}</p>
    <p>{{ reverseMsg }}</p>
    <button @click="test">测试组件的点击事件</button>
    <div>
      <input type="text" v-model="name" v-focus>
    </div>
    <p>{{ proid }}</p>
    <div ref="box">ref</div>
    {{ sex | sexFilter }}
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
  // 子组件接收父组件传递的数据
  // props: ['proid'],  // 方式一
  // props: { // 方式二
  //   proid: String
  // },
  props: { // 方式三
    proid: {
      type: String,
      required: true,
      default: 'hahahah' // 设置默认值 则可以不设置必须
      // validator: function (value) {
      //   return value.length < 3
      // }
    }
  },
  // 初始化数据
  data () {
    return {
      sex: 0,
      msg: 'hello world',
      name: '',
      obj: { id: 1, name: '李没睡', child: { name: '222' } }
    }
  },
  // 计算属性
  computed: {
    reverseMsg (): string {
      return this.msg.split('').reverse().join('')
    },
    newObj<T> (): T {
      return JSON.parse(JSON.stringify(this.obj))
    }
  },
  // 自定义方法
  methods: {
    test () {
      console.log('11111')
      this.obj.child.name = '3333'
    }
  },
  // 侦听属性
  watch: {
    name (newVal: string, oldVal: string) {
      console.log(newVal, oldVal)
    },
    'obj.name' (newVal: string, oldVal: string) {
      console.log(newVal, oldVal)
    },
    // obj<T> (newVal: T, oldVal: T) {
    //   console.log(newVal, oldVal)
    // }
    newObj: {
      deep: true,
      immediate: true,
      handler (newVal, oldVal) {
        console.log(newVal, oldVal)
      }
    }
  },
  // mounted生命周期
  mounted () {
    // 断言为 HTMLDivElement
    // const dom: HTMLDivElement = this.$refs.box as HTMLDivElement
    // // console.log(this.$refs === [])
    // dom.style.background = '#f66'
    (this.$refs.box as HTMLDivElement).style.background = '#f66'
  },
  // 过滤器 -- 全局过滤器 - 局部过滤器
  filters: {
    sexFilter (val: number) {
      return val === 1 ? '男' : '女'
    }
  },
  // 自定义指令
  directives: { 
    focus: { // 指令名称  使用时 v-focus
      inserted: function (el) { // el 代表的是dom元素
        el.focus()
      }
    }
  }

})
</script>

(2)类组件

<template>
  <div>
    <h2>类组件</h2>
    <p>{{ msg }}</p>
    <p>{{ reverseMsg }}</p>
    <button @click="test(555)">测试组件的点击事件</button>
    <div>
      <input type="text" v-model="name" v-focus>
    </div>
    <p> {{ proid }}  -- {{ title }}</p>
    <div ref='bbox'>bbox</div>
    {{ sex | sexFilter('person') }}
  </div>
</template>

<script lang="ts">
import { Vue, Component, Watch, Prop, Ref } from 'vue-property-decorator'

// 使用装饰器去装饰该组件
@Component({
  directives: { // 自定义指令
    focus: { // 指令名称  使用时 v-focus
      inserted: function (el) { // el 代表的是dom元素
        el.focus()
      }
    }
  },
  filters: { // 过滤器
    sexFilter (val: number, type: string) {
      if (type === 'person') {
        return val === 1 ? '男' : '女'
      } else {
        return val === 1 ? '公' : '母'
      }
    }
  }
})
export default class extends Vue {
  // ref 非空断言属性后加!     如果没有后续业务逻辑,可以使用 联合类型
  @Ref('bbox')
  bboxing!: HTMLDivElement
  //mounted生命周期
  mounted () {
    // this.bboxing.style.background = '#00f'
  }

  // 子组件接收父组件传递的数据
  @Prop({ required: true })
  readonly proid: string | undefined

  @Prop({ default: '默认标题' })
  readonly title?: string | undefined

  // 初始化数据
  // Type string trivially inferred from a string literal, remove type annotation
  // 表示 msg 不需要添加类型的注解
  msg = 'hello vue'
  name = ''
  obj = { id: 1, name: '李没睡', child: { name: '222' } }
  sex = 0

  // 自定义函数
  test (str: string) {
    console.log('2222' + str)
    this.obj.child.name = '3333'
  }

  // 计算属性
  get reverseMsg () {
    return this.msg.split('').reverse().join('-')
  }

  get newObj () {
    return JSON.parse(JSON.stringify(this.obj))
  }

  // 侦听属性
  @Watch('name')
  onNameChange<T> (newVal: T, oldVal: T) {
    console.log(newVal, oldVal)
  }
  // @Watch('obj.child.name')
  // onObjChange(newVal, oldVal) {
  //   console.log(newVal, oldVal)
  // }

  @Watch('newObj', { deep: true, immediate: true })
  onObjChange<T> (newVal: T, oldVal: T) {
    console.log(newVal, oldVal)
  }
}

</script>

(3)函数式组件(一般只进行展示)

<template functional>
  <div>
    <h2>函数式组件</h2>
    {{ props.a }} --- {{ props.b}}
  </div>
</template>

4、总结

  • 使用 TypeScript 开发前需要懂得装饰器的语法。
  • 开发时我们可以使用扩展式组件或者类组件,但是一般使用的是类组件。
  • 后续我们会讲解如何在 Vue + TypeScript 开发环境下进行状态管理以及数据请求等,这样我们就能基本完成项目的实际开发。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值