vue在渲染元素時,出於效率考慮,會盡量地複用已有的元素而非從新渲染javascript
example:css
htmlhtml
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="main.css"/> </head> <div id="app"> <template v-if="type === 'name'"> <label>用戶名:</label> <input placeholder="輸入用戶名"> </template> <template v-else> <label>郵箱:</label> <input placeholder="輸入郵箱"> </template> <button @click="handleToggleClick">切換輸入類型</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="main.js"></script> </body> </html>
jsvue
var app = new Vue({ el: '#app', data: { type: 'name' }, methods: { handleToggleClick: function() { this.type = this.type === 'name' ? 'mail' : 'name'; } } });
輸入內容後,點切換按鈕,雖然dom變了,只是替換了placehoder,input元素被複用java
若是不但願這樣作,可使用vue.js提供的key屬性,讓你本身決定是否複用元素,key的值必須是惟一的python
v-show是改變元素的css屬性display,當v-show表達式的值爲false時,元素會隱藏npm
html編程
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="main.css"/> </head> <div id="app"> <p v-show="status === 1">當status爲1時顯示該行</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="main.js"></script> </body> </html>
js數組
var app = new Vue({ el: '#app', data: { status: 1 } });
當須要將一個數組遍歷或枚舉一個對象循環顯示時,就用到v-for,表達式須要結合in來實現app
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="main.css"/> </head> <div id="app"> <ul> <li v-for="book in books">{{ book.name }}</li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="main.js"></script> </body> </html>
js
var app = new Vue({ el: '#app', data: { books: [ { name:'python核心編程'}, { name:'go學習筆記'}, { name:'vue.js實戰'} ] } });
在表達式中,books是數據,book是當前每一個元素,元素.name能取出對應的值
v-for也能取出當前項的索引
<li v-for="(book,index) in books">{{index}}-{{ book.name }}</li>
v-for也能用在內置標籤<template>上,將多個元素進行渲染
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="main.css"/> </head> <div id="app"> <template v-for="book in books"> <ul> <li>書名:{{book.name}}</li> <li>做者:{{book.author}}</li> </ul> </template> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="main.js"></script> </body> </html>
js
var app = new Vue({ el: '#app', data: { books: [ { name:'python核心編程', author:'a' }, { name:'go學習筆記', author: 'b' }, { name:'vue.js實戰', author:'c' } ] } });
除數組外,對象的屬性也是能夠遍歷的,兩個可選參數,鍵值和索引
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="main.css"/> </head> <div id="app"> <ul> <li v-for="(value,key,index) in user"> {{index}}-{{key}}:{{value}} </li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="main.js"></script> </body> </html>
js
var app = new Vue({ el: '#app', data: { user: { name:'somebody', age:28, gender:'男' } } });
vue的核心是數據與視圖的雙向綁定,當修改數組時m,Vue會檢測到數據變化,因此用v-for渲染的視圖也會當即更新
push pop shift splice sort reverse
example:將以前一個示例的數據books添加一項
app.books.push({ name: 'css揭祕', author: 'd' });
使用以上方法會該改變被這些方法調用的原始數組,有些方法不會改變原數組
filter slice concat
example:找出書名包含vue的
app.books = app.books.filter(function (item) { return item.name.match(/vue/); });
vue在檢測到數組變化時,並非直接從新渲染整個列表,而是最大化複用dom,含有相同元素的項不會被從新渲染,所以新數組來替換舊數據
須要注意的是,如下變更的數組中,vue是不能檢測到的,也不會觸發視圖更新
解決第一個問題能夠用vue內置的set方法
Vue.set(app.books,2,{ name: 'javascript', author: 'd', });
也能夠用splice方法
app.books.splice(2,1,{ name: 'javascript', author: 'e' });
若是不想改變原數組,想經過一個數組的副原本作過濾或排序的顯示,能夠用計算屬性來返回過濾或排序後的數組
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="main.css"/> </head> <div id="app"> <template v-for="book in filterBooks"> <ul> <li>書名:{{book.name}}</li> <li>做者:{{book.author}}</li> </ul> </template> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="main.js"></script> </body> </html>
js
var app = new Vue({ el: '#app', data: { books: [ { name:'python核心編程', author:'a' }, { name:'go學習筆記', author: 'b' }, { name:'vue.js實戰', author:'c' } ] }, computed: { filterBooks: function () { return this.books.filter(function (book) { return book.name.match(/vue/); }) } } });
排序和搜索相似,不會修改books
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="main.css"/> </head> <div id="app"> <template v-for="book in sortedBooks"> <ul> <li>書名:{{book.name}}</li> <li>做者:{{book.author}}</li> </ul> </template> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="main.js"></script> </body> </html>
js
var app = new Vue({ el: '#app', data: { books: [ { name:'python核心編程', author:'a' }, { name:'go語言學習筆記', author: 'b' }, { name:'vue.js實戰', author:'c' } ] }, computed: { sortedBooks: function () { return this.books.sort(function (a,b) { return a.name.length < b.name.length }) } } });
example:監聽一個按鈕的點擊事件,設置計數器,每次點擊加1
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="main.css"/> </head> <div id="app"> 點擊次數:{{ counter }} <button @click="counter++">+1</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="main.js"></script> </body> </html>
js
var app = new Vue({ el: '#app', data: { counter:0 } })
@click的表達式能夠直接使用JavaScript語句,也能夠是一個在Vue實例中methods選項內的函數名
example:再加一個加10的按鈕
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="main.css"/> </head> <div id="app"> 點擊次數:{{ counter }} <button @click="handleAdd()">+1</button> <button @click="handleAdd(10)">+10</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="main.js"></script> </body> </html>
js
var app = new Vue({ el: '#app', data: { counter:0 }, methods:{ handleAdd:function (count) { count = count || 1; this.counter += count } } })
練習:計算屬性/指令開發購物車
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>購物車示例</title> <link rel="stylesheet" href="main.css"/> </head> <div id="app"> <template v-if="list.length"> <table> <thead> <tr> <th> <button @click="allChoose">全選</button> </th> <th></th> <th>商品名稱</th> <th>商品單價</th> <th>商品數量</th> <th>操做</th> </tr> </thead> <tbody> <tr v-for="(item,index) in list"> <td> <input type="checkbox" v-model="item.checked"> </td> <td>{{ index+1 }}</td> <td>{{ item.name }}</td> <td>{{ item.price }}</td> <td> <button @click="handleReduce(index)" :disabled="item.count === 1">-</button> {{item.count}} <button @click="handleAdd(index)">+</button> </td> <td> <button @click="handleRemove(index)">移除</button> </td> </tr> </tbody> </table> <div>總價:{{totalPrice}}</div> </template> <div v-else>購物車爲空</div> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="main.js"></script> </body> </html>
js
var app = new Vue({ el:'#app', data: { list:[ { id:1, name:'iphone', price:6188, count:1, checked:true, }, { id:2, name:'ipad', price:5888, count:1, checked:true, }, { id:3, name:'mbp', price:18888, count :1, checked:true, } ] }, computed:{ totalPrice:function () { var total=0; for (var i=0;i< this.list.length;i++) { var item = this.list[i]; var status = this.list[i].checked; if (status === true) total += item.price * item.count; } return total.toString().replace(/\B(?=(\d{3})+$)/g,','); } }, methods:{ handleReduce: function (index) { if (this.list[index].count === 1) return; this.list[index].count--; }, handleAdd: function (index) { this.list[index].count++; }, handleRemove: function (index) { this.list.splice(index,1) }, allChoose: function () { for (var i=0;i< this.list.length;i++) { this.list[i].checked = true; } } } });
css
table { border:1px solid #e9e9e9; } th,td { padding: 8px 16px; border: 1px solid #e9e9e9; text-align: left; }