zoukankan      html  css  js  c++  java
  • 深入使用Vue + TS

    深入使用TS

    支持 render jsx 写法

    这里一共分两步

    1. 首先得先让 vue 支持 jsx 写法

    2. 再让 vue 中的 ts 支持 jsx 写法

    让 vue 支持 jsx

    按照官方做法,安装Babel 插件

    图片描述

    安装依赖

    npm install
      babel-plugin-syntax-jsx
      babel-plugin-transform-vue-jsx
      babel-helper-vue-jsx-merge-props
      babel-preset-es2015
      --save-dev

    .babelrc中添加:

    {
      "plugins": ["transform-vue-jsx"]
    }

    之后就可以这些写render,如下图:

    图片描述

    让 ts 支持 jsx

    首先配置 webpack
    找到./build/webpack.base.conf.js

    • 找到resolve.extensions 里面加上.tsx 后缀

      resolve: {
        extensions: ['.js', '.vue', '.json', '.ts', '.tsx']
      }
    • 找到module.rules 修改webpack对.tsx .ts 的解析

      module: {
        rules: [
          {
            test: /.(js|vue)$/,
            loader: 'eslint-loader',
            enforce: 'pre',
            include: [resolve('src'), resolve('test')],
            options: {
              formatter: require('eslint-friendly-formatter')
            }
          },
            // 从这里复制下面的代码就可以了
            // 如果之前按照起手式配置的同学,请替换配置
          {
            test: /.tsx?$/,
            exclude: /node_modules/,
            enforce: 'pre',
            loader: 'tslint-loader'
          },
          {
            test: /.vue$/,
            loader: 'vue-loader',
            options: Object.assign(vueLoaderConfig, {
              loaders: {
                ts: "ts-loader",
                tsx: "babel-loader!ts-loader"
              }
            })
          },
          {
            test: /.tsx?$/,
            exclude: /node_modules/,
            use: [
              "babel-loader",
              {
                loader: "ts-loader",
                options: { appendTsxSuffixTo: [/.vue$/] }
              }
            ]
          },
          // 复制截止
          {
            test: /.js$/,
            loader: 'babel-loader',
            include: [resolve('src'), resolve('test')]
          },

    上面的配置,主要意思是 vue 文件识别ts/tsx代码的时候,先过一遍ts-loader,在过一遍babel-loader,我知道这听起来有点蠢,但是jsx不能不要对吧?

    然后在 tsconfig.json中,添加对jsx的支持

     "compilerOptions": {
        "jsx": "preserve"
        }

    之后就可以顺利在.vue单文件中的tsjsx代码了,如下图所示:

    图片描述

    敲黑板,这里又有重点,使用 jsx 写法的话, 一定要使用 .tsx,不要用.ts了,切记!!!

    支持es6 / es7

    在 tsconfig.json中,添加对es6 / es7的支持,更多的配置请见tsconfig - 编译选项

    "lib": [
          "dom",
          "es5",
          "es6",
          "es7",
          "es2015.promise"
        ]

    图片描述

    不然的话,连Object.assign 这种最基本的函数也会在ts中报错,真的令人难过

    配置 vuex

    这里就比较简单了

    # 安装依赖
    npm i vuex vuex-class --save
    • vuex:在 vue 中集中管理应用状态

    • vuex-class :在 vue-class-component 写法中 绑定 vuex

    Store的配置跟原来一模一样,引用的时候有一点区别,下面的例子介绍了用法,应该一看便知,这里我不做赘述

    import Vue from 'vue'
    import Component from 'vue-class-component'
    import {
      State,
      Getter,
      Action,
      Mutation,
      namespace
    } from 'vuex-class'
    
    const ModuleGetter = namespace('path/to/module', Getter)
    
    @Component
    export class MyComp extends Vue {
      @State('foo') stateFoo
      @State(state => state.bar) stateBar
      @Getter('foo') getterFoo
      @Action('foo') actionFoo
      @Mutation('foo') mutationFoo
      @ModuleGetter('foo') moduleGetterFoo
    
      // 如果省略了参数,使用属性名
      // 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']
      }
    }

    让 vue 识别全局方法/变量

    在项目中使用 ui 组件是很正常的操作

    比如使用 Element-uI 的 meesage,用法如下图:

      this.$message({
        message: '恭喜你,这是一条成功消息',
        type: 'success'
      })

    但是在配置了 typescript之后

    图片描述

    那是因为 $message属性,并没有在 vue实例中声明

    解决办法也非常简单,那我们就声明一下呗

    在之前文章中创建的 src/vue-shim.d.ts文件中,增加如下代码:

    // 声明全局方法
    declare module 'vue/types/vue' {
      interface Vue {
        $Message: any,
        $Modal: any
      }
    }

    这样,之后再使用this.$message()的话就不会报错了

    支持 mixin

    我在vue-property-decorator里里外外找了好几圈,缺没有找到mixin这个修饰器

     // 如果全局mixin,那也太蠢了
     Vue.mixin( mixin )

    找非常多的 ts + vue 项目,但是没有找到我理想的mixin的方式,
    那么就自己进行探索咯,下图是我自己使用的目前最佳mixin方式:

    声明了一个mixin组件,如下图:

    图片描述

    其实就是我在mixin中声明了声明属性 / 方法,那么我就在vue实例中声明这个属性 / 方法

    使用方式如下图:

    图片描述

    支持 ProvidePlugin 的全局变量,比如 lodash 的 _

    如果我们在项目中有使用 jquery,lodash 这样的工具库的时候,肯定不希望在所有用到的地方都import _ from ‘lodash’
    @types/lodash

    那我们就来配置一下:

    首先还是在webpack.base.conf.js 中添加一个插件、并把这个 vendor拉出来

      entry: {
        app: './src/main.ts',
        vendor: [
          "lodash"
        ]
      }
    
      plugins: [
        new webpack.ProvidePlugin({
          _: 'lodash'
        })
      ]
     

    上面的意思是,当模块使用这些变量的时候wepback会自动加载

    然后,你需要告诉eslint这个 _ 是全局的

    .eslintrc.js中添加

      globals: {
        _: true
      },

    接下来,你还需要告诉ts这个 _ 是全局的

    vue-shim.d.ts

    declare global {
      const _: typeof lodash
    }

    如果没有上面这段声明,但是在 ts 中使用的话,会报如下的错误:

    图片描述

    这个问题Consider allowing access to UMD globals from modules · Issue #10178 · Microsoft/TypeScript · GitHub

    有一个很简单的解释,就是害怕你全局声明的_ 跟 import _ from 'lodash' 的行为不一致,这样的话,之后会留下隐患

  • 相关阅读:
    4 Apr 18 软件开发目录 logging模块的使用 序列化(Json, Pickle) os模块
    3 Apr 18 内置函数 列表生成式与生成器表达式 模块的使用之import 模块的使用之from…import…
    2 Apr 18 三元表达式 函数递归 匿名函数 内置函数
    30 Mar 18 迭代器 生成器 面向过程的编程
    29 Mar 18 函数 有参、无参装饰器
    28 Mar 18 函数
    27 Mar 18 函数的参数
    26 Mar 18 函数介绍
    23 Mar 18 文件处理
    22 Mar 18 补充数据类型+字符编码+文件处理
  • 原文地址:https://www.cnblogs.com/cczlovexw/p/11508251.html
Copyright © 2011-2022 走看看