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


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

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

    该模板对应的vnode是:

    const vnode = {
    	type: 'p',
    	props: {
    		class: 'foo bar'
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

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

    假设对象cls的内容如下:

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

    其对应的vnode是:

    const vnode = {
    	type: 'p',
    	props: {
    		class: {foo:true, bar:false}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

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

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

    const arr = [
    	// 字符串
    	'foo bar',
    	{
    		baz: true
    	}
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    其对应的vnode是

    const vnode = {
    	type: 'p',
    	props: {
    		class: [
    			'foo bar',
    			{ baz: true }
    		]
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    const vnode = {
    	type: 'p',
    	props: {
    		// 通过normalizeClass进行序列化
    		class: normalizeClass([
    			'foo bar',
    			{baz:true}	
    		])
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    最后等价为

    const vnode = {
    	type: 'p',
    	props: {
    		class:'foo bar baz'
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    至于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)
    		}
    	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

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

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

  • 相关阅读:
    Promise从入门到精通 (第二章 Promise的理解和使用)
    Hibernate知识大合集
    B. Trouble Sort
    R语言生物群落(生态)数据统计分析与绘图教程
    “蔚来杯“2022牛客暑期多校训练营5 B、C、F、G、H、K
    SVM 超平面计算例题
    找不到conda可执行文件:解决方法
    基于Mxnet实现语义分割-整体多模型【完整、附部分源码】
    vue引入vant框架
    (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • 原文地址:https://blog.csdn.net/loyd3/article/details/125967516