HI!記得我們在第一篇的時候有提過如何將Vue.js的資料綁定到View上面嗎?如果忘記的話可以看一下以下最簡單的範例:
HTML
<input id="name" :value="text" >
JavaScript
let name = new Vue({
el:'#name',
data:{
text:'神Q超人',
},
})
透過指定HTML
的元件來創建一個Vue物件,並在物件中用data
屬性傳入資料物件,這是一個Vue.js對View的單向綁定,而Vue.js還有提供雙向綁定!我們今天就來提一下要如何做到雙向綁定!
在Vue.js中有個v-model
屬性可以做到這件事情,他可以對input
、textarea
、select
、checkbox
和checkbox
這堆全部讓使用者輸入的表單做雙向的綁定,主要是透過事件去監聽使用者輸入的事件來更新我們一開始給的,感覺是不是很厲害?讓我們動手做看看吧!
像第一篇說的,Vue.js的用法都非常直覺,感覺很難的v-model
也是,只需要將v-model
當做屬性加到input
裡面就可以了!
HTML
<div id="name">
<!--為input設定一個v-model屬性,並將綁定的資料設定為text-->
<input v-model="text" :value="text">
<div>您的姓名是:{{text}}</div>
</div>
JavaScript
//這裡把資料拆出來
let nameData = {
text : '神Q超人'
}
let name = new Vue({
el:'#name',
data:nameData,
})
在HTML的部分,我們將text
這個資料綁定在三個地方,分別是input
的預設值、div
的內容和我們今天提到的v-model
,因為v-model
的關係,他在監聽到input
的資料如果改變,會即時更新text
裡面的值,而又因為div
內綁定了text
的資料,所以也會同步更新成新值,就像下方的操作:
很簡單吧!那讓我們繼續說下去!
這個表單就和input
一樣,不同的是文字可以在textarea
內折行,而厲害的是,就算折行Vue.js也不會忘記他:
HTML
<div id="introduce">
<textarea v-model="text" :value="text"></textarea>
<div>您的自我介紹內容:</div>
<pre>{{text}}</pre>
</div>
JavaScript
let introduceData = {
text : '自我介紹內容'
}
let introduce = new Vue({
el:'#introduce',
data:introduceData,
})
這邊題外話一下,上面我把text
放到一個pre
標籤中,這個<pre>
我之前發現的神奇標籤,在他裡面會保留textarea
內輸入的換行,這是我的秘密武器XD
select
比較特別,我們這裡應用上一篇講的迴圈來填入select
的選項,然後像上方一樣,在select
中增加v-model
去綁定數據。
不一樣的是,因為選項是動態產生的,資料會存在v-for="list in lists"
的list
中,但實際上的data
內並沒有list
這個屬性,所以必須再增加一個selectName
給v-model
綁定數據,這麼一來,只要select
的選項改變,list
內的item
就會把目前綁定的value
值(下方程式碼中的:value="list.item"
)寫給selectName
,而後方的資料變動,也就會同時更新View,可以看以下範例:
<div id="gender">
<select v-model="selectName">
<option v-for="list in lists" :value="list.item">{{list.item}}</option>
</select>
<div>選擇的性別是:{{selectName}}</div>
</div>
let genderData = {
selectName : '',
lists : [
{val:"M",item:'男'},
{val:"W",item:'女'},
]
}
let gender = new Vue({
el:'#gender',
data:genderData,
})
看到上方的結果,我們確實做到了select
的雙向綁定,但也許會有個問題,如果我要同時取得option
的value
和text
呢?就目前看來似乎只能綁定一個,所以這時候我們要利用事件綁定方法的@change
來處理這件事情!
HTML
<div id="gender">
<!--這裡把v-model先拿掉,要留著也可以,增加了@change事件-->
<select id="s_gender" :value="selectVal" @change="updateVal">
<option v-for="list in lists" :value="list.val" >{{list.item}}</option>
</select>
<div>選擇的性別是:{{selectName}}</div>
<div>該性別的值是:{{selectVal}}</div>
</div>
JavaScript
let genderData = {
selectName : '',
selectVal : '',
lists : [
{val:"M",item:'男'},
{val:"W",item:'女'},
]
}
let genderMethods = {
//將目前該性別選單的value和name寫入genderData的selectName及selectVal
updateVal : () =>{
let obj = document.getElementById('s_gender')
//取得值
genderData.selectVal = obj.value;
//取得目前選擇選項的文字
genderData.selectName = obj.options[obj.selectedIndex].text;
}
}
let gender = new Vue({
el:'#gender',
data:genderData,
methods:genderMethods,
})
結果會將兩個值都帶出來,不過上面的方法看起來有點複雜,其實只是土法煉鋼用change
事件去更新genderData
內屬性的值,並藉由單像綁定的特性更動前面的View,不過用這個方法就等於和沒v-model
的做法一樣,不曉得有沒有更好的方法,如果有其他做法還麻煩各位大大教我一下,謝謝!
下拉選單有兩個版本,一種是上面提到的單選的,另一種是複選的,其實我也不曉得從什麼時候,只要在select
中加入multiple
屬性,他自然就會變成複選的版本,Vue.js在處理複選的資料時,他會把所有選擇的資料,不管幾個都放進陣列再寫回後方的data
中,我們用剛剛的範例直接看看結果吧!
HTML
<div id="gender">
<!--在select屬性中加入multiple設定為複選-->
<select v-model="selectName" multiple >
<option v-for="list in lists" :value="list.item">{{list.item}}</option>
</select>
<div>選擇的性別是:{{selectName}}</div>
</div>
JavaScript
let genderData = {
selectName : '',
lists : [
{val:"M",item:'男'},
{val:"W",item:'女'},
]
}
let gender = new Vue({
el:'#gender',
data:genderData,
})
以上其實都沒有改變,就只是在select
中加入了multiple
屬性,不過這個在實務上似乎沒有那麼常見,結果會像下方,當我選擇一個或以上的值的時候,綁定的資料會變成陣列寫回!
看到這裡,應該就會輕鬆不少了,因為剩下的單選框和複選框的用法就和下拉選單差不多,直接來看看吧(原諒我偷懶直接把上面的下拉選單改成複選框XD)!
HTML
<div id="gender">
<div>
<span v-for="list in lists">
<input type="checkbox" :value="list.item" v-model="checkedNames"/>
<label>{{list.item}}</label>
</span>
</div>
<div>選擇的性別是:{{checkedNames}}</div>
</div>
JavaScript
let genderData = {
//這裡綁定的值要是陣列
checkedNames : [],
lists : [
{val:"M",item:'男'},
{val:"W",item:'女'},
]
}
let gender = new Vue({
el:'#gender',
data:genderData,
})
結果應該是和下拉選單的multiple
版本是一樣的,但是有個卡了我非常久的地方XD,如果是check
的話一開始由v-modle
綁定的資料應該要是陣列型態,也就是說checkedNames
的初始設置checkedNames:''
這樣是不行的,他必須要是checkedNames:[]
才可以,這點用在checkbox
的時候要注意一下!
終於來到最後了XD,這裡是單選框,也就是很單純的單一值,沒有多選就沒有陣列,那來看看壓軸的範例吧(如果你發現下面的範例和上面根本一模一樣,那絕對是錯覺XD)!
HTML
<div id="gender">
<div>
<span v-for="list in lists">
<input type="radio" :value="list.item" v-model="checkedNames"/>
<label>{{list.item}}</label>
</span>
</div>
<div>選擇的性別是:{{checkedNames}}</div>
</div>
JavaScript
let genderData = {
checkedNames : '',
lists : [
{val:"M",item:'男'},
{val:"W",item:'女'},
]
}
let gender = new Vue({
el:'#gender',
data:genderData,
})
做到了這裡,各位應該腦子裡都會有畫面大概會呈現什麼結果了吧!那我們一起來見證是不是和想像中一樣!
沒錯!所以其實看似很難的雙向綁定,在Vue.js中也變的簡單起來了,當然還是有些時候我們必須手動去取值給data
,就像上方下拉選單同時取value
和text
的情況,不過如果是我理解錯誤,拜託各位大大一定要告訴我!不想活在錯誤中啊XD,另外關於v-model
還有幾點要額外提的部分:
.lazy
在v-modle
中,我們使用雙向綁定,不論是input
或是select
資料都會即時的綁定,但是當你使用input
又不想讓他即時綁定資料,可以加上.lazy
屬性,他就像一般的onchange
一樣,只有在該input
失去焦點的時候才會重新綁定資料!
HTML
<div id="name">
<input v-model.lazy="text" :value="text">
<div>您的姓名是:{{text}}</div>
</div>
JavaScript
let nameData = {
text : '神Q超人'
}
let name = new Vue({
el:'#name',
data:nameData,
})
這麼一來就會如畫面上,當游標還停留在input
時,Vue.js就不會進行資料的綁定,只有在焦點離開input
的時候才會再綁定data
,當然如果是像select
之類的表單,在選擇的時候就等於離開焦點,所以也感受不到.lazy
的效果。
.number
這一個.number
則是會在type="number"
時使用,為了避免有文字輸入的情況,他會只容許數字進行綁定,例如:
HTML
<div id="age">
<input v-model.number="text" :value="text" type="number">
<div>您的年齡是:{{text}}</div>
</div>
JavaScript
let ageData = {
text : '神Q超人'
}
let age = new Vue({
el:'#age',
data:ageData,
})
可以看到,就算我一開始的data
是中文,他也不會進行資料綁定到input
的value
當中,一直到我把他的value
更改成數字,才會進行綁定。
.trim
這個屬性就單純多了,會在綁定資料的時候自動清除前後的空白!
HTML
<div id="name">
<input v-model.trim="text" :value="text">
<div>您的姓名是:{{text}}</div>
</div>
JavaScript
let nameData = {
text : '神Q超人'
}
let name = new Vue({
el:'#name',
data:nameData,
})
如上圖,當在文字的前後不論輸入多少空白都不會被綁定到data
中,不過文字與文字之間的空白則會保留,另外當焦點移開input
時,也會重新綁定成移除字串頭尾空白後的資料!
watch
的運作主要是因為v-model
幫我們做了兩件事情
v-bind
單向綁定資料,會因為每次綁定值的變動同步更新到View上。v-on:input
去偵測每次值的變動,觸發更新v-bind
綁定的值。所以以下兩種寫法是一樣的:v-model
<input v-model="text">
v-bind
&v-on:input
<input
v-bind:value="text"
v-on:input="text = $event.target.value">
參考文章:https://blog.csdn.net/u010320804/article/details/79486034
以上!講了很多關於v-modle
的用法和情況,不過這些都只是基本的而已,其實只要看懂一個就能夠應用在其他表單上,在這之後還有更可怕的在等著XD。最後也感謝各位大大的觀看!如果文章中有任何理解錯誤或是不清楚的地方,還請留言告訴我,我會盡快修正的!謝謝大家!
謝謝你的教學 陪伴我第四天
前幾章 我們透過控制台操作或是利用事件直接修改data資料
達到DOM重新繪製
這章簡單講 是做相反的事情
也就是修改畫面上看到的東西(你說的view)
藉此修改data資料 讓畫面上其他地方的資料做變動
目前看到前半段
一年多過去了 你應該也解決了(笑
不知道這算不算一種解決方法
其實就是在綁定的value屬性改成list
讓他可以取得物件的值 就行了
<div id="gender">
<select v-model="selectName">
<option v-for="list in lists" :value="list">{{list.item}}</option>
</select>
<div>選擇的性別是:{{selectName.item}}</div>
<div>性別的值是:{{selectName.val}}</div>
</div>
我先看到前半段
今天有點累了 明天接續後半段