最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 走近Ts,用了爽,用后一直爽(二)

    正文概述 掘金(yaoxfly)   2020-12-19   343

    前言

    上文《走近Ts,用了爽,用后一直爽(一)》 中写了Ts的一些类型、属性等简单语法,以及类、接口、装饰等高级用法后,今天我们来看看如何在vue项目中使用ts,目前使用公司项目用的较多的还是vue2.x,vue是渐进式的框架,我们学习也要渐进式的,所以本文也先围绕vue2.x来对Ts进行实战,为后期切换vue3.0打下基础。

    简介

        在使用前我们要先在项目中安装Ts,安装过程就不细说了,如果只是学习,推荐用vue的官方脚手架,里面就带有安装Ts选项。接着要安装下vue-class-componentvue-property-decorator

       安装之前我们先了解下vue-class-componentvue-property-decorator

       vue-class-componentvue 的官方库,作用是以class的模式编写组件。这种编写方式使vue组件可以使用继承、混入等高级特性,更重要的是使 Vue 组件更好的跟TS结合使用。

       vue-property-decorator 是社区出的, 基于vue-class-component 拓展出了很多操作符 @Prop @Emit @Inject 等;可以说是 vue-class-component 的一个超集, 使代码更为简洁明了,options里面需要配置 decorator库不支持的属性, 比如components, filters, directives等。

        这两者都是离不开装饰器的,装饰器已在ES提案中。decorator是装饰器模式的实践。装饰器模式呢,它是继承关系的一个替代方案。动态地给对象添加额外的职责。在不改变接口的前提下,增强类的功能。

    使用

    Component

       装饰器可以接收一个对象作为参数,可以在对象中声明 componentsfiltersdirectives等未提供装饰器的选项。

    
    <template>
     <div class="home">
       {{num | addOne('过滤器第二个参数')}}
       <Test
         ref="helloWorld"
         v-test="'h'"
       />
     </div>
    </template>
    
    
    <script lang='ts'>
    import { Component,Vue} from 'vue-property-decorator'
    import Test from '@/components/Test.vue'
    
    @Component({
        name: 'Home',
         //组件
        components: {
           Test
         },
         
         //局部指令
        directives: {
           test(el: HTMLElement, binding) {
            console.log('DOW:',el,'局部指令:' ,binding)
           }
        },
        
         // 局部过滤
        filters: {
           addOne(num: number, towParam: string) {
             console.log(towParam, '局部过滤器')
             return num + 3
           }
         }
         
         //混入
         // mixins: [ResizeMixin]
       })
    
       export default class extends Vue {
          private num: number = 1 //定义一个变量
       }
    </script>
    

    生命周期

     <template>
         <div class="home"></div>
     </template>
        
     <script lang='ts'>
       import { Component, Vue } from 'vue-property-decorator'
       
       @Component({
         name: 'LifeCycle',
       })
       
       export default class extends Vue {
         private num = 1
         private created(): void {
           console.log(this.num)
         }
         private mounted(): void {
           console.log(this.num)
         }
       }
       </script>
    

    方法、属性

     <template>
      <div class="home">
        <button @click="addAge">加1</button>
        {{ num }}
      </div>
    </template>
     
    <script lang='ts'>
    import { Component, Vue } from 'vue-property-decorator'
    @Component({
      name: 'AttrMethod',
    })
    export default class extends Vue {
      private num = 1 //属性
      private checked = true
    
      //方法
      private addAge(): void {
        this.num++
        this.checked = false
      }
    
      private mounted(): void {
        console.log(this.num)
      }
    }
    </script>
    

    computer(计算属性)

    <template>
      <div class="computer">
        {{ count(this.num, 2) }}
        {{ msg }}
      </div>
    </template>
     
    <script lang='ts'>
    import { Component, Vue } from 'vue-property-decorator'
    @Component({
      name: 'Computers',
    })
    export default class extends Vue {
      private num = 1
      private mounted(): void {
        console.log(this.num)
      }
     /*计算属性*/
    
      //传参写法
      private get count() {
        return function (num: number, numbers: number) {
          return num + numbers
        }
      }
    
      //普通写法
      private get msg() {
        return '普通写法的计算属性'
      }
    }
    </script>
    

    watch(监听)

    <template>
         <div class="watch">
            {{ num }}
         </div>
    </template>
    
    <script lang='ts'>
           import { Component, Vue, Watch } from 'vue-property-decorator'
           @Component({
             name: 'Watch',
           })
           export default class extends Vue {
             private num = 1
             private mounted(): void {
               this.timeOut()
             }
             private timeOut() {
               setTimeout(() => {
                 this.num++
               }, 1000)
             }
             //监听
             @Watch('num', { immediate: true, deep: true })
             onNumChange(val: string, old: string) {
               console.log(val, old, 'watch')
             }
           }
    </script>
    

    ref

    <template>
         <div class="watch">
           <img  src="../assets/logo.png" ref="img" />
           {{ num }}
           <Test ref="test" />
         </div>
    </template>
    
    <script lang='ts'>
       import { Component, Vue, Ref } from 'vue-property-decorator'
       import Test from '@/components/Test.vue'
       @Component({
         name: 'Watch',
         components: {
           Test,
         },
       })
       export default class extends Vue {
         private num = 1
         @Ref() readonly test!: Test //引入的组件的ref
         @Ref('img') readonly img!: HTMLButtonElement //普通html标签的ref
         private mounted(): void {
           console.log(
             '普通的ref使用方式:',
             this.$refs.test,
             '定义变量的ref使用方式:',
             this.test,
             '引入组件的ref'
           )
           console.log(this.img, this.$refs.img, '普通img标签的ref')
         }
       }
    </script>
    

    依赖注入

    • Provide
    <template>
      <div class="home">
        <Inject
          ref="helloWorld"
        />
      </div>
    </template>
    <script lang='ts'>
    // @ is an alias to /src
    /*eslint-disable */
    import {
      Component,
      Vue,
      Provide,
    } from 'vue-property-decorator'
    import Inject from '@/components/Inject.vue'
    
    const symbol = Symbol('baz')
    //装饰器注明此类
    @Component({
      name: 'Provide',
      components: {
        Inject
      },
      // mixins: [ResizeMixin]
    })
    export default class extends Vue {
      @Provide() foo = 'foo' //依赖注入
      @Provide() optional = 'optional' //依赖注入
      @Provide('bar') baz = 'bar'
    }
    </script>
    
    • Inject
    <template>
      <div class="hello">
        <h1 @click="returnValue">{{ msg }}</h1>
      </div>
    </template>
    
    <script lang="ts">
    import {
      Component,
      Vue,
      Inject
    } from 'vue-property-decorator'
    @Component
    export default class HelloWorld extends Vue {
      @Inject() readonly foo!: string //接收依赖注入的值
      @Inject({ from: 'optional', default: 'default' }) readonly optional!: string //父组件,爷爷组件没传optional时,使用default设置默认值
      @Inject('bar') readonly bar!: string
      
      private moun ted(): void {
        console.log( 22, this.foo, this.optional, this.bar)
      }
    }
    </script>
    

    Prop

    子组接收父组件传进来的值

    • 父组件
    <template>
     <div class="home">
    
       <Props
         :msg="msg"
         prop-c='11'
        
       />
     </div>
    </template>
    <script lang='ts'>
    // @ is an alias to /src
    /*eslint-disable */
    import {
     Component,
     Vue,
    
    } from 'vue-property-decorator'
    import Props from '@/components/Prop.vue'
    
    const symbol = Symbol('baz')
    //装饰器注明此类
    @Component({
     name: 'Prop',
     components: {
       Props
     },
     
    })
    export default class extends Vue {
     private msg: string = 'hello'
     private name: string = 'sss'
     private checked: boolean = true
     private num: number = 1
    }
    </script>
    
    • 子组件
    <template>
     <div class="hello">
       <h1 > {{ msg }}</h1>
       <span>{{ propB }}</span>
          <span>{{ propC }}</span>
     </div>
    </template>
    
    <script lang="ts">
    import {
     Component,
     Prop,
     Vue,
    } from 'vue-property-decorator'
    @Component
    export default class HelloWorld extends Vue {
     @Prop() private msg!: string //!,非null和undefined
     @Prop(Number) readonly propA: number | undefined
     @Prop({ default: 'default value' }) readonly propB!: string
     @Prop([String, Boolean]) readonly propC: string | boolean | undefined
    }
    </script>
    

    Emit

    向父组件发射个方法

    • 父组件
    
     <template>
      <div class="home">
        <EmitChild
          @return-value="returnValue"
        />
      </div>
    </template>
    <script lang='ts'>
    // @ is an alias to /src
    /*eslint-disable */
    import {
      Component,
      Vue,
    
    } from 'vue-property-decorator'
    import EmitChild from '@/components/Emit.vue'
    
    const symbol = Symbol('baz')
    //装饰器注明此类
    @Component({
      name: 'Emit',
      components: {
        EmitChild
      },
    })
    
    export default class extends Vue {
       private returnValue(aa:number):void {
         console.log(aa)
        }
    }
    </script>
    
    • 子组件
    <template>
      <div class="hello">
        <p @click="returnValue">
           emit
        </p>
      </div>
    </template>
    
    <script lang="ts">
    import {
      Component,
      Vue,
      Emit,
    } from 'vue-property-decorator'
    @Component
    export default class HelloWorld extends Vue {
      @Emit() //把方法发射出去可以让父组件使用
      returnValue() {
        return 10
      }
    }
    </script>
    

    PropSync

    实现sync修饰符(prop双向绑定)

    • 父组件
    <template>
      <div>
        <button @click="exportName">输出name</button>
        <PropSyncChild
          :name.sync="name"
        />
      </div>
    </template>
    <script lang='ts'>
    // @ is an alias to /src
    /*eslint-disable */
    import {
      Component,
      Vue,
    } from 'vue-property-decorator'
    import PropSyncChild from '@/components/PropSync.vue'
    
    //装饰器注明此类
    @Component({ 
      name: 'PropSync',
      components: {
        PropSyncChild
      },
    })
    export default class extends Vue {
      private name: string = 'sss'
      exportName():void{
         console.log(this.name)
      }
    }
    </script>
    
    
    • 子组件
    <template>
      <div class="hello">
        <p @click="setSyncedName">
         我是子组件: 同步、子组件修改父组件
        </p>
      </div>
    </template>
    
    <script lang="ts">
    import {
      Component,
      Vue,
      PropSync, 
    } from 'vue-property-decorator'
    @Component
    export default class HelloWorld extends Vue {
      @PropSync('name', { type: String }) syncedName!: string //同步,可让子组件修改父组件的值
      public setSyncedName(): void {
        console.log('prop双向绑定',)
        this.syncedName = '同步、子组件修改父组件'
      }
    }
    </script>
    

    Model

    实现v-model双向绑定

    • 父组件
    <template>
    <div >
      <button @click="setChecked"> 修改checked</button>
      <ModelChild
       v-model="checked"
      />
    </div>
    </template>
    <script lang='ts'>
      import {
        Component,
        Vue,
      } from 'vue-property-decorator'
      import ModelChild from '@/components/Model.vue'
      //装饰器注明此类
      @Component({
        name: 'Model',
        components: {
          ModelChild
        },
      })
      export default class extends Vue {
        private checked = false
       setChecked():void{
          this.checked=!this.checked
        }
      }
    </script>
    
    • 子组件
    <template>
     <div class="hello">
       我是子组件的checked: {{checked}}
     </div>
    </template>
    
    <script lang="ts">
       import {
         Component,
         Vue,
         Model,
       } from 'vue-property-decorator'
       @Component
       export default class HelloWorld extends Vue {
         @Model('change', { type: Boolean }) readonly checked!: boolean //v-model
       }
    </script>
    

    起源地下载网 » 走近Ts,用了爽,用后一直爽(二)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元