Vue.js轻松完成页面退却时,复原转动位置

媒介

Vue.js 2.x宣布以后,陆陆续续做了七八个项目,探索出来了一套本身的状况治理模式,我将之称为Vuet。它以划定规矩来驱动状况更新,它带来的是开辟效力上的飙升,它就像草原,而你是野马,任你随便驰骋,总之它是为迅速开辟而降生。

启事

在大型的Vue运用顺序开辟中,多组件通讯、多页面通讯,每每是跨不过的坎,一个页面组件中每每参杂着页面猎取数据的代码和相运用户操纵的代码,稍有不慎,就使得代码杂沓不堪。A、B、C三个页面中,都须要一样的数据,然后每个页面都写一次、发送一次要求,不久以后,代码就非常痴肥了。因而我们就须要vuex如许的第三方库来治理状况了

Vuet降生初志

从列表点击进去到概况,从概况返回后,我们希冀能显现回本来的位置,而不是悉数页面从新初始化,从新要求数据,如许带来的是用户体验的极端蹩脚的,我们希冀能有一种划定规矩来定义状况应当怎样更新,这便是Vuet.js降生的初志。它以划定规矩来定义状况的更新,它也是一种Vue.js全新的状况治理模式。生成的划定规矩驱动,使得本次教程的主题,也将变得非常简朴,由于我们只须要定义好页面更新的划定规矩即可完成。

有了Vuex还须要Vuet做什么?

Vuex和Vuet的起点不一样,Vuex不发起直接更新状况,而是经由过程提交mutation来更新状况,而Vuet则是许可的。因而Vuex和Vuet是可以合营运用的,而且有着差别的运用场景,该用Vuex的处所就用Vuex,可用Vuet的处所,就可以够运用Vuet

最先

上面空话了那末久,也是由于Vuet.js才方才降生,急需人人的支撑。嗯,接下来我们最先本次的主题!

目次构造

|-- pages                 // 页面组件
|   |-- topic             // 主题模块
|       |-- Detail.vue    // 主题概况
|       |-- List.vue      // 主题列表
|-- router                // router相干
|   |-- index.js          // 进口文件
|   |-- router.js         // 实例化VueRouter
|-- vuet                  // vuet相干
|   |-- index.js          // 进口文件
|   |-- topic-detail.js   // 主题概况的状况
|   |-- topic-list.js     // 主题列表的状况
|   |-- vuet.js           // 实例化Vuet
|- index.html             // 顺序页面进口文件
|- main.js                // Vue实例化进口文件

上面是我们本次项目的基础目次构造

装置模块

npm install vue vue-router vuet --save

这些都是基础的模块,想必不必多说,人人都晓得的。

route划定规矩

先给出官方文档地点
本章的主题,中心就是在route划定规矩身上,它能帮你猎取、更新、重置页面的状况,合营v-route-scroll指令就可以帮你处置惩罚页面的全局转动条和div元素本身的转动条

code社区api为例子

  • main.js

      import Vue from 'vue'
      import router from './router/'
      import vuet from './vuet/'
      
      export default new Vue({
        el: '#app',
        vuet,
        router,
        render (h) {
          return h('router-view')
        }
      })
  • vuet/index.js

      import vuet from './vuet'
      
      export default vuet
    
  • vuet/vuet.js

      import Vue from 'vue'
      import Vuet from 'vuet'
      import topicList from './topic-list'
      import topicDetail from './topic-detail'
      
      Vue.use(Vuet)
      
      const vuet = new Vuet({
        data () {
          return {
            loading: true, // 要求中
            loaderr: false // 要求失利
          }
        },
        pathJoin: '-', // 父子模块的衔接途径
        modules: {
          topic: {
            list: topicList,
            detail: topicDetail
          }
        }
      })
      
      vuet.beforeEach(({ path, params, state }) => {
        state.loading = true
        state.loaderr = false
      })
      
      vuet.afterEach((err, { path, params, state }) => {
        state.loading = false
        state.loaderr = !!err
      })
      
      export default vuet
    
  • vuet/topic-list.js

      export default {
        routeWatch: 'query', // 定义页面的更新划定规矩
        data () {
          return {
            data: [],
            tabs: [
              {
                label: '悉数',
                value: 'all'
              },
              {
                label: '英华',
                value: 'good'
              },
              {
                label: '分享',
                value: 'share'
              },
              {
                label: '问答',
                value: 'ask'
              },
              {
                label: '雇用',
                value: 'job'
              }
            ]
          }
        },
        async fetch ({ route }) {
          const { tab = '' } = route.query
          const { data } = await window.fetch(`https://cnodejs.org/api/v1/topics?mdrender=false&tab=${tab}`).then(response => response.json())
          return {
            data
          }
        }
      }
    
  • vuet/topic-detail.js

      export default {
        routeWatch: 'params.id', // 定义页面的更新划定规矩
        data () {
          return {
            data: {
              id: null,
              author_id: null,
              tab: null,
              content: null,
              title: null,
              last_reply_at: null,
              good: false,
              top: false,
              reply_count: 0,
              visit_count: 0,
              create_at: null,
              author: {
                loginname: null,
                avatar_url: null
              },
              replies: [],
              is_collect: false
            }
          }
        },
        async fetch ({ route }) {
          const { data } = await window.fetch(`https://cnodejs.org/api/v1/topic/${route.params.id}`).then(response => response.json())
          return {
            data
          }
        }
      }
    
  • router/index.js

      import router from './router'
      
      export default router
    
  • router/router.js

      import Vue from 'vue'
      import VueRouter from 'vue-router'
      import TopicList from '../pages/topic/List'
      import TopicDetail from '../pages/topic/Detail'
      
      Vue.use(VueRouter)
      
      const RouterView = {
        render (h) {
          return h('router-view')
        }
      }
      
      const router = new VueRouter({
        routes: [
          {
            path: '/',
            component: RouterView,
            children: [
              {
                path: '',
                name: 'topic-list',
                component: TopicList
              },
              {
                path: '/:id',
                name: 'topic-detail',
                component: TopicDetail
              }
            ]
          }
        ]
      })
      
      export default router
    
    • pages/topic/List.vue

        <template>
      <!-- 
         设置指令监听全局转动条,
         注重了,光是设置指令可不行,还须要在组件中运用route划定规矩,
         来处置惩罚页面转动的操纵,
         部分转动条直接去掉.window即可
         假如须要同时纪录全局转动条和div转动条直接设置.window.self即可
         它能做到N多个转动位置纪录,详细看官方文档喔!
         注:纪录div转动的话,须要设置一个name来辨认
         v-route-scroll="{ path: 'topic-detail', name: 'xxx' }"
      -->
      <div v-route-scroll.window="{ path: 'topic-list' }">
       <header>
         <ul>
           <li v-for="item in list.tabs">
             <router-link :to="{ name: 'topic-list', query: { tab: item.value } }">{{ item.label }}</router-link>
           </li>
         </ul>
       </header>
       <ul class="list">
         <li v-for="item in list.data">
             <router-link :to="{ name: 'topic-detail', params: { id: item.id } }">{{ item.title }}</router-link>
         </li>
       </ul>
      </div>
        </template>
        <script>
      import { mapRules, mapModules } from 'vuet'
        
      export default {
       mixins: [
         // 设置模块的更新划定规矩
         mapRules({
           route: 'topic-list'
         }),
         // 衔接模块的状况
         mapModules({
           list: 'topic-list'
         })
       ]
      }
        </script>
        <style scoped>
        
        </style>
    • pages/topic/Detail.vue

        <template>
      <div v-route-scroll.window="{ path: 'topic-detail' }">
       <h3>{{ detail.data.title }}</h3>
       <div v-html="detail.data.content"></div>
      </div>  
        </template>
        <script>
      import { mapRules, mapModules } from 'vuet'
        
      export default {
       mixins: [
         // 设置模块的更新划定规矩
         mapRules({
           route: 'topic-detail'
         }),
         // 衔接模块的状况
         mapModules({
           detail: 'topic-detail'
         })
       ]
      }
        </script>
        <style scoped>
        
        </style>

总结

咋的一看,Vuet看起来也不是很庞杂,只须要定义好模块状况,然后在组件中设置对应的划定规矩来更新模块的状况即可。实在vuet自带的route划定规矩可以支撑同时纪录全局转动条、div本身的转动条,如许就可以大大的提升了我们的用户体验

    原文作者:狼族小狈
    原文地址: https://segmentfault.com/a/1190000009742382
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