关于vue的笔记
閱讀本文前需要你有過vue的一些學習基礎,本博文對一些基礎的概念和示例不做重復介紹。如果你已經有扎實的基礎積累可以直接閱讀博文,會進入到更加深入的vue.js學習。
1.data屬性
注意只有這些被data代理的屬性是響應的。如果在實例創建之后添加新的屬性到實例上,它不會觸發視圖更新。
你得在new之前,就把所有的data都傳進去。實例創建之后,其實可以使用$set來加入屬性,也可以實現響應功能。
2.app.$data/ $el
Vue 實例暴露了一些有用的實例屬性與方法。這些屬性與方法都有前綴 $,以便與代理的 data 屬性區分。
app.$data === data // -> true
3.app.$set
你要知道一個事實:app.$data.msg === app.msg,而且由于vue的響應系統,所以你直接app.msg = 'Let us go!'和
app.$set(app.$data, 'msg', 'Let us go')是一樣的。
總之,因為javascript的對象是引用型數據,所以你只要使用對了引用,怎么搞都是一樣的。
4.計算屬性
所謂計算屬性,就是跟ES5的getter一樣的,用function來定義個屬性,當你獲取這個屬性的時候,實際上是要執行這個function,執行function的過程就是計算過程,所以也就叫計算屬性。所有的計算屬性被放在computed里面,computed和data, methods同級。
5. computed VS methods
計算屬性是基于它們的依賴進行緩存的! 計算屬性是基于它們的依賴進行緩存的! 計算屬性是基于它們的依賴進行緩存的! 重要的事情說三遍。。。計算屬性只有在它的相關依賴發生改變時才會重新求值。這就意味著只要 message 還沒有發生改變,多次訪問計算屬性會立即返回之前的計算結果,而不必再次執行函數。
這也同樣意味著下面的計算屬性將不再更新,因為 Date.now() 不是響應式依賴:
相比而言,只要發生重新渲染,method 調用總會執行該函數。
我們為什么需要緩存?假設我們有一個性能開銷比較大的的計算屬性 A ,它需要遍歷一個極大的數組和做大量的計算。 然后我們可能有其他的計算屬性依賴于 A 。如果沒有緩存,我們將不可避免的多次執行 A 的 getter!如果你不希望有緩存,請用 method 替代。6.watch屬性
watch是和data, methods, computed同級的一個參數,你可以在watch里面規定你要watch的屬性,當這些屬性發生變化的時候,它會執行對應的那個函數。栗子:
var app = new Vue({data: {message: '',msg: '',},watch: {message: function() { // 當app.$data.message發生變化的時候,執行這個函數this.msg = 'Changed!'},},})7.指令
指令也可以有參數,主要是指v-on和v-bind這兩個指令,它們后面跟上一個冒號,冒號和等號之間的內容就是參數,例如v-bind:src="src"。
- v-if
- <div v-if="is"></div>
- v-if是有dom消耗的,使用時不應該反復更改is值。
- v-show
- <div v-show="is"></div>
- is為false的時候,會給這個元素加一個display:none,僅僅是隱藏這個元素,不會有dom的消耗。
- v-for
- v-bind / :
- v-on / @
- v-model
- <input v-model="something">其實是<input v-bind:value="something" v-on:input="something = $event.target.value">的語法糖,也就是說v-model本身就已經包含了v-bind,所以當v-bind:value, v-on:input和v-model同時出現在一個input上時,這個v-bind, v-on會失效。理解這一點很重要。
- v-pre
- 不進行模板編譯的部分。
- <span v-pre>{{ this will not be compiled }}</span>
- v-once
once讓渲染失去了數據綁定機制,只有在第一次渲染的時候,會獲取當時的變量對應的數據進行渲染,渲染結束之后,將不再跟著數據變化而變化。
- 這個指令有的時候非常有用。比如一些組件并不需要跟著數據變化而變化的時候。
- v-cloak
- 這個指令保持在元素上直到關聯實例結束編譯。和 CSS 規則如 [v-cloak] { display: none }一起用時,這個指令可以隱藏未編譯的 Mustache 標簽直到實例準備完畢。
8. 自定義事件
vue提供了四個和事件相關的實例方法,分別是$on, $once, $off, $emit,用過jquery的同學應該非常熟悉了。
對于事件綁定而言,vue內部直接提供了非指令的事件系統,跟jquery的用法幾乎一樣,v-on主要是在模板中綁定DOM原生的一些事件,而$on, $once可以綁定自定義的事件,兩者互不干擾。$emit也無法觸發原生的DOM事件。
- $on
- 監聽當前實例上的自定義事件。事件可以由vm.$emit觸發?;卣{函數會接收所有傳入事件觸發函數的額外參數。
- $once
監聽一個自定義事件,但是只觸發一次,在第一次觸發之后移除監聽器。
$on和$once綁定的事件是在實例上,而非DOM元素上,所以它們跟DOM原生的事件是兩回事。DOM原生事件是在觸發DOM元素特定事件時被觸發的,比如click。但是對于這里的實例vm而言,click沒有來源,實例根本不存在被click之說,所以$on和$once跟DOM原生事件扯不上任何關系。同理,$emit也是作用于實例之上,既然實例跟原生的DOM事件扯不上關系,那么$emit也就跟原生DOM事件扯不上關系了。
所以說,$on和$once綁定的是一個自定義事件,這些事件是存儲在vue內部的事件管理器中,跟DOM事件是兩碼事,既然如此,跟v-on事件綁定也就是兩回事。
- $off
- 移除事件監聽器。
- 如果沒有提供參數,則移除所有的事件監聽器;
- 如果只提供了事件,則移除該事件所有的監聽器;
- 如果同時提供了事件與回調,則只移除這個回調的監聽器。
- 移除事件監聽器。
- $emit
- 觸發當前實例上的事件。附加參數都會傳給監聽器回調。
- $on
9.組件
組件(Component)是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素, Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以是原生 HTML 元素的形式,以 is 特性擴展。
在開發層面上,你只需要使用Vue.extend({...})就可以得到一個組件。而開發的大部分工作,就是寫好大括號里面的內容。
創建一個組件
上面說過了,開發層面上,創建一個組件只需要使用Vue.extend,如下:
var MyComponent = Vue.extend({template: '<div>OK</div>', })這樣就創建了一個組件構造器MyComponent。實際上,Vue.extend的結果是Vue的一個子類。既然是一個類,就可以被實例化,通過實例化得到一個組件實例。組件構造器是一個類,可以被實例化為組件實例。
var component1 = new MyComponent()關于Vue.extend,我們會在后文繼續深入。組件實例有一些方法可以用,例如$mount方法,這也在后面的Vue.extend部分去解釋。
注冊一個組件
// 局部注冊 new Vue({el: '#app',template: '<div><my-component></my-component></div>',components: {'my-component': MyComponent,}, }) // 全局注冊 Vue.component('my-component', MyComponent)全局注冊有一個好處,就是可以在任何一個vue實例中去使用。
使用一個注冊好的組件
使用一個組件(比如在模板中插入<my-component>元素)的本質,是創建一個組件實例。也就是說,一個<my-component>就是一個組件實例,它們共享一個組件構造器(一個js類)。
簡易注冊
上面我們的做法是先創建一個組件構造器,然后把組件構造器傳入實例構造器。在實踐開發中,基本不會這樣干,我們大部分都會使用簡易方式直接注冊,跳過創建步驟,相當于注冊過程會自動創建一個匿名的組件構造器:
Vue.component('my-component', {template: '<div>OK</div>', })data必須是函數
之所以必須是函數是由于js本身的特性(引用)帶來的。為了不使組件的實例化函數相互影響,data必須是函數。這個我覺得有點像閉包一樣,我們需要一個閉包來保護變量不受外部污染,使實例的data屬性都是獨立的不相互影響。(這是我的理解,不知道對錯哈)
prop
一說到prop就要提一提和它很像又經常容易搞混的attrbution。這兩個的區別就是attribution往往是固定的值的屬性,而prop往往是動態的狀態值屬性。最簡單的例子就是input checkbox的checked屬性,checked屬性的attr值是它的初始值,而prop值是它的當前值,這對于熟悉jquery的同學而已應該比較好理解。
為組件聲明props屬性
vue里面,組件實例的作用域是孤立的。這意味著不能(也不應該)在子組件的模板內直接引用父組件的數據。要讓子組件使用父組件的數據,我們需要通過子組件的props選項。
子組件要顯式地用 props 選項聲明它期待獲得的數據:
Vue.component('child', {// 聲明 propsprops: ['message'],// 就像 data 一樣,prop 可以用在模板內// 同樣也可以在 vm 實例中像 “this.message” 這樣使用template: '<span>{{ message }}</span>' })prop屬性命名注意點
屬性名在注冊組件時使用的是駝峰式命名方式。
Vue.component('child', {props: ['myMessage'],template: '<span>{{ myMessage }}</span>' })但是在使用組件的時候,傳入的屬性名得是短橫線隔開的:
<child my-message="hello!"></child>這是因為html不區分大小寫,你寫成的話,假如有一個屬性名是mymessage怎么辦?所以,一定要注意這一點。
事件反饋
前面一節指出,子組件不能自己主動修改prop,以防改變了父組件或app的值導致bug。那么如果子組件確實需要上級應用修改這些變量,讓自己更好的適應新情況怎么辦?那就讓父組件或app自己來改??墒歉附M件怎么知道自己要改?通過子組件的事件就可以做到了。
我們可以在子組件里面觸發事件,在父組件里面監聽這個事件,當事件被觸發時,父組件通過綁定的回調函數來執行prop的更改。當然除了更改prop,還可以做其他的事情。
只能使用v-on綁定自定義事件
前文我們指出,直接用實例的$on方法來綁定自定義事件。但是在這里不行,不能直接在父組件里面直接用$on,因為我們使用<my-component>實例化組件時,沒有得到一個變量用來存儲實例化對象,它相當于是匿名的,所以我們找不到它,當然也找不到它的$on。
那怎么辦?只能使用v-on來進行事件綁定。
<child @clicked="showSomething"></child>這里的clicked是事件名,在子組件里面,通過this.$emit('clicked')觸發事件。父組件里面,通過上面代碼中的@clicked="showSomething"監聽這個事件,而showSomething就是事件回調函數,是父組件methods方法之一。
使用v-model實現input雙向綁定
上面不是說只能使用v-on綁定事件嗎?是的,但是你是否還記得前文提到過v-model其實是v-bind和v-on的語法糖?上一節我們說過了,<child>可以使用v-bind,而這里又說可以使用v-on,所以只要情況允許,就可以使用v-model。
所謂情況允許,是指符合下面條件:
- 接受一個 value 屬性
- 在有新的 value 時觸發 input 事件
在父組件中才可以這樣使用:
<child v-model="someData"></child>等價于:
<child :value="someData" @input="someData = $event.target.value"></child>組件內部,綠色的keyup是input元素的DOM原生事件,udpate是回調函數,當keyup的時候執行update(),而update()的時候就$emit('input'),觸發了父組件的v-on:input。
基于這種原理,不一定要使用在input輸入框上,實際上,任何元素都可以模擬這種方式實現數據雙向綁定。當然,如果沒有輸入,雙向綁定的說法就很奇怪。
組件小結
組件的內容還有很多,但是項目中常用的就是組建的兩個特性,一個是隔離性,父子組件通信的方式使得組件具有隔離性,主要表現在兩個方面:
- 1.組件通過props屬性獲取父組件或app層面傳來的數據,這些數據不應該被直接修改,也就是說這些數據僅屬于組件的上一層,而不屬于當前組件,組件不能通過修改這些數據來影響上一層;
- 2.組件不能直接對父組件或app層產生影響,但是可以通過事件綁定對上一層進行事件通知,上一層接收到這些通知時,自己決定是否要進行變化。
組件的另一個特性就是可復用性。基于上面兩個方面的特性,組件應該是具備高可復用性的,當一個地方需要使用這個組件時,只需要實例化,并給適合的props即可。只要props給的符合要求,組件就可以根據自己的邏輯運行,既不受外界影響,也不影響外界。
本篇讀書筆記是對唐霜的編寫的這本vue.js中文教程的整理分析。個人覺得這本書(也可以稱之為長博客吧)編寫的很接地氣,比官網更通俗一些。
轉載于:https://www.cnblogs.com/syqcoding-life/p/9821729.html
總結
- 上一篇: SpringBoot的基础
- 下一篇: flask-session 在redis