记录--开始使用Vue 3时应避免的10个错误
Posted 林恒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录--开始使用Vue 3时应避免的10个错误相关的知识,希望对你有一定的参考价值。
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
Vue 3 稳定已经有一段时间了。许多代码库正在生产中使用它,其他人最终也必须进行迁移。我有机会与它一起工作,并记录了我的错误,这可能是你想避免的。
1.使用响应式助手声明基本类型
数据声明曾经很简单,但现在有多个辅助工具可用。现在的一般规则是:
- 使用
reactive
代替Object
,Array
,Map
,Set
- 使用
ref
代替String
,Number
,Boolean
对于原始值使用响应式会导致警告,并且该值不会被设置为响应式:
/* DOES NOT WORK AS EXPECTED */ <script setup> import reactive from "vue"; const count = reactive(0); </script>
[Vue warn]: value cannot be made reactive
事例:codesandbox.io/s/jolly-ish…
矛盾的是,反过来却行得通!例如,使用 ref
声明 Array 将在内部调用 reactive
。
2.解构失去响应式值
让我们想象一下,有一个具有计数器和一个按钮以增加计数器的响应式对象。
<template> Counter: state.count <button @click="add">Increase</button> </template> <script> import reactive from "vue"; export default setup() const state = reactive( count: 0 ); function add() state.count++; return state, add, ; , ; </script>
/* DOES NOT WORK AS EXPECTED */ <template> <div>Counter: count </div> <button @click="add">Increase</button> </template> <script> import reactive from "vue"; export default setup() const state = reactive( count: 0 ); function add() state.count++; return ...state, add, ; , ; </script>
地址:codesandbox.io/s/gracious-…
代码看起来一样,根据我们以前的经验,应该可以运行,但实际上,Vue 的反应性跟踪是基于属性访问的。这意味着我们不能赋值或解构一个响应性对象,因为与第一个引用的响应性连接会丢失。这是使用 reactive helper 的限制之一。
3.对".value"属性感到困惑
使用 ref
的怪癖之一可能很难适应。Ref
接受一个值并返回一个响应式对象。该值在对象内部在 .value
属性下可用。
const count = ref(0) console.log(count) // value: 0 console.log(count.value) // 0 count.value++ console.log(count.value) // 1
.value
不需要。<script setup> import ref from \'vue\' const count = ref(0) function increment() count.value++ </script> <template> <button @click="increment"> count // no .value needed </button> </template>
[object Object]
。// DON\'T DO THIS <script setup> import ref from \'vue\' const object = foo: ref(1) </script> <template> object.foo + 1 // [object Object] </template>
正确使用 ".value" 需要时间。尽管我偶尔会忘记它,但我发现我自己最初比需要的时候用得更频繁。
4. Emitted Events
自 Vue 初始版本以来,子组件可以使用 emits
与父组件通信。只需要添加一个自定义监听器来监听事件即可。
this.$emit(\'my-event\') <my-component @my-event="doSomething" />
defineEmits
宏来声明emit
s。<script setup> const emit = defineEmits([\'my-event\']) emit(\'my-event\') </script>
defineEmits
还是 defineProps
(用于声明props),都不需要导入。当使用 script setup
. 时,它们会自动可用。<script setup> const props = defineProps( foo: String ) const emit = defineEmits([\'change\', \'delete\']) // setup code </script>
5.声明额外选项
有一些 Options API 方法的属性在 script setup
中不受支持。
- name
- inheritAttrs
- 插件或库需要的自定义选项
解决方案是在同一组件中定义两个不同的脚本,如脚本设置RFC中所定义的那样:
<script> export default name: \'CustomName\', inheritAttrs: false, customOptions: </script> <script setup> // script setup logic </script>
6.使用 Reactivity Transform
响应性转换是 Vue 3 的一项实验性但有争议的特性,其目标是简化声明组件的方式。这个想法是利用编译时转换来自动解包 ref
并使 .value
变得过时。但现在已经被取消,并将在 Vue 3.3 中被移除。它仍然会以一个包的形式存在,但由于它不是 Vue 核心的一部分,所以最好不要在它上面投入时间。
7. 定义异步组件
异步组件以前是通过将它们包含在一个函数中来声明的。
const asyncModal = () => import(\'./Modal.vue\')
defineAsyncComponent
辅助函数进行显式定义:import defineAsyncComponent from \'vue\' const asyncModal = defineAsyncComponent(() => import(\'./Modal.vue\'))
8. 在模板中使用不必要的包装器
在Vue 2中,组件模板需要一个单一的根元素,这有时会引入不必要的包装器:
<!-- Layout.vue --> <template> <div> <header>...</header> <main>...</main> <footer>...</footer> </div> </template>
Vue路由跳转问题记录
最近项目上需要用Vue用来做app,在Vue中使用路由时遇到下面的问题。
路由设置如下:
{
path:\'/tab\',
component:Tab,
children:[{
path:\'layoutList\',
name:\'LayoutList\',
component:LayoutList
},{
path:\'layoutView/:layoutId\',
name:\'LayoutView\',
component:LayoutView
},{
path:\'layoutDetail/:viewId\',
name:\'LayoutDetail\',
component:LayoutDetail
}]
}
其中/tab是根地址,有3个子地址,3个子地址层级为:LayoutList => LayoutView => LayoutDetail
正常情况:假设当前路由为/tab/layoutList,需要跳转到LayoutView页面,可以通过router.push({path:\'layoutView/\'+item.id})
跳转后的路由为/tab/layoutView/1
当我想从LayoutView页面跳转到对应的LayoutDetail页面时:
情况一:(找不到页面)
跳转前地址:/tab/layoutView/1
跳转代码:router.push({path:\'layoutDetail/\'+item.id});
跳转后地址:/tab/layoutView/layoutDetail/27
情况二:(找不到页面)
跳转前地址:/tab/layoutView/1
跳转代码:router.push({path:\'/layoutDetail/\'+item.id});
跳转后地址:/layoutDetail/27
情况三:(找不到页面)
跳转前地址:/tab/layoutView/1
跳转代码:router.push({path:\'tab/layoutDetail/\'+item.id});
跳转后地址:/tab/layoutView/tab/layoutDetail/27
情况四:(页面正常显示)
跳转前地址:/tab/layoutView/1
跳转代码:router.push({path:\'/tab/layoutDetail/\'+item.id});
跳转后地址:/tab/layoutDetail/27
只有按照情况四的操作,才能正常显示出来页面。
vue路由会根据push的地址,如果地址不是/开头,会直接替换当前路由的最后一个/后的地址,
如果地址是/开头,会以push的地址作为绝对地址进行跳转。
另外我尝试还使用router.go({name:\'LayoutDetail\',params:{viewId:item.id}}),页面不会跳转且地址也不会改变。
如果文章有错误的地方或者有更好的方法,欢迎各位指出,谢谢!
以上是关于记录--开始使用Vue 3时应避免的10个错误的主要内容,如果未能解决你的问题,请参考以下文章