Vue provide/inject 部分源码分析 实现响应式数据更新

news/2024/7/10 2:52:01 标签: vue, 源码分析

下面是我自己曾经遇到 一个问题,直接以自己QA的形式来写吧

官网给出实例,说本身是不支持数据响应式的, 但是可以传入响应式数据,那么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并不会响应。这个点还没搞懂。

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</pre>

}

}

可以看出 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 就实现了上下传值,个人疑问就是 
child页面,直接把foo 绑定到data属性下,foo变化时,child中的data不变化。。 按道理,data中有get/set ,应该也是响应的,求大神分享
发现文章中的错误,或者有更好的建议,欢迎评论或进前端全栈群:866109386,来交流讨论吹水。


http://www.niftyadmin.cn/n/1301325.html

相关文章

kafka学习小结(springboot2+kafka组成集群模式1基础知识)

有幸公司已有搭建好的kafka服务器&#xff0c;这里和大家边学边看 springboot2 kafka基础&#xff1a;摘录的别人介绍 Replication & Leader election&#xff08;涉及到zookeeper核心问题&#xff0c;不是很明白&#xff09; Kafka通过Zookeeper管理集群配置&#xff0c…

function 与 = 的区别

文章转载自&#xff1a;https://www.cnblogs.com/hammerc/p/7390424.html 在JS中&#xff0c;箭头函数并不是简单的function(){}匿名函数的简写语法糖&#xff0c;实际上&#xff0c;箭头函数和匿名函数有个明显的区别&#xff1a;箭头函数内部的this是词法作用域&#xff0c;…

kafka学习小结(springboot2+kafka组成集群模式2基础实战)

搭建简单的springboot2项目 1.maven添 <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> </dependency> pom.xml配置添加 kafka:bootstrap-servers: 服务地址consumer:group-id: g…

单页面vue引入百度统计的使用方法

最近组长安排着做一个项目&#xff0c;h5的应用下载项目&#xff0c;想着做起来还是比较容易&#xff0c;可是看到提出的需求&#xff0c;我就有点懵逼了&#xff01;需要对应用的下载进行统计&#xff01;&#xff01;&#xff01;我当时就想着我前端怎么对页面点击按钮就行数…

Beyond Compare代码对比工具

一个程序员的工作不仅仅是写代码&#xff0c;还有代码的检查、比较、版本日志等等。 所以一个聪明的程序员会利用各种工具来简化这些工作。 比如&#xff1a; 代码的检查&#xff1a;我们会用一些ide&#xff08;如写ios用xcode&#xff0c;写c用vs&#xff0c;写android用a…

kafka学习小结(springboot2+kafka组成集群模式3同步异步模式)

接着上一篇补充 官网上关于这一块迷迷糊糊的看不懂&#xff0c;自己总结了下其中的差异&#xff1a; 我们一般没做特殊处理的就是同步模式&#xff0c;生产者发送消息&#xff0c;然后交给消费者&#xff0c;这里面我们也可以对消息的结果进行处理&#xff0c;防止消息丢失 k…

初识 vue —— 最简单的前后端交互示例

一、学习 vue 面临的问题 最近想学一门前端技术防身&#xff0c;看到博客园中写 vue 的多&#xff0c;那就 vue 吧。都说 vue 的官方教程写得好&#xff0c;所以我就从官方教程开始学习。官方教程说“Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进…

微信小游戏的电量监听

在说小游戏的电量监听事件之前&#xff0c;我想先提一下小程序的电量监听事件。 在微信小程序中&#xff0c;是没有电量监听事件的&#xff0c;因为小程序没有全屏&#xff0c;手机端的电量和wifi等信息一直可以看得到&#xff0c;所以小程序里就没有这样的api了。 说回小游戏…