以下面範例來說,在 input 輸入的內容,message 會同步變化
<div id="app">
<input v-model="message">
<p>Message is: {{ message }}</p>
</div>
var vm = new Vue({
el: '#app',
data() {
return {
message: ''
}
}
})
genDefaultModel
函數裡 modifiers
會影響 event
和 valueExpression
的值。
以上面例子來說,event
為 input
,valueExpression
為 $event.target.value
。然後會執行 genAssignmentCode
生成 code
程式碼
// src/platforms/web/compiler/directives/model.js
function genDefaultModel (
el: ASTElement,
value: string,
modifiers: ?ASTModifiers
): ?boolean {
//...
const { lazy, number, trim } = modifiers || {}
const needCompositionGuard = !lazy && type !== 'range'
const event = lazy
? 'change'
: type === 'range'
? RANGE_TOKEN
: 'input'
let valueExpression = '$event.target.value'
if (trim) {
valueExpression = `$event.target.value.trim()`
}
if (number) {
valueExpression = `_n(${valueExpression})`
}
let code = genAssignmentCode(value, valueExpression)
if (needCompositionGuard) {
code = `if($event.target.composing)return;${code}`
}
addProp(el, 'value', `(${value})`)
addHandler(el, event, code, null, true)
if (trim || number) {
addHandler(el, 'blur', '$forceUpdate()')
}
}
//...
export function parseModel (val: string): ModelParseResult {
val = val.trim()
len = val.length
if (val.indexOf('[') < 0 || val.lastIndexOf(']') < len - 1) {
index = val.lastIndexOf('.')
if (index > -1) {
return {
exp: val.slice(0, index),
key: '"' + val.slice(index + 1) + '"'
}
} else {
return {
exp: val,
key: null
}
}
}
//...
return {
exp: val.slice(0, expressionPos),
key: val.slice(expressionPos + 1, expressionEndPos)
}
}
// src/compiler/directives/model.js
/*************************************************
定義 genAssignmentCode
**************************************************/
export function genAssignmentCode (
value: string,
assignment: string
): string {
const res = parseModel(value)
if (res.key === null) {
return `${value}=${assignment}`
} else {
return `$set(${res.exp}, ${res.key}, ${assignment})`
}
}
genAssignmentCode
先對 v-model
對應的 value
解析,對上面例子,value
就是 messgae
,messgae
參數傳入 parseModel
,parseModel
的回傳值得到 res.key === null
,所以 genAssignmentCode
會回傳 message=$event.target.value
,接著 needCompositionGuard
為 true,最後得到code = if($event.target.composing)return;message=$event.target.value
。
// src/platforms/web/compiler/directives/model.js
function genDefaultModel (
el: ASTElement,
value: string,
modifiers: ?ASTModifiers
): ?boolean {
//...
const needCompositionGuard = !lazy && type !== 'range'
let code = genAssignmentCode(value, valueExpression)
if (needCompositionGuard) {
code = `if($event.target.composing)return;${code}`
}
}
接著執行 addProp
和 addHandler
// src/platforms/web/compiler/directives/model.js
function genDefaultModel (
el: ASTElement,
value: string,
modifiers: ?ASTModifiers
): ?boolean {
//...
addProp(el, 'value', `(${value})`)
addHandler(el, event, code, null, true)
//...
}
此處對 el 加上一個 prop,相當於在 input 上動態綁定 value 和對 el 加上 input 事件,以模板來想如下
<input
:value="message"
@input="message=$event.target.value"
>