1. 程式人生 > >weex官方demo weex-hackernews程式碼解讀(1)

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、簡單說明

  1. components ——vue元件
  2. views ——檢視
  3. store ——Vuex
  4. mixins——擴充套件
  5. filters——vue.js 的filter
  6. App.vue 主UI介面
  7. entry.js 入口程式
  8. 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>

未完待續