vue2升级vue3踩坑——【依赖注入】可能成功了,但【依赖注入】成功了不太可能

背景

博主最近做一些页面迁移的工作,即将某些页面以子应用的方式嵌入到其他系统的基座应用中(基于micro-app这一微前端方案实现)。

在迁移过程中,和主管聊了聊,觉得这是一个将老项目从vue2升级成vue3的契机,于是便说干就干了。

框架升级最优先的工作,我认为是梳理 ,明确哪些功能或写法是以前过度设计 了,哪些是滥用了等等。

本文主要讲的是我在梳理完一些页面后,发现它们在状态管理方面存在滥用第三方库的现象,导致很多完全没必要依赖vuex的地方,使用了vuex。

(根本就没用上vuex提供的别的功能!!!🤯)

我的解决方案是使用reactive维护store,再将这个类似store的状态变量provide出去,从而替换掉原先vue2版本项目中的通过vuex引入store的写法。

看到这里可能有同学会问了:"那么什么时候推荐使用vuex或者pinia这些状态管理库呢?"
这个话题我们下回再讨论~😊

本篇博客主要想和大家分享,我在使用【依赖注入】时发现的几种方式与其特点(优、劣)

如果选择了错误的方式,则会让页面出现丢失响应式的情况,导致渲染异常

信息对齐

什么是vue的响应式?

什么是丢失响应式?

建立在上一小节内容的基础上,本文中所讨论的"丢失响应式",就是指模板中使用的值发生变化后,Vue并不会检测这个变化,也不会相应地更新DOM,从而导致渲染异常的现象。

使用【依赖注入】的几种方式与其特点

  1. 当一个reactive对象被provide出去之后,如果在子孙组件以下方的方式使用,则会丢失响应式

script setup:

js 复制代码
const compareMessage = inject('compareMessage')
const compareMessageContent =  compareMessage.content
// 👆等同于对一个reactive进行解构赋值的写法
// const { content }  = compareMessage

template:

html 复制代码
 <p>
     <!-- 会丢失响应式 -->
    compareMessage to grand child: <em>{{ compareMessageContent}}</em>
  </p>
  1. 当一个reactive对象被provide出去之后,如果期望它还是响应式的数据,则可以有以下几种方式:
  • 直接在template中使用xxx.yyyy的方式,如:
html 复制代码
 <p>
    compareMessage to grand child: <em>{{ compareMessage.content }}</em>
  </p>
  • 可以使用computed进行包裹,不过不太推荐🙅‍,因为计算属性主要用于描述依赖响应式状态的复杂逻辑

script setup:

js 复制代码
const compareMessage = inject('compareMessage')
const compareMessageContent = computed(() => compareMessage.content) 

template:

html 复制代码
 <p>
      <!-- 不会丢失响应式 -->
    compareMessage to grand child: <em>{{ compareMessageContent}}</em>
  </p>
  • 可以使用toRefs,将其改为响应式,这种解法就更不推荐了×,硬解,和使用computed一样,toRefs最适合用在从组合式函数中返回响应式对象时
js 复制代码
const compareMessage = toRefs(reactive({ content: 'hello2'}))
//...

  <input v-model="compareMessage.content.value">
html 复制代码
<script setup>
const compareMessage = inject('compareMessage')
const {content} = compareMessage

</script>
<template>
<p>compareMessage to grand child: <em>{{ content}}</em></p>
</template>

【依赖注入】的推荐写法

  • 👉 个人认为的最佳实践,在provide一个类似于vuex的store对象时,这样去写
js 复制代码
const content = ref('hello')
provide('compareMessage', { content })

子孙组件:

html 复制代码
<script setup>
const compareMessage = inject('compareMessage')
// 解构赋值
const {content} = compareMessage
// 或者
// const compareMessageContent = compareMessage.content

</script>
<template>
      <!-- 不会丢失响应式 -->
<p>compareMessage to grand child: <em>{{ content}}</em></p>
</template>

结语

我用的最久的技术栈还是React,因此,本文提到的一些使用vue相关特性的方式和给出的解法,都是基于自己目前对于vue的理解。

如果掘友们有更好的想法与解法,欢迎评论区留言~

相关推荐
腾讯TNTWeb前端团队5 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰9 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪9 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪9 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy10 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom10 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom10 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom10 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom11 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom11 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试