.$data .#$el
$data表示vue實例中data的值
$el表示vue實例中el的值,注意 el效果等同getElementById.遇到多個同樣classname,只處理第一個
<div class="box">
{{ a }} //此處值為1
</div>
<div class="box">{{ a }}</div>
<div class="box">{{ a }}</div>
<script>
var data = { a: 1 }
var vm = new Vue({
el: '.box',
data: data
})
vm.$data === data // => true
vm.$el === document.getElementById('.box') // => true
// $watch 是一個實例方法
</script>
vue生命周期圖
上圖原文地址
每個 Vue 實例在被創建之前都要經過一系列的初始化過程。例如需要設置數據監聽、編譯模板、掛載實例到 DOM、在數據變化時更新 DOM 等。同時在這個過程中也會運行一些叫做生命周期鉤子的函數,給予用戶機會在一些特定的場景下添加他們自己的代碼。
例:
- created鉤子
created鉤子用在一個vue實例創建之后執行代碼:
new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 實例
console.log('a is: ' + this.a)
}
})
// => "a is: 1"
vue模版語法
文本
數據綁定最常見的形式就是使用“Mustache”語法 (雙大括號) 的文本插值:
<span>Message: {{ msg }}</span>
Mustache 標簽將會被替代為對應數據對象上 msg 屬性的值。無論何時,綁定的數據對象上 msg 屬性發生了改變,插值處的內容都會更新。
通過使用 v-once 指令,你也能執行一次性地插值,當數據改變時,插值處的內容不會更新。但請留心這會影響到該節點上所有的數據綁定:
<span v-once>這個將不會改變: {{ msg }}</span>
原始HTML
雙大括號會將數據解釋為普通文本,而非 HTML 代碼。為了輸出真正的 HTML ,你需要使用 v-html 指令:
<div v-html="rawHtml"></div>
以下是{{ Mustache }}語法與v-html的區別實例:
{{}}的語法會被解析成普通文本,v-html則會解析為HTML
特性
Mustache 語法不能作用在 HTML 特性上,遇到這種情況應該使用 v-bind 指令:
<div v-bind:id="dynamicId"></div>
延伸: vue的作用域和js作用域類似
示例:
<body>
<div class="app-5">
for
<span v-bind:id="src" v-bind:title="src">number</span>
<span v-bind:title="yeah">helloworld</span>
<div class="third">
<div v-bind:title="yeah">
div-next
</div>
</div>
<script>
var app5 = new Vue({
el: ".app-5",
data: {
src: "nice",
yeah: "good job"
}
})
</script>
</body>
//生成如下頁面
<div class="third">
<div title="good job">
div-next
</div>
</div>
上圖示例中,在<div class="app-5">下聲明一個new Vue,.app-5下的元素使用vue中變量yeah時,若自己的作用域下未找到,則到上級作用域去找,直到找到為止,若找不到,則報錯
使用js表達式
vue支持所有原生js表達式
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
但有個限制,每個綁定只能包含單個表達式,以下例子不會生效
<!-- 這是語句,不是表達式 -->
<!-- 表達式是由運算符構成,并運算產生結果的語法結構。
程序是由語句構成,語句則是由“;(分號)”分隔的句子或命令。
如果在表達式后面加上一個“;”分隔符,這就被稱為“表達式語句”。它表明“只有表達式,而沒有其他語法元素的語句” -->
{{ var a = 1 }}
<!-- 流控制也不會生效,請使用三元表達式 -->
{{ if (ok) { return message } }}
指令
指令 (Directives) 是帶有 v- 前綴的特殊屬性。指令屬性的值預期是單個 JavaScript 表達式 (v-for 是例外情況。指令的職責是,當表達式的值改變時,將其產生的連帶影響,響應式地作用于 DOM。
<p v-if="seen">現在你看到我了</p>
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
//若seen=true,則p內文字可見,若seen=false,p內文字消失
這里,v-if 指令將根據表達式 seen 的值的真假來插入/移除 <p> 元素。
參數
一些指令能夠接收一個“參數”,在指令名稱之后以冒號表示。例如,v-bind 指令可以用于響應式地更新 HTML 屬性:
<a v-bind:href="url"></a>
在這里 href 是參數,告知 v-bind 指令將該元素的 href 屬性與表達式 url 的值綁定。
另一個例子是 v-on 指令,它用于監聽 DOM 事件:
<a v-on:click="doSomething">
在這里參數是監聽的事件名
修飾符
修飾符 (Modifiers) 是以半角句號 . 指明的特殊后綴,用于指出一個指令應該以特殊方式綁定。例如,.prevent 修飾符告訴 v-on 指令對于觸發的事件調用 event.preventDefault():
<form v-on:submit.prevent="onSubmit"></form>
之后當我們更深入地了解 v-on 與 v-model時,會看到更多修飾符的使用
縮寫
v- 前綴作為一種視覺提示,用來識別模板中 Vue 特定的特性。當你在使用 Vue.js 為現有標簽添加動態行為 (dynamic behavior) 時,v- 前綴很有幫助,然而,對于一些頻繁用到的指令來說,就會感到使用繁瑣。同時,在構建由 Vue.js 管理所有模板的單頁面應用程序 (SPA - single page application) 時,v- 前綴也變得沒那么重要了。因此,Vue.js 為 v-bind 和 v-on 這兩個最常用的指令,提供了特定簡寫:
v-bind縮寫
<!-- 完整語法 -->
<a v-bind:href="url"></a>
<!-- 縮寫 -->
<a :href="url"></a>
v-on縮寫
<!-- 完整語法 -->
<a v-on:click="doSomething"></a>
<!-- 縮寫 -->
<a @click="doSomething"></a>
它們看起來可能與普通的 HTML 略有不同,但 : 與 @ 對于特性名來說都是合法字符,在所有支持 Vue.js 的瀏覽器都能被正確地解析。而且,它們不會出現在最終渲染的標記中。縮寫語法是完全可選的
計算屬性
模板內的表達式是非常便利的,但是它們實際上是用于簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。例如:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
在這個地方,模板不再簡單和清晰。你必須看一段時間才能意識到,這里是想要顯示變量 message 的翻轉字符串。當你想要在模板中多次引用此處的翻轉字符串時,就會更加難以處理。
這就是對于任何復雜邏輯,你都應當使用計算屬性的原因。
基礎例子
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// a computed getter
reversedMessage: function () {
// `this` points to the vm instance
return this.message.split('').reverse().join('')
}
}
})
結果:
Original message: "Hello"
Computed reversed message: "olleH"
這里我們聲明了一個計算屬性 reversedMessage。我們提供的函數將用作屬性 vm.reversedMessage 的 getter 函數:
console.log(vm.reversedMessage) // => 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // => 'eybdooG'
你可以打開瀏覽器的控制臺,自行修改例子中的 vm。vm.reversedMessage 的值始終取決于 vm.message 的值。
你可以像綁定普通屬性一樣在模板中綁定計算屬性。Vue 知道 vm.reversedMessage 依賴于 vm.message,因此當 vm.message 發生改變時,所有依賴于 vm.reversedMessage 的綁定也會更新。而且最妙的是我們已經以聲明的方式創建了這種依賴關系:計算屬性的 getter 函數是沒有連帶影響 (side effect),這使得它易于測試和推理。
計算屬性的緩存 vs 方法
你可能已經注意到我們可以通過在表達式中調用方法來達到同樣的效果:
<p>Reversed message: "{{ reversedMessage() }}"</p>
<script>
var vm = new Vue({
el: "p",
data: {
message: "happy"
},
methods: {
reversedMessage: function(){
return this.message.split("").reverse().join("")
}
}
})
</script>
我們可以將同一函數定義為一個方法而不是一個計算屬性。對于最終的結果,兩種方式確實是相同的。然而,不同的是計算屬性是基于它們的依賴進行緩存的。計算屬性只有在它的相關依賴發生改變時才會重新求值。這就意味著只要 message 還沒有發生改變,多次訪問 reversedMessage 計算屬性會立即返回之前的計算結果,而不必再次執行函數。
這也同樣意味著下面的計算屬性將不再更新,因為 Date.now() 不是響應式依賴:
computed: {
now: function () {
return Date.now()
}
}
相比之下,每當觸發重新渲染時,方法的調用方式將總是再次執行函數。
我們為什么需要緩存?假設我們有一個性能開銷比較大的的計算屬性 A,它需要遍歷一個極大的數組和做大量的計算。然后我們可能有其他的計算屬性依賴于 A 。如果沒有緩存,我們將不可避免的多次執行 A 的 getter!如果你不希望有緩存,請用方法來替代。
計算屬性 vs 被觀察的屬性
Vue 確實提供了一種更通用的方式來觀察和響應 Vue 實例上的數據變動:watch 屬性。當你有一些數據需要隨著其它數據變動而變動時,你很容易濫用 watch——特別是如果你之前使用過 AngularJS。然而,通常更好的想法是使用計算屬性而不是命令式的 watch 回調。細想一下這個例子:
<div id="demo">{{ fullName }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
上面代碼是命令式的和重復的。將它與計算屬性的版本進行比較:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
好得多了,不是嗎?
computed與methods
學到這里遇到了computed和methods兩個方法
用以下代碼對比
<body>
<div class="box">
<div class="child">
{{ message}}
</div>
<div class="child">
{{ timing }}
</div>
<div class="fn">
{{ timed() }}
</div>
</div>
<script>
var vm = new Vue({
el: ".box",
data: {
message: "hello"
},
methods: {
timed: function(){
return Date.now()
}
},
computed: {
timing: function(){
return Date.now()
}
}
})
</script>
</body>
//在控制臺改變vm.message結果時。div.fn的結果會改變,div.child的結果不會改變
methods方法返回的結果,在message改變時也會從新計算。computed則不會
計算屬性的 setter
計算屬性默認只有 getter ,不過在需要時你也可以提供一個 setter :
<body>
<div class="box">
{{ fullName }}
</div>
<script>
var vm = new Vue({
el: ".box",
data: {
firstName: "nick",
lastName: "song"
},
computed: {
fullName: {
get: function () {
return this.firstName + ' ' + this.lastName
},
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
})
</script>
</body>
現在再運行 vm.fullName = 'John Doe' 時,setter 會被調用,vm.firstName 和 vm.lastName 也相應地會被更新。
Class 與 Style 綁定
數據綁定的一個常見需求是操作元素的 class 列表和它的內聯樣式。因為它們都是屬性 ,我們可以用v-bind 處理它們:只需要計算出表達式最終的字符串。不過,字符串拼接麻煩又易錯。因此,在 v-bind 用于 class 和 style 時,Vue.js 專門增強了它。表達式的結果類型除了字符串之外,還可以是對象或數組。
綁定 HTML Class
對象語法
我們可以傳給 v-bind:class 一個對象,以動態地切換 class:
<div v-bind:class="{ active: isActive }"></div>
上面的語法表示 classactive 的更新將取決于數據屬性 isActive 是否為真值。
你可以在對象中傳入更多屬性用來動態切換多個 class。此外,v-bind:class 指令也可以與普通的 class 屬性共存。如下模板:
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
如下 data :
data: {
isActive: true,
hasError: false
}
渲染為:
<div class="static active"></div>
當 isActive 或者 hasError 變化時,class 列表將相應地更新。例如,如果 hasError 的值為 true ,class 列表將變為 "static active text-danger" 。
你也可以直接綁定數據里的一個對象:
<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
渲染的結果和上面一樣。我們也可以在這里綁定返回對象的計算屬性。這是一個常用且強大的模式:
<div v-bind:class="classObject"></div>
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
//expr1 && expr2 如果expr1 能轉換成false則返回expr1,否則返回expr2. 因此, 在Boolean環境中使用時, 兩個操作結果都為true時返回true,否則返回false.
數組語法
我們可以把一個數組傳給 v-bind:class,以應用一個 class 列表:
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
渲染為:
<div class="active text-danger"></div>
如果你也想根據條件切換列表中的 class,可以用三元表達式
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
此例始終添加 errorClass ,但是只有在 isActive 是 true 時添加 activeClass。
不過,當有多個條件 class 時這樣寫有些繁瑣。可以在數組語法中使用對象語法:
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
<script>
var vm = new Vue({
el: "div",
data: {
isActive: false,
errorClass: "error"
}
})
</script>
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
渲染為:
<div class="error"></div>