详解vue v-model

所属分类: 网络编程 / JavaScript 阅读数: 1593
收藏 0 赞 0 分享

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的资料请关注脚本之家其它相关文章!

更多精彩内容其他人还在看

layui table 复选框跳页后再回来保持原来选中的状态示例

今天小编就为大家分享一篇layui table 复选框跳页后再回来保持原来选中的状态示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Vue-Cli项目优化操作的实现

这篇文章主要介绍了Vue-Cli项目优化操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

解决包含在label标签下的checkbox在ie8及以下版本点击事件无效果兼容的问题

这篇文章主要介绍了解决包含在label标签下的checkbox在ie8及以下版本点击事件无效果兼容的问题,本文给大家总结的非常详细,需要的朋友可以参考下
收藏 0 赞 0 分享

vue 父组件通过v-model接收子组件的值的代码

这篇文章主要介绍了vue 父组件通过v-model接收子组件的值的代码,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

vue 全局环境切换问题

小编在开发使经常会碰到全局切换问题,今天小编给大家带来一篇教程给大家介绍vue 全局环境切换问题,感兴趣的朋友一起看看吧
收藏 0 赞 0 分享

element-ui 本地化使用教程详解

这篇文章主要介绍了element-ui 本地化使用教程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

在Vue项目中,防止页面被缩放和放大示例

今天小编就为大家分享一篇在Vue项目中,防止页面被缩放和放大示例,具有很好的参考 价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

vue h5移动端禁止缩放代码

今天小编就为大家分享一篇vue h5移动端禁止缩放代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Vue 3.0双向绑定原理的实现方法

这篇文章主要为大家详细介绍了Vue 3.0双向绑定原理的实现方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

nest.js 使用express需要提供多个静态目录的操作方法

这篇文章主要介绍了nest.js 使用express需要提供多个静态目录的操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享
查看更多