(2020-12-29)谈谈vue.js中inheritAttrs和$attrs的用法

  • inheritAttrs和$attrs的简介

首先我们可以先参考一下官方文档中对它们两个的介绍:

attrs的介绍包含了父作用域中不作为prop被识别(且获取)的特性绑定(class和style除外)。当一个组件没有声明任何prop时,这里会包含所有父作用域的绑定(class和style除外),并且可以通过v−bind="attrs" 传入内部组件——在创建更高层次的组件时非常有用。
inheritAttrs的介绍默认情况下父作用域的不被认作 props 的特性绑定 (attribute bindings) 将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例属性 $attrs 可以让这些特性生效,且可以通过 v-bind 显性的绑定到非根元素上。

猛的一看,会有点看不明白,所以我写了几个简单的demo用来描述它两的作用以及关系。

  • demo1

	<body>
		<div id="app">
			<my-com title="标题" l-attr1="自定义属性1" l-attr2="自定义属性2" class="mycom" style="color:red"></my-com>
		</div>
		<script type="text/javascript">
			// 创建组件
			Vue.component("my-com",{
				inheritAttrs:false,
				props:{
					title:String
				},
				template:`
				<div l-attr1 = "hello" class="div" style="width:500px">
					<h1>{{title}}</h1>
				</div>
				`,
			});
			// 创建实例对象
			var app = new Vue({
				el:"#app",
				data:{
					
				},
				methods:{
					
				}
			});
		</script>
	</body>

 我们可以看到这是一个非常简单的vue组件demo,我创建了一个my-com组件,并添加了两个自定义属性,理论上属性会在代码执行的过程中,通信到模板div标签中去,但是我在组件中添加了inheritAttrs:false让我们执行一下,看看会有什么作用?

奇怪的事情发生了,my-com标签中的属性并没有通信进来,相反class和style并没有受到什么影响,这里我们赶快记录一下,将inheritAttrs设置为false时会阻断组件间自定义属性的通信。

  • demo2

<body>
		<div id="app">
			<my-com title="标题" l-attr1="自定义属性1" l-attr2="自定义属性2" class="mycom" style="color:red"></my-com>
		</div>
		<script type="text/javascript">
			// 创建组件
			Vue.component("my-com",{
				inheritAttrs:false,
				props:{
					title:String
				},
				template:`
				<div l-attr1 = "hello" class="div" style="width:500px" v-bind="$attrs">
					<h1>{{title}}</h1>
				</div>
				`,
			});
			// 创建实例对象
			var app = new Vue({
				el:"#app",
				data:{
					
				},
				methods:{
					
				}
			});
		</script>
	</body>

我们可以看到此代码段中同时设置和绑定了inheritAttrs,$attrs属性,那么会有什么结果呢?

虽然inheritAttrs设置的是false,按照官方理论来说,会阻止组件间的通信,我们在my-com标签中的行内自定义属性是不能传递到模板中去的,但是因为模板绑定了$attrs属性,导致my-com的自定义属性依旧可以传递到模板中去。

通过这个案例我们不难看出虽然$attrs可以解除inheritAttrs设置成false的功能,但是相同的属性名,并不能进行覆盖,模板中原有的l-attr1属性值依旧是hello,并没有被覆盖,同学们一定要注意这一点细微的差别。

  • demo3

<body>
		<div id="app">
			<my-com title="标题" l-attr1="自定义属性1" l-attr2="自定义属性2" class="mycom" style="color:red"></my-com>
		</div>
		<script type="text/javascript">
			// 创建组件
			Vue.component("my-com",{
				inheritAttrs:true,
				props:{
					title:String
				},
				template:`
				<div l-attr1 = "hello" class="div" style="width:500px">
					<h1>{{title}}</h1>
				</div>
				`,
			});
			// 创建实例对象
			var app = new Vue({
				el:"#app",
				data:{
					
				},
				methods:{
					
				}
			});
		</script>
	</body>

 我们将inheritAttrs设置成true看看效果。

果然是正常通信的,my-com标签中的两个自定义属性全部进入,并且把相同属性名的属性进行了渲染,改变了原有属性值,这点一定要注意,会改变组件中原有属性值。

  • demo4

<body>
		<div id="app">
			<my-com title="标题" l-attr1="自定义属性1" l-attr2="自定义属性2" class="mycom" style="color:red"></my-com>
		</div>
		<script type="text/javascript">
			// 创建组件
			Vue.component("my-com",{
				inheritAttrs:true,
				props:{
					title:String
				},
				template:`
				<div l-attr1 = "hello" class="div" style="width:500px" v-bind="$attrs">
					<h1>{{title}}</h1>
				</div>
				`,
			});
			// 创建实例对象
			var app = new Vue({
				el:"#app",
				data:{
					
				},
				methods:{
					
				}
			});
		</script>
	</body>

 我们同样继续在模板中绑定上$attrs试试,结果会有什么不同呢?

结果与inheritAttrs设置成true的效果是一致的,看来我们重点要关注的inheritAttrs设置成false的状态下,绑定$attrs的效果。

  • 最后总结

通过这四个简单的案例我们可以轻松发现它俩之间存在的关系的作用:

inheritAttrs属性和$attrs属性的关系
inheritAttrs为false,不绑定$attrs属性会阻断回退的默认行为,保证根元素不会将自己的属性传递给子组件身上。
inheritAttrs为false,绑定$attrs属性不会阻断回退的默认行为,根元素的组件中的属性会传递给子组件身上,但是相同属性名的属性值不会改变。
inheritAttrs为true,不绑定$attrs属性不会阻断回退的默认行为,根元素的组件中的属性会传递给子组件身上,相同属性名的属性值会被渲染替换。
inheritAttrs为true,绑定$attrs属性不会阻断回退的默认行为,根元素的组件中的属性会传递给子组件身上,相同属性名的属性值会被渲染替换。

注意:这些操作均不影响 class 和 style 绑定。

博主水平有限,请大家指正!辛苦大家翻阅!谢谢!

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值