【小白读vue官方文档】vue中非props属性、$attrs和禁用 Attribute 继承

【小白读vue官方文档】vue中非prop的attribute、$attrs和禁用 Attribute 继承


注:props是properties的缩写,attrs是attributes的缩写,这两个词在一个叫“属性”,一个叫“特性”,很容易混淆,简单说来:

具体到vue中,我的理解是,如果用v-bind绑定(也就意味着子组件一定有props接收它,否则会报错),那它就是property,本质上是JS变量传值;如果是用普通的等号传给子组件一个写死的值 (比如color="#21C9A6") 且子组件的props里有接收这个值(比如props里有 color: String),那么它也是property

其他情况下,子组件没有props来接收这个属性,那么就是非props的 attribute ,会被当作字符串内联到html文档里,也就是接下来要讲的东西。

非prop的attribute

来自vue官方文档的描述:

一个非 prop 的 attribute 是指传向一个组件,但是该组件并没有相应 prop 定义的 attribute。

举个例子:
自定义一个test组件,并接受父组件传来的test1 test2 class style 属性,其中 test1 属性在props里被接收,并在模板中显示用$attrs显示。

    <div id="app">
        <test :test1='test1' test2='test2' class="container" style="color:red"></test>
    </div>
    <script>
        Vue.component('test',{
            props:['test1'],
            template:`
                <div>
                    {{this.$attrs}} 
                </div>
            `
        })
        var vm = new Vue({
            el:'#app',
            data:{
                test1:'haha'
            }  
        })
    </script>

关于$attrs,vue的官方文档这么描述:

包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (classstyle除外)。

最终$attrs显示的结果如下,因为只有test属性满足:即不是class,style这种每个html标签共有的属性,也没有被子组件的props接收,所以$attrs中只有一个属性test2
在这里插入图片描述
并且我们可以看到,非props属性被当成字符串内联到了html文档中,就像classstyle那样,虽然没有任何人知道test2属性是什么意思,但不妨碍它存在。

在这里插入图片描述

禁用 Attribute 继承

默认情况下,子组件的根元素会接收父组件绑定来的attribute,如果想禁止这一行为,就需要在子组件里把inheritAttrs属性手动设为false(默认是true)。这一点搭配子组件的$attrs属性就可以起到指定子组件template中的哪一个元素来继承父组件绑定的attribute的作用。

例如,我这里不想让label元素继承test2,想让里面的div元素继承test2:

    <div id="app">
        <test :test1='test1' test2='test2' class="container" style="color:red"></test>
    </div>
    <script>
        Vue.component('test',{
            inheritAttrs: false, //禁止label根元素继承attribute
            props:['test1'],
            template:`
            <label>
                <div v-bind='$attrs'>
                    {{this.$attrs}}
                </div>
            </label>
            `
        })
        var vm = new Vue({
            el:'#app',
            data:{
                test1:'haha'
            }  
        })
    </script>

可以看到,test2被内联在了div而不是根元素label上。
在这里插入图片描述

接下来,理解官方文档中的例子就不难了:
<base-input>组件中根元素是模板中的<label>,然而<label>绑定username数据,requiredplaceholder特性是没有卵用的,我们应该将它绑定给内层的<input>标签,于是有了下面这段代码:

Vue.component('base-input', {
  inheritAttrs: false, 禁止label根元素继承attribute
  props: ['label', 'value'],
  template: `
    <label>
      {{ label }}
      <input
        v-bind="$attrs"
        v-bind:value="value"
        v-on:input="$emit('input', $event.target.value)"
      >
    </label>
  `
})

然后在html中就可以像用原生<input>标签一样用<base-input>了,而不用担心哪个元素是真正的根元素:

<base-input
  v-model="username"
  required
  placeholder="Enter your username"
></base-input>
  • 13
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值