weex官方demo weex-hackernews程式碼解讀(1)
一、介紹
weex 是阿里出品的一個類似RN的框架,可以使用前端技術來開發移動應用,實現一份程式碼支援H5,IOS和Android。最新版本的weex已預設將vue.js作為前端框架,而weex-hacknews則是weex官方出品的,首個使用 Weex 和 Vue 開發的 Hacker News 原生應用,在專案中使用了 Vuex 和 vue-router等官方元件 。因此這個應用可以作為weex-vue開發的典範,分析該專案程式碼可以瞭解如何使用weex技術棧進行開發,實現同一份程式碼在 iOS、Android、Web 下都能完整地工作。
1、下載
下載地址:https://github.com/weexteam/weex-hackernews
使用git clone專案或者直接下載zip包
2、安裝
安裝依賴:
npm install
編譯程式碼:
npm run build
啟動 Web 服務
npm run serve
3、訪問
啟動服務後會監聽 1337 埠,訪問 http://127.0.0.1:1337/index.html 即可在瀏覽器中預覽頁面。
Chrome瀏覽器開啟,F12進入開發者模式,啟用手機模擬,可以看到如下的效果
3.1 首頁
3.2 評論頁
更多的請自行安裝體驗。
二、程式碼分析
將專案裡的src匯入到IDE裡,可以看到程式碼結構如下:
1、簡單說明
- components ——vue元件
- views ——檢視
- store ——Vuex
- mixins——擴充套件
- filters——vue.js 的filter
- App.vue 主UI介面
- entry.js 入口程式
- router.js ——vue-router
2、入口程式
上程式碼:
該段程式碼主要實現將各個元件和擴充套件匯入,執行各種初始化工作,包括view、store、router等核心功能。暫且說這麼多,後面再詳說。
3、vue-router
3.1 vue-router介紹
vue-router (https://github.com/vuejs/vue-router)是vue.js生態裡重要的一環,是vue.js官方router ,它與Vue.js核心深度整合,使得使用Vue.js構建單頁面應用程式變得輕而易舉,包含如下特性:
- 巢狀路由/檢視對映
- 基於元件的路由器配置
- 路由引數,查詢,萬用字元
- 整合Vue.js頁面過渡效果
- 導航控制
- 歷史記錄:HTML5 history mode 或者 hash mode
我們從hackernews專案來看如何使用vue-router:
3.2 程式碼分析
- 首先,需要import Router from 'vue-router',匯入Router,然後Vue.use(Router)
- rourter是基於元件的路由配置,所以還需要匯入各種View
-
最重要的,router需要返回Router的例項物件,關鍵是配置routes,如程式碼所示,routes是一個json-array,裡面的每一個json-object包含了path和component
- path支援字串、萬用字元
- component返回一個View
- 看到這裡大概就理解了router的原理,通過path去匹配,然後返回匹配的View,比如訪問主頁,route裡配置的是redirect:'/top', 則會跳轉到top
- 專案裡,top,new,show等都是StoriesView,只是型別不同,所以createStoriesView函式用於例項化不同型別的StoriesView
-
路由跳轉
-
跳轉:包含兩種方式,宣告和程式設計。
- <router-link :to="...">
-
router.push(...)
- router.push({ path: 'home' })
- router.push('home')
- router.push({ name: 'user', params: { userId: 123 }})
- 這裡順帶提一下mixins,在入口程式碼裡有
// register global mixins.
Vue.mixin(mixins)
我們來看mixins
- Vue.mixin 混合是一種靈活的分散式複用 Vue 元件的方式,所有混合物件的選項將被混入該元件本身的選項,因此上述程式碼實現為Vue元件增加jump方法,而jump的核心就是路由的跳轉。mixin後,可以在vue元件裡使用jump方法。例如:<div class="link" @click="jump('/top')">
4、vuex
4.1 vuex介紹
Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式儲存管理應用的所有元件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。Vuex 也整合到 Vue 的官方除錯工具 devtools extension,提供了諸如零配置的 time-travel 除錯、狀態快照匯入匯出等高階除錯功能。
狀態管理模式,開發中大型單頁應用時需要使用到,Vuex 借鑑了 Flux、Redux等成熟框架的思想開發而成。什麼是"狀態管理模式"呢,我們來看官方的說明:
讓我們從一個簡單的 Vue 計數應用開始:
new Vue({
// state
data () {
return {
count: 0
}
},
// view
template: `
<div>{{ count }}</div>
`,
// actions
methods: {
increment () {
this.count++
}
}
})這個狀態自管理應用包含以下幾個部分:
- state,驅動應用的資料來源;
- view,以宣告方式將state對映到檢視;
- actions,響應在view上的使用者輸入導致的狀態變化。
以下是一個表示"單向資料流"理念的極簡示意:
但是,當我們的應用遇到多個元件共享狀態時,單向資料流的簡潔性很容易被破壞:
- 多個檢視依賴於同一狀態。
- 來自不同檢視的行為需要變更同一狀態。
我們可以把元件的共享狀態抽取出來,以一個全域性單例模式管理。這樣元件樹構成了一個巨大的"檢視",不管在樹的哪個位置,任何元件都能獲取狀態或者觸發行為。另外,通過定義和隔離狀態管理中的各種概念並強制遵守一定的規則,程式碼將會變得更結構化且易維護。
Vuex包含State,Getters,Mutations ,Actions 和Modules 五大核心概念
- State : Vuex 使用 單一狀態樹,State是全域性唯一資料來源,可以理解為state為資料庫
- Getters可以認為是 store 的計算屬性,類似面向物件類裡的get,set
- mutation:更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation,每個 mutation 都有一個字串的 事件型別 (type) 和 一個 回撥函式 (handler)
-
Actions Action 類似於 mutation,不同在於:
- Action 提交的是 mutation,而不是直接變更狀態
- Action 可以包含任意非同步操作
- Modules : 使用單一狀態樹,導致應用的所有狀態集中到一個很大的物件。但是,當應用變得很大時,store 物件會變得臃腫不堪,Vuex 允許將 store 分割到模組(module),每個模組擁有自己的 state、mutation、action、getters
再來看下面的圖,Sate作為全域性資料來源,可以通過Action提交Mutation來改變State,State改變後自動Render到Vue的component,同時可以安裝vue.js提供的devtools檢視mutation變更記錄。
-
跳轉:包含兩種方式,宣告和程式設計。
4.2 程式碼分析
4.2.1 匯入Vuex
import Vuex from 'vuex'
4.2.2 定義Store,例項化Vuex.Store
4.2.3 定義state 和getters
state是全域性唯一資料,定義了包含items,lists等需要展示到UI上的資料,getters可以理解為state的一個切片或者檢視函式,返回符合條件的特定資料。
4.2.4 mutation
回顧下前面說的,state的所有改變必須是通過mutation,我們來看實現:
每個mutation是一個函式,第一個引數是state,第二個是所謂的載荷,理解為變化的資料
mutation如何呼叫的呢?
- store.commit('mutation名稱')
-
store.commit('mutation名稱', {
引數: 引數值
})
Vuex 規定mutation必須是同步函式,不能為非同步。
4.2.5 資料API
store最主要的功能就是獲取和儲存資料,如何獲取資料呢?
weex中通過stream提供網路訪問功能,通過stream.fetch獲取,注意fetch.js裡fetch函式返回的是一個Promise物件
關於Promise,不瞭解的可以檢視(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise)
store/fetch.js
4.2.6 action
進入store/action.js
看code:
export function FETCH_LIST_DATA({commit,dispatch,state},{type}){
commit('SET_ACTIVE_TYPE',{type})
return fetchIdsByType(type)
.then(ids=>commit('SET_LIST',{type,ids}))
.then(()=>dispatch('ENSURE_ACTIVE_ITEMS'))
}
- 定義了一個名為FETCH_LIST_DATA的action
- Action 函式接受一個與 store 例項具有相同方法和屬性的 context 物件,可以呼叫 context.commit 提交一個 mutation,或者通過 context.state 和 context.getters 來獲取 state 和 getters
- 為什麼FETCH_LIST_DATA的第一個引數是{commit,dispatch,state}?因為使用了ES2015 的 引數解構 來簡化程式碼
- commit('SET_ACTIVE_TYPE',{type}) 實現呼叫名為SET_ACTIVE_TYPE 的mutation,傳遞的引數為type,可以回過頭去看下mutation的定義
- fetchIdsByType返回的是Promise物件,後面兩個then理解為非同步結果回撥函式,第一個是操作成功,則呼叫SET_LIST Mutation,第二個then則是處理失敗
5、filters過濾器
filter是vue.js的一個特性,
過濾器是一個通過輸入資料,能夠及時對資料進行處理並返回一個數據結果的簡單函式。Vue有很多很便利的過濾器,可以參考官方文件, http://cn.vuejs.org/api/#過濾器 ,過濾器通常會使用管道標誌 " | ", 比如:
{{ msg | capitalize }}
// 'abc' => 'ABC'
專案裡的定義如下:
提供了獲取host,以及格式化時間的filter
看下如何使用過濾器
<text class="text-cellsmall-text">|{{comment.time|timeAgo}} ago</text>
未完待續…