本篇文章和大家分享 Vue3全家桶开发的比较常见问题,让大家可避坑踩雷,希望能够给大家提供帮助!
最近入门 Vue3 并完成 3 个项目,遇到问题蛮多的,今天就花点时间整理一下,和大家分享 15 个比较常见的问题,基本都贴出对应文档地址,还请多看文档~ 已经完成的 3 个项目基本都是使用 Vue3 (setup-script 模式)全家桶开发,因此主要分几个方面总结:
(学习视频分享:vue视频教程)
文档地址:https://v3.cn.vuejs.org/guide/composition-api-lifecycle-hooks.html
Vue2.x 和 Vue3.x 生命周期方法的变化蛮大的,先看看:
目前 Vue3.x 依然支持 Vue2.x 的生命周期,但不建议混搭使用,前期可以先使用 2.x 的生命周期,后面尽量使用 3.x 的生命周期开发。
由于我使用都是 script-srtup
模式,所以都是直接使用 Vue3.x 的生命周期函数:
// A.vue\ <script setup>\ import { ref, onMounted } from "vue";\ let count = ref<number>(0);\ \ onMounted(() => {\ count.value = 1;\ })\ </script>
每个钩子的执行时机点,也可以看看文档:v3.cn.vuejs.org/guide/insta…
这里主要介绍父组件如何去获取子组件内部定义的变量,关于父子组件通信,可以看文档介绍比较详细:v3.cn.vuejs.org/guide/compo…
我们可以使用全局编译器宏的defineExpose
宏,将子组件中需要暴露给父组件获取的参数,通过 {key: vlaue}
方式作为参数即可,父组件通过模版 ref 方式获取子组件实例,就能获取到对应值:
// 子组件\ <script setup>\ let name = ref("pingan8787")\ defineExpose({ name }); // 显式暴露的数据,父组件才可以获取\ </script>\ \ // 父组件\ <Chlid ref="child"></Chlid>\ <script setup>\ let child = ref(null)\ child.value.name //获取子组件中 name 的值为 pingan8787\ </script>
注意:
import
可以直接使用;definedProps 文档:v3.cn.vuejs.org/api/sfc-scr… 文档:v3.cn.vuejs.org/api/sfc-scr…
前面介绍 script-setup 模式提供的 4 个全局编译器宏,还没有详细介绍,这一节介绍 defineProps
和 withDefaults
。使用 defineProps
宏可以用来定义组件的入参,使用如下:
<script setup>\ let props = defineProps<{\ schema: AttrsValueObject;\ modelValue: any;\ }>();\ </script>
这里只定义props
属性中的 schema
和 modelValue
两个属性的类型, defineProps
的这种声明的不足之处在于,它没有提供设置 props 默认值的方式。
其实我们可以通过 withDefaults 这个宏来实现:
<script setup>\ let props = withDefaults(\ defineProps<{\ schema: AttrsValueObject;\ modelValue: any;\ }>(),\ {\ schema: [],\ modelValue: ''\ }\ );\ </script>
withDefaults 辅助函数提供了对默认值的类型检查,并确保返回的 props 的类型删除了已声明默认值的属性的可选标志。
在 Vue2.x 中我们可以通过 Vue.prototype
添加全局属性 property。但是在 Vue3.x 中需要将 Vue.prototype
替换为 config.globalProperties
配置:
// Vue2.x\ Vue.prototype.$api = axios;\ Vue.prototype.$eventBus = eventBus;\ \ // Vue3.x\ const app = createApp({})\ app.config.globalProperties.$api = axios;\ app.config.globalProperties.$eventBus = eventBus;
使用时需要先通过 vue 提供的 getCurrentInstance
方法获取实例对象:
当我们在使用 v-model
指令的时候,实际上 v-bind
和 v-on
组合的简写,Vue2.x 和 Vue3.x 又存在差异。
Vue2.x
在子组件中,如果要对某一个属性进行双向数据绑定,只要通过 this.$emit('update:myPropName', newValue)
就能更新其 v-model
绑定的值。
script-setup
模式下就不能使用 this.$emit
去派发更新事件,毕竟没有 this
,这时候需要使用前面有介绍到的 defineProps、defineEmits 两个宏来实现:
父组件使用的时候就很简单:
Vue3.x 对于一些开发过程中的异常,做了更友好的提示警告,比如下面这个提示:
这样能够更清楚的告知异常的出处,可以看出大概是 <elinput>这边的问题,但还不够清楚。这时候就可以添加 Vue3.x 提供的<strong>全局异常处理器</strong>,更清晰的<strong>输出错误内容和调用栈信息,代码如下</strong>:</elinput>
这时候就能看到输出内容如下:
一下子就清楚很多。当然,该配置项也可以用来集成错误追踪服务 Sentry 和 Bugsnag。推荐阅读:Vue3 如何实现全局异常处理?
当我们在控制台输出 ref
声明的变量时。
会看到控制台输出了一个 RefImpl
对象:
看起来很不直观。我们都知道,要获取和修改 ref
声明的变量的值,需要通过 .value
来获取,所以你也可以:
这里还有另一种方式,就是在控制台的设置面板中开启 「Enable custom formatters」选项。
image.png
image.png
这时候你会发现,控制台输出的 ref
的格式发生变化了:
更加清晰直观了。
这个方法是我在《Vue.js 设计与实现》中发现的,但在文档也没有找到相关介绍,如果有朋友发现了,欢迎告知~
使用 webpack 的同学应该都知道,在 webpack 中可以通过 require.context
动态导入文件:
在 Vite 中,我们可以使用这两个方法来动态导入文件:
import.meta.glob
该方法匹配到的文件默认是懒加载,通过动态导入实现,构建时会分离独立的 chunk,是异步导入,返回的是 Promise,需要做异步操作,使用方式如下:
import.meta.globEager
该方法是直接导入所有模块,并且是同步导入,返回结果直接通过 for...in
循环就可以操作,使用方式如下:
如果仅仅使用异步导入 Vue3 组件,也可以直接使用 Vue3 defineAsyncComponent API 来加载:
当项目比较复杂的时候,经常需要配置 alias 路径别名来简化一些代码:
在 Vite 中配置也很简单,只需要在 vite.config.ts
的 resolve.alias
中配置即可:
如果使用的是 TypeScript 时,编辑器会提示路径不存在的警告⚠️,这时候可以在 tsconfig.json
中添加 compilerOptions.paths
的配置:
当我们需要使用 scss 配置的主题变量(如 $primary
)、mixin方法(如 @mixin lines
)等时,如:
我们可以将 scss 主题配置文件,配置在 vite.config.ts
的 css.preprocessorOptions.scss.additionalData
中:
如果不想使用 scss 配置文件,也可以直接写成 scss 代码:
由于在 script-setup
模式下,没有 this
可以使用,就不能直接通过 this.$router
或 this.$route
来获取路由参数和跳转路由。当我们需要获取路由参数时,就可以使用 vue-router
提供的 useRoute
方法来获取,使用如下:
如果要做路由跳转,就可以使用 useRouter
方法的返回值去跳转:
当我们解构出 store 的变量后,再修改 store 上该变量的值,视图没有更新:
这时候点击按钮触发 changeName
事件后,视图上的 name
并没有变化。这是因为 store 是个 reactive 对象,当进行解构后,会破坏它的响应性。所以我们不能直接进行解构。这种情况就可以使用 Pinia 提供 storeToRefs
工具方法,使用起来也很简单,只需要将需要解构的对象通过 storeToRefs
方法包裹,其他逻辑不变:
这样再修改其值,变更马上更新视图了。
按照官网给的方案,目前有三种方式修改:
通过 store.属性名
赋值修改单笔数据的状态;
这个方法就是前面一节使用的:
通过 $patch
方法修改多笔数据的状态;
当我们需要同时修改多笔数据的状态时,如果还是按照上面方法,可能要这么写:
上面这么写也没什么问题,但是 Pinia 官网已经说明,使用 $patch
的效率会更高,性能更好,所以在修改多笔数据时,更推荐使用 $patch
,使用方式也很简单:
通过 action
方法修改多笔数据的状态;
也可以在 store 中定义 actions 的一个方法来更新:
使用时:
这三种方式都能更新 Pinia 中 store 的数据状态。
项目新安装的 element-plus 在开发阶段都是正常,没有提示任何警告,但是在打包过程中,控制台输出下面警告内容:
在官方 issues 中查阅很久:github.com/element-plu…
尝试在 vite.config.ts
中配置 charset: false
,结果也是无效:
最后在官方的 issues 中找到处理方法:
默认 elemnt-plus 的组件是英文态:
我们可以通过引入中文语言包,并添加到 ElementPlus 配置中来切换成中文:
这时候就能看到 ElementPlus 里面组件的文本变成中文了。
以上是我最近从入门到实战 Vue3 全家桶的 3 个项目后总结避坑经验,其实很多都是文档中有介绍的,只是刚开始不熟悉。也希望大伙多看看文档咯~
Vue3 script-setup 模式确实越写越香。
本文内容如果有问题,欢迎大家一起评论讨论。