Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 七周七種前端框架四:Vue.js 組件和組件通信

七周七種前端框架四:Vue.js 組件和組件通信

編輯:關於Android編程

基本是按照官網的 Guide 全部梳理了一遍:http://vuejs.org/guide/index.html 這裡我們以一個 Todo List 應用為例來把相關的只是都串起來,這篇裡面的全部代碼都在github上 https://github.com/lihongxun945/vue-todolist

Vue 實例

一個 Vue 應用是由一個 root vue instance 引導啟動的,而 Vue instance 是這麼創建的:

var vm = new Vue({
  // options
})

一個 instance 實際上就是 MVVM 中的一個 VM。 傳入的配置對象中data裡的所有屬性都會被掛載到 instance上,而為了避免命名沖突,Vue 內置方法都會以 $ 開頭的屬性掛載到 instance 上。

instance 從創建到銷毀會經歷如下生命周期:

在初始化的時候大致經過三步:

綁定數據監聽,即對 data 的監聽 編譯模板 插入document或者替換對應dom # Vue 基本語法

數據綁定

Vue 使用的是一種 類 mastache 語法。常用綁定語法分這麼幾類:

mastache 語法,比如 {{ data }} {{ data | filter}} v-bind 綁定屬性,比如 v-bind: href, v-bind:class v-on 綁定事件, 比如 v-on:click, v-on:submit

其中 v-* 都是 directive
例子:


屬性計算

Vue 支持一個很有意思的屬性計算語法,可以指定一個屬性由其他屬性計算出來,這樣就不用通過 $watch 來實現了:

var vm = new Vue({
  el: '#example',
  data: {
    a: 1
  },
  computed: {
    // a computed getter
    b: function () {
      // `this` points to the vm instance
      return this.a + 1
    }
  }
})
## 流程控制和列表相關的語法 包括 `v-if`, `v-show`, `v-else`, `v-for`

表單

雙向數據綁定:




## 動畫 動畫的實現方式和 Angular 以及 React 都是一樣的,都是通過添加和刪除 class 來實現的。 # Component

組件的基本用法

Component 的定義包括兩部分:

1 創建component類:

var Profile = Vue.extend({
  template: " Lily "
});

2 注冊一個 tagname:

Vue.component("me-profile", Profile);

這樣我們就可以通過 tagname 來使用這麼組件了:

  
    
    
...

Vue.component("me-profile", Profile); 屬於全局注冊,如果只是在某一個頁面內使用,可以通過局部注冊的方式:

