详解vue v-model


Posted in Javascript onAugust 31, 2020

1. v-model原理

vue中v-model是一个语法糖,所谓的语法糖就是对其他基础功能的二次封装而产生的功能。简单点说,v-model本身就是父组件对子组件状态以及状态改变事件的封装。其实现原理上分为两个部分:

通过props设置子组件的状态
通过监听子组件发出的事件改变父组件的状态,从而影响子组件的props值
通过以上两个部分,实现了父组件的状态和子组件状态进行了绑定的效果。

1.1 demo

v-model使用示例

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8" />
 <title>v-model示例</title>
 <script type="text/javascript" src="vue.js"></script>
 </head>

 <body>
 <div id="app">
 <div>这里是父组件的状态:</div>
 <div style="margin-bottom: 15px;">{{content}}</div>
 <Child v-model="content"></Child>
 </div>

 <template id="input">
 <div>
 <div>这里是子组件的输入区域:</div>
 <input :value="value" @input="contentChange" />
 </div>
 </template>

 <script type="text/javascript">
 var Child = {
 template: "#input",
 props: {
 value: {
 type: String,
 required: true
 }
 },
 methods: {
 contentChange(value){
 this.$emit("input", value.target.value);
 }
 }
 };

 var vueInstance = new Vue({
 el: "#app",
 components: {Child},
 data: {
 content: ""
 }
 })
 </script>
 </body>
</html>

在浏览器中打开上述html页面,可以看到实时效果:在子组件中的input框中输入内容可以在父组件区域实时显示,达到了子组件中状态和父组件状态实时绑定的效果。

2. 修改v-model默认监听的事件和设置prop的名称

v-model指令默认是在子组件上设置的prop名称是value,默认监听子组件上的input事件,在上面的demo上,如果我们修改子组件contentChange函数中发出的事件名称,在父组件中就无法实时获取到子组件的输入。

Vue中提供了通过在子组件上定义model属性来修改这两个参数名称的功能,不过该功能需要在版本2.2以上才能使用,如下demo所示:

2.1 demo

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8" />
 <title>v-model示例</title>
 <script type="text/javascript" src="vue.js"></script>
 </head>

 <body>
 <div id="app">
 <div>这里是父组件的状态:</div>
 <div style="margin-bottom: 15px;">{{content}}</div>
 <Child v-model="content"></Child>
 </div>

 <template id="input">
 <div>
 <div>这里是子组件的输入区域:</div>
 <input :value="content" @input="contentChange" />
 </div>
 </template>

 <script type="text/javascript">
 var Child = {
 template: "#input",
 model: {
 prop: "content",
 event: "contentChanged"
 },
 props: {
 content: {
 type: String,
 required: true
 }
 },
 methods: {
 contentChange(value){
 this.$emit("contentChanged", value.target.value);
 }
 }
 };

 var vueInstance = new Vue({
 el: "#app",
 components: {Child},
 data: {
 content: ""
 }
 })
 </script>
 </body>
</html>

3. Vue中对v-model指令处理分析

基于Vue2.0版本,分析我们在标签上写上v-model属性到vue组件实现响应的流程。

3.1 解析部分

3.1.1 在将HTML解析称AST时,会解析HTML中标签的属性

function processAttrs(el){
 ...
 name = name.replace(dirRE, '')
 // parse arg
 const argMatch = name.match(argRE)
 if (argMatch && (arg = argMatch[1])) {
 name = name.slice(0, -(arg.length + 1))
 }
 addDirective(el, name, value, arg, modifiers)
 ...
}

提取指令的名称,v-model的指令名称name为model,然后添加到实例的指令中

3.1.2 将指令相关内容添加到实例指令中

export function addDirective (
 el: ASTElement,
 name: string,
 value: string,
 arg: ?string,
 modifiers: ?{ [key: string]: true }
) {
 (el.directives || (el.directives = [])).push({ name, value, arg, modifiers })
}

在实例的指令属性中添加相应的指令,这样就实现了从html上的属性到Vue实例上指令格式的转换

3.2 指令设置部分

在将html解析称AST之后,实例对应的directives属性上就有了我们设置的v-model相关的值,包括参数值value,name是model

3.2.1 调用指令的构造函数

function genDirectives (el: ASTElement): string | void {
 const dirs = el.directives
 if (!dirs) return
 let res = 'directives:['
 let hasRuntime = false
 let i, l, dir, needRuntime
 for (i = 0, l = dirs.length; i < l; i++) {
 dir = dirs[i]
 needRuntime = true
 const gen = platformDirectives[dir.name] || baseDirectives[dir.name]
 if (gen) {
 // compile-time directive that manipulates AST.
 // returns true if it also needs a runtime counterpart.
 needRuntime = !!gen(el, dir, warn)
 }
 ...
}

在v-model指令的构造函数中会根据tag的种类进行不同的创建函数进行创建,如果我们自定义指令需要在子组件上添加属性,也需要在这个函数里面进行操作

3.2.2 普通tag下的v-model指令构造过程

function genDefaultModel 
 el: ASTElement,
 value: string,
 modifiers: ?Object
): ?boolean {
 ...
 addProp(el, 'value', isNative ? `_s(${value})` : `(${value})`)
 addHandler(el, event, code, null, true)
 ...
}
  • addProp在el上设置一个名称为value的prop,同时设置其值
  • addHandler在el上设置事件处理函数

