非Prop特性指的是,一个未被组件注册的特性。当组件接收了一个非Prop特性时,该特性会被添加到这个组件的根元素上。
示例

  1. <section id="app">
  2. <!-- age sex 是非prop特性(此处特性就是属性) -->
  3. <my-prop :name='name' age=10 sex='nan'></my-prop>
  4. </section>
  5. <script>
  6. Vue.component('my-prop',{
  7. // 此处并没有接收 age 与 sex 特性,那就是说明age与sex未被注册
  8. props:['name'],
  9. template:`
  10. <!-- prop特性会被添加到根元素上-->
  11. <div>
  12. <p>{{name}}</p>
  13. </div>`
  14. })
  15. const vm = new Vue({
  16. el: '#app',
  17. data: {
  18. name:'张三',
  19. },
  20. })
  21. </script>

以上面代码为例

  1. <my-prop :name='name' age=10 sex='nan'></my-prop>
  1. props:['name'],

age 和 sex 就是非prop特性(特性就是属性),因为props中并未有注册它们,它们会保存到 $attrs 上 ,
非prop特性默认会将其添加到该组件的根元素上

替换/合并已有的特性

想象一下 <my-cmp> 的模板是这样的:

  1. template:`<input type="date" class="b">`

添加一个特别的类名:

  1. <my-cmp
  2. class="my-cmp"
  3. ></my-cmp>

在这种情况下,我们定义了两个不同的 class 的值:

  • my-cmp,这是在组件的模板内设置好的
  • b,这是从组件的父级传入的

对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。所以如果传入 type=”text” 就会替换掉 type=”date” 并把它破坏!庆幸的是,class 和 style 特性会稍微智能一些,即两边的值会被合并起来,从而得到最终的值:my-cmp b。

禁用特性继承与$attrs

如果不希望组件的根元素继承特性,那么可以在组件选项中设置 inheritAttrs: false。如:

  1. Vue.component('my-cmp', {
  2. inheritAttrs: false,
  3. // ...
  4. })

使用 inheritAttrs: false$attrs 相互配合,我们就可以手动决定这些特性会被赋予哪个元素。如

  1. <section id="app">
  2. <my-prop :name='name' age=10 sex='nan'></my-prop>
  3. </section>
  4. <script>
  5. Vue.component('my-prop',{
  6. props:['name'],
  7. mounted(){
  8. console.log(this);
  9. console.log(this.$attrs);
  10. },
  11. inheritAttrs: false, //禁用特性继承
  12. template:`
  13. <div>
  14. <p>{{name}}</p>
  15. <!-- 将非prop特性添加到下面这个元素-->
  16. <p v-bind='$attrs'>{{this.$attrs}}</p>
  17. </div>`
  18. })
  19. const vm = new Vue({
  20. el: '#app',
  21. data: {
  22. name:'张三',
  23. },
  24. })
  25. </script>

效果图
image.png
注意:inheritAttrs: false 选项不会影响 style 和 class 的绑定。

$attrs

官方解释
image.png
资料中的解释
image.png
实现祖先组件传递数据给子孙组件

  1. <section id="app">
  2. <my-prop class="son" :name='name' age=10 sex='nan'>
  3. </my-prop>
  4. </section>
  5. <script>
  6. // vm的孙子组件
  7. Vue.component('my-prop-son',{
  8. props:['age','sex'],
  9. template:`
  10. <div>
  11. <button>{{sex}}</button>
  12. </div>
  13. `
  14. })
  15. // vm的儿子组件
  16. Vue.component('my-prop',{
  17. props:['name'],
  18. mounted(){
  19. console.log(this);
  20. console.log(this.$attrs);
  21. },
  22. inheritAttrs: false, //禁用特性继承
  23. template:`
  24. <div>
  25. <p>{{name}}</p>
  26. <!-- 将非prop特性添加到下面这个元素-->
  27. <p v-bind='$attrs'>{{this.$attrs.age}}</p>
  28. <!-- 向子组件 my-prop-son 传递数据,数据是从该子组件的父组件传递过来的-->
  29. <my-prop-son class='grandson' v-bind='$attrs'></my-prop-son>
  30. </div>`
  31. })
  32. const vm = new Vue({
  33. el: '#app',
  34. data: {
  35. name:'张三',
  36. },
  37. })
  38. </script>

效果图
image.png
控制台
image.png