var vm = new Vue({
  el: "#todo",
  components: {
    "my-profile": Profile
  },
  ...
}

其中因為我們的 Vue 實例是綁定在 todo 元素上的,所以如果把 my-profile 放在這個元素外面是無效的,只有放在這個裡面才會被 Vue 的這個實例引導初始化。

注意事項:
Vue 構造函數可以傳的參數基本都可以用在 Vue.extend 上,但是對 eldata 兩個參數需要注意,為了避免不同實例間共享同一個對象,總是要通過 function 返回一個新的對象比較靠譜:

var MyComponent = Vue.extend({
  data: function () {
    return { a: 1 }
  }
})

因為參數都一樣,其實他們倆就是同一個東西,不過一個是組件,一個是用來引導Vue啟動的。

模板注意事項

因為 Vue 就是原生的DOM,所以有些自定義標簽可能不符合DOM標准,比如想在 table 中自定義一個 tr,如果直接插入 my-component 不符合規范,所以應該這樣寫:


  

Props 傳遞數據

在 Vue 中每個組件都是獨立的,不能也不應該直接訪問父類的data。所以我們通過 props 來向子組件傳遞數據,是不是和 React 的方式很像?

不同於 React,在 Vue 中子組件需要先聲明自己的 props 才行:

var Profile = Vue.extend({
  props: ["name"],
  template: `
    

{{name}}'s Todo List

{{name}} is a good girl

` });

然後我們可以在使用 Profile 的時候這樣傳遞參數:


這種是通過字面量傳遞參數,所以傳遞的值一定是字符串。還有一種方式是動態傳參,通過 v-bind 來傳遞參數,可以雙向綁定數據或者傳非字符串參數:


v-bind 如果是一個字符串,則是綁定父組件的data中對應的字段,比如上面就是雙向綁定了 input 的值。如果是一個數字則就是綁定了一個數字。

Vue 還可以顯式指定單向還是雙向的數據綁定:









Props 校驗

一個好的組件總是應該先驗證參數是否正確,另外可能還需要設置一些參數的默認值:

var Profile = Vue.extend({
    input: {
      type: String
    }
});

父子組件通信

上面講到的 props 其實就是父組件向子組件傳遞消息的一種方式。
在子組件中有一個 this.$parentthis.$root 可以用來方法父組件和根實例。不過,現在我們應該避免這麼做。因為組件本身就是為了封裝獨立的邏輯,如果又去直接訪問父組件的數據就破壞了組件的封裝性。
所以我們應該還是應該通過父組件向子組件傳遞 props 的方式來通信。

當然 props 其實只能做回調。在 React 中就探討過這個問題,React 的做法就是通過 props 來做,傳一個回調函數給子組件。其實我不是很喜歡這種把回調函數傳來傳去的方式,我更喜歡的是事件的方式。Vue 中子組件可以通過通過事件和父組件進行通信的。向父組件發消息是通過 this.$dispatch,而向子組件發送消息是通過 this.$boardcast,這裡都是向所有的父親和孩子發送消息,但是一旦執行一個回調之後就會停止,除非這個回調函數顯式返回了 true

我們把之前的Todo List拆成不同的組件來實現,這樣可以體驗下如何進行組件的雙向通信,我們拆分出兩個組件,分別是 ListForm

Form 負責處理用戶輸入,並在提交表單的時候向父組件發送一個 add 消息,代碼如下:

var Form = Vue.extend({
  props: {
    username: {
      type: String,
      default: "Unnamed"
    }
  },
  data: function() {
    return {
      input: "",
    };
  },
  template: `
    

{{username}}'s Todo List

`, methods: { add: function() { this.$dispatch("add", this.input); //這裡就是向父組件發送消息 this.input = ""; } } });

List 只負責展示列表和處理用戶勾選操作,它接收到 add 消息之後會在自己上添加一個條目:

var List = Vue.extend({
  template: `
    
`, props: { initList: { type: Array } }, data: function() { return { list: [] } }, events: { add: function(input) { if(!input) return false; this.list.unshift({ title: input, done: false }); } } });

然後,因為這是兩個組件,當然需要一個 Vue 實例來引導啟動,我們的實例如下:

var vm = new Vue({
  el: "#todo",
  components: {
    "todo-form": Form,
    "todo-list": List
  },
  events: {
    add: function(input) {
      this.$broadcast("add", input);
    }
  }
});

注意,其實 FormList 在邏輯上是平級的組件,所以他們沒有父子關系,他們共同都是 vm 的孩子。這裡 vm 接到 Form 的消息之後會轉發給 List

html 代碼就更簡單了:

  
    
    
  

Slot

通過 Slot 可以實現把父組件渲染出來的HTML插入到子組件中,目前還不清楚什麼時候會需要這樣做,而且這麼做對子組件的侵入性太大。

動態切換組件

這個功能感覺有點多余,感覺很多情況下我們應該是通過邏輯代碼來實現切換,而不是通過Vue內置的動態組件來切換。不過用來實現一個類似 tab 切換的功能還是很方便的。

我們這裡給 Todo List 增加一個 about 頁面。那麼首先我們需要把 vm 改成一個組件,這個組件叫 Todo,它就是整個 Todo 頁面:

var Todo = Vue.extend({
  template: `
  
    
    
    not show
  
  `,
  components: {
    "todo-form": Form,
    "todo-list": List
  },
  events: {
    add: function(input) {
      this.$broadcast("add", input);
    }
  }
});

其實改動就第一行。

然後我們需要創建一個 About 組件:

var About = Vue.extend({
  template: `
  
    

About Todo List V0.1.0

Content here

` });

接下來是重點了,我們要創建一個實例 vm,這vm要負責切換這兩個頁面:

var vm = new Vue({
  el: "body",
  data: {
    currentView: "todo"
  },
  components: {
    "todo": Todo,
    "about": About
  }
});

這裡我們定義了一個 currentView 字段,當然可以是任意名稱,然後通過特殊的 component 標簽來進行組件切換:


  

上面的代碼有兩處需要注意:

通過 component 這個特殊標簽,然後用 :is 屬性來進行組件的切換。 radio 通過雙向綁定來修改 currentView 字段,從而實現點擊之後就可以進行切換。

數據綁定的實現原理

Vue 把雙向綁定稱作 reactive,可以翻譯為響應式數據綁定。內部是通過 ES5 定義的 gettersetter 方法實現的,所以不支持 IE8 及以下浏覽器,這種實現方式有兩個容易犯錯的地方:

如果在 data 上直接添加和刪除屬性是無法被檢測到的,一般刪除是不會的,但是可能會動態添加,這個時候應該通過 vm.$set(“name”, value) 的方式來添加。 無法檢測到對象內部的變化,也就是只能檢測 data 的屬性變化,如果 data.a 是一個對象,那麼 data.a.b = 1 這種變化是無法被檢測到的。這種情況下應該創建一個新的對象並賦值給 data.a 就行了。

異步更新機制

Vue 對DOM的更新是異步的! 這個異步是在一個異步隊列中進行的,不過這個異步隊列會在當前的 Event Loop 中執行完,所以如果修改了 Data 立刻去DOM中做查詢操作是不對的,這個時候DOM還沒有更新,正確的做法是這樣做:

vm.msg = 'new message' // change data
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
  vm.$el.textContent === 'new message' // true
})

或者這樣:

vm.$nextTick(function () {
  this.$el.textContent === 'new message' // true
})

花了半天時間才看完組件,下面應該去看一下另一個重點: Directive

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved