We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
记得第一次用vue开发项目时,曾经遇到过父组件调接口改变data里面的某个属性值并通过props传递给子组件,但是子组件并没有实时刷新的问题,当时试了下用watch监听,就解决了。当时初学,vue不怎么懂,更别说源码了,最近项目中又出现过一次这种情况,这就很奇怪了,我必须要解决这个问题。
data
props
watch
示例:https://blog.csdn.net/d295968572/article/details/80810349 PS:这是网上其他人的问题,大致与我一样。
根据我提出的问题,可以意识到,这种情况props传过来没有及时更新,但是watch监听却能获取到数据,那么watch与props之间有什么区别呢?官方文档也说父组件动态改变props值,子组件是能获取到的,但是我这里为何不行呢?
根据上面问题,我先去查看关于props以及watch的源码,其实以前有阅读过watch源码,知道它最终会走defineReactive方法进行观察。但令我没想到的是,props最终也走这个方法。。。
defineReactive
关于这两个初始化,可以去state.js里面找initProps和initWatch方法。
initProps
initWatch
再回顾一下initWatch方法,它内部调用了createWatcher方法(PS:computed初始化也走这个方法了),盖凡凡最终返回vm.$watch(expOrFn, handler, options),而$watch就在下面stateMixin方法内,stateMixin在 instance/index.js 中执行。$watch里面执行了const watcher = new Watcher(vm, expOrFn, cb, options)这段代码,其实就是实例化了一个Watcher,
createWatcher
vm.$watch(expOrFn, handler, options)
$watch
stateMixin
const watcher = new Watcher(vm, expOrFn, cb, options)
Watcher
然后Watcher里面调用get方法,get方法中调用pushTarget,pushTarget在dep.js里,对Dep.target赋值,接着继续看Watcher里面的get方法,这里直接value = this.getter.call(vm, vm),最后return value了。这里就很奇怪,这样看下来根本没有涉及到依赖监听机制啊,按道理不对啊。
get
pushTarget
Dep.target
value = this.getter.call(vm, vm)
return value
而且,我们只会对props以及在data里面初始化(或者通过this.$set设置)的属性进行watch,但是这里并没有判断被watch的属性是否存在this实例上,也没有判断被watch的属性是不是observe的,难不成我随便瞎写一个属性进行watch也行?
看示例:
如上图,即使被watch的属性并不存在,watch也能执行,只是undefined罢了!
这只是其中的一个小插曲,回到问题上来。
那么,如何实现依赖监听的呢?由于有之前阅读源码的基础,我记得最终watch也是要执行defineReactive的,他在哪里执行的呢?
答案是initData和initProps里面,其中initData里面铁定调用observe进行观察,Observer中又会生成新的Dep实例,并通过walk方法执行defineReactive。
initData
observe
Observer
Dep
walk
defineReactive里面又生成新的Dep实例,到了这个方法大家没差别,说明props传递进来的值改变也会通知其他依赖的,那么为何watch和computed能拿到异步调用接口的数据而props不行呢?
computed
他们间的区别在哪呢?我觉得应该是Watcher区别,watch和computed都实例化了Watcher,但是props没有,网上都说可能接口获取到数值时,组件mounted以经执行完了,所以子组件获取不到。咋一听有点道理,这句话说得其实是对的。
mounted
我觉得可能分两种情况(都跟异步获取数据有关): 1.子组件在mounted里面拿到props传值并赋值改变,如果父组件通过接口获取,但是拿到数据时子组件mounted已经执行完了,这时候不会再走mounted进行赋值了,所以发现页面是没变化,这是一个时机问题 2.不在mounted里面赋值,但是,编辑进入时,从媒体那边拿到数据的接口有时候非常慢,那么一进入页面第一视觉可能展示的是默认页面,这时候会误认为有问题,但是当接口获取到数据后页面变为正常,所以这里最好做一个loading效果以免错认为bug
但是watch和props的区别在哪里呢?(也可以认为是computed和data区别) watch和data以及props最大的区别应该是当数据响应式改变时,watch能拿到新旧值,只要发生变化就会触发并拿到新旧值,而data和props只能被动接受值改变,当需要值改变时触发其他方法时,computed以及watch更合适。 例如最近做的易直投,腾讯这条线计划分为:普通计划、微信朋友圈和微信公众号计划,微信朋友圈和普通计划进入单元页对应的区域定向数据源也不一样,都需要通过接口拿到,而编辑进入单元时,首先需要调接口获取计划类型,然后在根据计划类型去获取数据源,这时候我只能通过computed或者watch监听去判断该调哪个接口获取数据。这里就需要watch的回调了。
具体可以看相关源码:
其实源码里面注释也说了,当被watch的值改变时,会提供回调。。。。。。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
问题来源
记得第一次用vue开发项目时,曾经遇到过父组件调接口改变
data
里面的某个属性值并通过props
传递给子组件,但是子组件并没有实时刷新的问题,当时试了下用watch
监听,就解决了。当时初学,vue不怎么懂,更别说源码了,最近项目中又出现过一次这种情况,这就很奇怪了,我必须要解决这个问题。示例:https://blog.csdn.net/d295968572/article/details/80810349 PS:这是网上其他人的问题,大致与我一样。
思考及查看源码
根据我提出的问题,可以意识到,这种情况
props
传过来没有及时更新,但是watch
监听却能获取到数据,那么watch
与props
之间有什么区别呢?官方文档也说父组件动态改变props
值,子组件是能获取到的,但是我这里为何不行呢?根据上面问题,我先去查看关于
props
以及watch
的源码,其实以前有阅读过watch
源码,知道它最终会走defineReactive
方法进行观察。但令我没想到的是,props
最终也走这个方法。。。关于这两个初始化,可以去state.js里面找
initProps
和initWatch
方法。再回顾一下
initWatch
方法,它内部调用了createWatcher
方法(PS:computed初始化也走这个方法了),盖凡凡最终返回vm.$watch(expOrFn, handler, options)
,而$watch
就在下面stateMixin
方法内,stateMixin
在 instance/index.js 中执行。$watch
里面执行了const watcher = new Watcher(vm, expOrFn, cb, options)
这段代码,其实就是实例化了一个Watcher
,然后
Watcher
里面调用get
方法,get
方法中调用pushTarget
,pushTarget
在dep.js里,对Dep.target
赋值,接着继续看Watcher
里面的get
方法,这里直接value = this.getter.call(vm, vm)
,最后return value
了。这里就很奇怪,这样看下来根本没有涉及到依赖监听机制啊,按道理不对啊。而且,我们只会对props以及在data里面初始化(或者通过this.$set设置)的属性进行watch,但是这里并没有判断被watch的属性是否存在this实例上,也没有判断被watch的属性是不是observe的,难不成我随便瞎写一个属性进行watch也行?
看示例:
如上图,即使被watch的属性并不存在,watch也能执行,只是undefined罢了!
这只是其中的一个小插曲,回到问题上来。
那么,如何实现依赖监听的呢?由于有之前阅读源码的基础,我记得最终watch也是要执行
defineReactive
的,他在哪里执行的呢?答案是
initData
和initProps
里面,其中initData
里面铁定调用observe
进行观察,Observer
中又会生成新的Dep
实例,并通过walk
方法执行defineReactive
。defineReactive
里面又生成新的Dep
实例,到了这个方法大家没差别,说明props
传递进来的值改变也会通知其他依赖的,那么为何watch
和computed
能拿到异步调用接口的数据而props
不行呢?他们间的区别在哪呢?我觉得应该是
Watcher
区别,watch
和computed
都实例化了Watcher
,但是props
没有,网上都说可能接口获取到数值时,组件mounted
以经执行完了,所以子组件获取不到。咋一听有点道理,这句话说得其实是对的。我觉得可能分两种情况(都跟异步获取数据有关):
1.子组件在mounted里面拿到props传值并赋值改变,如果父组件通过接口获取,但是拿到数据时子组件mounted已经执行完了,这时候不会再走mounted进行赋值了,所以发现页面是没变化,这是一个时机问题
2.不在mounted里面赋值,但是,编辑进入时,从媒体那边拿到数据的接口有时候非常慢,那么一进入页面第一视觉可能展示的是默认页面,这时候会误认为有问题,但是当接口获取到数据后页面变为正常,所以这里最好做一个loading效果以免错认为bug
但是watch和props的区别在哪里呢?(也可以认为是computed和data区别)
watch和data以及props最大的区别应该是当数据响应式改变时,watch能拿到新旧值,只要发生变化就会触发并拿到新旧值,而data和props只能被动接受值改变,当需要值改变时触发其他方法时,computed以及watch更合适。
例如最近做的易直投,腾讯这条线计划分为:普通计划、微信朋友圈和微信公众号计划,微信朋友圈和普通计划进入单元页对应的区域定向数据源也不一样,都需要通过接口拿到,而编辑进入单元时,首先需要调接口获取计划类型,然后在根据计划类型去获取数据源,这时候我只能通过computed或者watch监听去判断该调哪个接口获取数据。这里就需要
watch
的回调了。具体可以看相关源码:
其实源码里面注释也说了,当被watch的值改变时,会提供回调。。。。。。
The text was updated successfully, but these errors were encountered: