• 【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是为了方便开发者,在底层的实现上,必须需要对值进行正常化后再使用

  • 相关阅读:
    物联公司网页设计制作 简单静态HTML网页作品 静态企业网页作业成品 学生网站模板
    mac有些软件无法删除,CleanMyMac X 4.14.3轻松帮你解决
    Lua05——Lua基本数据类型
    centos php 启动命令
    数据库事务中“锁”的分类
    泛型的使用案例,以及年月日的定制排序,传入Comparator对象
    【统计学概念】初学者指南:了解置信区间
    老实说,分支预测,是高手过招的杀手锏,但是对写业务代码没啥帮助。
    守护线程?
    一些编程的基础
  • 原文地址:https://blog.csdn.net/loyd3/article/details/125967516