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 相关文章推荐
让插入到 innerHTML 中的 script 跑起来的实现代码
Jul 01 Javascript
jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)
Oct 20 Javascript
javascript实现网站加入收藏功能
Dec 16 Javascript
Node.js程序中的本地文件操作用法小结
Mar 06 Javascript
javascript读取文本节点方法小结
Dec 15 Javascript
微信小程序之picker日期和时间选择器
Feb 09 Javascript
js禁止浏览器页面后退功能的实例(推荐)
Sep 01 Javascript
使用原生js封装的ajax实例(兼容jsonp)
Oct 12 Javascript
可能被忽略的一些JavaScript数组方法细节
Feb 28 Javascript
使用微信SDK自定义分享的方法
Jul 03 Javascript
JavaScript设计模式之门面模式原理与实现方法分析
Mar 09 Javascript
原生JS中应该禁止出现的写法
May 05 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下通过exec获得计算机的唯一标识[CPU,网卡 MAC地址]
2011/06/09 PHP
php快速查找数据库中恶意代码的方法
2015/04/01 PHP
Zend Framework动作助手Json用法实例分析
2016/03/05 PHP
PHP引用的调用方法分析
2016/04/25 PHP
YII框架常用技巧总结
2019/04/27 PHP
php设计模式之工厂方法模式分析【星际争霸游戏案例】
2020/01/23 PHP
给Javascript数组插入一条记录的代码
2007/08/30 Javascript
ExtJs之带图片的下拉列表框插件
2010/03/04 Javascript
关于IE浏览器以及Firefox下的javascript冒泡事件的响应层级
2010/10/14 Javascript
jquery实现滑动图片自己测试的例子
2013/11/05 Javascript
JavaScript修改浏览器tab标题小技巧
2015/01/06 Javascript
js判断登录与否并确定跳转页面的方法
2015/01/30 Javascript
深入理解jQuery3.0的domManip函数
2016/09/01 Javascript
Bootstrap基本样式学习笔记之表单(3)
2016/12/07 Javascript
angularjs实现猜数字大小功能
2020/05/20 Javascript
微信小程序实现折叠展开效果
2018/07/19 Javascript
vue实现todolist功能、todolist组件拆分及todolist的删除功能
2019/04/11 Javascript
详解微信小程序胶囊按钮返回|首页自定义导航栏功能
2019/06/14 Javascript
微信小程序 wx:for遍历循环使用实例解析
2019/09/09 Javascript
JS 创建对象的模式实例小结
2020/04/28 Javascript
jquery实现手风琴案例
2020/05/04 jQuery
用python读写excel的方法
2014/11/18 Python
python删除服务器文件代码示例
2018/02/09 Python
python实现反转部分单向链表
2018/09/27 Python
Python中整数的缓存机制讲解
2019/02/16 Python
解决python super()调用多重继承函数的问题
2019/06/26 Python
python+Django+pycharm+mysql 搭建首个web项目详解
2019/11/29 Python
HTML5单页面手势滑屏切换原理分析
2017/07/10 HTML / CSS
日本动漫周边服饰销售网站:Atsuko
2019/12/16 全球购物
《角的度量》教学反思
2016/02/18 职场文书
详解CocosCreator消息分发机制
2021/04/16 Javascript
MySQL子查询中order by不生效问题的解决方法
2021/08/02 MySQL
MySQL数据库⾼可⽤HA实现小结
2022/01/22 MySQL
redis复制有可能碰到的问题汇总
2022/04/03 Redis
《LOL》“克隆大作战”久违归来 幻灵战队皮肤上线
2022/04/03 其他游戏
讲解Python实例练习逆序输出字符串
2022/05/06 Python