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 相关文章推荐
一个javascript参数的小问题
Mar 02 Javascript
W3C Group的JavaScript1.8 新特性介绍
May 19 Javascript
js cookies实现简单统计访问次数
Nov 24 Javascript
读JavaScript DOM编程艺术笔记
Nov 15 Javascript
jQuery点击后一组图片左右滑动的实现代码
Aug 16 Javascript
JS实现切换标签页效果实例代码
Nov 01 Javascript
javascript中this指向详解
Apr 23 Javascript
基于JS实现EOS隐藏错误提示层代码
Apr 25 Javascript
Angularjs使用指令做表单校验的方法
Mar 31 Javascript
使用jQuery ajaxupload插件实现无刷新上传文件
Apr 23 jQuery
ES6中Math对象新增的方法实例详解
Apr 25 Javascript
angular4中关于表单的校验示例
Oct 16 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
codeigniter框架The URI you submitted has disallowed characters错误解决方法
2014/05/06 PHP
PHP查询并删除数据库多列重复数据的方法(利用数组函数实现)
2016/02/23 PHP
Yii2 GridView实现列表页直接修改数据的方法
2016/05/16 PHP
PHP+MySQL高并发加锁事务处理问题解决方法
2018/04/30 PHP
js 在定义的时候立即执行的函数表达式(function)写法
2013/01/16 Javascript
用jquery生成二级菜单的实例代码
2013/06/24 Javascript
JavaScript代码性能优化总结(推荐)
2016/05/16 Javascript
bootstrap datepicker 与bootstrapValidator同时使用时选择日期后无法正常触发校验的解决思路
2016/09/28 Javascript
详解JavaScript常量定义
2017/01/03 Javascript
js 颜色选择插件
2017/01/23 Javascript
canvas红包照片实例分享
2017/02/28 Javascript
vue如何使用async、await实现同步请求
2019/12/09 Javascript
html-webpack-plugin修改页面的title的方法
2020/06/18 Javascript
Element中Slider滑块的具体使用
2020/07/29 Javascript
用js实现放大镜效果
2020/10/28 Javascript
一个超级简单的python web程序
2014/09/11 Python
python定时执行指定函数的方法
2015/05/27 Python
Python搭建APNS苹果推送通知推送服务的相关模块使用指南
2016/06/02 Python
Pycharm学习教程(4) Python解释器的相关配置
2017/05/03 Python
PyQt5每天必学之QSplitter实现窗口分隔
2018/04/19 Python
解决Python3中的中文字符编码的问题
2018/07/18 Python
PyQt5 在label显示的图片中绘制矩形的方法
2019/06/17 Python
django实现支付宝支付实例讲解
2019/10/17 Python
在python中使用pymysql往mysql数据库中插入(insert)数据实例
2020/03/02 Python
python实现密码验证合格程序的思路详解
2020/06/01 Python
Python程序慢的重要原因
2020/09/04 Python
python录音并调用百度语音识别接口的示例
2020/12/01 Python
HTML5中div、article、section的区别及使用介绍
2013/08/14 HTML / CSS
Html5+CSS3+EL表达式问题小结
2020/12/19 HTML / CSS
开学典礼感言
2014/02/16 职场文书
公关活动策划方案
2014/05/25 职场文书
党员四风问题对照检查材料
2014/09/27 职场文书
十一国庆节“向国旗敬礼”主题班会活动方案
2014/09/27 职场文书
工程催款通知书
2015/04/17 职场文书
2016学习雷锋精神活动倡议书
2015/04/27 职场文书
python基础之类方法和静态方法
2021/10/24 Python