【vue设计与实现】挂载和更新 3-class的处理

在Vue.js中,仍然有一些属性需要特殊处理,比如class属性。这是因为Vue.js对class属性做了增强。
在Vue.js中为元素设置类名有以下几种方式:
方式一:指定class为一个字符串值

<p class="foo bar"></p>

该模板对应的vnode是:

const vnode = {
	type: 'p',
	props: {
		class: 'foo bar'
	}
}

方式二:指定class为一个对象值。

<p :class="cls"></p>

假设对象cls的内容如下:

const cls = {foo:true, bar:false}

其对应的vnode是:

const vnode = {
	type: 'p',
	props: {
		class: {foo:true, bar:false}
	}
}

方式三:class是包含上面两种情况的数组

<p :class="arr"></p>

这个数组时字符串值和对象值的组合

const arr = [
	// 字符串
	'foo bar',
	{
		baz: true
	}
]

其对应的vnode是

const vnode = {
	type: 'p',
	props: {
		class: [
			'foo bar',
			{ baz: true }
		]
	}
}

正因为class的值是多种类型的,所以必须在设置元素的class之前将值转化为统一的字符串形式,再把改字符串作为元素的class值去设置。因此需要通过封装一个normalizeClass函数,来达成需求,例如:

const vnode = {
	type: 'p',
	props: {
		// 通过normalizeClass进行序列化
		class: normalizeClass([
			'foo bar',
			{baz:true}	
		])
	}
}

最后等价为

const vnode = {
	type: 'p',
	props: {
		class:'foo bar baz'
	}
}

至于normalizeClass函数的实现,后面再做详细介绍。

在获得正常化的class值后,接下来就是如果将其设置到元素上,而在浏览器中为一个元素设置class有三种方式,即setAttribute,el.className和el.classList,而其中className的性能最好,所以要调整patchProps函数,使用className来设置class属性,代码如下:

const renderer = createRenderer({
	// 省略其他选项
	
	patchPros(el,key,preValue,nextValue){
		if(key==='class'){
			el.className = nextValu || ''
		}else if(shouldSetAsProps(el,key,nextValue)){
			const type = typeof el[key]
			if(type === 'boolean' && nextValue=== ''){
				el[key] = true
			}else{
				el[key] = nextValue
			}
		}else{
			el.setAttribute(key, nextValue)
		}
	}
})

其实除了class属性外,对style属性也做了增强,所以对style也是相似的处理。

通过对class的处理,可以看到vnode.props对象中定义的属性值的类型并不总是和DOM元素属性的数据结构保持一致,这取决于上层API的设计。Vue.js允许对象类型的值作为class是为了方便开发者,在底层的实现上,必须需要对值进行正常化后再使用

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值