一篇看完就把Vue.js融會貫通
Vue是一個專注于前端UI的框架。它的主要能力是:
- 聲明式綁定。包括數據綁定、事件綁定
- 基于組件的編程。讓開發(fā)者可以把整個應用分為若干組件,分而治之
本篇文字會講解聲明式綁定,并且會談及Vue的引入、數據綁定、事件綁定、Vue實例、指令。特別的,同樣的案例,我也用來講解Vue最為引以為傲的組件技術。案例是一個微小的叫做counter的應用,看起來是這樣的:
有一個標簽顯示數字0,當點擊按鈕“+”,數字會每次加1。代碼如下。你可以直接保存代碼到html文件中,然后用瀏覽器打開,如果是IE的話必須是IE8或者或以上版本:
- <script src="https://unpkg.com/vue/dist/vue.js"></script>
- <div id="app">
- <span>{{count}}</span>
- <button @click="inc">+</button>
- </div>
- <script>
- var app = new Vue({
- data () {
- return {count: 0}
- },
- methods: {
- inc () {this.count++}
- }
- })
- app.$mount('#app')
- </script>
你可以實際的操作,看到按鈕和數字的互動變化。然后我們來看Vue如何做到的。
首先,必須引入Vue.js庫。我們使用<script>,像是任何古老的js庫或者框架的引入一樣,引入Vue.js。為了方便,我們沒有下載vue.js ,而是使用了vue.js的一個網上提供的拷貝。此拷貝由http://unpkg.com/提供。接下來的代碼分為HTML標簽和放置于<script>內的js代碼。
隨后我們看HTML。它就是有一個div標簽內嵌套button和span標簽,看起來和普通HTML別無二致。除了{{count}}、和@click屬性之外。形如{{key}}的符號,是一種特殊的記號,表示的含義是:
從該標簽所在的Vue實例內的data函數返回的對象內查找名為‘key’的項目值,把這個值拿來填充{{key}}所占據的位置的內容。
具體到本案例,Vue實例內包含了data和methods。從而{{count}}最終定位得到返回對象,{count: 0},從而得到值0,并使用0填充到<span>標簽的內容上。這就是<span>{{count}}</span>的填充過程。
而@click表示的含義是:
把button的onclick事件掛接到對應Vue實例的methods對象內的指定方法上。這里就是inc()方法。
Vue實例通過調用$mount方法,把JavaScript內的數據和方法和HTML內對應的標簽塊關聯起來。當然,可以不使用$mount方法,而是采用:
new Vue({
el:'#app',
...
通過el成員的值#app,關聯到div#app上。兩者是等同的。但是我更喜歡$mount,因為它認為:
- Vue實例自身的內容
- 它對HTML的關聯
是兩回事。分開看會更好。
真正神奇的地方來了,這就是Vue的響應式編程特性。我們看到inc()方法內只是修改了this.count這個數字,UI上的<span>內容就會變化呢?我們本來以為的流程應該是:“我們首先修改this.count,然后拿這個修改過的值通過DOM API去更新<span>”。然而{{count}}這樣的數據綁定,不僅僅意味著把this.count的值顯示出來,也意味著當this.count被修改的時候,<span>的內容會跟著更新。這就是響應式編程,具體的魔法由Vue內部完成。開發(fā)者只要通過{{}}形式的聲明,告訴Vue說,“我的這塊內容應該顯示Vue實例內的某個數據,并且當Vue實例數據更新時,這里的顯示也要更新”即可。
Vue實例還做的另外一件事,是托管了data()返回的數據對象。數據對象的方法本來的做法是:
- this.$data.count
因為Vue實例的托管,你可以通過
- this.count
訪問達到data對象的count。這樣的簡易設計,真是討人喜歡。
再看下@click,它其實是v-on:click的簡寫,就是說本來應該寫為:
- <button v-on:click="inc">+</button>
這里就需要引出一個非常常用的、叫做“指令”的概念。指令是帶有v-前綴的特殊HTML標簽屬性。。指令的職責就是當其表達式的值改變時相應地將某些行為應用到DOM 上。
- 指令能接受一個參數,在指令后以“:”指明。
- 指令能接受一個修飾符,是以“.”指明的特殊后綴
- 指令能接受一個屬性值,預期是單一JavaScript表達式
讓我們回顧一下在介紹里的例子:v-on就是一個指令,它接受一個參數為click,接受的屬性值為inc。語義我們已經在上文提及,就是把onclick事件綁定到inc方法上。
指令的概念非常重要,也是擴展和復用代碼的一種方式,除了我們看到的v-on,還有很多可以使用的指令,比如v-for用于循環(huán)復制當前標簽等等。類似{{count}},其實可以使用v-text指令替代:
- <span v-text="count"></span>
更多指令我會在后續(xù)文章中繼續(xù)提及。
在新的vue版本中組件被認為更好的復用代碼和分離關注點的方式。接下來,我們使用同樣的案例,講解組件。我們可以看到HTML代碼:
- <div id="app">
- <span>{{count}}</span>
- <button @click="inc">+</button>
- </div>
標簽<span>和<button>其實一起合作,完成一個完整的功能,它們是內聚的;因此組件的基礎概念,如果可以使用一個自定義標簽,把它們兩個包裝到一個組件內會是一種更好的實踐。以此觀念,做完后應該得到這樣的代碼:
- <div id="app">
- <counter></counter>
- </div>
實際上開發(fā)起來并不困難,只是需要創(chuàng)建一個組件,把本來在Vue實例內的方法和數據,移動到此組件內,把在HTML內的兩個標簽也移動到組件的模板內。以下代碼是可以直接保存為html文件,并使用瀏覽器來打開運行的:
- <script src="https://unpkg.com/vue/dist/vue.js"></script>
- <div id="app">
- <counter></counter>
- </div>
- <script>
- var counter = {
- 'template':'<div><span>{{count}}</span><button v-on:click="inc">+</button></div>',
- data () {
- return {count: 0}
- },
- methods: {
- inc () {this.count++}
- }
- }
- var app = new Vue({
- components:{
- counter : counter
- }}
- )
- app.$mount('#app')
- </script>
這一次,我們見到了新的內容:
- Vue的新屬性template。它的值用來加載html模板代碼。本案例中,就是放置本來在主HTML內的兩個標簽。需要注意的是,它們之外包括了一個div標簽。因為Vue2.0版本要求作為模板的html必須是單根的。
- Vue的新屬性components,用來注冊一個局部組件。正是在此處,組件counter被注冊,從而在html標簽內可以直接使用<counter></counter>來引用組件counter的。
盡管這個案例太小了,還看不出太大的好處。但是這樣的組件引入,讓相關性強的html元素和對應的數據、代碼內聚到了一起,這是符合軟件工程原則的、因此是值得鼓勵的行為。
新組件完全可以分離到另外一個script文件內,從而達到不僅僅是邏輯上的代碼和主html分離,也做到了物理上的分離。
另外,使用template在代碼內些html,還是比較煩人:
- 你得小心的在外層使用單引號,在內部使用雙引號
- 混雜js和html觀感不佳
此時,可以使用的替代方法:
- render函數。實際上所有的template字符串本來在內部就被編譯為render函數的
- 單文件組件技術
- 或者vue支持的JSX。
當然,后兩種方法就需要轉譯器和打包工具的配合。比如Babel和webpack的。這些內容,請搜索參考
- vue.js - advance - render 函數小抄
- vue.js的起步
暫時不在討論之列。