attribute 和 property 是 Web 开发中,比较容易混淆的概念,而对于 value,因其特殊性,更易困惑,本文尝试做一下梳理和例证

attribute 和 property 的概念

简单的说,attribute 是元素标签的属性,property 是元素对象的属性,例如:

<input id="input" value="test value">
<script>
let input = document.getElementById('input');
console.log(input.getAttribute('value')); // test value
console.log(input.value); // test value
</script>
  • input 的 value attribute 是通过标签里的 value="test value" 定义的,可以通过 input.getAttribute('value') 获取,可以通过 input.setAttribute('value', 'New Value') 更新
  • input 的 value property 可通过 input.value 获取和更新,初始值是与 attribute 中的赋值一致的

attribute 和 property 的绑定

如果在最开始的时候,更新 attribute value 的值,property 的值也会随之改变

但是更新 property value 的值(在文本框输入或给 input.value 赋新值 ),attribute 的值不会随之改变,而且此时再更新 attribute 的值,property 的值也不再随之改变,如此动画所示,也可访问此页面尝试进行操作

这其实是脏值标记(dirty value flag)在起作用,dirty value flag 的初始值为 false,即 attribute value 的更新默认会改变对应的 property value,但是一旦用户交互修改了 property value,dirty value flag 的值就变为 true,即attribute value 的更新就不会改变对应的 property value 了

所以在实际项目中,我们一般都是在处理作为 property 的 value

Vue.js 对 value 的处理

一般情况使用 :value

Vue.js 的 v-bind,一般情况下是在处理 attribute,如果要作为 property 处理的话,需要加上 .prop

不过 v-bind:value 却大都默认为处理 property 值,因为被强制转化了,例如:

<input id="input" :value="'test value'" >
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let input = new Vue({
el: '#input',
mounted () {
console.log(this.$el.getAttribute('value')); // null
console.log(this.$el.value); // test value
console.log(this._vnode.data) // {attrs: {id: "input"}, domProps: {value: "test value"}}
}
});
</script>

可见,Vue.js 将 value 作为 VNode 的 data 中的 domProps 的属性,而不是 attrs 的属性,所以挂载后会成为作为 property 的 value

在 Vue.js 源码中,强制转化 property 的处理如下:

// src/compiler/parser/index.js
function processAttrs (el) {
...
if ((modifiers && modifiers.prop) || (
!el.component && platformMustUseProp(el.tag, el.attrsMap.type, name)
)) {
addProp(el, name, value, list[i], isDynamic)
} else {
addAttr(el, name, value, list[i], isDynamic)
}

其中 platformMustUseProp 在 web 平台的定义如下:

// src/platforms/web/util/attrs.js
const acceptValue = makeMap('input,textarea,option,select,progress')
export const mustUseProp = (tag: string, type: ?string, attr: string): boolean => {
return (
(attr === 'value' && acceptValue(tag)) && type !== 'button' ||
(attr === 'selected' && tag === 'option') ||
(attr === 'checked' && tag === 'input') ||
(attr === 'muted' && tag === 'video')
)
}

由上可知,类型不为 button 的 input, textarea, option, select, progress 的 value 会强制作为 property,而不需要设置为 :value.prop

例如 textarea 标签,其本身其实并不支持 value attribute,所以以下代码中的 value 的值并不会显示在多行文本框中

<textarea value="test value"></textarea>

但是在 Vue.js 中, 以下代码能成功绑定到 value property 并显示在多行文本框中

<textarea :value="'test value'"></textarea>

特殊情况使用 :value.prop

以上 Vue.js 源码需要注意的还有,强制作为 property, 还要满足 !el.component,即不为动态组件,因为动态组件的 el.component 的值为其 is attribute 的值

即动态组件的的 v-bind 默认都是作为 attribute的,如果要作为 property,就要使用 .prop,例如:

<div id="app">
<component :is="element" :value.prop="'test value'"></component>
<button @click="change">Change</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
element: 'input'
},
methods: {
change () {
this.element = 'input' === this.element ? 'textarea' : 'input';
}
}
});
</script>

如果以上 component 中,删除 :value.prop 的 .prop,切换到 textarea 时,其值就不会显示在多行文本框中,可以在此页面点击切换标签查看

总结

  • 作为 attribute 和 property 的 value 的绑定关系会在用户交互更新值后失效
  • Vue.js 一般使用 :value 即可让 value 作为 property
  • Vue.js 动态模版需要使用 :value.prop 才可让 value 作为 property

