介绍

我负责 Vue3 x Pinia x TypeScript 项目。
写单个组件文件的方法介绍composition api已经有一段时间了,所以很容易写很多信息。

我很难过,因为日语中几乎没有对使用 Pinia 有帮助的信息。
这次记录一下使用Pania时类型定义的方法。希望对以后介绍Pinia的人有所帮助。

我也发过一篇文章总结了单个组件的打法,请参考
https://qiita.com/manzoku_bukuro/items/a2dd20e787617b033592

商店符号

在输入之前,请检查 Pinia Store 文件描述方法。至于 Pinia 的 Store 文件的描述方法,类似 API 的写作风格什么时候如何编写类似 Options API有。

组合API样式描述方法

描述如下。

商店/柜台.ts
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', () => {
    const count = ref(0);

    const doubleCount = computed(() => count.value * 2);

    function increment() {
        count.value++;
    }

    return { count, doubleCount, increment };
})
  • 状态是使用 Composition API ref,reactive 定义的
  • 使用计算定义的吸气剂
  • 使用函数定义操作
  • 返回已定义状态、getter 和操作的内容,最后以 return

符号特征如下。您不必描述状态、getter 和操作等属性,因此您可以用简洁的方式编写它。
但是,在我看来,它太干净了,很难区分状态、getter 和 action……(尤其是 getter 和 action)
并且为了使用使用DefineStoreOptions的类型定义方式,后面会讲到,我参与的项目写了一个Options API风格。

选项 API 样式说明

商店/柜台.ts
import { defineStore } from 'pinia';

export const useCounterStore = defineStore({
    id: 'counter',
    state: () => ({
        counter: 1,
    }),
    getters: {
        doubleCount: (state) => return state.counter * 2;
    },
    actions: {
        const increment = () => {
            count.value++;
        };
    },
})

我将上面的源代码重写为 Options API 样式。除了定义id的部分,写法和Vuex是一样的,所以我想很多人会觉得这个比较容易理解。松树官方文件即使你看,我也觉得基础知识是在 Options API 风格中描述的。
从现在开始,我们将使用 Options API 样式描述方法来描述类型定义的方法。

如何在 Pinia 中定义类型

在 Store 中定义类型有几种方法,所以我将描述我所知道的方法。
我们将在 store 目录下键入未在下面定义类型的文件。

初始存储文件

商店/example.ts
import { defineStore } from "pinia";

export const useExampleStore = defineStore({
    id: 'example',
    state: () => ({
        name: '田中太郎',
        sales: 0,
		menus: ['ホーム', '一覧'],
        book: { title: '人間失格', price: 1070 },
    }),
    getters: {
		introduction: (state) => {
			return `私の名前は${state.name}です。`;
		},
		bookPrice: (state) => {
			return state.book.price * 1.08;
		},
	},
	actions: {
		changeName(name) {
			this.name = name;
		},
		buyBook(count) {
			this.sales = this.bookPrice * count;
			return `現在の売上は${this.sales}です。`
		}
	},
})

模式 1. 一个一个地定义状态变量

使用类型断言as

此模式是在 State 中的每个变量之后使用 as 定义的。

import { defineStore } from "pinia";

export interface Book {
    title: string;
    price: number;
}
export const useExampleStore = defineStore({
    id: 'example',
	state: () => ({
		name: '田中太郎' as string,
		sales: 0 as number,
		menus: ['ホーム', '一覧'] as string[],
		book: { title: '人間失格', price: 1070 } as Book,
	}),
...
})

模式2. 统一定义State变量的类型

as定义State属性变量定义的对象

一种包装和键入 state 属性的方法,而不是在每个变量之后键入。

state: () => ({
    name: '田中太郎',
    sales: 0,
    menus: ['ホーム', '一覧'],
    book: { title: '人間失格', price: 1070 },
} as {
    name: string,
    sales: number,
    menus: string[],
    book: Book,
}),

这很好,但我认为如果将 state 中定义的类型包装在接口中会更容易理解。

...
export interface exampleState {
	name: string;
	sales: number;
	menus: string[];
	book: Book;
}
export const useExampleStore = defineStore({
	id: 'example',
    state: () => ({
        name: '田中太郎',
        sales: 0,
        menus: ['ホーム', '一覧'],
        book: { title: '人間失格', price: 1070 },
    } as exampleState),
)}

在 State 中传递() 后面键入的对象

它是一种在状态后面传递类型定义对象的方法,如下所示。在以下情况下,对象被包装在接口中并传递。

export interface exampleState {
	name: string;
	sales: number;
	menus: string[];
	book: Book;
}
export const useExampleStore = defineStore({
	id: 'example',
    state: (): exampleState => ({
        name: '田中太郎',
        sales: 0,
        menus: ['ホーム', '一覧'],
        book: { title: '人間失格', price: 1070 },
    }),
)}

(重要!!)模式 3. 使用 DefineStoreOptions 类型定义 State、Getters 和 Actions

也许本文中最有用的信息是如何定义类型。
定义存储()可选参数使用功能。您可以通过在defineStore 的头部传递Id、State、GTters、Actions 的类型定义参数来省略defineStore() 中的类型定义。
即使你在网上搜索,也很少有使用DefineStoreOptions定义类型的信息,Pinia 官方文档被翻译成日文并作为参考实施。下面是源码。

import { defineStore, type _GettersTree } from "pinia";

export interface Book {
	title: string;
	price: number;
}
export interface exampleState {
	name: string;
	sales: number;
	menus: string[];
	book: Book;
}

export interface exampleGetters extends _GettersTree<exampleState> {
	introduction: (state: exampleState) => string;
	bookPrice: (state: exampleState) => number;
}
export interface exampleActions {
	changeName: (name: string) => void;
	buyBook: (count: number) => string;
}

export const useSampleStore = defineStore<string, exampleState, exampleGetters, exampleActions>({
    id: 'example',
	state: () => ({
		name: '田中太郎',
		sales: 0,
		menus: ['ホーム', '一覧'],
		book: { title: '人間失格', price: 1070 },
	}),
	getters: {
		introduction: (state) => {
			return `私の名前は${state.name}です。`;
		},
		bookPrice: (state) => {
			return state.book.price * 1.08;
		},
	},
	actions: {
		changeName(name) {
			this.name = name;
		},
		buyBook(count) {
			this.sales = this.bookPrice * count;
			return `現在の売上は${this.sales}です。`
		}
	},
})

defineStore<Id, S, G, A> 的形式传递类型

ExampleState、exampleGetters 和 exampleActions 都用接口定义,并在 defineStore 的头部传递,如defineStore<string(idの型), exampleState(stateの型), exampleGetters(gettersの型), exampleActions(actionsの型)>。这样就不需要在defineStore里面描述类型定义了,源代码也变得更干净了。

使用_GettersTree

当我定义exampleGetters(gettersの型) 时,我最初写道:

export interface exampleGetters {
	introduction: (state: exampleState) => string
	bookPrice: (state: exampleState) => number
}

但是,以下错误消息按原样显示。
Piniaの型定義
嗯,getters 属性参数状态的输入方式似乎有问题。

状态在 getter 中定义的属性的参数中定义。这个状态也是需要打字的,但是需要使用稍微特殊的描述方式。

export interface exampleGetters extends _GettersTree<exampleState> {
	introduction: (state: exampleState) => string;
	bookPrice: (state: exampleState) => number;
}

如上图,需要继承_GettersTree<Stateの型>形式定义的State类型。错误现在消失了。

为未使用的属性传递空对象

如果您想在未定义 getter 或操作时使用 DefineStoreOptions,只需将一个空对象作为您不想使用的属性的参数传递。

export const useSampleStore = defineStore<string, {}, {}, {}>({
    id: 'example',
	state: () => ({}),
	getters: {},
	actions: {},
})

综上所述

在主项目中实际使用的 Pinia 的类型定义方法是使用 Pattern 3 DefineStoreOptions 的方法。不需要在里面写杂乱无章的类型化描述,源代码也变得很容易理解是在做什么样的处理。
但是,如果只有一个变量来定义 State,或者如果您正在处理一个既没有定义 Getters 也没有定义 Actions 的 Store 文件,使用 DefineStoreOptions 将使无用的部分突出,因此您可以使用 Pattern 1 或 Pattern 定义类型2. 做了。

请随时根据需要使用它。

推特我也在做


原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308633157.html

相关文章: