本文就着以前幾天的文章 Vue2 移動端開發環境搭建 繼續擴展,上一篇文章有人反饋說講到最後只有 rem
是移動端相關的知識,沒錯我我的認爲除了 rem
和 touch
事件特殊外其它與 pc 端無異(手機系統版本和瀏覽器的 bug 放在這裏討論無心義),下面請出今天的大咖 vuexcss
說到這裏有兩個疑:html
1.什麼是狀態管理工具?vue
狀態管理工具起源於早期的 Flux,意在管理項目中各個狀態,狀態保存在 store 中,狀態是隻讀的,只能經過 action 觸發 store 的更新。react
2.問咱們爲何使用狀態管理工具?android
當一個項目逐漸壯大咱們須要管理的狀態就會變得繁雜,例如:父級組件傳遞狀態到子組件,子組件再次改變同一個狀態時就要想辦法告訴父級組件狀態改變了,狀況再複雜點呢!子組件之間又相互影響,又影響到其餘子組件的父組件呢?狀況變得愈來愈糟糕,咱們須要一個全局的公共狀態管理容器,把咱們的狀態都放進去統一管理。ios
大型項目對狀態的管理需求越來約大,從而發展到今天的 react + redux 組合,angular + ngRedux 組合, vue + vuex 組合。git
這裏 redux 做爲後起之秀有不少真對 Flux 的改進。感興趣的能夠深刻了解,這裏只關心 vuex 並且是 2.x,用過 1.x 版本的能夠順利過渡到 2.x。github
Vuex2 官方文檔: http://vuex.vuejs.org/en/inde...
能看懂文檔的能夠跳過實戰了。。。web
實戰開始以前先放出文檔,歸根結底仍是由於文檔描述過於簡單(簡陋),看的我雲裏霧裏,這個對於搞過 redux 的我而言不是原理不理解,而是用法上沒有一個能讓我一眼看懂的簡單粗暴的例子。vuex
方便你們理解工做流程,先給出官方的配圖
從左邊看 vue components(組件) -> action(只能經過 dispatch 調用,與此同時能夠異步與後端的 API 作交互) -> mutations(只能經過 action 發起 commit 調用,此時開發工具能夠監測到數據的流動) -> state (mutations 傳遞修改過的狀態到 state)-> state 自動同步到視圖
完成整個循環數據的流動是單向的,從而避免了雙向數據流動的複雜性,不一樣的組件能夠修改同一個狀態,並將修改後的狀態同步到全部關聯此狀態的組件。
原理就解釋到這,直接上一個實際例子。
這個例子的背景是我須要一個 webview,說到這不得不提 android 和 ios 的區別,目的就是全局判斷設備類型存入 state 在局部直接取到類型作判斷。
這裏其實能夠經過 props 傳遞 data 實現,說到這裏考慮到可能產生多級子組件,我每一層都須要 props 傳遞,又顧及到是全局屬性(由於嵌入到哪一個平臺的頁面就走那個平臺的接口)
安裝 vuex 的步驟就省了,在以前的文章介紹過了
在 src 下新建文件夾 vuex,進入 vuex 新建 store.js
而後去 main.js 加入
import store from './vuex/store'
再修改 Vue 實例以下
new Vue({ el: '#app', router, store, render: h => h(App) })
咱們去新建的 store.js
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex) export default new Vuex.Store({ state: { platform: '' }, mutations: { SET_APP(state, platform) { state.platform = platform; } }, actions: { setApp({commit}, platform) { commit('SET_APP', platform); } }, getters: { getApp: (state) => state.platform } })
看到這裏不急着往下進行,官方給的建議是 state、mutations、actions、getters 都分離成單獨文件再引入到 store.js 中,這裏只是爲了提供一個簡單粗暴的例子,把大部分流程都封裝在一個文件裏了,也方便修改測試。跟着上面工做流程圖一步一步的走一遍,不難發現咱們整個流程走下來只差組件分別調用 setApp 和 getApp 了。
說到組件先來看看完整的 App.vue
<template> <div id="app"> <div class="logo"> <img src="./assets/logo.png"> </div> <article-content></article-content> <share></share> <comment></comment> </div> </template> <script> import comment from './component/Comment.vue'; import articleContent from './component/ArticleContent.vue'; import share from './component/Share.vue'; export default { data () { return { } }, components: { articleContent, comment, share }, mounted () { let u = navigator.userAgent; if ( u.indexOf('Android') > -1 || u.indexOf('Adr') > -1 ) { this.$store.dispatch('setApp', 'android'); } else if ( !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) ) { this.$store.dispatch('setApp', 'ios'); } } } </script> <style lang="sass"> @import "/style/base.scss"; </style>
這裏引入了三個組件,在 mounted()
裏咱們判斷設備類型併發起 dispatch ,關鍵方法是 this.$store.dispatch('setApp', ...args);
簡單易懂咱們 dispatch 了一個 action(setApp),而後 commit 到 mutations(SET_APP),在 SET_APP 中修改了 state.platform
下面看看子組件是怎麼獲取,由於都是重複的用法因此只給一個 share 組件
<template> <div class="article-share-block"> <div class="divider-line" layout="row" layout-align="center center"> <div class="left-line" flex></div> <p class="label">分享到</p> <div class="right-line" flex></div> </div> <div layout="row" layout-align="space-between center"> <img class="share-icon" v-tap="{ methods: share, target: 'wechatTimeline' }" src="../img/wechat_timeline.png" alt=""> <img class="share-icon" v-tap="{ methods: share, target: 'wechatFriend' }" src="../img/wechat_friend.png" alt=""> <img class="share-icon" v-tap="{ methods: share, target: 'weibo' }" src="../img/weibo.png" alt=""> <img class="share-icon" v-tap="{ methods: share, target: 'qq' }" src="../img/qq.png" alt=""> </div> </div> </template> <script> export default { data () { return { platform: '' } }, mounted () { this.platform = this.$store.getters.getApp; }, methods: { initIOS() { window.connectWebViewJavascriptBridge((bridge) => { this.webviewBridge = bridge; }); }, share(target) { if (this.platform === 'ios') { this.initIOS(); this.webviewBridge.callHandler('invokeArticleShare', { shareTarget: target }); } else if (this.platform === 'android') { window.idarex.invokeArticleShare(target); } } } } </script> <style lang="sass"> @import "../style/component/share.scss"; </style>
仍是看關鍵語句 this.platform = this.$store.getters.getApp;
,這樣咱們能夠取到 state 中的 platform 完成一個完整存取數據的循環。
說到這,不要急着把完整的組件粘貼運行,必定會抱錯的,由於引入了第三方指令庫(v-tap 實現移動端 tap 事件),這些都是次要的也不必還原個人項目,整個原理和流程說的已經很清楚了,直接建立本身的組件跑一下就沒什麼問題了,大同小異。
vuex 的原理其實簡單易懂,本文經過一個小 demo 完成了一個簡單流程,但真實項目裏我不推薦這麼作,最好把 store.js 模塊化,方便後期維護,官方還提供了中間件等概念,準備在項目應用的能夠研讀源代碼,從工程化的角度規劃一下項目,當前 vue2 比較盛行,相信不久在 github 上會有大量的優秀項目供你們參考。
文章出自 orange 的 我的博客 http://orangexc.xyz/