You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
if(el.component){genComponentModel(el,value,modifiers)// component v-model doesn't need extra runtimereturnfalse}elseif(tag==='select'){genSelect(el,value,modifiers)}elseif(tag==='input'&&type==='checkbox'){genCheckboxModel(el,value,modifiers)}elseif(tag==='input'&&type==='radio'){genRadioModel(el,value,modifiers)}elseif(tag==='input'||tag==='textarea'){genDefaultModel(el,value,modifiers)}elseif(!config.isReservedTag(tag)){genComponentModel(el,value,modifiers)// component v-model doesn't need extra runtimereturnfalse}elseif(process.env.NODE_ENV!=='production'){
...
}
/** * Convert an input value to a number for persistence. * If the conversion fails, return original string. */
export functiontoNumber(val: string): number|string{constn=parseFloat(val)returnisNaN(n) ? val : n}
说到v-model,就想到了双向数据绑定,而且往往最常见的是在表单元素
<input>,<textarea>,<select>
中的使用,在一些自定义组件中也使用到了v-model。那么为什么v-model双向数据绑定,自动更新元素呢?
因此我们将来好好探讨一下:
<input v-model="..."><textarea v-model="..."></textarea>
源码分析<input type="checkbox" v-model="..."><input type="radio" v-model="...">
源码分析<select v-model="..."><option>...</option></select>
源码分析vue v-model源码分析
vue如何获取v-mode的值(value)
vue通过这一行取到了v-model中的值,例如v-model="isChecked",v-model="inputValue"中isChecked和inputValue的值。
源码地址:web/compiler/directives/model.js 14~20行
其中ASTDirective的interface定义如下:
源码地址:packages/vue-template-compiler/types/index.d.ts 80~86行
用于生成各种类型model的gen*函数
其中包括gen*开头的生成model的各种函数,我们会在下文中进行分析。
源码地址:web/compiler/directives/model.js 37~61行
vue如何设置v-mode的值(value)
genAssignmentCode函数(事件更新时,最终set v-model值的函数)
源码地址:src/compiler/directives/model.js 36~46行
<input v-model="..."><textarea v-model="..."></textarea>
源码分析一句话概览:text和textarea标签的value属性和input事件及genDefaultModel函数。
等价于:
真的是这样吗?我们来看看源码。
genDefaultModel函数
源码分析在源码中有注释。
通过源码我们可以看出:
input(type=“text”)和textarea的v-model,通过value prop获得值,最终被解析为设置value attribute和input(若设置lazy,则触发change)事件,从而实现双向绑定。
源码地址:web/compiler/directives/model.js 127~147行
<input type="checkbox" v-model="..."><input type="radio" v-model="...">
源码分析一句话概览:input标签的checkbox和radio类型的checked属性和change事件及源码genCheckboxModel函数和genRadioModel函数。
等价于:
genCheckboxModel函数
genRadioModel函数
源码分析在源码中有注释。
通过源码我们可以看出:
input(type=“checkbox”)和input(type="radio")的v-model,通过value prop获得值,最终被解析为设置checked attribute和change事件,从而实现双向绑定。
源码地址:web/compiler/directives/model.js 67~96行
<select v-model="..."><option>...</option></select>
源码分析一句话概览:select标签的value属性和change事件及源码genSelect函数。
等价于:
genSelect 函数
源码分析在源码中有注释。
通过源码我们可以看出:
select的v-model,通过value prop获得值,最终被解析为设置selected attribute和change事件,从而实现双向绑定。
源码地址:web/compiler/directives/model.js 110~125行
自定义组件中的v-model源码分析
一句话概览:如何理解自定义组件中的v-model及genComponentModel,transformModel函数?
其实不仅仅是input,textarea,和select这些常见的原生表单元素可以使用v-model,对于自定义的vue组件我们也可以使用v-model。
如何从源码去理解这一段话吗?
genComponentModel函数(构造出需要调用transformModel函数的el.model对象)
源码地址:src/compiler/directives/model.js 6~31行
重点关注el.model这一行。因为vue在创建自定义组件时,会对el.model这一行进行一些操作。
transformModel函数(转化组件v-model的value和callback到prop和event handler)
源码地址:src/core/vdom/create-component.js 250~268行
”lovingVue的值会传入checked这个prop“的源码解释:
data.attrs || (data.attrs = {}))[prop] = data.model.value
。获取到组价的v-model="lovingVue"中lovingVue的值,并且将v-model的longVue传入props的checked。若对如何获取v-model中的值有不理解,具体可以看上文第一部分vue v-model源码分析(vue如何获取v-mode的值(value))。
"同时当组件触发一个change事件并且附带了一个新值的时候,lovingVue的值会被更新。"的源码解释:
通过
el.model = {... callback: }
和const callback = data.model.callback
可以推断出:el.on.change = callback,而这个callback又是genAssignmentCode,在genAssignmentCode中会对v-model的值进行set。若是对如何set v-model的值有疑问,可以查看上文中的vue v-model源码分析(vue如何设置v-mode的值(value))。v-model的.lazy,.number,.trim修饰符源码分析
源码地址:shared/util.js 97~100行
参考资料:
https://cn.vuejs.org/v2/guide/components.html#%E5%9C%A8%E7%BB%84%E4%BB%B6%E4%B8%8A%E4%BD%BF%E7%94%A8-v-model
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event
The text was updated successfully, but these errors were encountered: