解讀Vue實例的屬性及模板渲染
1 概述
Vue.js是通過new Vue({...})
來聲明一個實例的,在這個實例中包含瞭當前頁面的HTML結構、數據和事件。
Vue實例是MVVM模式中的ViewModel,實現瞭數據和視圖的雙向綁定。
在實例化時可以傳入一個選項對象,它包含數據、模板、掛載元素、方法、生命周期鉤子函數等選項。
2 el:與DOM元素綁定
el
是element
的簡寫,用來和DOM元素進行綁定,對應的是DOM元素的id屬性值(類似id選擇器)。
用法如下:
<div id="xxx"></div> <script> var vm = new Vue({ el: "#xxx" // xxx為id名 }) </script>
3 data:定義雙向綁定的數據
在Vue實例中初始化的data中的所有數據會自動進行監聽綁定,可以使用兩個大括號 {{}}
來綁定data中的數據。
用法如下:
<div id="xxx"></div> <script> var vm = new Vue({ el: "#xxx", data: { 健: 值 } }) </script>
健為屬性的名稱,值為初始值。
示例代碼:
<div id="app"> <h2>{{message}}</h2> <input type="text" v-model="message"> </div> <script> var vm = new Vue({ el: "#app", data: { message: "橘貓吃不胖" } }) </script>
如果在輸入框中輸入其他內容,h2標簽也會顯示該內容,vue與h2標簽的綁定是單向的,與input標簽的綁定是雙向的。
註:data中的數據都是淺拷貝。這意味著,如果修改原來的對象也會改變data,從而觸發更新事件。
4 computed:計算屬性
computed
是計算屬性,當我們要用到的屬性不存在,需要通過已有屬性計算得來,這時使用計算屬性。computed
底層借助瞭Object.defineproperty
方法提供的getter
和setter
來實現。
使用方法可以跟data
中的屬性一樣使用,註意用的時候不要加“()
”。
它是data
屬性的補充。在進行數據綁定的時候,對數據要進行一定的處理才能展示到HTML頁面上。
雖然Vue提供瞭非常好的表達式綁定方法,但是隻能應對低強度的需求。
用法如下:
<div id="xxx"></div> <script> var vm = new Vue({ el: "#xxx", computed: { 方法名: function () {} } }) </script>
例如,把一個日期按照規定格式進行輸出,可能就需要對日期對象做一些格式化。
Vue提供的計算屬性(computed)允許開發者編寫一些方法,協助進行綁定數據的操作。
<div id="app"> <table> <tr> <td>姓名:</td> <td>{{name}}</td> </tr> <tr> <td>生日:</td> <td>{{getBirthday}}</td> </tr> </table> </div> <script> var vm = new Vue({ el: "#app", data: { name: "橘貓吃不胖", birthday: 1014228510514 // 傳瞭一個毫秒數 }, computed: { // 計算屬性,對data中的數據進行處理 getBirthday: function () { // getBirthday就是表格中的{{getBirthday}},其本質是一個屬性 let date = new Date(this.birthday); return date.getFullYear() + "年" + (date.getMonth() + 1) + "月" + date.getDate() + "日"; } } }) </script>
每一個計算屬性都包含一個getter
和一個setter
。
上面的示例是計算屬性的默認用法, 隻是利用瞭getter
來讀取。在需要時,也可以提供一個setter
函數, 當手動修改計算屬性的值就像修改一個普通數據那樣時,就會觸發setter
函數,執行一些自定義的操作。
getter函數執行的時機:
(1)初次讀取時會執行一次
(2)當依賴的數據發生改變時會被再次調用
計算屬性computed
優勢:與methods
實現相比,它的內部有緩存機制,計算屬性隻有在它相關依賴發生改變時才會重新求值,效率更高,調試方便。
註意:
(1)計算屬性最終會出現在Vue實例vm上,直接讀取使用即可
(2)如果計算屬性要被修改,那必須寫set函數去響應修改,且set中要引起計算時依賴的數據發生改變
示例:在輸入框中分別輸入姓和名,最後將全名顯示在頁面上,感受getter
方法;在控制臺中修改全名,感受setter
方法。
<div id="app"> 姓:<input type="text" v-model="xing"><br><br> 名:<input type="text" v-model="ming"><br><br> 你的姓名是:{{fullName}} </div> <script> var vm = new Vue({ el: "#app", data: { xing: "", // 初始值為空 ming: "" }, computed: { fullName: { get() { return this.xing + "-" + this.ming; // 返回值為全名 }, set(value) { let arr = value.split("-"); this.xing = arr[0]; this.ming = arr[1]; } } } }) </script>
如下所示,在輸入框中輸入姓和名,會將全名顯示在下方。
如果在控制臺中修改全名,會修改掉輸入框中的值。
5 methods:定義Vue實例的方法
methods
需要搭配v-on
指令來監聽DOM事件,我們在methods
對象中定義方法,最終會在Vue實例上,其中的this
會指向Vue的實例vm
,因此其中配置的函數不可以使用箭頭函數,否則會改變this
的指向。
用法如下:
<div id="xxx"></div> <script> var vm = new Vue({ el: '#xxx', methods: { 方法名: function () { } } }) </script>
示例代碼:
<div id="app"> <p>原始字符串:"{{ message }}"</p> <p>反向字符串:"{{ reversedMessage()}}"</p> </div> <script> var vm = new Vue({ el: '#app', data: { message: '橘貓吃不胖' }, methods: { reversedMessage: function () { return this.message.split('').reverse().join('') } } }) </script>
6 Vue中的三種模板
6.1 html模板
- html模板:基於DOM的模板,模板都是可解析的有效的HTML插值
- 文本:使用{{ }}語法,作用:替換實例上的屬性值,當值改變時,插值內容處會自動更新
- 原生的html:雙大括號輸出的是文本,不會解析html(想要解析html,可以使用指令v-html)
- 屬性:使用v-bind進行綁定,可以響應變化
<div id="wrap"> <p>你的名字是{{list.name}}</p> </div> <script> var list = { name: "donna", age: 20 } var vm = new Vue({ el: "#wrap", data: { list } }); </script>
6.2 字符串模板
先定義字符串模板,然後在vue 的選項對象裡面利用template綁定。字符串模板的優先級會比html模板高,如果html和字符串模板中都有內容,會用字符串模板裡的內容替換html模板。需要註意的是定義的字符串模板中根節點隻能有一個。還有字符串用 ` 引起來是可以換行的。
示例代碼:
<div id="app"></div> <script> let obj = { content: "橘貓吃不胖" } let str = `<div>Hello {{content}}</div>`; new Vue({ el: "#app", data: obj, template: str }) </script>
除瞭用變量定義模板字符串,還可以用script標簽,給script 標簽定義id,根節點隻能有一個,將html結構寫在一對script標簽中,設置type=“x-template”,模板將會替換掛載的元素。掛載元素的內容都將被忽略。Vue實例的template屬性設置為給定的script標簽
示例代碼:
<div id="app"></div> <script type="x-template" id="test"> <div> <p>姓名:{{obj.name}}</p> </div> </script> <script> let obj = { name: "張三" } new Vue({ el: "#app", data: { obj }, template: "#test" }) </script>
6.3 render函數模板
render(createElement){ createElement(標簽名,[數據對象],子元素)//子元素為數組或對象 }
數據對象的屬性:
class:{ }, //綁定class style:{ }, //綁定樣式, attrs:{ }, //添加行間屬性 domProps:{ }, //DOM元素屬性 on:{ }, //綁定事件
示例代碼:
<div id="app"></div> <style> .bg { background-color: pink; } </style> <script> new Vue({ el: "#app", render(createElement) { return createElement( "ul", { class: { bg: true }, style: { listStyle: "none" }, attrs: { name: "tt" } }, [ createElement("li", "蘋果"), createElement("li", "香蕉"), createElement("li", "橘子") ] ) } }) </script>
7 watch屬性
watch
屬性用來觀察和響應Vue實例上的數據變動,watch
屬性是一個配置對象,它有兩個屬性:一個是鍵,一個是值。
鍵是需要觀察的表達式,值可以為以下形式:
- 對應的回調函數,回調函數得到的參數為新值和舊值。
- 方法名稱的字符串(通過
methods
聲明) - 包含額外選項的對象。當使用對象語法時,回調函數應被聲明在
handler
中。額外的選項包含:
選項 | 說明 |
---|---|
immediate | 在初始化時立即調用回調函數handler。第一次調用時,舊值將為undefined |
deep | 如果源是對象或數組,則強制深度遍歷源,以便在深度變更時觸發回調 |
flush | 調整回調的刷新時機 |
onTrack / onTrigger | 調試偵聽器的依賴關系 |
new Vue({ ... watch: { // 值為回調函數形式,newVal表示新的值,oldVal表示舊的值 要監視的數據: function (newVal, oldVal) { } // 值為方法名形式: 要監視的數據: "methods中聲明的方法名" // 值為包含額外選項的對象: 要監視的數據: { immediate: xxx, handler(newVal, oldVal) {}, deep: xxx, } } })
示例:點擊按鈕給屬性a
做減法,監聽新值與舊值。
<div id="app"> <button @click="a--">減1</button> <p>{{message}}</p> </div> <script> new Vue({ el: "#app", data: { a: 10, message: " ", }, watch: { a: function (val, oldVal) { this.message = "a的原值是:" + oldVal + ",a的新值是:" + val; } } }) </script>
或者使用Vue實例中的$watch()
,也可以達到監視效果,該方法的返回值是一個取消觀察函數,用來停止觸發回調,用法如下:
// 完整形式 const vm = new Vue({ }) // unwatch:取消觀察函數 let unwatch = vm.$watch("要監視的對象", { immediate: true, // 配置一些屬性 ... handler(newVal, oldVal) { // 回調函數 unwatch(); // 停止監聽對象 } }) // 簡寫形式 const vm = new Vue({ }) // unwatch:取消觀察函數 let unwatch = vm.$watch("要監視的對象", function (newVal, oldVal) {} })
示例:點擊按鈕給屬性a
做減法,監聽新值與舊值。當值為5時,停止監聽。
<div id="app"> <button @click="a--">減1</button> <p>{{message}}</p> </div> <script> const vm = new Vue({ el: "#app", data: { a: 10, message: " ", } }) let unwatch = vm.$watch("a", { handler(val, oldVal) { if (val === 5) { unwatch(); } this.message = "a的原值是:" + oldVal + ",a的新值是:" + val; } }) </script>
computed與watch的區別
- computed能完成的功能,watch都可以完成;watch能完成的功能,computed不一定能完成。
- 例如:watch可以進行異步操作(使用setTimeout函數)。
8 模板渲染
8.1 條件渲染
條件渲染分為兩種方式,一種是v-if
,另一種是v-show
。v-if
又分為單路分支、雙路分支和多路分支。隻有if
後面的值為true
時才會有DOM元素,為false
時不會有DOM元素
1、v-if
方式渲染:在<template>
中配合v-if
渲染,在使用v-if
控制元素的時候,需要將它添加到這個元素上。然而,如果需要切換很多元素時,一個一個添加比較麻煩。這時,可以使用<template></template>
將一組元素進行包裹
<div id="app"> <template v-if="yes"> <h2>vue</h2> </template> </div> <script> var vm = new Vue({ el: "#app", data: { yes: true } }) </script>
2、v-show
方式渲染:用法與v-if
大致相同
8.2 列表渲染
列表渲染用v-for指令根據一組數據的選項列表進行渲染。v-for指令需要采用item in items 形式的特殊語法,其中items是源數據
<div class="app"> <ul> <li v-for="item in items">{{item.text}}</li> </ul> </div> <script> new Vue({ el: '.app', data: { items: [ { text: 'Name'}, { text: 'Age'}, { text: 'Like'} ] } }) </script>
可以使用v-for迭代對象的屬性
<div class="app"> <ul> <li v-for="item in obj">{{item}}</li> </ul> </div> <script> new Vue({ el: '.app', data: { obj: { firstname: '歐陽', lastname: '靜靜', age:18 } } }) </script>
總結
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- vue2.x版本中computed和watch的使用及關聯和區別
- Vue基礎之偵聽器詳解
- Vue中的 watch監聽屬性詳情
- Vue計算屬性與監視(偵聽)屬性的使用深度學習
- vue Watch和Computed的使用總結