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还有提供双向绑定!我们今天就来提一下要如何做到双向绑定!
v-model
在Vue.js中有个v-model
属性可以做到这件事情,他可以对input
、textarea
、select
、checkbox
和checkbox
这堆全部让使用者输入的表单做双向的绑定,主要是透过事件去监听使用者输入的事件来更新我们一开始给的,感觉是不是很厉害?让我们动手做看看吧!
input
像第一篇说的,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
的资料,所以也会同步更新成新值,就像下方的操作:
很简单吧!那让我们继续说下去!
textarea
这个表单就和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
的选项,然后像上方一样,在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版本
下拉选单有两个版本,一种是上面提到的单选的,另一种是複选的,其实我也不晓得从什么时候,只要在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
属性,不过这个在实务上似乎没有那么常见,结果会像下方,当我选择一个或以上的值的时候,绑定的资料会变成阵列写回!
checkbox
看到这里,应该就会轻鬆不少了,因为剩下的单选框和複选框的用法就和下拉选单差不多,直接来看看吧(原谅我偷懒直接把上面的下拉选单改成複选框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
的时候要注意一下!
radio
终于来到最后了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
还有几点要额外提的部分:
1. .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
的效果。
2. .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
更改成数字,才会进行绑定。
3. .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
时,也会重新绑定成移除字串头尾空白后的资料!
补充说明(感谢fysh711426大大在此篇文章中的补充)
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。最后也感谢各位大大的观看!如果文章中有任何理解错误或是不清楚的地方,还请留言告诉我,我会尽快修正的!谢谢大家!