zoukankan      html  css  js  c++  java
  • 在Vue项目中使用Typescript

    3.0迟迟没有发布release版本,现阶段在vue项目中使用Typescript需要花不小的精力在工程的配置上面。主要的工作是webpack对TS,TSX的处理,以及2.x版本下面使用class的形式书写vue 组件的一些限制和注意事项。

    webpack 配置

    配置webpack对TS,TSX的支持,以便于我们在Vue项目中使用Typescript和tsx。

    module.exports = {
        entry: './index.vue',
        output: { filename: 'bundle.js' },
        resolve: {
            extensions: ['.ts', '.tsx', '.vue', '.vuex']
        },
        module: {
            rules: [
                { test: /.vue$/, loader: 'vue-loader',
                  options: {
                    loaders: {
                      ts: 'ts-loader',
                      tsx: 'babel-loader!ts-loader',
                    }
                  }
                },
                { 
                    test: /.ts$/, 
                    loader: 'ts-loader', 
                    options: { appendTsSuffixTo: [/TS.vue$/] }             },
                { 
                    test: /.tsx$/, 
                    loader: 'babel-loader!ts-loader', 
                    options: { 
                        appendTsxSuffixTo: [/TSX.vue$/] 
                    } 
                }
            ]
        }
    }

    在上面的配置中,vue文件中的TS内容将会使用ts-loader处理,而TSX内容将会按照ts-loader-->babel-loader的顺序处理。

    appendTsSuffixTo/appendTsxSuffixTo配置项的意思是说,从vue文件里面分离的script的ts,tsx(取决于<script lang="xxx"></script>)内容将会被加上ts或者tsx的后缀,然后交由ts-loader解析。

    我在翻看了ts-loader上关于appendTsxSuffixTo的讨论发现,ts-loader貌似对文件后缀名称有很严格的限定,必须得是ts/tsx后缀,所以得在vue-loader extract <script>中内容后,给其加上ts/tsx的后缀名,这样ts-loader才会去处理这部分的内容。

    ts-loader只对tsx做语法类型检查,真正的jsx-->render函数应该交由babel处理。

    所以我们还需要使用plugin-transform-vue-jsx来将vue jsx转换为真正的render函数。

    // babel.config.json
    {
      "presets": ["env"],
      "plugins": ["transform-vue-jsx"]
    }

    同时,配置TS对tsx的处理为preserve,让其只对tsx做type类型检查。

    // tsconfig.json
    {
      "compilerOptions": {
        "jsx": "preserve",
    }

    使用vue cli 4.x

    高版本的vue cli如4.x已经集成了vue + typescript的配置。选择use Typescript + Use class-style component syntax选项创建工程。

    创建后的工程目录如下:

    在src根目录下,有两个shims.xx.d.ts的类型声明文件。

    //  shims.vue.d.ts
    declare module "*.vue" {
      import Vue from "vue";
      export default Vue;
    }
    // shims.jsx.d.ts
    import Vue, { VNode } from "vue";
    declare global {
      namespace JSX {
        // tslint:disable no-empty-interface
        interface Element extends VNode {}
        // tslint:disable no-empty-interface
        interface ElementClass extends Vue {}
        interface IntrinsicElements {
          [elem: string]: any;
        }
      }
    }

    它们是作什么用的呢?

    shims.vue.d.ts给所有.vue文件导出的模块声明了类型为Vue,它可以帮助IDE判断.vue文件的类型。

    shims.jsx.d.ts 为 JSX 语法的全局命名空间,这是因为基于值的元素会简单的在它所在的作用域里按标识符查找。当在 tsconfig 内开启了 jsx 语法支持后,其会自动识别对应的 .tsx 结尾的文件,(也就是Vue 单文件组件中<script lang="tsx"></script>的部分)可参考官网 tsx

    基本用法

    在vue 2.x中使用class的方式书写vue组件需要依靠vue-property-decorator来对vue class做转换。

    <script lang="ts">
    import { Component, Prop, Vue } from "vue-property-decorator";
    export default class extends Vue {
      @Prop({ default: 'default msg'}) private msg!: string;
      name!: string;
      show() {
        console.log("this.name", this.name);
      }
    }
    </script>

    导出的class是经过Vue.extend之后的VueComponent函数(理论上class就是一个Function)。

    其最后的结果就像我们使用Vue.extend来扩展一个Vue组件一样。

    // 创建构造器
    var Profile = Vue.extend({
      template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
      data: function () {
        return {
          firstName: 'Walter',
          lastName: 'White',
          alias: 'Heisenberg'
        }
      }
    })
    
    export default {
        components: {
            Profile 
        }
    }

    注意上面的Profile组件并不是和我们平时一样写的Vue组件是一个plain object配置对象,它其实是一个VueComponent函数。

    父组件实例化子组件的时候,会对传入的vue object 进行扩展,使用Vux.extend转换为组件函数。
    如果components中的值本身是一个函数,就会省略这一步。这一点, 从Vue 源码中可以看出。

    if (isObject(Ctor)) {
        Ctor = baseCtor.extend(Ctor)
    }

    上面的Ctor就是在components中传入的组件,对应于上面导出的Profile组件。

    使用vuex

    使用vuex-class中的装饰器来对类的属性做注解。

    
    import Vue from 'vue'import Component from 'vue-class-component'import {
      State,
      Getter,
      Action,
      Mutation,
      namespace
    } from 'vuex-class'
    
    const someModule = namespace('path/to/module')
    
    @Component
    export class MyComp extends Vue {
      @State('foo') stateFoo
      @State(state => state.bar) stateBar
      @Getter('foo') getterFoo
      @Action('foo') actionFoo
      @Mutation('foo') mutationFoo
      @someModule.Getter('foo') moduleGetterFoo
    
      // If the argument is omitted, use the property name
      // for each state/getter/action/mutation type
      @State foo
      @Getter bar
      @Action baz
      @Mutation qux
    
      created () {
        this.stateFoo // -> store.state.foo
        this.stateBar // -> store.state.bar
        this.getterFoo // -> store.getters.foo
        this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true })
        this.mutationFoo({ value: true }) // -> store.commit('foo', { value: true })
        this.moduleGetterFoo // -> store.getters['path/to/module/foo']
      }
    }

    mixin

    对于mixin,我们使用class的继承很容易实现类似功能。

    import Vue from 'vue'
    import { Component } from 'vue-property-decorator'
    @Component
    class DeployMixin extends Vue{
      name: string;
      deploy(){
        // do something
      }
    }
    @Component
    class Index extends DeployMixin{
      constructor(){ 
        super()
      }
      sure(){
        this.deploy()
      }
    }

    广州设计公司https://www.houdianzi.com 我的007办公资源网站https://www.wode007.com

    VS code jsx快捷键

    设置 VS code中对emmet的支持

    "emmet.includeLanguages": {
        "JavaScript": "html"
    }

    或者是

    "emmet.includeLanguages": {
        "JavaScript": "javascriptreact"
    }
  • 相关阅读:
    [WPF 自定义控件]好用的VisualTreeExtensions
    [UWP]从头开始创建并发布一个番茄钟
    [WPF 自定义控件]使用TextBlockHighlightSource强化高亮的功能,以及使用TypeConverter简化调用
    [WPF 自定义控件]排序、筛选以及高亮
    《写给大家看的设计书》,推荐给想了解设计的程序员
    [WPF 自定义控件]使用WindowChrome自定义RibbonWindow
    [书籍]通过《番茄工作法图解》复习番茄工作法
    [WPF 自定义控件]使用WindowChrome的问题
    [WPF 自定义控件]使用WindowChrome自定义Window Style
    时时监听input内容的改变
  • 原文地址:https://www.cnblogs.com/qianxiaox/p/13830974.html
Copyright © 2011-2022 走看看