Convert Vuejs Typescript Options to Composition Api 中的奇怪问题

Posted

技术标签:

【中文标题】Convert Vuejs Typescript Options to Composition Api 中的奇怪问题【英文标题】:odd problems in Convert Vuejs Typescript Options to Composition Api 【发布时间】:2020-05-13 18:34:12 【问题描述】:

问题已解决,请通读问题,了解如何逐步解决问题

我阅读了有关组合 api(https://vue-composition-api-rfc.netlify.com/#api-introduction) 的信息,并尝试转换我现有的代码,该代码基于 vuejs 中 Option api 上的 typescript,但我未能使其工作,并且对组合 api 如何真正工作感到困惑。

我的工作代码如下:

<script lang="ts">
  import Vue from "vue";
  import inputFields from "@/mixins/inputField/inputField";
  import VuePersianDatetimePicker from "vue-persian-datetime-picker"
  import util_timestampz_formatter, util_timestampz_now from "@/utils/commonUtility";
  import InputFieldHelper from "@/mixins/Helpers/FormGeneratorInputFieldHelper/InputField.Helper.mixin";

  export default Vue.extend(
    name: "DateTimePicker",
    props: ['instance', "value", "formSection", "isEnable"],
    components: 
      datePicker: VuePersianDatetimePicker
    ,
    data() 
      return 
        inputField: new InputFieldHelper(this.value, this.instance, this.formSection, this.isEnable)
      
    ,
    mounted() 
      //@ts-ignore
      this.instance.min = util_timestampz_now();
    ,
    methods: 
      updateValue() 
        let new_data = this.inputField.updateValue();
        new_data ? this.$emit("updateValue", new_data) : "";
      ,
      updateDateTime(time: string) 
        //@ts-ignore
        this.inputField.inputValue = util_timestampz_formatter(this.inputField.inputValue);
        //@ts-ignore
        this.updateValue();
      ,
    
  );
</script>

composition api 中转换后的版本低于运行不正常的版本:

<script lang="ts">
  import Vue from "vue";
  import reactive, createComponent, onMounted from "@vue/composition-api";
  import VuePersianDatetimePicker from "vue-persian-datetime-picker"
  import util_timestampz_formatter, util_timestampz_now from "@/utils/commonUtility";
  import InputFieldHelper from "@/mixins/Helpers/FormGeneratorInputFieldHelper/InputField.Helper.mixin";
  import FormGeneratorInputField from "@/types";

  export default createComponent(
    name: "DateTimePicker",
    props: 
      instance,
      value,
      formSection,
      isEnable,
    ,
    components: 
      datePicker: VuePersianDatetimePicker
    ,
    setup(props, context) 
      const inputField = reactive(new InputFieldHelper(props.value, props.instance, props.formSection, props.isEnable));
      onMounted(() => 
        props.instance.min = util_timestampz_now();
      );
      const updateValue = () => 
        let new_data = inputField.updateValue();
        new_data ? context.$emit("updateValue", new_data) : "";
      ;
      const updateDateTime = (time: string) => 
        inputField.inputValue = util_timestampz_formatter(inputField.inputValue);
        updateValue();
      ;
      return 
        inputField, updateValue, updateDateTime
      
    
  );
</script>

哪个 webstorm 显示 3 错误:

有没有办法正确解决这个问题?

..................

更新1:

我在使用 props 时犯了错误(我以为我是新的 vue,它不需要类型,它会自动从父组件的 typescript 中获取它)。多亏了古问题,问题已经解决并得到解决。

对于在获取道具类型错误时遇到类似问题的任何人,如下图所示

感谢https://frontendsociety.com/using-a-typescript-interfaces-and-types-as-a-prop-type-in-vuejs-508ab3f83480,您可以将创建的类型接口作为如下函数传递:

但仍有一些问题需要解决,如下所示:

1.当我删除反应性时,反应性似乎无法正常工作,并且在模板中显示“未解析的变量或缺少导入语句”

......................

update2分享道具和使用合成功能:

对我来说,在将基于选项的 api 转换为组合 api 之后,它似乎比新的更好,这要归功于古和 Maximilian shrwazmuller(我强烈建议观看这个免费视频:https://www.youtube.com/watch?v=V-xK3sbc7xI)和谷歌搜索与https://vue-composition-api-rfc.netlify.com/api.html#template-refs 苦苦挣扎,我将代码重写为如下所示:

<script lang="ts">
  import createComponent, onMounted from "@vue/composition-api";
  import VuePersianDatetimePicker from "vue-persian-datetime-picker"
  import util_timestampz_formatter, util_timestampz_now from "@/utils/commonUtility";
  import 
    useInputFieldComposition,
    inputFieldProps
   from "@/mixins/Helpers/FormGeneratorInputFieldHelper/inputField.composition";
  import ComponentPropsOptions from "@vue/composition-api/dist/component/componentProps";

  export default createComponent(
    name: "DateTimePicker",
    props: inputFieldProps as ComponentPropsOptions,
    components: 
      datePicker: VuePersianDatetimePicker
    ,
    setup(props, context) 
      const inputField, updateValue = useInputFieldComposition(props, context);
      onMounted(() => 
        props.instance.min = util_timestampz_now();
      );
      const updateDateTime = (time: string) => 
        inputField.inputValue = util_timestampz_formatter(inputField.inputValue);
        updateValue();
      ;
      return 
        inputField, updateValue, updateDateTime
      
    
  );
</script>

如您所见,它非常简洁,因为组件之间共享的所有内容都在另一个文件中(命名为:inputFiled.compositons),如下所示:

//inputField.composition.ts
import PropType, reactive from "@vue/composition-api";
import FormGeneratorInputField from "@/types";
import InputFieldHelper from "@/mixins/Helpers/FormGeneratorInputFieldHelper/InputField.Helper.mixin";

export const inputFieldProps = 
  instance: 
    type: Object as PropType<FormGeneratorInputField>,
    required: true
  ,
  value: 
    type: Object,
    required: true
  ,
  formSection: 
    type: String,
    required: true
  ,
  isEnable: 
    type: Boolean,
    required: true
  ,
;
export const useInputFieldComposition = (props: any, context: any) => 
  let inputField  = reactive(new InputFieldHelper(props.value, props.instance, props.formSection, props.isEnable));
  const updateValue = (): any => 
    let new_data = inputField.passInfoMixedValue();
    new_data ? context.emit("updateValue", new_data) : "";
    return new_data;
  ;

  return 
    props, inputField, updateValue
  

正如您所见,通过此功能,我们可以充分发挥打字稿的潜力。

最后我应该告诉你,如果你遵循路径并使用 vue-composition api,你的项目将完美运行,但 webstorm 会向你显示一些关于模板中特定代码的警告,比如未解析的变量。这些新的语法支持正在开发中,您可以在本期中看到 https://youtrack.jetbrains.com/issue/WEB-41565 所以不要担心它并使用它。

【问题讨论】:

三个// @ts-ignore…哎哟! 【参考方案1】:

阅读documentation on props。这是一个例子:

    props: 
      instance: 
        type: Object,
        required: true
      ,
      value: 
        type: Object,
        required: true
      ,
      formSection: 
        type: Object,
        required: true
      ,
      isEnable: 
        type: Boolean,
        required: false
      ,
    ,

为了启用更好的类型,可以使用PropType

import  PropType  from "@vue/composition-api/dist/component/componentProps";
// …

    props: 
      instance: 
        type: Object as PropType<FormGeneratorInputField>,
        required: true
      ,
      // …

要发出事件,请遵循错误消息中的建议:context.emit("updateValue")

关于InputFieldHelper的实例,我建议重构这个类的实现:

class InputFieldHelper 
  readonly inputField: 
    inputValue: string | null
  

  constructor(/* … */) 
    this.inputField = reactive(
      inputValue: null
    )
  

然后,使用它:

const helper = new InputFieldHelper(props.value, props.instance, props.formSection, props.isEnable);

const inputField = helper.inputField;

【讨论】:

当我删除反应性时,反应性似乎消失了,在 tempate 中,它告诉我未解析的变量或类型 UpdateDateTime 好的,所以将reactive 保留在InputFieldHelper 的实例周围。对于UpdateDateTime,可能是大写的“U”。 不,它不是大写的,程序运行良好,在 webstorm 中这告诉我该消息。当我使用响应式时,在 updateDateTime 它告诉我尝试分配给 const 或 readonly 变量。那么我该怎么做才能解决这些问题? @SeyyedKhandon 我编辑了一些关于InputFieldHelper 的建议。 谢谢,首先这个“PropType”是一个漂亮的答案(超过 ()=>...),所以我使用了它。但第二个我宁愿不使用 vuejs 特定的语法污染类。我希望有一个更好的解决方案,就像你以前的建议一样正确解决这个问题

以上是关于Convert Vuejs Typescript Options to Composition Api 中的奇怪问题的主要内容,如果未能解决你的问题,请参考以下文章

[TypeScript] Using Assertion to Convert Types in TypeScript

VueJS 项目和 TypeScript 中的范围错误

VueJS + Typescript:类型上不存在属性

如何使用 VueJS / Typescript 导入 JSON 文件?

VueJs:服务器端渲染和 Typescript 出错

在没有 webpack 的情况下使用 VueJs 和 Typescript