浅析vue中的provide / inject 有什么用处


Posted in Javascript onNovember 10, 2019

1.前言

vue的父子组件通信用什么?

:prop和$emit的组合。

如果是爷孙组件呢?

:那么就要用父组件来转发数据和事件了。

如果是太爷爷和孙子组件呢?

:当然是vuex啦

emmm 好的,没我啥事了,我这就走。

不行,我还能再挣扎一会儿!肯定有一部分兄弟做的项目比较小,组件通信的情况不是很多,懒得引入vuex,那么provide/inject就是爷孙(不限于爷孙/父子,中间隔了多少级都可以)通信问题的最好解决方案啦!

2.官方文档抄过来的介绍

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。

provide 选项应该是

  • 一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作。

inject 选项应该是:

  • 一个字符串数组,或
  • 一个对象(详情点击 这里 )

3.基本用法

// 祖先组件 提供foo
//第一种
export default {
 name: "grandfather",
 provide(){
  return{
   foo:'halo'
  }
 },
}
//第二种
export default {
 name: "grandfather",
 provide:{
  foo:'halo~~~~'
 },
}
//后代组件 注入foo
export default {
 inject:['foo'],
}

上面的两种用法有什么区别吗?

  • 如果你只是传一个字符串,像上面的‘halo',那么是没有区别的,后代都能读到。
  • 如果你需要传一个对象(如下所示代码),那么第二种是传不了的,后代组件拿不到数据。所以建议只写第一种
//当你传递对象给后代时
provide(){
  return{
   test:this.msg
  }
 },

注意: 一旦注入了某个数据,比如上面示例中的 foo,那这个组件中就不能再声明 foo 这个数据了,因为它已经被父级占有。

4.什么时候才是可响应的?

如果你使用过vuex,那么你会认为,上面的例子中,如果我把 foo:'halo' 改成 foo:'world' ,子组件会及时响应数据变更,视图完成更新。

可惜,没有

在vue官方文档中有这么一句话

提示: provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

这里不探讨vue为什么要这么设计,我这里只展示啥时候provide/inject可响应

provide(){
 return{
  test:this.msg
 }
},
data() {
 return {
  msg: "Welcome to Your Vue.js App",
 }
}
mounted(){
 setTimeout(()=>{
  this.msg = "halo world";
  console.log(this._provided.msg)
  //log:Welcome to Your Vue.js App
 },3000)
},

如上所示,这样做是不行的,打印出来的 provided 中的数据并没有改,子组件取得值也没变。

你甚至可以直接给 this._provided.msg 赋值,但是 即使 是 _provided.msg 里面的值改变了,子组件的取值,依然没有变。

当你像下面这样做的时候,就可以响应了

provide(){
 return{
  test:this.activeData
 }
},
data() {
 return {
  activeData:{name:'halo'},
 }
}
mounted(){
 setTimeout(()=>{
  this.activeData.name = 'world';
 },3000)
}

这就是vue中写道的 对象的属性 是可以响应的

然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

5.实现全局变量

全局变量?provide/inject不是只能从祖先传递给后代吗?没错,我们只要绑定到最最顶层的组件即可。

就是你啦! app.vue

我们把一整个实例都扔给后代!

//app.vue
export default {
 name: 'App',
 provide(){
  return{
   app:this
  }
 },
 data(){
  return{
   text:"it's hard to tell the night time from the day"
  }
 },
 methods:{
  say(){
   console.log("Desperado, why don't you come to your senses?")
  }
 }
}
//其他所有子组件,需要全局变量的,只需要按需注入app即可
export default {
 inject:['foo','app'],
 mounted(){
  console.log(this.app.text);//获取app中的变量
  this.app.say();//可以执行app中的方法,变身为全局方法!
 }
}

这个也是可响应的噢~

6.实现页面刷新

1 . 用vue-router重新路由到当前页面,页面是不进行刷新的

2 . 采用window.reload(),或者router.go(0)刷新时,整个浏览器进行了重新加载,闪烁,体验不好

那我们怎么做呢?

跟上面的原理差不多,我们只在控制路由的组件中写一个函数(使用 v-if 控制 router-view 的显示隐藏,这里的原理不作赘述),然后把这个函数传递给后代,然后在后代组件中调用这个方法即可刷新路由啦。

//app.vue
<router-view v-if="isShowRouter"/>
export default {
 name: 'App',
 provide(){
  return{
   reload:this.reload
  }
 },
 data(){
  return{
   isShowRouter:true,
  }
 },
 methods:{
  reload(){
   this.isShowRouter = false;
   this.$nextTick(()=>{
    this.isShowRouter = true;
   })
  }
 }
}
//后代组件
export default {
 inject:['reload'], 
}

