Vue与TS的多种组合(一:类组件)💕

164 阅读1分钟

1、基于类组件的Vue组件

在vue中其实也可以实现像React那样的类组件,基本用法如下

//ClassCom组件
<template>
  <div>
    <h1>{{ title }}</h1>
  </div>
</template>
<script>
  import Component from 'vue-class-component'
  import Vue from 'vue'
  @Component
  export default class ClassCom extends Vue {
    //定义数据
    data() {
      return {
        title: '基于class的Vue组件'
      }
    }
  }
</script>

//App根组件
<template>
  <div id="app">
    <ClassCom></ClassCom>
  </div>
</template>

<script>
  import Component from 'vue-class-component'
  import Vue from 'vue'
  import ClassCom from './ClassTS/ClassComponent.vue'
  @Component({
    components: {
      ClassCom
    }
  })
  export default class App extends Vue {}
</script>

效果图

屏幕截图 2022-07-10 184247.jpg 基于TS的支持,通过vue提供的@Component这个装饰器,将类注册成组件在页面中使用

扩展用法

既然有了类组件,那么选项式API大部分就能够被替代

定义数据、方法

直接在class中定义、data函数的形式都是支持的

<script>
  import Component from 'vue-class-component'
  import Vue from 'vue'
  @Component
  export default class ClassCom extends Vue {
    //定义数据
    message: string = 'Hello!'
    data() {
      return {
        title: '基于class的Vue组件',
        words: 'typescript'
      }
    }
    //定义方法
    change(value) {
      this.title = value
    }
</script>

计算属性

计算属性可以对依赖进行计算,最终返回一个新值,那么这个功能就可以使用get、set实现

<template>
  <div>
    <h1>{{ title }}</h1>
    <button @click="change('我是类组件')">改变</button>
    <hr />
    <section>
      <h1>计算属性</h1>
      <h2>{{ this.words }}</h2>
      <h2>{{ this.toUpper }}</h2>
      <button @click="toUpper += '+vue'">改变文字</button>
    </section>
  </div>
</template>
<script>
  import Component from 'vue-class-component'
  import Vue from 'vue'
  @Component
  export default class ClassCom extends Vue {
    //定义数据
    data() {
      return {
        title: '基于class的Vue组件',
        words: 'typescript'
      }
    }
    //定义方法
    change(value) {
      this.title = value
    }
    //计算属性
    get toUpper() {
      return this.words.substring(0, 1).toUpperCase() + this.words.substring(1)
    }
    set toUpper(value) {
      this.words = value
    }
  }
</script>

效果如下

未命名 ‑ Made with FlexClip.gif

生命周期

<script>
  import Component from 'vue-class-component'
  import Vue from 'vue'
  @Component
  export default class ClassCom extends Vue {
    created() {
      console.log('created')
    }
    mounted() {
      console.log('mounted!')
    }
  }
</script>

生命周期依然生效

屏幕截图 2022-07-10 191203.jpg

extends实现属性继承

既然是类那么肯定能通过extends实现继承咯

//基类
<template>
  <div> </div>
</template>
<script lang="ts">
  import Component from 'vue-class-component'
  import Vue from 'vue'
  @Component
  export default class Base extends Vue {
    name = 'Base'
    say(words: string) {
      console.log(words)
    }
  }
</script>

//衍生类
<template>
  <div>
    <h1>{{ name }}</h1>
    <button @click="say(name)">说话</button>
  </div>
</template>
<script lang="ts">
  import Component from 'vue-class-component'
  import Base from '../components/Base.vue'
  @Component({
    components: {
      Base
    }
  })
  export default class Derive extends Base {}
</script>
<style lang=""></style>

最终效果

未命名 ‑ Made with FlexClip.gif

混入mixin

有时我们可能想要一次性继承多个类,那么就可以使用mixin

//另一个基类
<template>
  <div> </div>
</template>
<script lang="ts">
  import Component from 'vue-class-component'
  import Vue from 'vue'
  @Component
  export default class OtherBase extends Vue {
    color = 'yellow'
  }
</script>

//上面的衍生类
<template>
  <div>
    <h1>{{ name }}</h1>
    <button @click="say(name)">说话</button>
    <div
      :style="{
        background: color
      }"
      >OtherBase</div
    >
  </div>
</template>
<script lang="ts">
  import Component, { mixins } from 'vue-class-component'
  import Base from '../components/Base.vue'
  import OtherBase from '../components/OtherBase.vue'
  @Component({
    components: {
      Base
    }
  })
  export default class Derive extends mixins(Base, OtherBase) {}
</script>
<style lang=""></style>

最终效果

屏幕截图 2022-07-10 214524.jpg

render函数

同样也可以使用render函数,替代template,同样也支持JSX语法

<script>
  import Component from 'vue-class-component'
  import Vue from 'vue'
  @Component
  export default class ClassCom extends Vue {
    created() {
      console.log('created')
    }
    mounted() {
      console.log('mounted!')
    }
    //定义数据
    data() {
      return {
        title: '基于class的Vue组件',
        words: 'typescript'
      }
    }
    //定义方法
    change(value) {
      this.title = value
    }
    //计算属性
    get toUpper() {
      return this.words.substring(0, 1).toUpperCase() + this.words.substring(1)
    }
    set toUpper(value) {
      this.words = value
    }
    render() {
      return (
        <div>
          <h1>{this.title}</h1>
          <button
            onClick={() => {
              this.change('我是类组件')
            }}
          >
            改变
          </button>
          <hr />
          <section>
            <h1>计算属性</h1>
            <h2>{this.words}</h2>
            <h2>{this.toUpper}</h2>
            <button
              onClick={() => {
                this.toUpper += '+vue'
              }}
            >
              改变文字
            </button>
          </section>
        </div>
      )
    }
  }
</script>

感觉瞬间回到React了有没有😎

至于其他的选项式API,其实可以在Component装饰器中进行配置,类似这样

<script>
import Vue from 'vue'
import Component from 'vue-class-component'
import OtherComponent from './OtherComponent.vue'
@Component({
  components: {
    OtherComponent
  }
})
export default class HelloWorld extends Vue {}
</script>

总结

类组件能够更好的与TS的类型推断相结合,个人感觉,类组件在vue2中用处是大于vue3的,在vue3中也有更好的与TS的组合方式,当然如果你只是单纯的喜欢类组件的写法