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操作数据库的实例代码
Oct 17 Javascript
zTree插件之单选下拉菜单实例代码
Nov 07 Javascript
js数组去重的方法汇总
Jul 29 Javascript
Highcharts学习之数据列
Aug 03 Javascript
JS提示:Uncaught SyntaxError:Unexpected token ) 错误的解决方法
Aug 19 Javascript
js选项卡的制作方法
Jan 23 Javascript
Vue.js 父子组件通信的十种方式
Oct 30 Javascript
详解React项目中碰到的IE问题
Mar 14 Javascript
Emberjs 通过 axios 下载文件的方法
Sep 03 Javascript
JS页面获取 session 值,作用域和闭包学习笔记
Oct 16 Javascript
详解JavaScript作用域 闭包
Jul 29 Javascript
JavaScript数组常用的增删改查与其他属性详解
Oct 13 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
php&amp;mysql 日期操作小记
2012/02/27 PHP
PHP判断密码强度的方法详解
2017/05/26 PHP
php判断str字符串是否是xml格式数据的方法示例
2017/07/26 PHP
[原创]PHP正则匹配中英文、数字及下划线的方法【用户名验证】
2017/08/01 PHP
使用jquery实现select添加实现后台权限添加的效果
2011/05/28 Javascript
仿jQuery的siblings效果的js代码
2011/08/09 Javascript
setInterval与clearInterval的使用示例代码
2014/01/28 Javascript
JS实现距离上次刷新已过多少秒示例
2014/05/23 Javascript
document.forms用法示例介绍
2014/06/26 Javascript
jquery右下角自动弹出可关闭的广告层
2015/05/08 Javascript
修改jquery中dialog的title属性方法(推荐)
2016/08/26 Javascript
基于jquery二维码生成插件qrcode
2017/01/07 Javascript
vue中用动态组件实现选项卡切换效果
2017/03/25 Javascript
nodejs个人博客开发第四步 数据模型
2017/04/12 NodeJs
深究AngularJS中$sce的使用
2017/06/12 Javascript
JavaScript模块详解
2017/12/18 Javascript
vue router动态路由下让每个子路由都是独立组件的解决方案
2018/04/24 Javascript
swiper.js插件实现pc端文本上下滑动功能示例
2018/12/03 Javascript
windows如何把已安装的nodejs高版本降级为低版本(图文教程)
2020/12/14 NodeJs
[51:06]2018DOTA2亚洲邀请赛3月29日 小组赛A组 KG VS Liquid
2018/03/30 DOTA
python在windows和linux下获得本机本地ip地址方法小结
2015/03/20 Python
Python 3.6 性能测试框架Locust安装及使用方法(详解)
2017/10/11 Python
浅谈用Python实现一个大数据搜索引擎
2017/11/28 Python
使用Python编写Prometheus监控的方法
2018/10/15 Python
django+echart绘制曲线图的方法示例
2018/11/26 Python
使用Python生成200个激活码的实现方法
2019/11/22 Python
python字符串常用方法及文件简单读写的操作方法
2020/03/04 Python
Python OrderedDict字典排序方法详解
2020/05/21 Python
为什么说python更适合树莓派编程
2020/07/20 Python
美国基督教约会网站:ChristianCafe.com
2020/02/04 全球购物
公司门卫管理制度
2014/02/01 职场文书
2014年信用社工作总结
2014/11/25 职场文书
五好家庭事迹材料
2014/12/20 职场文书
工作检讨书大全
2015/01/26 职场文书
工作岗位职责范本
2015/02/15 职场文书
pandas中DataFrame数据合并连接(merge、join、concat)
2021/05/30 Python