一、vue中template的三種寫法
第一種(字符串模板寫法):
直接寫在vue構造器里,這種寫法比較直觀,適用於html代碼不多的場景,但是如果模板里html代碼太多,不便於維護,不建議這么寫.
<body> <div id="app"></div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: "#app", data: { message: '字符串拼接' }, template: '<div>\ <h1>{{message}}</h1>\ <div>', }) </script> </body>
第二種(使用script元素)HTML5標准之前的寫法
<div id="app"></div> <script type="text/x-template" id="tem"> <div> <h1>{{message}}</h1> </div> </script> new Vue({ el: "#app", data: { message: 'HTML5標准之前的寫法,存在一定弊端(可自行google)\ 之后HTML5發布的template元素彌補了此方式的缺點' }, template: '#tem', })
通過使用<script type="x-template" id="template2">
同時把script標簽的id掛載到Vue實例化對象的template中 這種模板的好處是可以通過script的特性,通過src外部引入來使用.
第三種(使用template元素)HTML5標准之后的寫法【第二種的升級版】
div id="app"></div> <template id="tem"> <div> <h1>{{message}}</h1> </div> </template> new Vue({ el: "#app", template: '#tem', data: { message: 'HTML5中的template標簽' } })
在html中加入template標簽,給於這個template標簽一個id,然后通過實例化的Vue對象的template屬性掛載template模板
二、v-bind
動態地綁定標簽中的一個或多個屬性,或一個組件 prop 到表達式。v-bind指令可以在其名稱后面帶一個參數,中間用一個冒號隔開。這個參數通常是HTML元素的特性(attribute)。
v-bind指令:實現對屬性的綁定,以動態的切換屬性的值。
示例
<body> <div id="app"> <!-- v-bind 是Vue中提供的用於綁定屬性的指令 --> <!-- <input type="button" value="按鈕" v-bind:title="mytitle" > --> <!-- 簡寫方式 --> <input type="button" value="按鈕" :title="mytitle" > </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系統', mytitle:'v-bind綁定,自己定義的title' }, }) </script> </body>
v-bind:class='xxx':xxx為表達式結果的類型,除了字符串外,還可以是對象或數組;
語法:v-bind:屬性名="常量 || 變量名 || 對象 || 數組"。
簡寫形式:屬性名='變量名.....'
v-bind 進行屬性綁定所有的屬性都可以進行綁定,注意只要使用了v-bind后面的字符串一定是數據屬性的值。
常見的使用方式
v-bind:src="imageSrc" 可以縮寫: :src="imgaeSrc" :class="{ red: isRed }" 或 :class="[classA, classB]" :style="{ fontSize: size + 'px' }" 或 :style="[styleObjectA, styleObjectB]"
綁定一個有屬性的對象,比如:v-bind="{ id: someProp, 'other-attr': otherProp }"
1、綁定字符串
<body> <div id="app"> <!-- v-bind 是Vue中提供的用於綁定屬性的指令 --> <h3 v-bind:title="title">我是一個三級標題</h3> <img v-bind:src="imgSrc" v-bind:title="time"> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系統', title: "哈哈哈2323", imgSrc: './timg.jpg', time: `頁面加載於${new Date().toLocaleString()}` }, }) </script> </body>
顯示效果
當鼠標懸停在h3標簽幾秒之后,會顯示值“頁面加載於”。懸浮在圖片上會顯示time的值。
v-bind的簡便寫法(只寫冒號“:”不寫v-bind):
`<img :src=``"imgSrc"` `:title=``"time"``>`
2、數組語法
我們可以把一個數組傳給v-bind:class,以應用一個 class 列表:
<body> <div id="app"> <div v-bind:class="[activeClass, errorClass]">數組綁定class</div> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系統', activeClass: 'active', errorClass: 'text-danger' }, }) </script> </body>
顯示效果
如果你也想根據條件切換列表中的 class,可以用三元表達式:
`<div v-bind:``class``=``"[isActive ? activeClass : '', errorClass]"``></div>`
這樣寫將始終添加 errorClass
,但是只有在 isActive
是 true時才添加 activeClass
。
不過,當有多個條件 class 時這樣寫有些繁瑣。所以在數組語法中也可以使用對象語法:
`<div v-bind:``class``=``"[{ active: isActive }, errorClass]"``></div>`
三、v-on
動態地綁定一個或多個特性,或一個組件 prop 到表達式;其作用和v-bind類似。注意:如果用在普通元素上時,只能監聽 原生 DOM 事件;但是如果用在自定義元素組件上時,也可以監聽子組件觸發的自定義事件。
<body> <div id="app"> <!-- Vue 中提供了 v-on: 事件綁定機制 --> <input type="button" value="按鈕" :title="mytitle + '123'" v-on:click="show"> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系統', mytitle: '這是一個自己定義的title', }, methods: { // 這個 methods屬性中定義了當前Vue實例所有可用的方法 show: function () { alert('Hello') } }//show屬性對應函數 }) </script> </body>
顯示效果
示例二
<body> <div id="app"> <!-- Vue 中提供了 v-on: 事件綁定機制 --> <input type="button" value="按鈕" :title="mytitle + '123'" v-on:mouseover="show"> </div> <!-- 鼠標覆蓋事件 --> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系統', mytitle: '這是一個自己定義的title', }, methods: { // 這個 methods屬性中定義了當前Vue實例所有可用的方法 show: function () { alert('Hello') } }//show屬性對應函數 }) </script> </body>
v-on
接收一個需要調用的方法名稱,上面例子里的show就是自己定義的方法的名稱。在vue中所有的事件都聲明在methods中。
注意:v-on有簡便寫法,可以直接用@替代
`<button @click = ``"clickHandler"``>切換</button>`
v-on 與v-bind結合切換加載class
<style type="text/css"> .box { width: 100px; height: 100px; background: red; } .box2 { background: green; } </style> </head> <body> <div id="app"> <div class="box" v-bind:class="{box2:isGreen}"></div> <!-- 如果isGreen是true,那么v-bind綁定的屬性會自動加入class屬性,如果是false,則不會 --> <button @click="changeColor">切換顏色</button> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> // 指令系統 v-* var app = new Vue({ el: "#app", data: { isGreen: false, }, methods: { changeColor: function () { this.isGreen = !this.isGreen; } } }) </script> </body>
頁面顯示效果如下
四、更新元素的指令v-text與v-html
1、v-text
v-text等價於 {{}} ,實現原理:innerText。
更新元素的 textContent(**innerText**)
。如果要更新部分的 textContent
,需要使用 {{ Mustache }}
插值。v-text不能出來html標簽
<body> <div id="app"> <!--<h3>{{msg}}</h3>--> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { // 數據屬性 msg: 'hello指令系統', msg2: '<a href="#">這是我的數據</a>' }, template:` <div> <h4>{{msg}}</h4> <h3 v-text='msg2'></h3> </div> ` }) </script> </body>
顯示效果如下所示:
2、v-html
v-html實現原理是js中的innerHTML方法。v-html可以處理標簽的替換
更新元素的 innerHTML
。注意:內容按普通 HTML 插入 - 不會作為 Vue 模板進行編譯。如果試圖使用 v-html
組合模板,可以重新考慮是否通過使用組件來替代。
<body> <div id="app"> <!--<h3>{{msg}}</h3>--> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { // 數據屬性 msg: 'hello指令系統', msg2: '<a href="#">這是我的數據</a>' }, template:` <div> <h4>{{msg}}</h4> <h3 v-text='msg2'></h3> <h2 v-html="msg2"></h2> </div> ` }) </script> </body>
顯示效果如下所示:
使用v-html需要注意:
1)在網站上動態渲染任意 HTML 是非常危險的,因為容易導致 XSS 攻擊。只在可信內容上使用 v-html
,永不用在用戶提交的內容上。
2)在單文件組件里,scoped
的樣式不會應用在 v-html
內部,因為那部分 HTML 沒有被 Vue 的模板編譯器處理。如果你希望針對 v-html
的內容設置帶作用域的 CSS,你可以替換為 CSS Modules 或用一個額外的全局 <style>
元素手動設置類似 BEM 的作用域策略。
五、條件渲染指令v-if 與v-show
1、v-if
條件渲染指令,根據表達式的真假來添加或刪除元素。其語法結構是:v-if="expression",其中expression是一個返回bool值的表達式,其結果可以直接是true或false,也可以是返回true或false的表達式。
v-else-if
v-else
2、v-show
也是條件渲染指令,不同的是有 v-show 的元素會始終渲染並保持在 DOM 中。和v-if指令不同點在於:v-show是根據表達式之真假值,切換元素的 display CSS 屬性,當條件變化時該指令觸發過渡效果。
示例
<head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> .box{ color: red; } </style> </head> <body> <div id="app"> <div class="box" v-if="isShow">v-if 控制的元素</div> <div class="box" v-show="isShow">v-show 控制的元素</div> <input type="button" value="切換按鈕" v-on:click='toggle'> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系統', isShow:true, }, methods:{ toggle:function(){ this.isShow = !this.isShow; } } }) </script> </body>
效果
如上圖所示,v-if和v-show的不同就是:帶有v-show的元素始終會被渲染並保留在DOM中,v-show只是簡單地切換元素的CSS屬性display。
3、v-if 與 v-show 的區別
v-if
是“真正”的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子組件適當地被銷毀和重建。
v-if
也是惰性的:如果在初始渲染時條件為假,則什么也不做——直到條件第一次變為真時,才會開始渲染條件塊。
相比之下,v-show
就簡單得多——不管初始條件是什么,元素總是會被渲染,並且只是簡單地基於 CSS 進行切換。
一般來說,v-if
有更高的切換開銷,而 v-show
有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show
較好;如果在運行時條件很少改變,則使用 v-if
較好。
4、v-else
你可以使用 v-else
指令來表示 v-if
的“else 塊”:
<div v-if="Math.random() > 0.5"> Now you see me </div> <div v-else> Now you don't </div>
v-else
元素必須緊跟在帶 v-if
或者 v-else-if
的元素的后面,否則它將不會被識別。
5、v-else-if
2.1.0 新增
v-else-if
,顧名思義,充當 v-if
的“else-if 塊”,可以連續使用:
<div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div>
類似於 v-else
,v-else-if
也必須緊跟在帶 v-if
或者 v-else-if
的元素之后。
六、v-for
基於數據渲染一個列表,類似於JS中的遍歷。其數據類型可以是 Array | Object | number | string。
該指令之值,必須使用特定的語法(item, index) in items, 為當前遍歷元素提供別名。 v-for的優先級別高於v-if之類的其他指令。
一個對象的 v-for 你也可以用 v-for 通過一個對象的屬性來迭代。
// 遍歷obj中每個key對應的value <ul> <li v-for="value in obj">{{value}}</li> </ul> // 遍歷obj的value和key <ul> <li v-for="(value, key) in obj">{{value}}</li> </ul> // 遍歷obj的value、key和索引 <ul> <li v-for="(value, key, index) in obj">{{value}}</li> </ul>
1、v-for遍歷普通數組
v-for
指令需要使用 item in items
形式的特殊語法,items
是源數據數組並且 item
是數組元素迭代的別名。
<body> <div id="app"> <!-- <p>{{list[0]}}</p> <p>{{list[1]}}</p> <p>{{list[2]}}</p> <p>{{list[3]}}</p> <p>{{list[4]}}</p> --> <p v-for="(item, i) in list">索引值:{{i}} --- 每一項:{{item}}</p> </div> <script src="./lib/vue.js"></script> <script> // 創建 Vue 實例,得到 ViewModel var vm = new Vue({ el: '#app', data: { list: [1, 2, 3, 4, 5, 6] }, methods: {} }); </script> </body>
頁面顯示效果如下:
2、v-for遍歷對象數組
<body> <div id="app"> <p v-for="(user, i) in list">Id:{{ user.id }} --- 名字:{{ user.name }} --- 索引:{{i}}</p> </div> <script src="./lib/vue.js"></script> <script> // 創建 Vue 實例,得到 ViewModel var vm = new Vue({ el: '#app', data: { list: [ { id: 1, name: 'nicholas' }, { id: 2, name: 'jack' }, { id: 3, name: 'pony' }, { id: 4, name: 'lucy' } ] }, methods: {} }); </script> </body>
頁面顯示效果如下
3、v-for遍歷對象
<body> <div id="app"> <!-- 注意:在遍歷對象身上的鍵值對的時候, 除了 有 val key ,在第三個位置還有 一個 索引 --> <p v-for="(val, key, i) in user">值是: {{ val }} --- 鍵是: {{key}} -- 索引: {{i}}</p> </div> <script src="./lib/vue.js"></script> <script> // 創建 Vue 實例,得到 ViewModel var vm = new Vue({ el: '#app', data: { user: { id: 1, name: 'nicholas', gender: '男' } }, methods: {} }); </script> </body>
頁面顯示效果如下
4、v-for迭代數字
<body> <div id="app"> <!-- in 后面我們放過 普通數組,對象數組,對象, 還可以放數字 --> <!-- 注意:如果使用 v-for 迭代數字的話,前面的 count 值從 1 開始 --> <p v-for="count in 10">這是第 {{ count }} 次循環</p> </div> <script src="./lib/vue.js"></script> <script> // 創建 Vue 實例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {} }); </script> </body>
頁面顯示效果如下
5、v-for中key的作用:為什么使用v-for時必須添加唯一的key屬性
key的作用:
key是為了給Vue一個提示,以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素,需要為每項提供一個唯一的key屬性。
舉個例子
沒有加key的情況:
<body> <div id="app" > <div> <input type="text" v-model="name" > <button @click="add">添加</button> </div> <ul> <li v-for="item in list"> <input type="checkbox">ID:{{item.id}} -------name:{{item.name}} </li> </ul> </div> <script> var vm = new Vue({ el:'#app', data:{ name: '', list: [ { id:0,name:'nicholas1號' }, { id:1,name:'nicholas2號' }, { id:2,name:'nicholas3號' } ] }, methods:{ add() { // 1.拼接處一個完整的用戶信息對象,包含ID 和name const newUser= {id: this.list.length,name: this.name}; // 2.把拼接出來的用戶信息對象 調用this.list.unshift方法把對象追加到數組的第一個 this.list.unshift(newUser); } } }) </script> </body>
沒有加key的時候,當我選中第二個“nicholas2號”后,再添加nicholas4號時:
則會出現問題:選中的變成了“nicholas1號”,位置依舊是第二個,很顯然這不是我們想要的結果,解決這個問題的方法就是加key屬性
加上key的情況:
<body> <div id="app" > <div> <input type="text" v-model="name" > <button @click="add">添加</button> </div> <ul> <li v-for="item in list" :key='item.id'> <!-- 增加key屬性 --> <input type="checkbox">ID:{{item.id}} -------name:{{item.name}} </li> </ul> </div> <script> var vm = new Vue({ el:'#app', data:{ name: '', list: [ { id:0,name:'nicholas1號' }, { id:1,name:'nicholas2號' }, { id:2,name:'nicholas3號' } ] }, methods:{ add() { // 1.拼接處一個完整的用戶信息對象,包含ID 和name const newUser= {id: this.list.length,name: this.name}; // 2.把拼接出來的用戶信息對象 調用this.list.unshift方法把對象追加到數組的第一個 this.list.unshift(newUser); } } }) </script> </body>
加上key以后,當我選中第二個“nicholas2號”后,再添加nicholas4號時:
注意:key的取值必須是number 或 string,不能是對象,而且使用 v-for 循環的每一項的值,都要保證唯一性 。
參考資料