目錄html
首發日期:2019-01-20前端
上篇內容講了vue
v-model能夠把某個實例的數據與元素的數據綁定。這樣當其中一份數據發生變化時,與之綁定的數據也會發生變化。好比:把示例中的數據(在頁面中用{{}}
顯示出來)與輸入框的數據綁定npm
表單輸入框有value這個值,在表單輸入框裏使用v-model會把表單輸入框與實例的數據進行「智能」綁定(爲何說智能,由於有些輸入框的數據是value屬性,有些不是)。數組
你能夠用 v-model 指令在表單 <input>
、<textarea>
及<select>
元素上建立雙向數據綁定。它會根據控件類型自動選取正確的方法來更新元素。儘管有些神奇,但 v-model 本質上不過是語法糖。它負責監聽用戶的輸入事件以更新數據,並對一些極端場景進行一些特殊處理。瀏覽器
v-model 會忽略全部表單元素的 value、checked、selected 特性的初始值而老是將 Vue 實例的數據做爲數據來源。若是但願輸入框有初始值,你應該在組件的 data 選項中聲明初始值。app
會把單行文本輸入框的value綁定到實例的數據中,由於value的數據就是單行文本輸入框的數據。dom
<body> <div id="vm"> <input v-model="message" placeholder="edit me"> <p>Message is: {{ message }}</p> <input type="text" v-bind:value="message"> <!-- 不能使用普通的value=message,否則會識別不成正確的message,因此第三行用了v-bind --> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#vm', data:{ message:"hello world!" } }) </script>
會把多行文本元素內的文本綁定到實例的數據中,由於多行文本元素內的文本就是單行文本輸入框的數據。函數
<body> <div id="vm"> <span>Multiline message is:</span> <p style="white-space: pre-line;">{{ message }}</p> <br> <textarea v-model="message" placeholder="add multiple lines"></textarea> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#vm', data:{ message:"hello world!" } }) </script>
在文本區域
<textarea></textarea>
使用插值表達式{{}}
來插值並不會生效,應該用 v-model 來代替。性能
單個複選框:複選框也有value,不給定value值的時候value默認是布爾值(被勾選是true,沒有勾選是false)
<body> <div id="vm"> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#vm', data:{ checked:false } }) </script>
多個複選框:指定了value以後,實例綁定的數據是對應的value值【因爲是多個複選框綁定到同一個實例上,因此這個實例數據應該是數組類型的。】
<body> <div id='example-3'> <input type="checkbox" id="jack" value="Jack" v-model="checkedNames"> <label for="jack">Jack</label> <input type="checkbox" id="john" value="John" v-model="checkedNames"> <label for="john">John</label> <input type="checkbox" id="mike" value="Mike" v-model="checkedNames"> <label for="mike">Mike</label> <br> <span>Checked names: {{ checkedNames }}</span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#example-3', data:{ checkedNames:[] // 值爲多個input的value的數組 } }) </script>
radio也有value,因此與實例綁定的數據就是value的值
<body> <div id="example-4"> <input type="radio" id="one" value="One" v-model="picked"> <label for="one">One</label> <br> <input type="radio" id="two" value="Two" v-model="picked"> <label for="two">Two</label> <br> <span>Picked: {{ picked }}</span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#example-4', data: { picked: ''// picked的值爲input的value值 } }) </script>
select的值來源與子標籤option。當select 的option沒有value值的時候,默認綁定的數據爲option元素的文本值;當有value時,默認綁定的數據爲option元素的value值。
<body> <div id="example-5"> <select v-model="selected"> <option disabled value="">請選擇</option> <option value ='a'>A</option> <!-- 這個用來測試有value的狀況--> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#example-5', data: { selected: "" // selected 的值爲 a/B/C } }) </script>
select框容許多選時:那麼這時候實例的數據應該是一個數組,數組元素是option的文本值(無value時)或value
<body> <div id="example-5"> <select multiple style="width: 50px;" v-model="selected"> <option disabled value="">請選擇</option> <option value='a'>A</option> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#example-5', data: { selected: [] // 全選時: [ "a", "B", "C" ] } }) </script>
在默認狀況下,v-model 在每次 input 事件觸發後將輸入框的值與數據進行同步 (除了輸入法組合文字時,這時候數據還沒徹底輸入到輸入框中)。
你能夠添加 lazy 修飾符,從而轉變爲使用 change 事件進行同步:
<!-- 在「change」時而非「input」時更新 --> <input v-model.lazy="msg" >
若是想自動將用戶的輸入值轉爲數值類型,能夠給 v-model 添加 number 修飾符:
<input v-model.number="age" type="number">
這一般頗有用,由於即便在 type="number" 時,HTML 輸入元素的值也總會返回字符串。若是這個值沒法被 parseFloat() 解析,則會返回原始的值。
若是要自動過濾用戶輸入的首尾空白字符,能夠給 v-model 添加 trim 修飾符:
<input v-model.trim="msg">
咱們平時也可使用class='xxx'或style='xxx:xxxx'來綁定樣式。爲何要選擇轉去使用Vue的樣式綁定?由於在Vue中class或style也能夠定義成數據,你可能會想要「發生XXX狀況後,某元素變成某樣式」,這個時候你須要定義「行爲」來切換樣式了,而這時候若是你使用Vue本身的樣式切換會比較方便(由於首先你要獲取某個元素的class屬性,而後再從新賦值,這個操做可能須要本身定義一些dom操做)。
使用v-bind:class
來進行class綁定
格式一:傳入的數據格式是{ class名: 布爾數據,.... }
,布爾數據影響class是否出如今元素的class屬性中。
<div id="app"> <div v-bind:class="{ active: isActive }">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { isActive: true // 影響着active這個class是否出現 }, }) --> <!-- <style> .active { color: red; } </style> -->
格式一:傳入的數據格式是對象名
,對象的數據格式是{ class名: 布爾數據,.... }
,布爾值影響class是否出如今元素的class屬性中。
<div id="app"> <div v-bind:class="classObject">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { classObject: { active: true } }, }) --> <!-- <style> .active { color: red; } </style> -->
格式一:
<div id="app"> <div v-bind:class="[activeClass]">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { activeClass:'active' }, }) --> <!-- <style> .active { color: red; } </style> -->
使用v-bind:style
來進行style綁定
格式一:傳入的數據格式是{ 樣式名: 實例數據名(樣式值), .... }
<div id="app"> <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { activeColor:'red', fontSize: 14 }, }) -->
格式二:傳入的數據是一個對象,對象的數據格式是{ 樣式名: 樣式值, .... }
<div id="app"> <div v-bind:style="styleObject">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { styleObject: { color:'red', fontSize: "14px" } }, }) -->
傳入的數據是一個數組,數組的元素是多個對象,對象的數據格式是{ 樣式名: 樣式值, .... }
<div id="app"> <div v-bind:style="[styleObject]">haha</div> </div> <!-- var app = new Vue({ el: '#app', data: { styleObject: { color:'red', fontSize: "14px" } }, }) -->
可使用v-on:事件類型='函數名'
來綁定事件。
<div id="app"> <button v-on:click="myclick">點擊事件</button> <!-- on:後面跟事件類型 --> </div> <!-- var app = new Vue({ el: '#app', methods: { // 注意:是在methods裏面定義函數 myclick:function (){ alert("message") } } }) -->
事件修飾符能夠影響事件的運行,事件修飾符使用.
跟在事件類型的後面,例如:<a v-on:click.stop="doThis"></a>
。
v-on:click.prevent='myFunction'
。<body> <div id="app"> <a v-on:click.prevent='myFunction' href='#'>aaa</a> <!-- 默認狀況下,點擊a元素會進行跳轉, 上面用#來演示,若是url多了一個#說明a的原生事件觸發了, 而咱們如今用prevent來阻止了a元素原始的事件 --> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', methods: { myFunction: function () { alert('haha') } } }) </script>
你可能須要監聽鍵盤來觸發事件,好比最經常使用的就是監聽enter鍵了。
按鍵修飾符也使用.
跟在事件類型的後面 ,例如:<input v-on:keyup.enter="submit">
<!-- 完整語法 --> <a v-on:click="doSomething">...</a> <!-- 縮寫 --> <a @click="doSomething">...</a>
Vue的指令是以v-開頭的,它們各有各的左右,在前面已經介紹了很多了。如今再彙總一下。
爲何要特地地說一下數組的操做呢?由於數組是很是經常使用的數據類型,而在Vue中有些數組操做並不會觸發視圖更新。爲了確保數據是「響應式」的,因此特地講一下這個。
下面的代碼演示了使用普通數組操做方法時「響應失敗」的狀況:
<body> <div id="app"> <p>{{ myArray}}</p> <button @click='addValue1'>下標法添加</button> <button @click='addValue2'>push法</button> <!-- 若是你點了第一個,再點第二個,第一個的添加會在第二個的時候再成功顯示 --> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { myArray: [1,2,3] }, methods: { addValue1: function(){ this.myArray[1]=333 }, addValue2: function(){ this.myArray.push('999999') } } }) </script>
下面這些對數組操做的方法將會觸發視圖更新。
push()
:向數組末尾添加元素pop()
:從數組末尾取出一個元素shift()
:數組的第一個元素從其中刪除,並返回第一個元素的值unshift()
:向數組的開頭添加一個或更多元素,並返回新的長度splice()
:從數組中添加/刪除項目,而後返回被刪除的項目sort()
:對數組的元素進行排序reverse()
:對數組的元素進行逆序排序【官網的話】因爲 JavaScript 的限制,Vue 不能檢測如下變更的數組:
- 當你利用索引直接設置一個項時,例如:
vm.items[indexOfItem] = newValue
- 當你修改數組的長度時,例如:
vm.items.length = newLength
爲了解決第一類問題,如下兩種方式均可以實現和 vm.items[indexOfItem] = newValue 相同的效果,同時也將觸發狀態更新:
Vue.set(vm.items, indexOfItem, newValue)
或vm.items.splice(indexOfItem, 1, newValue)
或vm.$set(vm.items, indexOfItem, newValue)
爲了解決第二類問題,你可使用 splice:vm.items.splice(newLength)
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 如今修改a是響應式的 vm.b = 2 // `vm.b` 不是響應式的
<body> <div id="app"> <p>{{ numbers }}</p> <ul > <li v-for="n in evenNumbers">{{ n }}</li> </ul> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { numbers: [ 1, 2, 3, 4, 5 ] }, computed: { evenNumbers: function () { return this.numbers.filter(function (number) { return number % 2 === 0 }) } } }) </script>
Vue 會盡量高效地渲染元素,一般會複用已有元素而不是從頭開始渲染。這麼作除了使 Vue 變得很是快以外,還有其它一些好處。
而由於複用問題,因此可能會致使如下問題。因爲輸入框被複用,因此輸入框的數據殘留了下來。
<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address"> </template>
Vue 爲你提供了一種方式來表達「這兩個元素是徹底獨立的,不要複用它們」。只需添加一個具備惟一值的 key 屬性便可(沒有key的label仍然被複用了):
<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="username-input"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address" key="email-input"> </template>
當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它默認用「就地複用」策略。若是數據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數據項的順序, 而是簡單複用此處每一個元素,而且確保它在特定索引下顯示已被渲染過的每一個元素。
這個默認的模式是高效的,可是隻適用於不依賴子組件狀態或臨時 DOM 狀態 (例如:表單輸入值) 的列表渲染輸出。
爲了給 Vue 一個提示,以便它能跟蹤每一個節點的身份,從而重用和從新排序現有元素,你須要爲每項提供一個惟一 key 屬性。理想的 key 值是每項都有的惟一 id。這個特殊的屬性至關於 Vue 1.x 的 track-by ,但它的工做方式相似於一個屬性,因此你須要用 v-bind 來綁定動態值 (在這裏使用簡寫):
<div v-for="item in items" :key="item.id"> <!-- 內容 --> </div>
建議儘量在使用 v-for 時提供 key,除非遍歷輸出的 DOM 內容很是簡單,或者是刻意依賴默認行爲以獲取性能上的提高,由於它是 Vue 識別節點的一個通用機制。