理解property和attribute
这个要看具体的语境了。不过我们可以从词源的角度来区分一下这两者:
property
形容词
property 的词源可追溯到 proper ,意为合适的,适当的。
短语示例:
a proper job 一份合适(自己的)工作名词
proper加上ty后缀变为名词prproperty,意为特性
短语示例:
chemical property 化学性质,比如酒精易挥发的化学性质。
attribute
an abstraction belonging to or characteristic of an entity
对实体的抽象或者特征描述。
比如,我们谈论一条鱼这个实体,说这条鱼具有对称性,此时我们的意思是这条鱼具有这个属性,而不是说只有这条鱼具有对称性。
这样总结下来,property是attribute的子集,property代表专属于一个实体的属性。
但是在编码的过程中,程序员总有抽象不完善的情况,这也是为什么property和attribute会混淆的原因。
vue3中的property和attribute
在vue3中property也就是props所定义的一个组件的属性,这些属性会由组件接收,同时在接收的时候会对其进行校验数据类型和值的正确性。
如下一段代码很好地解释了vue3中什么是property:
class User { _name set name(name) { if(!name) { alert('名称不能为空') } this._name = name } get name() { return this._name } }
而attribute则更像没人管的野孩子。下面一段介绍是vue3对非prop的attribute的描述:
一个非 prop 的 attribute 是指传向一个组件,但是该组件并没有相应 props 或 emits 定义的 attribute。常见的示例包括 class 、 style 和 id attribute。可以通过 $attrs property 访问那些 attribute。
xml中的属性节点
html 所构成的 dom 树,元素节点上的 attribute 的类型是属性节点,也是树的一个level。
dom api 在处理这些属性时,如果是对象的 property ,则会交由对象的 property 处理器去处理,而如果对象没有相应的 property ,则会将由 xml 解析出来的 attribute 添加到 attributes 这个属性上去。
vue3.0的attribute强制行为
接触过强类型语言比如Java的都会知道【 强制类型转换 】这样一个术语。
int i = (int)(1.23);
vue框架在编译模板代码时也会进行类似的【 强制类型转换 】
模板代码如下:
<template> <div id="draggable" draggable /> </template>
在vue2中,上述的模板会被渲染为:
<div id="draggable" draggable="true" />
在vue3中,上述的模板会被渲染为:
<div id="draggable" draggable=""></div>
也就是说vue3中没有强制行为,你在模板中看到的就是最终的渲染结果。
源代码分析
function setAttr(el: Element, key: string, value: any, isInPre?: any) { if (isInPre || el.tagName.indexOf('-') > -1) { baseSetAttr(el, key, value) } else if (isBooleanAttr(key)) { // set attribute for blank value // e.g. <option disabled>Select one</option> if (isFalsyAttrValue(value)) { el.removeAttribute(key) } else { // technically allowfullscreen is a boolean attribute for <iframe>, // but Flash expects a value of "true" when used on <embed> tag value = key === 'allowfullscreen' && el.tagName === 'EMBED' ? 'true' : key el.setAttribute(key, value) } } else if (isEnumeratedAttr(key)) { el.setAttribute(key, convertEnumeratedValue(key, value)) } else if (isXlink(key)) { if (isFalsyAttrValue(value)) { el.removeAttributeNS(xlinkNS, getXlinkProp(key)) } else { el.setAttributeNS(xlinkNS, key, value) } } else { baseSetAttr(el, key, value) } } function baseSetAttr(el, key, value) { if (isFalsyAttrValue(value)) { el.removeAttribute(key) } else { // #7138: IE10 & 11 fires input event when setting placeholder on // <textarea>... block the first input event and remove the blocker // immediately. /* istanbul ignore if */ if ( isIE && !isIE9 && el.tagName === 'TEXTAREA' && key === 'placeholder' && value !== '' && !el.__ieph ) { const blocker = e => { e.stopImmediatePropagation() el.removeEventListener('input', blocker) } el.addEventListener('input', blocker) // $flow-disable-line el.__ieph = true /* IE placeholder patched */ } el.setAttribute(key, value) } } export const convertEnumeratedValue = (key: string, value: any) => { return isFalsyAttrValue(value) || value === 'false' ? 'false' : // allow arbitrary string value for contenteditable key === 'contenteditable' && isValidContentEditableValue(value) ? value : 'true' } export const isBooleanAttr = makeMap( 'allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,' + 'default,defaultchecked,defaultmuted,defaultselected,defer,disabled,' + 'enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,' + 'muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,' + 'required,reversed,scoped,seamless,selected,sortable,' + 'truespeed,typemustmatch,visible' ) export const isEnumeratedAttr = makeMap('contenteditable,draggable,spellcheck')
vue2 在解析模板之后,得到了关于dom结构的js对象描述。
通过调用 dom api 来创建节点并为节点添加属性【 setAttribute 】。
大致分为:
布尔类型属性The values "true" and "false" are not allowed on boolean attributes. To represent a false value, the attribute has to be omitted altogether.
也就是说布尔类型的值如果没有这个属性则是false,有了这个属性,则不论其属性值是false还是true,都会被浏览器解析为true.
枚举属性Some attributes, called enumerated attributes, take on a finite set of states. 这些属性值的可能情况是有限的
值得一提的是 draggable 和 contenteditable 都是枚举属性,虽然它们看起来像是布尔类型。
那么这两种类型的属性, vue2.0 是怎么处理的呢?
首先vue的自定义组件是不在这两种处理范畴之内的。 对于布尔类型值, vue 模板则不会一棍子打死,如果真的是 falsy 值, vue 框架会自动帮你去除掉这个属性,调用 removeAttribute 方法。至于allowfullscreen这个虽然是一个boolean类型的值,但用在embed标签上,则要求是 true 。 其次,如果是枚举类型的值,则会对枚举类型的值进行转化。如果是falsy的值,则为'false'。可枚举类型的值实际上就3个 contenteditable,draggable,spellcheck ,如果是 contenteditable 则按照所见即所得的原则处理,其他都强制转换为 true 。 最后,不在上述情况的属性,则是如果是falsy的值,则移除,其他的值则是原样设置。
vue3.0的变化
删除枚举 attribute 的内部概念,并将这些 attribute 视为普通的非布尔 attribute 重大改变 :如果值为布尔值,则不再删除 attribute false 。相反,它被设置为 attr=[false]。移除 attribute,使用 null 或者 undefined 。vue3不再强制变更属性值,这样有了所见即所得的效果,可以解除正常四维对于这些诡异行为的困惑。
至于为什么要这样做,仁者见仁,智者见智。
以上就是Vue 3.0的attribute强制行为理解学习的详细内容,更多关于Vue attribute强制行为的资料请关注其它相关文章!
查看更多关于Vue 3.0的attribute强制行为理解学习的详细内容...