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 相关文章推荐
发布BlueShow v1.0 图片浏览器(类似lightbox)blueshow.js 打包下载
Jul 21 Javascript
Javascript 获取LI里的内容
Dec 17 Javascript
Javascript面向对象设计一 工厂模式
Dec 20 Javascript
创建公共调用 jQuery Ajax 带返回值
Aug 01 Javascript
控制文字内容的显示与隐藏示例
Jun 11 Javascript
js实现图片缓慢放大缩小效果
Aug 02 Javascript
详解vue-cil和webpack中本地静态图片的路径问题解决方案
Sep 27 Javascript
vue jsx 使用指南及vue.js 使用jsx语法的方法
Nov 11 Javascript
vue自定义键盘信息、监听数据变化的方法示例【基于vm.$watch】
Mar 16 Javascript
jquery树形插件zTree高级使用详解
Aug 16 jQuery
layui使用button按钮 点击出现弹层 弹层中加载表单的实例
Sep 04 Javascript
解决vue安装less报错Failed to compile with 1 errors的问题
Oct 22 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递归返回值时出现的问题解决办法
2013/02/19 PHP
php单态设计模式(单例模式)实例
2014/11/18 PHP
Yii框架引用插件和ckeditor中body与P标签去除的方法
2017/01/19 PHP
详解PHP中的 input属性(隐藏 只读 限制)
2017/08/14 PHP
PHP实现类似于C语言的文件读取及解析功能
2017/09/01 PHP
js浮动图片的动态效果
2013/07/10 Javascript
JavaScript SweetAlert插件实现超酷消息警告框
2016/01/28 Javascript
javascript基础知识分享之类与函数化
2016/02/13 Javascript
vue项目中做编辑功能传递数据时遇到问题的解决方法
2016/12/19 Javascript
jQuery+ThinkPHP+Ajax实现即时消息提醒功能实例代码
2017/03/21 jQuery
Javascript实现登录记住用户名和密码功能
2017/03/22 Javascript
JavaScript验证知识整理
2017/03/24 Javascript
React简单介绍
2017/05/24 Javascript
vue 之 .sync 修饰符示例详解
2018/04/21 Javascript
jquery 动态遍历select 赋值的实例
2018/09/12 jQuery
vue3 源码解读之 time slicing的使用方法
2019/10/31 Javascript
JS前端广告拦截实现原理解析
2020/02/17 Javascript
Python numpy生成矩阵、串联矩阵代码分享
2017/12/04 Python
python检测文件夹变化,并拷贝有更新的文件到对应目录的方法
2018/10/17 Python
Python中的random.uniform()函数教程与实例解析
2019/03/02 Python
python判断所输入的任意一个正整数是否为素数的两种方法
2019/06/27 Python
远程部署工具Fabric详解(支持Python3)
2019/07/04 Python
pyenv与virtualenv安装实现python多版本多项目管理
2019/08/17 Python
python各层级目录下import方法代码实例
2020/01/20 Python
Django REST 异常处理详解
2020/07/15 Python
如何以Winsows Service方式运行JupyterLab
2020/08/30 Python
英国领先的鞋类零售商:Shoe Zone
2018/12/13 全球购物
机械专业个人求职自荐信格式
2013/09/21 职场文书
《两只鸟蛋》教学反思
2014/02/10 职场文书
个人培训自我鉴定
2014/03/28 职场文书
三项教育活动实施方案
2014/03/30 职场文书
土建专业毕业生自荐书
2014/07/04 职场文书
毕业生银行实习自我鉴定
2014/10/14 职场文书
成绩报告单家长评语
2014/12/30 职场文书
Python趣味实战之手把手教你实现举牌小人生成器
2021/06/07 Python
SQL Server数据库查询出现阻塞之性能调优
2022/04/10 SQL Server