Vue 实例属性:$attrs 和 $ listeners

vm.$attrs

包含了父作用域不作为 prop 被识别(且获取)的 attribute 绑定(class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定(class 和 style 除外),并且可以通过 v-bind=“$attrs” 传入内部组件 -- 在创建高级别的组件时非常有用。

总之就是包含了所有父组件在子组件上设置的属性(除了 prop 传递的属性、class 和 style)。

<div id="app">
  <base-input
    label="姓名"
    class="name-input"
    placeholder="请输入姓名"
    test-attrs="$attrs"
  ></base-input>
</div>
Vue.component("base-input", {
  inheritAttrs: false, //此处设置禁用继承特性
  props: ["label"],
  template: `
  <label>
    {{label}}-
    {{$attrs.placeholder}}-
    <input v-bind="$attrs"/>
  </label>
  `,
  mounted: function() {
    console.log(this.$attrs);
  }
});
const app = new Vue({
  el: "#app"
});

在生命周期方法 mounted 中打印 $attrs,显示除了 class 和 prop 定义的属性之外的其他属性。打印的结果如下:

{
  placeholder: '请输入姓名',
  test-attrs: '$attrs'
}

通过 v-bind="$attrs" 传入子组件内部的 input 标签。渲染的 DOM 结构如下:

<label>
  姓名-
  请输入姓名-
  <input placeholder="请输入姓名" test-attrs="$attrs" />
</label>

vm.$listeners

包含了父作用域的(不含 .native 修饰器的)v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件 -- 在创建更高层级的组件时非常有用。

它是一个对象,里面包含了作用在这个组件上所有的监听器(监听事件),可以通过 v-on="$listeners" 将事件监听指向这个组件内的子元素(包括内部的子组件)。

<div id="app">
  <child1
    :p-child1="child1"
    :p-child2="child2"
    :p-child-attrs="1231"
    v-on:test1="onTest1"
    v-on:test2="onTest2">
  </child1>
</div>
<script>
  Vue.component("Child1", {
    inheritAttrs: true,
    props: ["pChild1"],
    template: `
    <div class="child-1">
    <p>in child1:</p>
    <p>props: {{pChild1}}</p>
    <p>$attrs: {{this.$attrs}}</p>
    <hr>
    <child2 v-bind="$attrs" v-on="$listeners"></child2></div>`,
    mounted: function() {
      this.$emit("test1");
    }
  });
  Vue.component("Child2", {
    inheritAttrs: true,
    props: ["pChild2"],
    template: `
    <div class="child-2">
    <p>in child->child2:</p>
    <p>props: {{pChild2}}</p>
    <p>$attrs: {{this.$attrs}}</p>
      <button @click="$emit('test2','按钮点击')">触发事件</button>
    <hr> </div>`,
    mounted: function() {
      this.$emit("test2");
    }
  });
  const app = new Vue({
    el: "#app",
    data: {
      child1: "pChild1的值",
      child2: "pChild2的值"
    },
    methods: {
      onTest1() {
        console.log("test1 running...");
      },
      onTest2(value) {
        console.log("test2 running..." + value);
      }
    }
  });
</script>

父组件在 child1 组件中设置两个监听事件 test1 和 test2 ,分别在 child1 组件和 child1 组件内部的 child2 组件中执行。还设置了三个属性 p-child1p-child2p-child-attrs。其中 p-child1p-child2 被对应的组件的 prop 识别。所以:
p-child1 组件中$attrs为 { "p-child2": "pChild2的值", "p-child-attrs": 1231 };
p-child2 组件中$attrs{ "p-child-attrs": 1231 }

inheritAttrs

默认情况下,父作用域的不被认作 props 的 attribute 绑定(attribute bindings)将会'回退'且作为普通的 HTML attribute 应用在子元素的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过 $attrs 可以让这些 attribute 生效,且可以通过 v-bind 显性的绑定到非根元素上。

注意:这个选项不影响 class 和 style 绑定。

将上述案例,设置 inheritAttrs: true, dom 结构如下:

<label placeholder="请输入姓名" test-attrs="$attrs">
  姓名-
  请输入姓名-
  <input placeholder="请输入姓名" test-attrs="$attrs" />
</label>

没有被 props 绑定的属性 placeholder 和 test-attrs 显示到了子节点根节点上了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值