Vue 3.0的attribute强制行为理解学习

目录
  • 理解property和attribute
    • property
      • 形容词
      • 名词
    • attribute
  • vue3中的property和attribute
    • xml中的属性节点
  • vue3.0的attribute强制行为
  • 源代码分析
  • vue3.0的变化

理解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。常见的示例包括 classstyle 和 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. 这些属性值的可能情况是有限的

值得一提的是draggablecontenteditable都是枚举属性,虽然它们看起来像是布尔类型。

那么这两种类型的属性,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强制行为的资料请关注我们其它相关文章!

(0)

相关推荐

  • 浅谈js中的attributes和Attribute的用法与区别

    一:Attribute的几种用法和含义(attributes和Attribute都是用来操作属性的) getAttribute:获取某一个属性的值: setAttribute:建立一个属性,并同时给属性捆绑一个值: createAttribute:仅建立一个属性: removeAttribute:删除一个属性: getAttributeNode:获取一个节点作为对象: setAttributeNode:建立一个节点: removeAttributeNode:删除一个节点: 1.getAttrib

  • 关于.NET Attribute在数据校验中的应用教程

    前言 Attribute(特性)的概念不在此赘述了,相信有点.NET基础的开发人员都明白,用过Attribute的人也不在少数,毕竟很多框架都提供自定义的属性,类似于Newtonsoft.JSON中JsonProperty.JsonIgnore等 自定义特性 .NET 框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索.该信息根据设计标准和应用程序需要,可与任何目标元素相关. 创建并使用自定义特性包含四个步骤: 声明自定义特性 构建自定义特性 在目标程序元素上应用自定义特性 通过反

  • JS removeAttribute()方法实现删除元素的某个属性

    在 JavaScript 中,使用元素的 removeAttribute() 方法可以删除指定的属性.用法如下: removeAttribute(name) 参数 name 表示元素的属性名. 示例1 下面示例演示了如何动态设置表格的边框. <script> window.onload = function () { //绑定页面加载完毕时的事件处理函数 var table = document.getElementByTagName("table")[0]; //获取表格

  • vue中的attribute和property的具体使用及区别

    目录 作为 attribute 和 property 的 value 及 Vue.js 的相关处理 attribute 和 property 的概念 attribute 和 property 的绑定 Vue.js 对 value 的处理 一般情况使用 :value 特殊情况使用 :value.prop 总结 作为 attribute 和 property 的 value 及 Vue.js 的相关处理 attribute 和 property 是 Web 开发中,比较容易混淆的概念,而对于 val

  • JS中DOM元素的attribute与property属性示例详解

    一.'表亲戚':attribute和property 为什么称attribute和property为'表亲戚'呢?因为他们既有共同处,也有不同点. attribute 是 dom 元素在文档中作为 html 标签拥有的属性: property 是 dom 元素在 js 中作为对象拥有的属性. 从定义上可以看出: 对于 html 的标准属性来说,attribute 和 property 是同步的,是会自动更新的 但是对于自定义的属性来说,他们是不同步的.(自定义属性不会自动添加到property)

  • Vue 3.0的attribute强制行为理解学习

    目录 理解property和attribute property 形容词 名词 attribute vue3中的property和attribute xml中的属性节点 vue3.0的attribute强制行为 源代码分析 vue3.0的变化 理解property和attribute 这个要看具体的语境了.不过我们可以从词源的角度来区分一下这两者: property 形容词 property的词源可追溯到proper,意为合适的,适当的. 短语示例: a proper job 一份合适(自己的)

  • 对vue.js中this.$emit的深入理解

    对于vue.js中的this.emit的理解:this.emit('increment1',"这个位子是可以加参数的"):其实它的作用就是触发自定义函数. 看例子: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <script src="vue.js"

  • Vue 2.0 侦听器 watch属性代码详解

    用法 -------------------------------------------------------------------------------- 先来看看官网的介绍: 官网介绍的很好理解了,也就是监听一个数据的变化,当该数据变化时执行我们的watch方法,watch选项是一个对象,键为需要观察的表达式(函数),还可以是一个对象,可以包含如下几个属性: handler        ;对应的函数                          ;可以带两个参数,分别是新的值

  • 详解Vue.js3.0 组件是如何渲染为DOM的

    本文主要是讲述 Vue.js 3.0 中一个组件是如何转变为页面中真实 DOM 节点的.对于任何一个基于 Vue.js 的应用来说,一切的故事都要从应用初始化「根组件(通常会命名为 APP)挂载到 HTML 页面 DOM 节点(根组件容器)上」说起.所以,我们可以从应用的根组件为切入点. 主线思路:聚焦于一个组件是如何转变为 DOM 的. 辅助思路: 涉及到源代码的地方,需要明确标记源码所在文件,同时将 TS 简化为 JS 以便于直观理解 思路每前进一步要能够得出结论 尽量总结归纳出流程图 应用

  • vue cli4.0 如何配置环境变量

    目录 1.创建不同环境变量文件 2.给.env文件添加内容 3.在package.json中添加不同环境对应的执行语句 4.使用 温馨提示:本文只适用于vue-cli 3.0及以上的版本哦~ ------------------正文开始------------------ 开发项目时,经常会需要在不同环境中切换.那么我们如何配置不同的环境变量呢? 为了更加方便消化本文章,建议先看下官方文档: 环境变量和模式 看完官方的文档如果还没有明白,可以参考本文. 在vue-cli构建的项目中,默认有3种模

  • vue 3.0 使用ref获取dom元素的示例

    前言 附上vue3.0文档:Vue3中文文档 - vuejs Vue 2.x获取DOM <div ref="myRef"></div> this.$refs.myRef Vue 3.0获取单个DOM <template> <div ref="myRef">获取单个DOM元素</div> </template> <script> import { ref, onMounted } fr

  • Vue.js2.0中的变化小结

    最近自己在学习Vue.js,在看一些课程的时候可能Vue更新太块了导致课程所讲知识和现在Vue的版本不符,从而报错,我会在以后的帖子持续更新Vue的变化与更新,大家也可以一起交流,共同监督学习! 1.关于Vue中$index获取索引值已经取消,多用于多个元素的操作,像ul中的li,通过v-for来建立多个li,如果对于其中的某个或者一些li操作的话,需要使用到索引值,用法如下; <template> <div class="hello"> <h1>{

  • 使用vue.js2.0 + ElementUI开发后台管理系统详细教程(二)

    在上篇文章给大家介绍了使用vue.js2.0 + ElementUI开发后台管理系统详细教程(一) 1. 引入路由工具vue-router,切换视图 # 安装vue-router cnpm install vue-router --save-dev 2. 使用vue-router main.js import Vue from 'vue' import App from './App' import VueRouter from 'vue-router' import routeConfig f

  • vue router2.0二级路由的简单使用

    本文实例为大家分享了vue router2.0二级路由的具体代码,供大家参考,具体内容如下 1.app.vue中 <template> <div id="app"> <router-view></router-view> </div> </template> 2.router中index.js(路由的路径配置) import Vue from 'vue' import Router from 'vue-router

  • 使用vue.js2.0 + ElementUI开发后台管理系统详细教程(一)

    1. 根据官方指引,构建项目框架 # 安装vue $ cnpm install vue@2.1.6 # 全局安装 vue-cli $ cnpm install --global vue-cli # 创建一个基于 webpack 模板的新项目my-project $ vue init webpack my-project # 进入项目目录 $ cd my-project # 安装依赖,走你 $ cnpm install # 运行项目 $ cnpm run dev 2. 运行项目之后,会看到以下界面

随机推荐