vue3开发的需要注意的一些问题

263 阅读3分钟

1.为什么使用ref定义的数据要有.value

你可能会好奇:为什么我们需要使用带有 .value 的 ref,而不是普通的变量?为了解释这一点,我们需要简单地讨论一下 Vue 的响应式系统是如何工作的。 当你在模板中使用了一个 ref,然后改变了这个 ref 的值时,Vue 会自动检测到这个变化,并且相应地更新 DOM。这是通过一个基于依赖追踪的响应式系统实现的。当一个组件首次渲染时,Vue 会追踪在渲染过程中使用的每一个 ref。然后,当一个 ref 被修改时,它会触发追踪它的组件的一次重新渲染。

在标准的 JavaScript 中,检测普通变量的访问或修改是行不通的。然而,我们可以通过 getter 和 setter 方法来拦截对象属性的 get 和 set 操作。

该 .value 属性给予了 Vue 一个机会来检测 ref 何时被访问或修改。在其内部,Vue 在它的 getter 中执行追踪,在它的 setter 中执行触发。从概念上讲,你可以将 ref 看作是一个像这样的对象: js ``

// 伪代码,不是真正的实现
const myRef = { 
_value: 0,  
get value() {
    track()    
    return this._value 
},  
set value(newValue) {
   this._value = newValue   
   trigger()  
}}

另一个 ref 的好处是,与普通变量不同,你可以将 ref 传递给函数,同时保留对最新值和响应式连接的访问。当将复杂的逻辑重构为可重用的代码时,这将非常有用。

注意,在模板中使用 ref 时,我们不需要附加 .value。为了方便起见,当在模板中使用时,ref 会自动解包。

2.关于v-if和v-show

v-show 不支持在 <template> 元素上使用,也不能和 v-else 搭配使用。
v-if 支持在 <template> 元素上使用

3.当组件中没有根元素,那么从组件冲传过来的值怎么接受

因为可以没有根标签,所以在组件上写属性的时候需要指定给那个元素增加属性 可以利用$attr 如果你的组件有多个根元素,你将需要指定哪个根元素来接收这个 class。你可以通过组件的 $attrs 属性来实现指定:
template

<!-- MyComponent 模板使用 $attrs 时 -->
<p :class="$attrs.class">Hi!</p><span>This is a child component</span>

`<MyComponent class="baz" />`
这将被渲染为:
html
<p class="baz">Hi!</p>
<span>This is a child component</span>   

4.v-if 和 v-for

同时使用 v-if 和 v-for 是不推荐的,因为这样二者的优先级不明显。 当 v-if 和 v-for 同时存在于一个元素上的时候,v-if 会首先被执行。

5.使用一个对象绑定多个 prop​

如果你想要将一个对象的所有属性都当作 props 传入,你可以使用没有参数的 v-bind,即只使用 v-bind 而非 :prop-name。例如,这里有一个 post 对象:

const post = {  id: 1,  title: 'My Journey with Vue'}

以及下面的模板: template

<BlogPost v-bind="post" />

而这实际上等价于: template

<BlogPost :id="post.id" :title="post.title" />

6.关于透传

有几点需要注意: • 和 props 有所不同,透传 attributes 在 JavaScript 中保留了它们原始的大小写,所以像 foo-bar 这样的一个 attribute 需要通过 $attrs['foo-bar'] 来访问。 • 像 @click 这样的一个 v-on 事件监听器将在此对象下被暴露为一个函数 $attrs.onClick。 现在我们要再次使用一下之前小节中的 <MyButton> 组件例子。有时候我们可能为了样式,需要在 <button> 元素外包装一层 <div>


<div class="btn-wrapper">  <button class="btn">click me</button></div>

我们想要所有像 class 和 v-on 监听器这样的透传 attribute 都应用在内部的 <button> 上而不是外层的 <div> 上。我们可以通过设定 inheritAttrs: false 和使用 v-bind="$attrs" 来实现:

<div class="btn-wrapper">  <button class="btn" v-bind="$attrs">click me</button></div>

小提示:没有参数的 v-bind 会将一个对象的所有属性都作为 attribute 应用到目标元素上。

7.停止侦听器​

在 setup() 或 <script setup> 中用同步语句创建的侦听器,会自动绑定到宿主组件实例上,并且会在宿主组件卸载时自动停止。因此,在大多数情况下,你无需关心怎么停止一个侦听器。

一个关键点是,侦听器必须用同步语句创建:如果用异步回调创建一个侦听器,那么它不会绑定到当前组件上,你必须手动停止它,以防内存泄漏。如下方这个例子:


<script setup>
import { watchEffect } from 'vue'

// 它会自动停止
watchEffect(() => {})

// ...这个则不会!
setTimeout(() => {
  watchEffect(() => {})
}, 100)
</script>
要手动停止一个侦听器,请调用 watch 或 watchEffect 返回的函数:

js
const unwatch = watchEffect(() => {})

// ...当该侦听器不再需要时
unwatch()

注意,需要异步创建侦听器的情况很少,请尽可能选择同步创建。如果需要等待一些异步数据,你可以使用条件式的侦听逻辑: