Vue provide/inject 部分源码分析 实现响应式数据更新
provide/inject 数据响应式更新的坑及源码解析
下面是我自己曾经遇到 一个问题,直接以自己QA的形式来写吧
自问自答了,需要的同学也可以直接访问segmentfault地址
官网给出实例,说本身是不支持数据响应式的, 但是可以传入响应式数据,那么provide,inject就可以实现响应式。
我这里理解应该没错哈,有不对的地方请指出。
我自己写的demo,做了如下更改
parent 页面:
export default {
provide(){
return {foo:this.fonnB}
},
data(){
return {fonnB:'old word'}
}
created() {
setTimeout(()=>{
this.fonnB="new words"; // 这种跟新,仅仅foonB变化了,foo没有变化
this._provided.foo="new words";
//这种更新 foo变化了,但子组件获得的foo 依旧是old words
console.log( this._provided)
},1000)
},
}
child页面:
export default {
inject:['foo'],
data(){
return {chilrfoo:this.foo}
}
}
通过上面2个方法,经过验证,子组件页面都没办法实现响应更新this.foo的值。
求解释,谢谢
以上是我自己的问题, 下面是我基本理解后,在自己回答的问题
现做了如下修改,可以达到父亲组件改变,下面的孙子组件都能更新数据.这样就是传入了一个响应式数据,如果需要双向数据的话,需要在child页面的computed 中手动写set 函数,computed 本身就只相当于一个get函数。
值得注意是:child页面data 数据中childfooOld并不会响应。如果这里childfooOld=this.foo ,obj的形式也是可以响应的,那么a也是响应式数据。
如果是单数据格式不能响应,childfooOld下没有set/get 只是在data下的set/get 是控制data下属性变化时触发的,而不是this.foo.a 触发的;
parent页面:
export default {
provide(){
return {foo:this.fonnB}
},
data(){
return {
fonnB:{a:'old word'}
}
}
created() {
setTimeout(()=>{
this.fonnB.a="new words";
//这种更新 foo变化了,但子组件获得的foo 依旧是old words
},1000)
},
}
child页面:
export default {
inject:['foo'],
data(){
return {
childfooOld:this.foo.a
}
},
computed:{
chilrfoo(){
return this.foo.a
}
}
}
关于prodive 和inject 源码部分如下
export function initInjections (vm: Component) {
const result = resolveInject(vm.$options.inject, vm)
if (result) {
observerState.shouldConvert = false
Object.keys(result).forEach(key => {
defineReactive(vm, key, result[key])
})
observerState.shouldConvert = true
}
}
可以看出 prodive 也运用了defineReactive 函数,增加了自身的set,get函数,也是响应式数据,如下图
如下 是inject 源码,我没看出来那里明确增加了set/get,但是打印出来结果inject 也是有set/get的
export function resolveInject (inject: any, vm: Component): ?Object {
if (inject) {
// inject 是 :any 类型因为流没有智能到能够指出缓存
const result = Object.create(null)
// 获取 inject 选项的 key 数组
const keys = hasSymbol
? Reflect.ownKeys(inject).filter(key => {
/* istanbul ignore next */
return Object.getOwnPropertyDescriptor(inject, key).enumerable
})
: Object.keys(inject)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
const provideKey = inject[key].from
let source = vm
while (source) {
if (source._provided && provideKey in source._provided) {
result[key] = source._provided[provideKey]
break
}
source = source.$parent
}
if (!source) {
if ('default' in inject[key]) {
const provideDefault = inject[key].default
result[key] = typeof provideDefault === 'function'
? provideDefault.call(vm)
: provideDefault
} else if (process.env.NODE_ENV !== 'production') {
warn(`Injection "${key}" not found`, vm)
}
}
}
return result
}
}
通过computed 就实现了上下传值
当然可以直接 通过绑定data属性,但是不能是单数据绑定,一定是地址类传值
Vue provide/inject 部分源码分析 实现响应式数据更新的更多相关文章
- Vue系列---理解Vue.nextTick使用及源码分析(五)
_ 阅读目录 一. 什么是Vue.nextTick()? 二. Vue.nextTick()方法的应用场景有哪些? 2.1 更改数据后,进行节点DOM操作. 2.2 在created生命周期中进行DO ...
- 【Vue源码学习】响应式原理探秘
最近准备开启Vue的源码学习,并且每一个Vue的重要知识点都会记录下来.我们知道Vue的核心理念是数据驱动视图,所有操作都只需要在数据层做处理,不必关心视图层的操作.这里先来学习Vue的响应式原理,V ...
- 读Vue源码二 (响应式对象)
vue在init的时候会执行observer方法,如果value是对象就直接返回,如果对象上没有定义过_ob_这个属性,就 new Observer实例 export function observe ...
- vue源码解析之响应式原理
关于defineReactive等使用细节需要自行了解 一些关键知识点 $mount时 会 new Watcher 把组件的 updateComponent 方法传给watcher 作为getter ...
- Vue.js 源码分析(八) 基础篇 依赖注入 provide/inject组合详解
先来看看官网的介绍: 简单的说,当组件的引入层次过多,我们的子孙组件想要获取祖先组件的资源,那么怎么办呢,总不能一直取父级往上吧,而且这样代码结构容易混乱.这个就是这对选项要干的事情 provide和 ...
- Vue.js 源码分析(九) 基础篇 生命周期详解
先来看看官网的介绍: 主要有八个生命周期,分别是: beforeCreate.created.beforeMount.mounted.beforeupdate.updated .beforeDes ...
- Vue.js 源码分析(三十二) 总结
第一次写博客,坚持了一个多月时间,Vue源码分析基本分析完了,回过头也看也漏了一些地方,比如双向绑定里的观察者模式,也可以说是订阅者模式,也就是Vue里的Dep.Watcher等这些函数的作用,网上搜 ...
- Vue.js 源码分析(三十) 高级应用 函数式组件 详解
函数式组件比较特殊,也非常的灵活,它可以根据传入该组件的内容动态的渲染成任意想要的节点,在一些比较复杂的高级组件里用到,比如Vue-router里的<router-view>组件就是一个函 ...
- Vue.js 源码分析(四) 基础篇 响应式原理 data属性
官网对data属性的介绍如下: 意思就是:data保存着Vue实例里用到的数据,Vue会修改data里的每个属性的访问控制器属性,当访问每个属性时会访问对应的get方法,修改属性时会执行对应的set方 ...
随机推荐
- 特征降维之SVD分解
奇异值分解.特征值分解是一个提取矩阵特征很不错的方法,但是它只是对方阵而言的,在现实的世界中,我们看到的大部分矩阵都不是方阵,比如说有N个学生,每个学生有M科成绩,这样形成的一个N * M的矩阵就不可 ...
- 微信小程序--录制音频,播放音频
1.在pages创建一个main文件夹2.在main文件夹下创建一个miain.js文件.添加代码: const constant = require('../../utils/constant.js ...
- hadoop-2.3.0-cdh5.1.0完全分布式集群配置及HA配置(待)
一.安装前准备: 操作系统:CentOS 6.5 64位操作系统 环境:jdk1.7.0_45以上,本次采用jdk-7u55-linux-x64.tar.gz master01 10.10.2.57 ...
- map-reduce的八个流程
下面讲解这八个流程 Inputformat-->map-->(combine)-->partition-->copy&merge-->sort-->red ...
- 31、NGS 常用分析软件
转载:http://www.zilhua.com/2081.html 参考资料:http://bioinfo.mc.vanderbilt.edu/NGS/software.htm 1. Mapping ...
- 使用Cors后台设置WebAPI接口跨域访问
昨天根据项目组前端开发工程师反映,在浏览器端无法直接使用ajax访问后台接口获取数据,根据他的反映,我查阅了相关跨域的解决方案: 一:使用jsonP,但是jsonP只能使用GET请求,完全不符合我项目 ...
- 图解Laravel的生命周期
先来张图大致理解下laravel的生命周期. 下面对应相应的代码,解释上图. //文件路径:laravel/public/index.php /** * laravel的启动时间 */ define( ...
- cookie 、Session 和自定义分页
cookie cookie的由来 大家都知道Http协议是无状态的. 无状态的意思 是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系, 他不会受前面的请求响应情况直接影响, ...
- JWT使用过程中遇到的问题
1.创建token的盐设置过于简单,出现secret key byte array cannot be null or empty. 异常 解决方法:jwt:config:key:hwy ------ ...
- LeetCode: 453 Minimum Moves to Equal Array Elements(easy)
题目: Given a non-empty integer array of size n, find the minimum number of moves required to make all ...