17

我正在尝试将Flow添加到 Vue 2 webpack-template。为了记录,我只在运行时(文件遵循.vue格式/标准)。

我的第一次尝试是通过 cli 使用流,我意识到它不会工作,因为它不知道如何处理.vue文件。

我的第二次尝试是添加一个 webpack 加载器(即 flow-status-webpack-plugin)并运行 Flow check 作为构建的一部分(例如eslint作品)。那没有成功,所以我研究了其他选择。

我的第三次尝试是使用 babel 插件,一开始还算成功。我使用了 babel-plugin-typecheck + babel-plugin-syntax-flow。Webpack 中没有输出,但是类型错误会破坏应用程序。我对这种方法很好;它可以与 CI 一起正常工作并破坏构建。

这是我的.babelrc样子:

{
  ...
  "plugins": [
    ...
    ["typecheck", {
      "disable": {
        "production": true
      }
    }],
    "syntax-flow",
    "transform-flow-strip-types"
  ],
  ...
}

此时,Flow 对全局方法按预期工作,但在 Vue 组件中不起作用:

<template>...</template>

<script>
/* @flow */
const flowIt = (a: number): number => {
  return a * 10
}

flowIt(20)
flowIt('bah') // Uncaught TypeError: Value of argument "a" violates contract. Expected: number Got: string

export default {    
  mounted: function () {
    flowIt(20)
    flowIt('bah') // Sees nothing wrong here
  }
}
</script>

<style>...</style>

最重要的是,目标是不要因为 Flow 而更改应用程序代码。理想情况下,我会像往常一样使用 Vue:

<template>...</template>

<script>
/* @flow */
export default {  
  methods: {
    flowIt (a: number): number {
      return a * 10
    }
  },

  mounted: function () {
    this.flowIt(20)
    this.flowIt('bah') // Should throw a type error.
  }
}
</script>

<style>...</style>

不确定这是否与 Vue 有很大关系,就像我在 Flow 方面的经验一样(提示:没有那么有经验)。我在想我需要一些类型文件来让 Flow “理解” Vue 组件的结构(我猜对指令也是如此)。

对于那些有更多经验的人,您是如何让 Flow 与 Vue + webpack 一起正常工作的?

4

5 回答 5

6

使用 eslint + 流

这是集成 flow 和 vue 的另一种方法。与此同时,flow来到了eslint。因此,我们可以直接将流错误视为 lint 错误。这是一种更简洁的方法,但随后流程与您的构建过程耦合(您不能flow check独立运行,但需要通过 webpack 运行整个构建管道以获取错误)。仍在等待此问题得到解决,以便在2017 年 5 月 10 日的.vue文件中获得完整的流支持。

在大多数情况下这很好,但有些人可能仍然想要运行的灵活性(和速度)flow check。这也可能取决于您的 CI 设置。

以下是设置 flow 和 eslint 的方法:

  1. 安装部门

    yarn add \
      babel-plugin-syntax-flow \
      babel-plugin-transform-class-properties \
      babel-plugin-transform-flow-strip-types \
      eslint \
      babel-eslint \
      eslint-plugin-html \
      eslint-plugin-flowtype-errors \
      eslint-plugin-vue \
      eslint-config-vue \
      flow-bin \
    -D
    
  2. 配置.babelrc

    {
      ...
      "plugins": [
        "babel-plugin-transform-class-properties",
        "babel-plugin-syntax-flow",
        "babel-plugin-transform-flow-strip-types"
      ]
    }
    
  3. 配置.eslintrc

    {
      "parser": "babel-eslint",
    
      "plugins": [
        "html",
        "flowtype-errors"
      ],
    
      "extends": [
        "vue"
      ],
    
      "rules": {
        "flowtype-errors/show-errors": 2
      }
    }
    
  4. 创建一个.flowconfig文件。如果您没有要配置的内容,它可以为空。

在这种情况下不需要其他解决方法,您可以/* @flow */在任何.vue文件的脚本标签中使用。请参阅此处的原始帖子。

于 2017-05-10T10:03:47.520 回答
5

通过注释掉<template>,<style>和部分,您仍然可以将 Flow 用于 .vue 组件的 JS<script>部分:

 /* @flow
 <style>
 ...style definitions here
 </style>
 <template>
 ...html...
 </template>
 */
 // <script>
 export default {  
   methods: {
      flowIt (a: number): number {
         return a * 10
      }
   },

   mounted: function () {
      this.flowIt(20)
      this.flowIt('bah') //Won't throw error, as flowIt is attached to
                         //this.
   }
}
// </script>

<template>, <style> and <script>即使被注释,vue 编译器仍会识别这些部分,但流类型检查器将忽略它们并仅处理正确的 javascript 部分。

不幸的是,这不会为您提供 100% 的类型覆盖率,因为 Flow 将无法检查附加到this(Vue 组件本身)的函数和对象,但是,您仍然可以从 Flow 对外部函数调用的类型检查中受益(例如 Vuex 操作和 getter,其他 javascript 导入模块),如果您在组件的方法中扩展了业务逻辑,则在使用方法参数时可以获得一些类型安全性。

于 2016-10-18T14:48:43.043 回答
4

除了Nik 的回答之外,值得一提的是,将他的“评论”策略与运行时检查器相结合,使“包”更加完整。一种方法是使用babel-plugin-tcomb。这将使运行时检查器成为 webpack / 构建过程的一部分(保存时)+flow check作为 CI 脚本的一部分。

对于开发,tcomb 将进行运行时检查并抛出异常(控制台)。它不做静态检查,所以以下

<script>
/* @flow */
const flowIt = (a: number): number => {
  return '' // Sees nothing wrong here, should be a number
}

// Vue component
export default {    
  ...
}
</script>

不会按预期工作。但是,以下将:

<template>{{ foo('bar') }} <!-- Type error --></template>
<script>
/* @flow */
const flowIt = (a: number): number => {
  return '' // Type error
}

// Vue component
export default {    
  methods: {
    foo: (x) => { flowIt(x) // Type error }
  },

  mounted: () => {
    flowIt([]) // Type error
  }
}
</script>

这并不理想,但它会在每次保存后进行检查,并且会捕获大多数类型错误。值得一提:tcomb 使用相同的注解(内部使用 Flow),因此它可以开箱即用。

Ofc,这还不够好,有点违背了 Flow 的观点。flow check如前所述,解决方案是仍然在 CI 上运行。这需要进行一些更改:

  1. 更新 .flowconfig 以加载 .vue 文件:

    ...
    [options]
    module.file_ext=.vue
    module.file_ext=.js
    ...
    
  2. 在包含@flow pragma 的注释中包含模板和样式块;注释掉脚本标签(这里提到了这种方法):

    /* @flow
    <template>...</template>
    
    <style>...</style>
    */
    
    // <script>
    ...
    // </script>
    

    这有点尴尬,但我找不到更好的方法。理想情况下,Flow 将能够处理<script>HTML 文档中的标签,但这只是目前的愿望清单(参见问题)。

  3. 在生产中禁用 tcomb

    {
      ...
      "plugins": [
        ...
        "syntax-flow",
        "transform-flow-strip-types"
      ],
      "env": {
        "development": {
          "plugins": ["tcomb"]
        }
      }
    }
    
于 2016-10-19T11:43:43.550 回答
2

我认为这个问题已经解决了,现在你可以在没有 hack 的情况下使用 Flow 和 Vue 组件。有关配置详细信息,请参阅这篇相当精彩的文章: https ://alligator.io/vuejs/components-flow/

于 2017-03-30T11:56:40.273 回答
1

我已经为vuewith实现了一个项目模板flowhttps://github.com/wemake-services/wemake-vue-template它支持单文件组件、linting、测试jest、构建和服务器端渲染。

Vue

这是您的组件的外观:

<template>
...
</template>

<script>
// @flow

import Vue from 'vue'
import { Store } from 'vuex'
import Component from 'nuxt-class-component'
import { Getter, State } from 'vuex-class'
import AppLogo from '~/components/AppLogo'
import Comment from '~/components/Comment'
import type { CommentType, StateType } from '~/types'

@Component({
  components: {
    AppLogo,
    Comment
  }
})
export default class Index extends Vue {
  @State('comments') comments: Array<CommentType>
  @Getter('hasComments') hasComments: boolean

  fetch (
    { store, app }: { store: Store<StateType>, app: Vue }
  ): Promise<Array<CommentType>> {
    // Uncomment the next line to test flow types:
    // console.log(this.comments + 12)
    return store.dispatch('fetchComments', app)
  }
}
</script>

它需要配置几件事:

  1. 依赖关系。一切都以flow它的名字命名:https ://github.com/wemake-services/wemake-vue-template/blob/master/template/package.json
  2. 创建有效.flowconfig的 . 这可能很棘手:https ://github.com/wemake-services/wemake-vue-template/blob/master/template/.flowconfig
  3. 配置.babelrchttps ://github.com/wemake-services/wemake-vue-template/blob/master/template/.babelrc
  4. 配置eslinthttps ://github.com/wemake-services/wemake-vue-template/blob/master/template/.eslintrc
  5. flow-typed install每次正常安装后触发: https ://github.com/wemake-services/wemake-vue-template/blob/master/template/package.json#L12

Vuex

您还可以注释vuex存储:状态、提交处理程序、getter 和操作。您可以@vue-flow-typed/vuex用于这部分。

这就是它的外观:

type StateType = {
  comments: string[]
}

function state (): StateType {
  return {
    comments: null
  }
}

const getters = {
  hasComments (state: StateType): boolean {
    return Boolean(state.comments && state.comments.length > 0)
  }
}

const mutations = {
  'SET_COMMENTS': (
    state: StateType, comments: string[]
  ) => {
    state.comments = comments
  }
}

const actions = {
  async fetchComments (
    { commit, state }: ActionContext<StateType>
  ) {
    const data = await Promise.resolve(['good', 'nice'])
    commit('SET_COMMENTS', data)
    // Uncomment next line to see typing in action:
    // console.log(state.comments, state.fake)

    return data
  }
}

但请注意,仍然无法注释某些部分。在此处阅读有关已知问题的更多信息:https ://github.com/sobolevn/vue-flow-typed#known-problems

于 2018-02-09T17:57:45.213 回答