IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue组件之间通信(provide/inject与$attrs/$listeners) 之四 -> 正文阅读

[JavaScript知识库]vue组件之间通信(provide/inject与$attrs/$listeners) 之四

一. provide/inject

? ? ?是Vue.js2.2.0版本后新增的API,虽然官方文档说,provide和inject主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中,但是在插件 / 组件库(比如 iView,事实上 iView 的很多组件都在用)。

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

provide?选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。

inject?选项应该是:一个字符串数组,或一个对象(属性值是一个对象时,包含from和default默认值)

?注意:provideinject绑定并不是可响应的。这显然不是设计的失误,而是刻意的。如果要详细了解,请参考:API — Vue.js

//祖先级组件(上级组件)
<template>
    <div>
        <Pro></Pro>
    </div>
</template>
<script>
import Pro from '../components/provide.vue';
export default {
    data(){
        return{
        }
    },
     provide:{
        foo:'liuhua'
    },
    components:{
        Pro,
    }
}
</script>
<style scoped>
</style>
//子孙级组件(下级组件)
<template>
    <div>
        <p>{{foo}}</p>
    </div>
</template>
<script>
export default {
    data(){
        return {
        }
    },
    inject:['foo'],
}
</script>
<style scoped>
</style>

我们在上级组件中设置了一个provide:foo,值为liuhua,它的作用就是将foo这个变量提供给它的所有下级组件。而在下级组件中通过inject注入了从上级组件中提供的foo变量,那么在下级组件中,就可以直接通过this.foo来访问了

我们一般会在main.js中导入app.vue作为根组件,我们需要在app.vue上做文章,这就是我们实现功能的关键。我们可以这样理解:app.vue作为一个最外层的根组件,用来存储所有需要的全局数据和状态。因为项目中的所有组件(包含路由),它的父组件(或根组件)都是app.vue,所有我们可以把整个app.vue实例通过provide对外提供。那么,所有的组件都能共享其数据,方法等。

//app.vue,部分代码省略:
<script>
export default {
    provide () {
      return {
        app: this
      }
    },
    data () {
      return {
        userInfo: null
      }
    },
    methods: {
      getUserInfo () {
        // 这里通过 ajax 获取用户信息后,赋值给 this.userInfo,以下为伪代码
        $.ajax('/user/info', (data) => {
          this.userInfo = data;
        });
      }
    },
    mounted () {
      this.getUserInfo();
    }
  }
</script>

?上面,我们把整个app.vue的实例`this`对外提供,接下来,任何组件(或路由)只要通过`inject`注入app.vue的话,都可以通过this.app.xxx的形式来访问app.vue的data,computed,method等内容

<template>
  <div>
    {{ app.userInfo }}
  </div>
</template>
<script>
export default {
    inject: ['app']
 }
</script>

只要一个组件使用了 `provide` 向下提供数据,那其下所有的子组件都可以通过 `inject` 来注入,不管中间隔了多少代,而且可以注入多个来自不同父级提供的数据。需要注意的是,一旦注入了某个数据,比如 `app`,那这个组件中就不能再声明 `app` 这个数据了,因为它已经被父级占有

我们介绍的这对 API,主要还是在独立组件中发挥作用

二.$attrs/$listeners

  • $attrs是在vue的2.40版本以上添加的。
  • 项目中有多层组件传参可以使用$attrs,可以使代码更加美观,更加简洁,维护代码的时候更方便。如果使用普通的父子组件传参prop和$emit$on会很繁琐;如果使用vuex会大材小用,只是在这几个组件中使用,没必要使用vuex;使用事件总线eventBus,使用不恰当的话,有可能会出现事件多次执行。
  • 非props属性:父组件传入子组件属性,但子组件没有接收称为非props属性,非props属性默认会加到子组件标签最外层(inheritAttrs:true,如果是false就不放到标签最外层显示)

  • 所有的非props属性都可以通过$attrs收到

    • 应用: v-bind="$attrs" 将所有的非props属性绑定到相应标签,也可以用于组件

  • 所有组件上的方法绑定子组件都可以通过$listeners接收

    • 应用: v-on="$listeners" 将所有的方法又绑定到组件相应标签,也可以用于组件

//最上层父级 传递数据的
<template>
  <div>
    <!-- 非props属性:组件标签上传入的属性如果子组件没有接收会跑到子组件标签最外层
    
     -->
    <!--通常: .native修饰符 才可以在组件标签上使用原生的事件 -->
    <Son
      src="https://img01.yzcdn.cn/vant/logo.png"
      @click="sonClick"
      @mouseleave="sonClick"
    ></Son>

  </div>
</template>
<script>
import Son from "./components/son.vue";
export default {
  components: {
    Son,
  },
  methods: {
    sonClick() {
      console.log("sonClick");
    },
  },
};
</script>
子组件

<template>
  <div>
    <!-- 孙组件 通过该组件 接收祖先组件传递的src 与两个方法 -->
    <SonSon v-bind="$attrs" v-on="$listeners"></SonSon>
    <button @click="btnClick">打印$listeners</button>

    <!-- 子组件 接收父组件传递的src 与两个方法 -->
    <!-- <img v-bind="$attrs" v-on="$listeners" class="img" alt="" /> -->
    {{ $attrs }}

    <!-- <img :a='1' :b="2" class="img" alt="" /> -->
    <!-- 等价于如下方式 -->
    <!-- <img v-bind="obj" class="img" alt="" /> -->
  </div>

</template>
<script>
import SonSon from "./sonson.vue";
export default {
  components: {
    SonSon,
  },

  data() {
    return {
      obj: {
        a: 1,
        b: 2,
      },
    };
  },
  //   props: ["src"],//接收传递的值后,则$attrs失效
  methods: {
    btnClick() {
      console.log(this.$listeners);
    },
  },
};
</script>

情况一:

直接在孙组件中用$attras接收祖先传递的 非props属性,用$listeners接收祖先的方法

<template>
  <div>
    <img v-bind="$attrs" alt="" />
    <button v-on="$listeners">孙组件</button>
  </div>
</template>
<script>
export default {

};
</script>

?情况二:

儿子组件,中间层,作为父组件和孙子组件的传递中介,在儿子组件中给孙子组件添加v-bind="$attrs",这样孙子组件才能接收到数据,

在孙子组件中一定要使用props接收从父组件传递过来的数据,直接与prop传值一样使用在孙组件中

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-28 11:10:38  更:2021-11-28 11:11:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:28:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码