vue监听器为什么执行两遍
-
Vue监听器执行两遍的原因主要是由于Virtual DOM的工作机制。
Vue中的监听器是通过数据劫持的方式实现的。当数据发生改变时,Vue会通过setter方法来监听数据的变化,并将变化通知给相关的视图进行更新。这个过程主要分为两个阶段:依赖收集和派发更新。
首先,在依赖收集阶段,Vue会先将需要监听的数据与当前组件实例进行关联,也就是将当前组件实例作为观察者,将需要监听的数据作为被观察目标。在Vue中,这个关联是通过初始化Watcher实例来完成的。
在这个过程中,Watcher实例会将自己添加到一个全局的Watcher栈中,同时将当前的被观察目标(即需要监听的数据)添加到Watcher实例的依赖列表中。然后,通过访问被观察目标的getter方法,将Watcher实例添加到被观察目标的依赖收集列表中。
接着,在派发更新阶段,当被观察目标的setter方法被触发时,会将更新通知发送给所有依赖收集列表中的Watcher实例。每个Watcher实例会执行自己的回调函数,即更新视图的操作。
由于Vue的数据响应式机制是基于Object.defineProperty或Proxy来实现的,所以在派发更新阶段,每个Watcher实例执行回调函数时,既会触发具体的更新操作,也会触发被观察目标的getter方法。而在getter方法中,又会访问Watcher实例,导致Watcher实例被再次添加到Watcher栈中。
因此,实际上每个Watcher实例会在派发更新阶段执行两次。第一次是在依赖收集阶段,用于将Watcher实例添加到依赖收集列表中;第二次是在派发更新阶段,用于执行回调函数进行视图更新。这就是为什么Vue监听器会执行两遍的原因。
需要注意的是,并不是所有的监听器都会执行两遍。只有在getter方法中访问了依赖的Watcher实例,才会导致监听器执行两遍。如果getter方法中没有访问依赖的Watcher实例,那么监听器只会执行一次。
2年前 -
在Vue中,当我们使用watch选项来定义一个监听器时,有时会观察到监听器会执行两次的情况。这可能是由于以下几个原因:
-
初始化阶段:在Vue实例化之后,watcher会在初始化阶段被触发一次。这是为了确保在Vue实例初始化完成后,能够立即获得正确的数据状态,并执行相应的逻辑。
-
值的变化:当Vue监听的数据发生变化时,watcher会被触发。在某些情况下,数据的变化可能会导致其他相关数据的变化,或者触发其他计算属性的更新,从而再次触发watcher。
-
异步更新:Vue为了提高性能,对一些异步操作进行了优化。当我们使用Vue提供的异步方法(如nextTick)或者一些异步操作时,watcher也可能会被触发两次。这是由于Vue对于异步操作进行了优化,多次触发watcher可以确保数据的更新及时反应到视图上。
-
监听数组和对象:当我们监听的是一个数组或对象时,它们的内部元素或属性发生变化时,watcher也会被触发。这可能导致watcher被多次执行。
-
深度监听:在Vue中,我们可以使用deep选项来进行深度监听,以便监听嵌套对象或数组的变化。当我们开启了深度监听时,watcher会在初始化阶段和值的变化阶段被触发两次。
虽然watcher会执行两次,但我们不必担心性能问题,因为Vue会智能地跳过没有改变的watcher,以提高性能并避免不必要的重新渲染。同时,我们可以通过合理使用watch选项的immediate和deep属性,以及合理处理异步操作,来避免watcher被重复执行带来的问题。
2年前 -
-
在Vue中,当我们使用Vue实例的监听器时,有时会观察到监听器被执行两次的情况。这种情况往往是由于Vue的响应式系统和数据变化检测机制所引起的。
Vue的响应式系统是通过侦测数据变化来更新相关的视图。当我们通过监听器(例如
watch,computed等)来监听数据变化时,Vue会将监听器添加到数据的依赖关系列表中。当数据发生变化时,Vue会通知相关的监听器进行更新。要理解监听器执行两次的原因,我们需要了解Vue的数据变化检测机制。Vue使用了一个叫做“依赖追踪”的技术来追踪数据和视图之间的关系。Vue会在模板编译时,将所有的数据属性都转换成
getter和setter的形式。当我们访问一个数据属性时,Vue会自动将该数据属性添加到当前的依赖关系列表中。对于监听器来说,每当数据变化时,监听器的回调函数会被执行。但是为了保证数据的一致性,Vue会进行“脏检查”,即检查数据的所有依赖关系是否全部执行过。如果有未执行的依赖关系,Vue会再次执行一次所有的监听器,直到所有的依赖关系都被执行过为止。
让我们举个例子来看看具体的操作流程:
- 创建一个Vue实例,并定义需要监听的数据。
- 添加监听器,例如使用
watch或computed来监听数据变化。 - 当数据发生变化时,Vue会将监听器的回调函数添加到依赖关系列表中。
- 检查依赖关系列表,如果有未执行的依赖关系,执行所有的监听器。
- 执行监听器的回调函数,更新相关的视图。
- 检查依赖关系列表,如果还有未执行的依赖关系,继续执行所有的监听器。
- 重复步骤6,直到所有的依赖关系都执行完毕。
所以,当我们观察到监听器被执行两次时,说明Vue在进行脏检查时发现有未执行的依赖关系,从而再次执行所有的监听器。这种机制保证了数据和视图的一致性,确保所有的依赖关系都被及时更新。
需要注意的是,如果我们使用了多个监听器来监听同一个数据属性,那么这些监听器的执行顺序可能是不确定的。因此,在编写监听器时,我们应该确保其独立性和可靠性,不依赖其他监听器的执行顺序。
2年前