vueのモバイル体験における最適化ソリューション

14869 ワード

昨年末にモバイル端末でvueの開発フレームワークを自分で組んだので、体験があまりよくないような気がします.先週はまたモバイル端末のプロジェクトをします.だから私は2日間かけて前の開発フレームワークを以下のように最適化しました.
  • カスタムvuex-plugins-loading
  • ルーティング切り替えアニメーション+keep alive動的管理キャッシュコンポーネント
  • better-scrollとvueのベストプラクティス(better-scrollのvue化)
  • カスタムコマンド(vue-finger:クリック、長押し、ダブルクリック、ドラッグ移動、マルチタッチ、スライド、回転、スケールジェスチャーを含む)
  • 移動端適合案
  • 状況別処理ページトップ
  • ルーティング怠け者
  • カスタムvuex-plugins-loading
    各ページがデータロードが完了する前にloadingを表示します.まず、各ページの設定状態、show、hide状態を思い浮かべます.しかし、このような冗長コードが多すぎて、自分で書くのが面倒です.私の前のreactのプロジェクトでdvaを使って、その中にdva-loadingライブラリがあって、前に研究したことがあるので、私は彼の考えを使って、自分でvuex-loadingを書きました.実装構想:vuexにloadingを管理するmoduleを登録し、非同期のactionをバインドすることで、各actionのloadingをvuexに存在させることで、私は各ページでvuexのstoreで対応するaction loadingを持つだけでこの目的を達成することができます.
     ##     
        store.subscribeAction({
          before: action => {
            if (shouldEffect(action, includes, excludes)) {
              store.commit({ type: namespace + '/SHOW', payload: action.type })
            }
          },
          after: action => {
            if (shouldEffect(action, includes, excludes)) {
              store.commit({ type: namespace + '/HIDE', payload: action.type })
            }
          }
        })
      }
    }
    

    使用する前にsubscribeActionがこのプラグインをインストールしたいことを知っておくことができます.ここをクリックして、starに覚えておいてください.注意:上記のコードを使用すると、vuexは3.1.0バージョンでなければなりません.subscribeActionは3.1.0に追加されたので
    補足
    vuex-plugins-loadingというデータストリームの処理を推奨する理由を書くと思います.
    私も一昨年dvaに接触しました.jsのとき、このようなデータストリームを処理する考え方は、プロジェクト全体をより明確にし、反復しやすいと感じました.他の人があなたのフレームワーク全体を引き継ぐのは簡単です.
    今、私の側がどのようにdvaに基づいているかを話します.jsの思想はvuexをカプセル化している.実は簡単です
    ## store        index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    import home from './modules/home'
    import createLoadingPlugin from 'vuex-plugins-loading'
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      modules: {
        home,
      },
      plugins: [createLoadingPlugin()]
    })
    
    # home.js
    import { loadDataApi } from '../../service/api'
    
    const state = {
      listData: [],
    }
    
    const mutations = {
      getData (state, payload) {
        state.listData = state.listData.concat(payload.res.data.data)
        state.page = payload.res.data.page
        state.pageNumber = Math.ceil(payload.res.data.total / payload.res.data.pageSize)
      },
      refreshData (state, payload) {
        state.listData = payload.res.data.data
      },
    }
    const getters = {
    
    }
    const actions = {
      loadMore ({ commit, state }, data) {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            const { page, type } = data
            loadDataApi({ page }).then(res => {
              if (res.code === 200) {
                if (type === 'loadMore') {
                  commit({
                    type: 'getData',
                    res: res
                  })
                } else {
                  commit({
                    type: 'refreshData',
                    res: res
                  })
                }
                resolve()
              } else {
                reject(res.error)
                Toast(res.error)
              }
            })
          }, 1000)
        })
      }
    }
    
    ## Home.vue
    computed: {
        // Getting Vuex State from store/modules/home
        ...mapState({
          listData: state => state.home.listData,
          loading: state => state['@@loading'].effects['home/loadMore']
        }),
      },
      methods: {
        ...mapActions('home', ['initData', 'plusPage', 'initPage']),
        // onLoad     
        onLoad () {
          this.requestData('loadMore')
        },
        requestData (type) {
          setTimeout(() => {
            this.$store.dispatch('home/loadMore', {
    
            }).then(() => {
            })
          }, 1000)
        },
        onRefresh () {
          this.initPage().then(() => {
            this.requestData('refresh')
          })
        },
    

    1.まずvuex-plugins-loading内層はどのように実現されていますか?
    1.plugins: [createLoadingPlugin()],
    2.loading: state => state['@@loading'].effects['home/loadMore']
    1このプラグインを使用すると、あなたが使用した各actionがバインドされ、私が2を使用すると、バインドactionのloadingが取得されます.この中には2つの過程があります.store.subscribeActionのbeforeとafter.私がactionを呼び出した後、私のloadingはずっとtrueで、これはbeforeの中での操作です.私のactionにpromiseが包まれている場合、resolve()またはreject()を歩いてからaction全体が完了します.その後afterを歩きます.
    before
    after
    なぜ大量の論理をvuexに入れて処理するのかと聞かれるのは知っています.実は私はかえってこのようにしてあなたのプロジェクト全体を明確化することができて、メンテナンス性が高いと思っています.反復しやすい.
    .vueファイルは、vuex内のデータをページレンダリングするだけです.
    storeではデータをアクセスし、フィルタリングします.
    serveレイヤはapiをカプセル化するために使用されます
    これで一目瞭然
    ルーティング切り替えアニメーション+keep alive動的管理キャッシュコンポーネント
    以前はグローバル設定ルーティング切り替えアニメーションを採用していましたが、体験効果はあまりよくありませんでした.特にリストページに戻ると、ページが反発し、ページ切り替え時に一時的な空白が発生します.
    改造前のものも、他人のやり方を参考にしている.
    ## app.vue
     "transitionName"> 
        "data">
            
        
     
     
      computed: {
        //      vuex  
        ...mapState({
          data: state => {
            return state.global.data
          }
        })
      },
      methods: {
        //   Keep_alive  
        setKeep_alive (to) {
          if (to.meta.keepAlive) {
            this.$store.dispatch({
              type: 'global/setData',
              payload: to.name
            })
          }
        }
      },
      watch: {
        '$route' (to, from) {
          //    from     to  
          this.setKeep_alive(to)
          const routeDeep = ['/', '/list', '/detail', '/reservation', '/addCars']
          const toDepth = routeDeep.indexOf(to.path)
          const fromDepth = routeDeep.indexOf(from.path)
          if (!from.name) {
            this.transitionName = 'fold'
            return
          }
          this.transitionName = toDepth > fromDepth ? 'fold-left' : 'fold-right'
        }
      },
    
    ## router.js
    scrollBehavior (to, from, savedPosition) {
        // keep-alive              
        if (savedPosition && to.meta.keepAlive) {
          return savedPosition
        }
        //       
        return new Promise((resolve) => {
          setTimeout(() => {
            resolve({ x: 0, y: 1 })
          }, 0)
        })
      },
    

    二つの問題
  • リストページが一定の位置にスライドした後、詳細ページにジャンプし、リストページに戻るバウンド理由:オリジナルスクロールバーの位置は変わらず、scrollBehaviorを使用して、上記のコードからスクロールバーが点滅する過程が先にトップに置かれ、最後に保持された位置にスクロールすることがわかります.
  • ページの切り替え時に一時的な空白があり、移行が正常ではありません.

  • 改造後
    ## app.vue
    "data">
      
    
    computed: {
        //      vuex  
        ...mapState({
          data: state => {
            return state.global.data
          }
        })
      },
      methods: {
        //   Keep_alive  
        setKeep_alive (to) {
          if (to.meta.keepAlive) {
            this.$store.dispatch({
              type: 'global/setData',
              payload: to.name
            })
          }
        }
      },
      watch: {
        '$route' (to, from) {
          //    from     to  
          this.setKeep_alive(to)
        }
      },
    
    list.vue
    "scroll"
      class="scroll-home"
      :scrollbar="scrollbar"
      :probeType="3"
      :pullDownRefresh="pullDownRefresh"
      :pullUpLoad="true"
      @pullingDown="onRefresh"
      @scroll="scroll"
      @pullingUp="onLoad"
    >
     
    "contantView">

    1.better-scrollを採用すると、最初の問題は直接解決できます.しかもscrollBehaviorを設置する必要はなく、better-scrollを見に行くことができます
    2.ページCSSに「position:absolute;」の設定を追加し、このとき、ページはドキュメントフローから離れ、スペースを占めず、次のページを押し下げずにスムーズな移行を完了します.better-scrollを使用してページCSSに「position:fixed;」の設定を追加します.
    ページレイアウトにflexレイアウトがある場合は、flexコンポーネントにabsoluteまたはfixedのdivを追加する必要があります.
    上記のコードにはkeep aliveがキャッシュルーティングを動的に管理する考え方がある.
    better-scrollとvueのベストプラクティス
    以前、ある文章でBetterScrollを見たのは、現在最もよく使われているモバイル端末のスクロールプラグインかもしれないので、今回は試してみたいと思います.滴滴オープンソースのcube-uiコンポーネントライブラリで使われているスライドコンポーネントの多くはbetter-scrollベースで、体験してみるといいですね.どうしてcubeを使わなかったの?個人的にテーマの色が少し醜いと感じたからです.だから自分でbetter-scrollに基づいてvueバージョンのscrollコンポーネントをパッケージするつもりです.そんなに言わないで、すぐに図を描きます.
    better-scrollを使いたいのはもう一つの理由があります.ドロップダウンのアニメーションをカスタマイズしたいです.
    demoとソースコードを見たいならここをクリックしてください.starをあげるのを忘れないでね
    カスタム命令vue-finger
    クリック、長押し、ダブルクリック、ドラッグ移動、マルチタッチ、スライド、回転、ズームジェスチャーを含む
    これは私の側が他の人のdemoに基づいて改造したもので、これらの指令の中であなたは移動端のジェスチャーの面でやりたいことをたくさんすることができます.あとはこれらのコマンドを反復して、オリジナルに近い体験をするコンポーネントを作ります.私のgithubに注目してください.
    モバイル・エンド・アダプティブ・スキーム
    ## rem.js
    const baseSize = 32
    //    rem   
    function setRem () {
      //           750       ,         。
      const scale = document.documentElement.clientWidth / 750
      //            
      document.documentElement.style.fontSize = (baseSize * Math.min(scale, 2)) + 'px'
    }
    //    
    setRem()
    //             rem
    window.onresize = function () {
      setRem()
    }
    
    ## main.js
    import './rem'
    

    あと最後まであと一歩.よくスタイルを书く学生にとって、px転remはうんざりしているのではないでしょうか.こちらの処理方法は、プロジェクトのルートディレクトリにpostcssを新規作成することです.config.jsファイル.このように設計原稿のスタイルに従って、正常にpxを書くだけでいいです.プロジェクトを実行すると自動的にremに移行します.
    module.exports = {
      plugins: {
        'autoprefixer': {
          browsers: ['Android >= 4.0', 'iOS >= 7']
        },
        'postcss-pxtorem': {
          rootValue: 16,
          propList: ['*']
        }
      }
    }
    

    状況に応じてページをトップに配置する方法
    vue-routerではscrollBehaviorという方法が前述されています.
    ## router.js
    scrollBehavior (to, from, savedPosition) {
        // keep-alive              
        if (savedPosition && to.meta.keepAlive) {
          return savedPosition
        }
        //       
        return new Promise((resolve) => {
          setTimeout(() => {
            resolve({ x: 0, y: 1 })
          }, 0)
        })
      },
    

    しかし、ページを追加してアニメーションを回転させたような気がします.ページにリバウンドがあります.だから私はそれを放棄しました.アニメーションを追加しないことは考えられます.私はbetter-scrollを使ってからこの問題を心配する必要はありません.better-scrollドキュメントの紹介を見ると、better-scrollはモバイル側の運用のために生まれたものであることがわかります.
    ルートインロード
    構築アプリケーションをパッケージ化すると、JavaScriptパッケージが非常に大きくなり、ページのロードに影響します.異なるルーティングに対応するコンポーネントを異なるコードブロックに分割し、ルーティングがアクセスされると対応するコンポーネントをロードすることができれば、より効率的になります.これはルート怠惰ロードであることが重要です.公式文書を見たらみんな使うはずですが、ここでは紹介しません.
    //      
    const _import_ = file => () => import('./views/' + file + '.vue')
    
    routes: [
        {
          path: '/',
          name: 'home',
          component: _import_('Home/Home'),
          meta: {
            title: '  ',
            keepAlive: true
          }
        },
    ]
    

    やっと書き終わりました.以上がモバイル端末で最適化を体験した実戦です.皆さんの役に立つことを願っています.今後、何か良い最適化案があれば、更新を続けます.ありがとうございました.いいと思うよね?
    転載先:https://juejin.im/post/5cdd2457f265da034e7eb2f9