一般来讲vue父组件的数据发生变化会触发父组件渲染,如果父组件传入子组件的props数据发生变化会触发子组件渲染,如果 vue 中 父组件的props和子组件的数据同时发生变化,子组件会渲染2次吗?
如题
在Vue的源码中,当响应式数据发现改变的时候并不会立刻更新页面,而是执行执行queueWatcher函数,而这个函数内部维护着一个队列,而需要执行更新的组件会被推入到这个队列中,如果你在一个事件循环多次向这个队列中push同一个组件,它只会push一次,因为它每次push的时候都会拿你正在push的组件的id去跟队列中的组件的id比较,如果存在就不再push。Vue会把队列通过nextTick来执行,而nextTick也不是立刻执行的,它内部是以Promise,mutationObserver,setImmediate,setTimeout其中一个来执行,优先级就是上面的排列顺序,所以它就变成了一个异步任务。因此子组件只会更新一次。
Vue视图更新源码分析如下:
/***将观察程序推入观察程序队列。*ID重复的作业将被跳过,除非*在刷新队列时推送。*/export function queueWatcher(watcher: Watcher) { // 首先获取当前 watcher 的 id const id = watcher.id // 判断这个 watcher 是否已经存在,因为 Vue 并不是在数据发生变化之后立刻更新视图 // 而是收集起来的,因此在上一次没有更新视图之前,即使数据发生改变也无需再添加,因为 // watcher 更新视图的时候使用的数据依然是最新的数据 if (has[id] != null) { // 已经存在就不再收集 return } if (watcher === Dep.target && watcher.noRecurse) { return } has[id] = true if (!flushing) { // 否则把 watcher 放到一个队列中,在下一次事件循环的时候再一次性更新视图; queue.push(watcher) } else { // if already flushing, splice the watcher based on its id // if already past its id, it will be run next immediately. let i = queue.length - 1 while (i > index && queue[i].id > watcher.id) { i-- } queue.splice(i + 1, 0, watcher) } // queue the flush // 接着就开始执行渲染 if (!waiting) { waiting = true if (__DEV__ && !config.async) { flushSchedulerQueue() return } // 执行渲染,可以看到它调用的就是 nextTick 方法; // flushSchedulerQueue 就是刷新页面的 nextTick(flushSchedulerQueue) }}function flushSchedulerQueue() { currentFlushTimestamp = getNow() flushing = true let watcher, id//刷新前对队列进行排序。//这样可以确保://1。组件从父级更新到子级。(因为父母总是//在子项之前创建)//2。组件的用户观察程序在其渲染观察程序之前运行(因为//用户观察程序是在渲染观察程序之前创建的)//3。如果组件在父组件的观察程序运行期间被破坏,//它的观察者可以被跳过。 queue.sort(sortCompareFn)//不要缓存长度,因为可能会推送更多的观察者//当我们运行现有的观察程序时 for (index = 0; index < queue.length; index++) { watcher = queue[index] if (watcher.before) { watcher.before() } id = watcher.id has[id] = null watcher.run() //在dev-build中,检查并停止循环更新。 if (__DEV__ && has[id] != null) { circular[id] = (circular[id] || 0) + 1 if (circular[id] > MAX_UPDATE_COUNT) { warn( 'You may have an infinite update loop ' + (watcher.user ? `in watcher with expression "${watcher.expression}"` : `in a component render function.`), watcher.vm ) break } } }
在 Vue 中,当父组件的 props 数据发生变化时,子组件会被重新渲染。然而,子组件的数据变化并不会影响父组件的渲染次数。这是因为 Vue 的响应式原理是单向的:父组件通过 props 将数据传递给子组件,子组件内部的数据变化不会反馈给父组件。
如果父组件的 props 数据和子组件的数据同时发生变化,子组件的渲染次数取决于哪个变化先发生。如果父组件的 props 数据先发生变化,子组件会被重新渲染。如果子组件的数据先发生变化,由于 Vue 的懒加载机制,父组件可能不会感知到这个变化,因此不会触发重新渲染。
需要注意的是,如果子组件内部使用了 key 属性,并且 key 属性的值发生了变化,那么 Vue 会认为这是一个全新的子组件,会销毁旧的子组件并创建新的子组件,这样就会触发两次渲染。所以,如果需要让 Vue 感知子组件的数据变化并重新渲染,一种常用的方法是改变子组件的 key 属性值。
本文向大家介绍vue的props实现子组件随父组件一起变化,包括了vue的props实现子组件随父组件一起变化的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了vue的props实现父组件变化子组件一起变化,供大家参考,具体内容如下 类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 绑定动态 Props 到父组件的数据。每当父组件的数据变化时,也会传导给
我对react还比较陌生,我一直在分解一个web应用程序,并用react组件替换部分。我现在正在开发一个组件,其中包含我创建的几个不同组件。 在新组件中,我在componentDidMount函数中进行API调用,并创建子组件。乍一看,一切看起来都很完美,但当我们在其中一个子组件中进行状态更改,然后在父组件中进行更改时,子组件将其状态重置为更改之前的状态。 我知道发生了什么,州政府没有被传递给家长
诉求:react父组件某些值改变后,需要让子组件同步更新,但是这个过程不能让父组件重新渲染 请帮忙罗列下所有可能的方式
本文向大家介绍详解vue父子组件间传值(props),包括了详解vue父子组件间传值(props)的使用技巧和注意事项,需要的朋友参考一下 先定义一个子组件,在组件中注册props 在父组件中,引入子组件,并传入子组件内需要的值 这种方式只能由父向子传递,子组件不能更新父组件内的data 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
我在用vue-cli支架做网页包 我的Vue组件结构/传家宝目前看起来如下: 应用程序 在应用程序级别,我需要一个vuejs组件方法,该方法可以将子组件的所有数据聚合到一个JSON对象中,然后发送到服务器。 有没有办法访问子组件的数据?具体来说,多层深? 如果没有,传递oberservable数据/参数的最佳实践是什么,这样当子组件修改它时,我就可以访问新的值?我试图避免组件之间的硬依赖关系,所以
本文向大家介绍浅谈Vue父子组件和非父子组件传值问题,包括了浅谈Vue父子组件和非父子组件传值问题的使用技巧和注意事项,需要的朋友参考一下 本文介绍了浅谈Vue父子组件和非父子组件传值问题,分享给大家,具体如下: 1.如何创建组件 1.新建一个组件,如:在goods文件夹下新建goodsList.vue 2.在main.js中引入 import goodsList from 'goods/good