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中的undefined 与 null 的区别  补充篇
Mar 17 Javascript
JavaScript中的稀疏数组与密集数组[译]
Sep 17 Javascript
js浮动图片的动态效果
Jul 10 Javascript
js获取select标签选中值的两种方式
Jan 09 Javascript
异步安全加载javascript文件的方法
Jul 21 Javascript
js确认框confirm()用法实例详解
Jan 07 Javascript
修改jquery中dialog的title属性方法(推荐)
Aug 26 Javascript
jquery easyui validatebox remote的使用详解
Nov 09 Javascript
AngularJS入门教程之路由机制ngRoute实例分析
Dec 13 Javascript
js实现消息滚动效果
Jan 18 Javascript
Vue 重置组件到初始状态的方法示例
Oct 10 Javascript
layui关闭弹窗后刷新主页面和当前更改项的例子
Sep 06 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
本地计算机无法启动Apache故障处理
2014/08/08 PHP
PHP中empty和isset对于参数结构的判断及empty()和isset()的区别
2015/11/15 PHP
Thinkphp结合ajaxFileUpload实现异步图片传输示例
2017/03/13 PHP
2017年最新PHP经典面试题目汇总(上篇)
2017/03/17 PHP
Extjs ajax同步请求时post方式参数发送方式
2009/08/05 Javascript
JavaScript中的变量声明早于赋值分析
2012/03/01 Javascript
js获取键盘按键响应事件(兼容各浏览器)
2013/05/16 Javascript
jquery next nextAll nextUntil siblings的区别介绍
2013/10/05 Javascript
通过正则表达式实现表单验证是否为中文
2014/02/18 Javascript
Jquery给基本控件的取值、赋值示例
2014/05/23 Javascript
JavaScript实现将UPC转换成ISBN的方法
2015/05/26 Javascript
JavaScript访问字符串中单个字符的两种方法
2015/07/03 Javascript
js实现有过渡渐变效果的图片轮播相册(兼容IE,ff)
2016/01/19 Javascript
DOM操作和jQuery实现选项移动操作的简单实例
2016/06/07 Javascript
让浏览器崩溃的12行JS代码(DoS攻击分析及防御)
2016/10/10 Javascript
Javascript中的prototype与继承
2017/02/06 Javascript
30分钟精通React今年最劲爆的新特性——React Hooks
2019/03/11 Javascript
js正则表达式简单校验方法
2021/01/03 Javascript
vue实现按钮切换图片
2021/01/20 Vue.js
python实现数独算法实例
2015/06/09 Python
Python基于list的append和pop方法实现堆栈与队列功能示例
2017/07/24 Python
linux环境下的python安装过程图解(含setuptools)
2017/11/22 Python
python自动查询12306余票并发送邮箱提醒脚本
2018/05/21 Python
ubuntu 16.04下python版本切换的方法
2019/06/14 Python
如何使用django的MTV开发模式返回一个网页
2019/07/22 Python
python解析yaml文件过程详解
2019/08/30 Python
Python编写万花尺图案实例
2021/01/03 Python
css3旋转木马_动力节点Java学院整理
2017/07/12 HTML / CSS
应届毕业生简历自我评价
2014/01/31 职场文书
《独坐敬亭山》教学反思
2014/04/08 职场文书
学生安全承诺书
2014/05/22 职场文书
班级标语大全
2014/06/21 职场文书
惊天动地观后感
2015/06/10 职场文书
公司趣味运动会开幕词
2016/03/04 职场文书
python中24小时制转换为12小时制的方法
2021/06/18 Python
苹果M1芯片安装nginx 并且部署vue项目步骤详解
2021/11/20 Servers