7.结尾

vue中有这样的提示

注意: provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。

provide/inject平时用的比较少,多数用于开发组件,但某些情况下还是很好用的。

业务庞大而复杂的,还是建议使用 vuex ~

总结

以上所述是小编给大家介绍的vue中的provide / inject 有什么用处,希望对大家有所帮助!

Javascript 相关文章推荐
任意位置显示html菜单
Feb 01 Javascript
jQuery源码分析-03构造jQuery对象-工具函数
Nov 14 Javascript
Underscore.js 的模板功能介绍与应用
Dec 24 Javascript
jQuery遍历json中多个map的方法
Feb 12 Javascript
jquery实现点击弹出可放大居中及关闭的对话框(附demo源码下载)
May 10 Javascript
Javascript实现通过选择周数显示开始日和结束日的实现代码
May 30 Javascript
js不间断滚动的简单实现
Jun 03 Javascript
使用微信内嵌H5网页解决JS倒计时失效问题
Jan 13 Javascript
基于DOM节点删除之empty和remove的区别(详解)
Sep 11 Javascript
js实现图片粘贴上传到服务器并展示的实例
Nov 08 Javascript
微信小程序导入Vant报错VM292:1 thirdScriptError的解决方法
Aug 01 Javascript
查找Vue中下标的操作(some和findindex)
Aug 12 Javascript
Vue项目中使用jsonp抓取跨域数据的方法
Nov 10 #Javascript
webpack4 optimization使用总结
Nov 10 #Javascript
vue ssr服务端渲染(小白解惑)
Nov 10 #Javascript
node后端服务保活的实现
Nov 10 #Javascript
vue动态循环出的多个select出现过的变为disabled(实例代码)
Nov 10 #Javascript
vue父子组件的通信方法(实例详解)
Nov 10 #Javascript
分享Angular http interceptors 拦截器使用(推荐)
Nov 10 #Javascript
You might like
在Windows版的PHP中使用ADO
2006/10/09 PHP
php Try Catch异常测试
2009/03/01 PHP
PHP CodeBase:将时间显示为&quot;刚刚&quot;&quot;n分钟/小时前&quot;的方法详解
2013/06/06 PHP
php web环境和命令行环境下查找php.ini的位置
2019/07/17 PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
2020/02/27 PHP
jquery实现输入框动态增减的实例代码
2013/07/14 Javascript
Javascript 遍历页面text控件详解
2014/01/06 Javascript
jquery实现可点击伸缩与展开的菜单效果代码
2015/08/31 Javascript
AngularJS ng-app 指令实例详解
2016/07/30 Javascript
JS数组交集、并集、差集的示例代码
2017/08/23 Javascript
Vue.js中的computed工作原理
2018/03/22 Javascript
vuejs+element UI点击编辑表格某一行时获取内容填入表单的示例
2018/10/31 Javascript
基于Vue实现图片在指定区域内移动的思路详解
2018/11/11 Javascript
Vue 表情包输入组件的实现代码
2019/01/21 Javascript
Vue多组件仓库开发与发布详解
2019/02/28 Javascript
简单分析js中的this的原理
2019/08/31 Javascript
JavaScript中变量提升机制示例详解
2019/12/27 Javascript
详解elementUI中input框无法输入的问题
2020/04/27 Javascript
Node.js API详解之 util模块用法实例分析
2020/05/09 Javascript
[01:07:13]TNC vs Pain 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
Python编写一个闹钟功能
2017/07/11 Python
python 字典中文key处理,读取,比较方法
2018/07/06 Python
利用python和百度地图API实现数据地图标注的方法
2019/05/13 Python
python Pillow图像处理方法汇总
2019/10/16 Python
Under Armour美国官网:美国知名高端功能性运动品牌
2016/09/05 全球购物
Converse匡威法国官网:美国著名帆布鞋品牌
2018/12/05 全球购物
党支部特色活动方案
2014/08/20 职场文书
关于环保的活动方案
2014/08/25 职场文书
2014年小学生教师节演讲稿范文
2014/09/10 职场文书
房屋登记授权委托书范本
2014/10/09 职场文书
个人作风建设总结
2014/10/23 职场文书
2014党的群众路线教育实践活动总结材料
2014/10/31 职场文书
redis哨兵常用命令和监控示例详解
2021/05/27 Redis
Mysql分库分表之后主键处理的几种方法
2022/02/15 MySQL
css3应用示例:新增的选择器
2022/03/16 HTML / CSS
CSS元素定位之通过元素的标签或者元素的id、class属性定位详解
2022/09/23 HTML / CSS