3.3 指令响应变化部分

3.3.1 createPatchFunction统一处理指令的钩子函数
createPatchFunction函数返回一个patch函数,在patch处理过程中,会调用指令的钩子函数,包括:

  • bind
  • inserted
  • update
  • componentUpdated
  • unbind

4. 总结

4.1 编译过程

  1. 从html上解析所设置的指令
  2. 通过gen*函数将指令设置到AST上
  3. 调用指令的构造函数,设置指令需要在编译时期处理的事情

4.2 初始化过程

通过在patch函数中,调用统一的钩子函数,触发指令的钩子函数,实现相应的功能

以上就是详解vue v-model的详细内容,更多关于vue v-model的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
动态创建的表格单元格中的事件实现代码
Dec 30 Javascript
javascript表格隔行变色加鼠标移入移出及点击效果的方法
Apr 10 Javascript
基于Angularjs实现分页功能
May 30 Javascript
jQuery基于toggle实现click触发DIV的显示与隐藏问题分析
Jun 12 Javascript
BootStrap Table 获取同行不同列元素的方法
Dec 19 Javascript
解决vue组件中使用v-for出现告警问题及v for指令介绍
Nov 11 Javascript
JavaScript canvas实现围绕旋转动画
Nov 18 Javascript
使用Electron构建React+Webpack桌面应用的方法
Dec 15 Javascript
详解基于Vue cli生成的Vue项目的webpack4升级
Jun 19 Javascript
JavaScript使用类似break机制中断forEach循环的方法
Nov 13 Javascript
layer.prompt输入层的例子
Sep 24 Javascript
微信小程序开发(一):服务器获取数据列表渲染操作示例
Jun 01 Javascript
vue.js 输入框输入值自动过滤特殊字符替换中问标点操作
Aug 31 #Javascript
vue路由结构可设一层方便动态添加路由操作
Aug 31 #Javascript
element-ui tree结构实现增删改自定义功能代码
Aug 31 #Javascript
vue elementui tree 任意级别拖拽功能代码
Aug 31 #Javascript
Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作
Aug 31 #Javascript
JS遍历树层级关系实现原理解析
Aug 31 #Javascript
Element-ui el-tree新增和删除节点后如何刷新tree的实例
Aug 31 #Javascript
You might like
我的论坛源代码(一)
2006/10/09 PHP
利用PHP生成静态html页面的原理
2016/09/30 PHP
Jquery 表单取值赋值的一些基本操作
2009/10/11 Javascript
JS判断文本框内容改变事件的简单实例
2014/03/07 Javascript
JQuery表格拖动调整列宽效果(自己动手写的)
2014/09/01 Javascript
Node.js中HTTP模块与事件模块详解
2014/11/14 Javascript
jQuery实现TAB选项卡切换特效简单演示
2016/03/04 Javascript
第一次接触Bootstrap框架
2016/10/24 Javascript
基于Bootstrap仿淘宝分页控件实现代码
2016/11/07 Javascript
WebSocket实现简单客服聊天系统
2017/05/12 Javascript
vue踩坑记-在项目中安装依赖模块npm install报错
2019/04/02 Javascript
python 全文检索引擎详解
2017/04/25 Python
利用Python循环(包括while&amp;for)各种打印九九乘法表的实例
2017/11/06 Python
解决Ubuntu pip 安装 mysql-python包出错的问题
2018/06/11 Python
python3 常见解密加密算法实例分析【base64、MD5等】
2019/12/19 Python
Python reques接口测试框架实现代码
2020/07/28 Python
python dict如何定义
2020/09/02 Python
python 实用工具状态机transitions
2020/11/21 Python
pycharm 2020.2.4 pip install Flask 报错 Error:Non-zero exit code的问题
2020/12/04 Python
斯福泰克软件测试面试题
2015/02/16 面试题
Tomcat的缺省是多少,怎么修改
2014/04/09 面试题
英语生日邀请函
2014/01/23 职场文书
学生会干部自荐信
2014/02/04 职场文书
技术总监管理职责范本
2014/03/06 职场文书
教职工代表大会主持词
2014/04/01 职场文书
寒假家长评语大全
2014/04/16 职场文书
党的群众路线学习笔记
2014/11/06 职场文书
表扬通报怎么写
2015/01/16 职场文书
计算机专业自荐信
2015/03/05 职场文书
综合素质评价自我评价
2015/03/06 职场文书
初任公务员培训心得体会
2016/01/08 职场文书
2019行政前台转正申请书范文3篇
2019/08/15 职场文书
创业计划书之面包店
2019/09/12 职场文书
MySQL 服务和数据库管理
2021/11/11 MySQL
Win11电脑显示本地时间与服务器时间不一致怎么解决?
2022/04/05 数码科技
CSS list-style-type属性使用方法
2023/05/21 HTML / CSS