系列文章的目錄在 ? 這裏html
除了 Vue.js 在 Weex 和 Web 中的差別之外,Vue.js 自身的各類特性都是能夠正常使用的。因此,這篇文章其實和 Weex 並沒多大關係,我就給你們簡單羅列幾個在 weex-hackernews 項目裏用到的特性(這幾個特性愈來愈高階):vue
Vue mixin 文檔node
mixin 是一種複用代碼的技巧,能夠將多個組件共同的邏輯抽象成 mixin,官方文檔中寫的很詳細。它會將 mixin 中定義的方法合併到組件上,若是包含生命週期函數,則先調用 mixin 中的方法再執行組件自身的;若是屬性有衝突,組件自身的方法會覆蓋掉 mixin 中定義的。git
在 weex-hackernews 中的 src/mixin/index.js 裏定義了一個簡單的 mixin:github
export default { methods: { jump (to) { if (this.$router) { this.$router.push(to) } } } }
它只包含了一個方法,就是 jump
,它經過調用路由的 push
方法來實現頁面跳轉。web
而後,在 src/entry.js 中全局註冊了這個 mixin
。shell
import Vue from 'vue' import mixins from './mixins' // register global mixins. Vue.mixin(mixins)
在實際應用中應該謹慎地註冊全局 mixin,若是不是全局通用的操做,建議仍是隻給用到的組件添加 mixin。apache
如此一來,全部組件都能調用到 jump
方法,例如 app-header.vue 這個組件,它自身沒有 <script>
標籤,可是可以在模板中給點擊事件綁定 jump
函數。在 weex-hackernews 裏,點擊左上角的 logo 能夠返回首頁。segmentfault
<div class="logo" @click="jump('/')"> <image class="image" src="https://news.ycombinator.com/favicon.ico"></image> </div>
通常來講你們都傾向認爲組合要優於繼承,在 Vue 裏使用 mixin 實現「組合」,比用
ParentComponent.extend({})
模擬繼承要好一些。並且在.vue
文件裏,要想繼承其餘組件也挺麻煩的。從另一個角度上來說,若是真的是有一些邏輯能抽離出來,也優先考慮寫成獨立的模塊,export
可用的接口,要用的時候直接import
進來便可。依賴框架自己的特性越少,代碼就越容易複用。數組
在使用 v-bind
指令的時候,支持使用過濾器 (filter) 對綁定的值再進行處理;接收變量中的原始值做爲參數,返回處理後的值,支持將多個過濾器串聯在一塊兒使用,相似 shell 命令中「管道」的寫法。
過濾器的使用方法和 mixin
相似,如今 src/filter/index.js 中寫好要註冊的方法,在 src/entry.js 中全局註冊了這些 filters
。
import Vue from 'vue' import * as filters from './filters' // register global utility filters. Object.keys(filters).forEach(key => { Vue.filter(key, filters[key]) })
在 weex-hackernews 的 story.vue 文件中第六行用到了 host
過濾器,用來獲取 url 中的網站地址。
<text class="small-text" v-if="story.url">({{ story.url | host }})</text>
在第十三行用到了 timeAgo
過濾器,會把時間戳轉成可讀時間字符串。
<text class="small-text text-cell"> | {{ story.time | timeAgo }} ago</text>
在 src/filter/index.js 中的實現是這樣的:
function host (url) { if (!url) return '' const host = url.replace(/^https?:\/\//, '').replace(/\/.*$/, '') const parts = host.split('.').slice(-3) if (parts[0] === 'www') parts.shift() return parts.join('.') } function timeAgo (time) { const between = Date.now() / 1000 - Number(time) if (between < 3600) { return pluralize(~~(between / 60), ' minute') } else if (between < 86400) { return pluralize(~~(between / 3600), ' hour') } else { return pluralize(~~(between / 86400), ' day') } }
效果以下:
除此以外
在 comment.vue 裏用到了 unescape 過濾器。
在 ArticleView.vue 裏用到了 https 過濾器。
<solt>
)槽是 Vue.js 中用來實現「內容分發」的功能的,能夠理解爲內容的佔位符。參考 external-link.vue 例子:
<template> <div @click="open"> <slot></slot> </div> </template>
在 story.vue 裏使用時,<external-link>
標籤中的內容將會替換到 <slot>
。
<external-link :url="story.url" class="story-link"> <text class="story-title">{{story.title}}</text> <text class="small-text" v-if="story.url">({{ story.url | host }})</text> </external-link>
Vue 能夠實現遞歸組件,能夠在本身的模板中調用本身,只須要你寫上 name
屬性就能夠了。
支持寫遞歸組件,聽起來好像是框架在故意炫技,爲何會有這種奇葩功能?由於的確有這種奇葩需求…… 例如 Hacker News 裏的評論,是能夠無限展開的。
其實每條評論都有一個惟一 id
的,每條評論下邊的回覆的 id
都存在 kids
屬性上;存的只是 id
不是真實的評論數據。從網絡獲取到某條評論以後,還有根據 kids
數組中的 id
獲取評論下的全部回覆,而後獲取回覆下的全部評論,而後獲取評論下的全部回覆…… 這很明顯是個遞歸過程。即便評論的數據用樹形結構去存,你不知道樹的深度,仍是得用遞歸的方式把全部評論渲染出來。
【評論】和【回覆】是一個意思,爲了好表達才用的倆詞,漢語就是比英語詞多……
下面問題來了,如何渲染這種遞歸的評論?用正常的組件好像很難實現這種效果,我沒想到很合適的寫法,有興趣能夠試着想一下。
讓組件支持遞歸很簡單,只要加上 name
屬性就好了,而後就能夠在本身的模板中調用本身。
<!-- comment.vue --> <template> <div> <text>tips:</text> <comment></comment> </div> </template> <script> export default { name: 'comment' } </script>
上邊就是一個最簡單的遞歸組件的例子,寫了 name
屬性並且在模板中用了本身。可是它死循環了,沒有結束條件,最終會報一個 "max stack size exceeded" 的錯。
在 weex-hackernews 裏,comment.vue 就是一個遞歸組件。它用於渲染一條評論,在內部有使用它本身渲染本身的評論。效果以下:
下邊是 <comment>
組件簡化後的核心代碼:
<template> <div v-if="comment"> <text>{{comment.text}}</text> <comment v-for="id in comment.kids" :id="id"></comment> </div> </template> <script> import store from '../store' export default { name: 'comment', props: ['id'], computed: { comment () { return store.state.items[this.id] } } } </script>
在 <comment>
組件中,comment
屬性的數據是根據當前的 id
屬性從 store 中取出來的,而後根據 comment.kids
循環建立多個 <comment>
標籤,而且把 id
屬性傳下去。子 <comment>
標籤根據傳遞過來的 id
屬性從 store 中獲取 comment
數據渲染自身,而後根據 comment.kids
循環建立多個 <comment>
標籤,而且把 id
屬性傳下去。…… 依次遞歸。
再具體的細節,就建議直接看 comment.vue 的代碼了。至於 store 是如何獲取數據的,關注後續講 Vuex 的文章。
通篇講的是 Vue 2.0 的特性,與 Weex 沒有半毛錢關係,我想說明的是,這些特性在 Weex 裏都是徹底可用的。
Vue 2.0 的特性比較多,能力很強大,這裏只講了很小一部分;只要思路清晰,各類奇葩效果也能優雅的實現。在 Vue 2.0 的全部特性中,只要不是強依賴與 Web 自己的特性,均可以在 Weex 裏用。若是你對 Web 平臺有足夠的瞭解,在寫代碼的時候就能時刻清楚哪些特性是 Web / DOM 強相關的,哪些是跨平臺通用的,這對你寫跨端(Weex)或者跨棧(node.js)的程序頗有幫助。