vivipure / TIL

Today I learned
0 stars 0 forks source link

Vue 2.7 升级之旅 #53

Open vivipure opened 1 year ago

vivipure commented 1 year ago

前言

公司呆久了,总会有很多项目会被重构,重构的过程和结果都能让人很有收获。最近我又作为主程,开始了一个H5编辑器项目的重构。

重构过程中不仅涉及到UI的更改,还加了很多的新的功能。之前的数据结构也设计的不太合理,导致开发难度还是挺大的。

原技术栈: Vue 2 + VueX

升级后: Vue 2.7 + TS + Pinia

使用Vue 2.7 的原因

不用Vue3 是因为还有很多公用组件是Vue2 的,Vue3 升级成本较大。Vue 2.7 支持 setup 语法,加上 TS,开发体验俱佳。

升级TS 原因

编辑器项目,数据结构较多。各种数据处理和转化,有了TS才能得心应手

Pinia

pinia 代替 Vuex ,一是为了适配 composition api 的写法。二是对 store 进行抽离。Vuex 的设计导致 store 中的数据太过臃肿,且 mutation 确实没多大用。

过程

首先是升级 Vue

npm i vue@2.7.13 
npm i pinia

加上 TS 支持

npm i ts-loader  -D
npm i typescript -D

类型声明文件

// setup 宏支持
/// <reference types="vue/macros-global" />

// vue 组件定义
declare module '*.vue' {
    import type { DefineComponent } from 'vue'
    const component: DefineComponent<{}, {}, any>
    export default component
}

// 扩展window 属性
interface Window {
    LOAD_STATUS: boolean
}
// 环境变量定义
declare var HTTP_ENV: 'prod' | 'test'

本来想把构建工具换成 Vite 的,但是项目依赖的 Module Federation 组件, vite 的插件还是存在一些问题。因此还是使用 webpack 5进行构建。后续会考虑增加对 Vite 的支持

结果

总的来说,Vue 2.7 + TS + Pinia 这一套是真的爽。composition api 还好,主要是 TS, 使用 TS 重写了数据结构之后,各种开发十分方便,类型提示几乎杜绝了以前经常出现的解析和转化bug.

vivipure commented 1 year ago

Pina 的使用

pinia 支持 composition api 的写法,在options api 中 也可以继续使用。

入口文件中引入

import Vue from 'vue'
import { createPinia, PiniaVuePlugin } from 'pinia'

Vue.use(PiniaVuePlugin)

const pinia = createPinia()

new Vue({
    pinia,
    render: h => h(App),
}).$mount('#app')

定义store

定义store 支持 options 方式 也支持 类似setup 返回的形式,推荐 options 方式,类型推导还是挺好用的。

// 定义
export const useBaseStore = defineStore('base', {
    state: () => ({
     count: 0 as number,
     obj: null as Apple | null,
    }),
    getters: {
        doubleCount(state) {
            return state.count * 2
        },

    },
    actions: {
        incrementCount() {
             this.count++
        },      
})

在 getters 中即可以用 this 也可以用 state, 使用 this 时不能使用箭头函数

在 actions 中只能使用 this

使用 store

setup 中引入函数进行调用调用

import { useBaseStore } from '~/store/base'

const baseStore = useBaseStore()

options api 中 需要使用 mapState

import { mapState } from 'pinia'
import { useBaseStore } from '~/store/base'

 computed: {
        ...mapState(useBaseStore, ['count']),
 },

通过函数调用得到的数据为整个store, 可以通过对象方式获取具体数据。直接解构获取数据会丢失响应性,需要使用 storeToRefs方法, 获取具体 ref

import { storeToRefs } from 'pinia'

const count= storeToRefs(store).count Ref<number>

注意点

  1. 定义的不同的 store 之间可以相互调用
  2. 使用store 必须在 pinia 初始化到 Vue 实例中之后。
vivipure commented 1 year ago

Volar 设置

关闭 volar.inlayHints.eventArgumentInInlineHandlers, 这个选项将事件在模板中显示 $event