Vue实现父孙传值$attrs

315 阅读2分钟

作用

现在的需求是想要实现父孙之间的传值,我们能够想到的哪几种方式了?

  1. 我们使用VueX来进行数据管理,但是如果项目中多个组件共享状态比较少,项目比较小,并且全局状态比较少,那使用VueX来实现该功能,并没有发挥出VueX的威力。

  2. 使用B来做中转站,当A组件需要把信息传给C组件时,B接受A组件的信息,然后利用属性传给C组件,这是一种解决方案,但是如果嵌套的组件过多,会导致代码繁琐,代码维护比较困难;如果C中状态的改变需要传递给A, 使用事件系统一级级往上传递

  3. 自定义一个Vue 中央数据总线,这个情况适合碰到组件跨级传递消息,但是使用VueX感觉又有点浪费的项目中,但是缺点是,碰到多人合作时,代码的维护性较低,代码可读性低

在vue2.4中,为了解决该需求,引入了attrsattrs 和listeners , 新增了inheritAttrs 选项。 在版本2.4以前,默认情况下父作用域的不被认作props的属性将会作为普通的HTML特性应用在子组件的根元素上。如下列的例子

  • 父组件
<template>
<div>
  <child-dom
   :foo="foo"
   :coo="foo"
  >
  </child-dom>
</div>
</template>
<script>
import childDom from "./ChildDom.vue";
export default {
  data() {
     return {
       foo:"Hello, world",
       coo:"Hello,rui"
     }
  },
  components:{childDom},
}
</script>
  • 子组件
<template>
<div>
   <p>foo:{{foo}}</p>
</div>
</template>
<script>
export default {
name:'child-dom'
props:["foo"]
}
</script>

子组件中没有接受coo所以coo就作为普通的HTML的一个属性

$attrs的用法

实现父先孙传值的需求

  • 父组件

给子组件关联数据,子组件如果不用props接收,那么这些数据就作为普通的HTML特性应用在子组件的根元素上

<template>
  <div>
    <p>父组件</p>
    <Child :foo="foo" :obj="obj"></Child>
  </div>
</template>

<script>
import Child from "./B1.vue";
export default {
  components: {
    Child,
  },
  data() {
    return {
      foo: "foo",
      obj: {
        name: "wangjinyu",
        like: "watch tv",
      },
    };
  },
};
</script>

<style>
</style>
  • 儿子组件

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

<template>
  <div class='child-view'>
    <p>儿子组件</p>
    <GrandChild v-bind="$attrs"></GrandChild>
  </div>
</template>

<script>
import GrandChild from './GrandChild.vue'
export default {
  // 继承所有父组件的内容,把传值作为html的属性,显示在dom元素上面
  inheritAttrs: true,
  components: { GrandChild },
  data() {
    return {
    }
  }
}
</script>
  • 孙子组件

在孙子组件中一定要使用props接收从父组件传递过来的数据

<template>
  <div>
    <p>孙组件</p>
    <div>{{foo}}</div>
    <div>{{obj.name}}</div>
  </div>
</template>

<script>
export default {
  props: {
    foo: {
      type: String,
      default: "",
    },
    obj: {
      type: Object,
      default: () => {},
    },
  },
  // 不想继承所有父组件的内容,同时也不在组件根元素dom上显示属性
  inheritAttrs: false,
};
</script>

<style>
</style>
  • 结果展示