作为 attribute 和 property 的 value 及 Vue.js 的相关处理的更多相关文章

  1. Vue.js 插件开发详解

    前言 随着 Vue.js 越来越火,Vue.js 的相关插件也在不断的被贡献出来,数不胜数.比如官方推荐的 vue-router.vuex 等,都是非常优秀的插件.但是我们更多的人还只停留在使用的阶段 ...

  2. 前端架构之路:使用Vue.js开始第一个项目

    Vue.js做为目前前端最热门的库之一,为快速构建并开发前端项目多了一种思维模式.本文通过一个简单的实例开始上手Vue.js开发.   一.技术准备 笔者建议在开始项目前,对以下两个技术点进行了解. ...

  3. Vue.js 学习笔记 第5章 内置指令

    本篇目录: 5.1 基本指令 5.2 条件渲染指令 5.3 列表渲染指令 v-for 5.4 方法与事件 5.5 实战:利用计算属性.指令等知识开发购物车 回顾一下第2.2节,我们己经介绍过指令(Di ...

  4. vue.js路由vue-router

    学习网址:https://segmentfault.com/blog/vueroad 转载至:https://segmentfault.com/a/1190000009350679#articleHe ...

  5. 浅尝Vue.js组件(一)

    本篇目录: 组件名 组件注册 全局注册 基础组件的自动化全局注册 局部注册 在模块系统中局部注册 Prop 单向数据流 Prop验证 类型检查 非Prop特性 替换/合并已有的特性 禁用特性继承 自定 ...

  6. 学习vue.js的正确姿势(转载)

    最近饶有兴致的又把最新版 Vue.js 的源码学习了一下,觉得真心不错,个人觉得 Vue.js 的代码非常之优雅而且精辟,作者本身可能无 (bu) 意 (xie) 提及这些.那么,就让我来吧:) 程序 ...

  7. Vue.js开始第一个项目

    前端架构之路:使用Vue.js开始第一个项目   Vue.js做为目前前端最热门的库之一,为快速构建并开发前端项目多了一种思维模式.本文通过一个简单的实例开始上手Vue.js开发. 一.技术准备 使用 ...

  8. vue.js路由vue-router(一)——简单路由基础

    前言 vue.js除了拥有组件开发体系之外,还有自己的路由vue-router.在没有使用路由之前,我们页面的跳转要么是后台进行管控,要么是用a标签写链接.使用vue-router后,我们可以自己定义 ...

  9. Vue.js+vue-element搭建属于自己的后台管理模板:什么是Vue.js?(一)

    Vue.js+vue-element搭建属于自己的后台管理模板:Vue.js是什么?(一) 前言 本教程主要讲解关于前端Vue.js框架相关技术知识,通过学习一步一步学会搭建属于自己的后台管理模板,并 ...

随机推荐

  1. vue开发路由相关基础知识和笔记

    路由实现:hash模式 和 history模式 hash模式: 概述 在浏览器中符号"#",#以及#后面的字符称之为hash,用window.location.hash读取: 特点 ...

  2. python框架Django实战商城项目之工程搭建

    项目说明 该电商项目类似于京东商城,主要模块有验证.用户.第三方登录.首页广告.商品.购物车.订单.支付以及后台管理系统. 项目开发模式采用前后端不分离的模式,为了提高搜索引擎排名,页面整体刷新采用j ...

  3. python爬虫的数据库连接问题

    1.需要导的包 import pymysql 2.# mysql连接信息(字典形式) db_config ={ 'host': '127.0.0.1',#连接的主机id(107.0.0.1是本机id) ...

  4. 【猫狗数据集】使用预训练的resnet18模型

    数据集下载地址: 链接:https://pan.baidu.com/s/1l1AnBgkAAEhh0vI5_loWKw提取码:2xq4 创建数据集:https://www.cnblogs.com/xi ...

  5. 前端要了解的seo

    一.搜索引擎工作原理 当我们在输入框中输入关键词,点击搜索或查询时,然后得到结果.深究其背后的故事,搜索引擎做了很多事情. 在搜索引擎网站,比如百度,在其后台有一个非常庞大的数据库,里面存储了海量的关 ...

  6. js 统计一个字符串中出现的字符最多的字符

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. 简单认识并使用JavaScript【供后端人员作为了解】

    JS(JavaScript)Web的脚本语言 脚本语言:无法独立执行,必须嵌入到其他语言当中结合使用 作用:控制页面特效展示 注:JavaScript没有访问系统的权限,并且JavaScript和Ja ...

  8. [Alg] 文本匹配-单模匹配与多模匹配

    实际场景: 网站的用户发了一些帖子S1, S2,...,网站就要审核一下这些帖子里有没有敏感词. 1. 如果网站想查一下帖子里有没有一个敏感词P,这个文本匹配要怎么做更快? 2. 如果网站想查一下帖子 ...

  9. Github Pages访问太慢?通过Netlify免费加速

    github pages vs netlify Github Pages为Github提供的一项静态站点托管服务,它直接从Github仓库获取静态文件进行发布,然后提供一个github.io的二级域名 ...

  10. VS2019 C++动态链接库的创建使用(2) - 客户调用接口

    因为动态链接库里的内容是自己定义的,所以在外部程序调用时我们自己知道库里包含哪些变量和函数,如果我们提供库给其他人使用,则最好增加一个头文件,告知库里包含的函数: ①将动态链接库源文件内容增加红色框内 ...