Vue.js中provide/inject实现响应式数据更新的方法示例


Posted in Javascript onOctober 16, 2019

vue.js官方文档:https://cn.vuejs.org/v2/api/#provide-inject

首先假设我们在祖辈时候传入进来是个动态的数据,官方不是说如果你传入了一个可监听的对象,那么其对象还是可响应的么?

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 } 
 },
 created() {
  setTimeout(()=>{
   // 子组件获得的foo 依旧是old words
   console.log( this.foo)
  },2000)
 }
}

结果:

通过上面方式,经过验证,子组件页面都没办法实现响应更新this.foo的值。可能我们对官方理解还是有误,下面通过网上资料和自己构思实现了响应式数据更新

示例(结果仍不可行)

很明显上面再父组件定时器内我们是改变了数据源,这个时候我们就在想,我们改变的数据到底有没有传入到子孙组件中,那么要验证这个问题,我们不妨可以在子孙组件中手动写set 函数,computed 本身就只相当于一个get函数,当然,你也可以试试watch

parent父页面:

export default {
provide() {
   return  { foo: this.fonnB }
  },
  data(){
   return {
    fonnB: 'old word'
   } 
  }
   created() {
   setTimeout(()=>{
    this.fonnB = "new words";  
    // 这里foo变化了,但子组件获得的foo 依旧是old words
   },1000)

  },

 }

child子页面:

export default {
  inject:['foo'],
  data(){
   return {
    childfooOld: this.foo
   } 
  },
  computed:{
    chilrdfoo() {
      return this.foo
    }
  },
 created () {
    console.log(this.foo)
    // -> 'old word'
    setTimeout(() => {
      console.log(this.chilrdfoo); // 这里计算属性依旧是old words
    }, 2000);
   }
 }

通过computed,我们都知道data中有get/set,数据也是响应式的,但为什么没更新,有点疑惑,如果有大佬知道能解释清楚的可以探讨。

但是,但是,但是!实际需求肯定没有这么简单,往往我们需要的是共享父组件里面的动态数据,这些数据可能来自于data 或者 store。 就是说父组件里面的数据发生变化之后,需要同步到子孙组件里面。这时候该怎么做呢?
我想的是将一个函数赋值给provide的一个值,这个函数返回父组件的动态数据,然后在子孙组件里面调用这个函数。
实际上这个函数存储了父组件实例的引用,所以每次子组件都能获取到最新的数据。代码长下面的样子:

Parent组件:

<template>
  <div class="parent-container">
   Parent组件
   <br/>
   <button type="button" @click="changeName">改变name</button>
   <br/>
   Parent组件中 name的值: {{name}}
   <Child v-bind="{name: 'k3vvvv'}" />
  </div>
</template>

<style scoped>
 .parent-container {
  padding: 30px;
  border: 1px solid burlywood;
 }
</style>

<script>
import Child from './Child'
export default {
 name: 'Parent',
 data () {
  return {
   name: 'Kevin'
  }
 },
 methods: {
  changeName (val) {
   this.name = 'Kev'
  }
 },
 provide: function () {
  return {
   nameFromParent: this.name,
   getReaciveNameFromParent: () => this.name
  }
 },
 // provide: {
 // nameFromParent: this.name,
 // getReaciveNameFromParent: () => this.name
 // },
 components: {
  Child
 }
}
</script>

Child组件

<template>
 <div class="child-container">
  Child组件
  <br/>
  <GrandSon />
 </div>
</template>
<style scoped>
 .child-container {
  padding: 30px;
  border: 1px solid burlywood;
 }
</style>
<script>
import GrandSon from './GrandSon'
export default {
 components: {
  GrandSon
 }
}
</script>

GrandSon组件:

<template>
 <div class="grandson-container">
  Grandson组件
  <br/>
  {{nameFromParent}}
  <br/>
  {{reactiveNameFromParent}}
 </div>
</template>
<style scoped>
 .grandson-container {
  padding: 30px;
  border: 1px solid burlywood;
 }
</style>
<script>
export default {
 inject: ['nameFromParent', 'getReaciveNameFromParent'],
 computed: {
  reactiveNameFromParent () {
   return this.getReaciveNameFromParent()
  }
 },
 watch: {
  'reactiveNameFromParent': function (val) {
   console.log('来自Parent组件的name值发生了变化', val)
  }
 },
 mounted () {
  console.log(this.nameFromParent, 'nameFromParent')
 }
}
</script>

结果:

来自于reactiveNameFromParent ,随着祖先组件变化而变化了

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js最简单的拖拽效果实现代码
Sep 24 Javascript
jQuery .tmpl(), .template()学习资料小结
Jul 18 Javascript
js实现照片墙功能实例
Feb 05 Javascript
JavaScript判断是否为数字的4种方法及效率比较
Apr 01 Javascript
实例讲解javascript注册事件处理函数
Jan 09 Javascript
jQuery模拟360浏览器切屏效果幻灯片(附demo源码下载)
Jan 29 Javascript
深入浅析JavaScript中的Function类型
Jul 09 Javascript
JS匿名函数类生成方式实例分析
Nov 26 Javascript
vue实现导航栏效果(选中状态刷新不消失)
Dec 13 Javascript
使用原生js编写一个简单的框选功能方法
May 13 Javascript
Vue简单实现原理详解
May 07 Javascript
JavaScript冒泡算法原理与实现方法深入理解
Jun 04 Javascript
javascript实现点亮灯泡特效示例
Oct 15 #Javascript
vue-cli 为项目设置别名的方法
Oct 15 #Javascript
Vue 实现输入框新增搜索历史记录功能
Oct 15 #Javascript
Centos7 安装Node.js10以上版本的方法步骤
Oct 15 #Javascript
微信小程序如何实现五星评价功能
Oct 15 #Javascript
node.js express框架实现文件上传与下载功能实例详解
Oct 15 #Javascript
ES6 Promise对象概念及用法实例详解
Oct 15 #Javascript
You might like
模仿OSO的论坛(二)
2006/10/09 PHP
php懒人函数 自动添加数据
2011/06/28 PHP
php获取客户端电脑屏幕参数的方法
2015/01/09 PHP
微信网页授权(OAuth2.0) PHP 源码简单实现
2016/08/29 PHP
php mysql_real_escape_string addslashes及mysql绑定参数防SQL注入攻击
2016/12/23 PHP
Thinkphp5+plupload实现的图片上传功能示例【支持实时预览】
2019/05/08 PHP
javascript 带有滚动条的表格,标题固定,带排序功能.
2009/11/13 Javascript
JS 无法通过W3C验证的处理方法
2010/03/09 Javascript
JavaScript日历实现代码
2010/09/12 Javascript
自制基于jQuery的智能提示插件一枚
2011/02/18 Javascript
如何使用jQUery获取选中radio对应的值(一句代码)
2013/06/03 Javascript
javascript实现div的显示和隐藏的小例子
2013/06/25 Javascript
jQuery 1.9移除了$.browser可以使用$.support来替代
2014/09/03 Javascript
Position属性之relative用法
2015/12/14 Javascript
AngularJS压缩JS技巧分析
2016/11/08 Javascript
浅谈vue项目重构技术要点和总结
2018/01/23 Javascript
Vue中插入HTML代码的方法
2018/09/21 Javascript
nuxt 每个页面head标签内容设置方式
2020/11/05 Javascript
python使用正则表达式检测密码强度源码分享
2014/06/11 Python
简单介绍Python的Django框架的dj-scaffold项目
2015/05/30 Python
python3 对list中每个元素进行处理的方法
2018/06/29 Python
详解numpy矩阵的创建与数据类型
2019/10/18 Python
Python多线程:主线程等待所有子线程结束代码
2020/04/25 Python
python代数式括号有效性检验示例代码
2020/10/04 Python
HTML5 placeholder(空白提示)属性介绍
2013/08/07 HTML / CSS
Kathmandu澳洲户外商店:新西兰户外运动品牌
2017/11/12 全球购物
C#实现对任一张表的数据进行增,删,改,查要求,运用Webservice,体现出三层架构
2014/07/11 面试题
四年级数学教学反思
2014/02/02 职场文书
张家口市高新区党工委群众路线教育实践活动整改方案
2014/10/25 职场文书
物业工程部经理岗位职责
2015/04/09 职场文书
何玥事迹观后感
2015/06/16 职场文书
画展观后感
2015/06/17 职场文书
学习弘扬焦裕禄精神心得体会
2016/01/23 职场文书
同学会演讲稿
2019/04/02 职场文书
Nginx流量拷贝ngx_http_mirror_module模块使用方法详解
2022/04/07 Servers
Android在Sqlite3中的应用及多线程使用数据库的建议
2022/04/24 Java/Android