詳解vue v-model
1. v-model原理
vue中v-model是一個(gè)語(yǔ)法糖,所謂的語(yǔ)法糖就是對(duì)其他基礎(chǔ)功能的二次封裝而產(chǎn)生的功能。簡(jiǎn)單點(diǎn)說(shuō),v-model本身就是父組件對(duì)子組件狀態(tài)以及狀態(tài)改變事件的封裝。其實(shí)現(xiàn)原理上分為兩個(gè)部分:
通過(guò)props設(shè)置子組件的狀態(tài)
通過(guò)監(jiān)聽(tīng)子組件發(fā)出的事件改變父組件的狀態(tài),從而影響子組件的props值
通過(guò)以上兩個(gè)部分,實(shí)現(xiàn)了父組件的狀態(tài)和子組件狀態(tài)進(jìn)行了綁定的效果。
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>這里是父組件的狀態(tài):</div> <div style="margin-bottom: 15px;">{{content}}</div> <Child v-model="content"></Child> </div> <template id="input"> <div> <div>這里是子組件的輸入?yún)^(qū)域:</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>
在瀏覽器中打開(kāi)上述html頁(yè)面,可以看到實(shí)時(shí)效果:在子組件中的input框中輸入內(nèi)容可以在父組件區(qū)域?qū)崟r(shí)顯示,達(dá)到了子組件中狀態(tài)和父組件狀態(tài)實(shí)時(shí)綁定的效果。
2. 修改v-model默認(rèn)監(jiān)聽(tīng)的事件和設(shè)置prop的名稱
v-model指令默認(rèn)是在子組件上設(shè)置的prop名稱是value,默認(rèn)監(jiān)聽(tīng)子組件上的input事件,在上面的demo上,如果我們修改子組件contentChange函數(shù)中發(fā)出的事件名稱,在父組件中就無(wú)法實(shí)時(shí)獲取到子組件的輸入。
Vue中提供了通過(guò)在子組件上定義model屬性來(lái)修改這兩個(gè)參數(shù)名稱的功能,不過(guò)該功能需要在版本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>這里是父組件的狀態(tài):</div> <div style="margin-bottom: 15px;">{{content}}</div> <Child v-model="content"></Child> </div> <template id="input"> <div> <div>這里是子組件的輸入?yún)^(qū)域:</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中對(duì)v-model指令處理分析
基于Vue2.0版本,分析我們?cè)跇?biāo)簽上寫上v-model屬性到vue組件實(shí)現(xiàn)響應(yīng)的流程。
3.1 解析部分
3.1.1 在將HTML解析稱AST時(shí),會(huì)解析HTML中標(biāo)簽的屬性
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,然后添加到實(shí)例的指令中
3.1.2 將指令相關(guān)內(nèi)容添加到實(shí)例指令中
export function addDirective ( el: ASTElement, name: string, value: string, arg: ?string, modifiers: ?{ [key: string]: true } ) { (el.directives || (el.directives = [])).push({ name, value, arg, modifiers }) }
在實(shí)例的指令屬性中添加相應(yīng)的指令,這樣就實(shí)現(xiàn)了從html上的屬性到Vue實(shí)例上指令格式的轉(zhuǎn)換
3.2 指令設(shè)置部分
在將html解析稱AST之后,實(shí)例對(duì)應(yīng)的directives屬性上就有了我們?cè)O(shè)置的v-model相關(guān)的值,包括參數(shù)值value,name是model
3.2.1 調(diào)用指令的構(gòu)造函數(shù)
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指令的構(gòu)造函數(shù)中會(huì)根據(jù)tag的種類進(jìn)行不同的創(chuàng)建函數(shù)進(jìn)行創(chuàng)建,如果我們自定義指令需要在子組件上添加屬性,也需要在這個(gè)函數(shù)里面進(jìn)行操作
3.2.2 普通tag下的v-model指令構(gòu)造過(guò)程
function genDefaultModel el: ASTElement, value: string, modifiers: ?Object ): ?boolean { ... addProp(el, 'value', isNative ? `_s(${value})` : `(${value})`) addHandler(el, event, code, null, true) ... }
- addProp在el上設(shè)置一個(gè)名稱為value的prop,同時(shí)設(shè)置其值
- addHandler在el上設(shè)置事件處理函數(shù)
3.3 指令響應(yīng)變化部分
3.3.1 createPatchFunction統(tǒng)一處理指令的鉤子函數(shù)
createPatchFunction函數(shù)返回一個(gè)patch函數(shù),在patch處理過(guò)程中,會(huì)調(diào)用指令的鉤子函數(shù),包括:
- bind
- inserted
- update
- componentUpdated
- unbind
4. 總結(jié)
4.1 編譯過(guò)程
- 從html上解析所設(shè)置的指令
- 通過(guò)gen*函數(shù)將指令設(shè)置到AST上
- 調(diào)用指令的構(gòu)造函數(shù),設(shè)置指令需要在編譯時(shí)期處理的事情
4.2 初始化過(guò)程
通過(guò)在patch函數(shù)中,調(diào)用統(tǒng)一的鉤子函數(shù),觸發(fā)指令的鉤子函數(shù),實(shí)現(xiàn)相應(yīng)的功能
以上就是詳解vue v-model的詳細(xì)內(nèi)容,更多關(guān)于vue v-model的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Vue 的 v-model用法實(shí)例
- vue v-model的用法解析
- Vue循環(huán)中多個(gè)input綁定指定v-model實(shí)例
- vue中v-model對(duì)select的綁定操作
- vue.js 解決v-model讓select默認(rèn)選中不生效的問(wèn)題
- VUE table表格動(dòng)態(tài)添加一列數(shù)據(jù),新增的這些數(shù)據(jù)不可以編輯(v-model綁定的數(shù)據(jù)不能實(shí)時(shí)更新)
- Vue v-model組件封裝(類似彈窗組件)
- vue.js自定義組件實(shí)現(xiàn)v-model雙向數(shù)據(jù)綁定的示例代碼
- vue 父組件通過(guò)v-model接收子組件的值的代碼
- vue中input的v-model清空操作
- Vue v-model相關(guān)知識(shí)總結(jié)
相關(guān)文章
@vue/cli4升級(jí)@vue/cli5?node.js?polyfills錯(cuò)誤的解決方式
最近在升級(jí)vue/cli的具有了一些問(wèn)題,解決問(wèn)題的過(guò)程也花費(fèi)了些時(shí)間,所以下面這篇文章主要給大家介紹了關(guān)于@vue/cli4升級(jí)@vue/cli5?node.js?polyfills錯(cuò)誤的解決方式,需要的朋友可以參考下2022-09-09element-ui中的clickoutside點(diǎn)擊空白隱藏元素
這篇文章主要為大家介紹了element-ui中的clickoutside點(diǎn)擊空白隱藏元素示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03vue項(xiàng)目base64轉(zhuǎn)img方式
這篇文章主要介紹了vue項(xiàng)目base64轉(zhuǎn)img方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Vue?運(yùn)行高德地圖官方樣例,設(shè)置class無(wú)效的解決
這篇文章主要介紹了Vue?運(yùn)行高德地圖官方樣例,設(shè)置class無(wú)效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10實(shí)例詳解vue.js淺度監(jiān)聽(tīng)和深度監(jiān)聽(tīng)及watch用法
這篇文章主要介紹了vue.js淺度監(jiān)聽(tīng)和深度監(jiān)聽(tīng)及watch用法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-08-08