vuet 插件之 route:实现简易版 vue-cnode,实现列表点击详情返回后显示之前的数据

2017-05-23 10:31:19 +08:00
 1340641314

在 Vue 2.x 发布之后,各种 cnode 设置的版本随之而来,但是很多的版本都没有实现从列表点击详情后返回列表能显示原来的数据。下面我就给大家介绍下 Vuet 的 route 插件,他能够轻松的帮你实现这个功能,我们以 cnode 社区的 API 为例,一步步带大家实现这个功能 第一步我们需要先安装 Vue、VueRouter、Vuet

npm install --save vue vue-router vuet

第二步,我们创建 Vuet 的实例,vuet.js

import Vue from 'vue'
import Vuet from 'vuet'

Vue.use(Vuet)

const { fetch } = window

export default new Vuet({
  data () {
    return {}
  },
  modules: {
    cnode: { // 定义模块名称
      route: { // 要使用的插件
        list: { // 这里可以随便起个名称
          data () { // 定义这个数据的基本字段
            return {
              list: []
            }
          },
          watch: 'query', // route 插件的配置,如果有多个条件的话,可以设置一个数组
          fetch () { // 配置请求的方法,必须 return 一个 Promise
            const search = this.app.$route.fullPath.split('?')[1] || ''
            return fetch(`https://cnodejs.org/api/v1/topics?${search}`)
              .then(response => response.json())
              .then((res) => {
                return { list: res.data }
              })
          }
        },
        detail: { // 这里是详情,和列表页面同理
          data () {
            return {
              id: '',
              author_id: '',
              tab: '',
              content: '',
              title: '',
              last_reply_at: '',
              good: false,
              top: false,
              reply_count: 0,
              visit_count: 0,
              create_at: '',
              author: {
                loginname: '',
                avatar_url: ''
              },
              replies: [],
              is_collect: false
            }
          },
          watch: 'params.id',
          fetch () {
            return fetch(`https://cnodejs.org/api/v1/topic/${this.app.$route.params.id}`)
              .then(response => response.json())
              .then((res) => {
                return res.data
              })
          }
        }
      }
    }
  }
})

第三步,我们创建 Vue 和 VueRouter 的实例,mian.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import vuet from './vuet'
import List from './List'
import Detail from './Detail'

Vue.use(VueRouter)

// 配置路由相关
const router = new VueRouter({
  routes: [
    {
      path: '/',
      name: 'index',
      component: List
    },
    {
      path: '/:id',
      name: 'detail',
      component: Detail
    }
  ]
})

export default new Vue({
  el: '#app', // 这里是因为演示的目的,随便写的,根据你的程序写对应的初始化元素
  vuet, // 在 Vue 的根组件中安装 vuet
  router,
  render (h) {
    return h('router-view')
  }
})

第四步,我们创建列表组件 List.vue

<template>
  <div>
    <header>
      <span v-for="(item, $index) in tabs" :key="item.value">
        <router-link :to="{ name: 'index', query: { tab: item.value } }">
          {{ item.label }}
        </router-link>
      </span>
    </header>
    <ul>
      <li v-for="(item, $index) in list.list" :key="item.id">
        <router-link :to="{ name: 'detail', params: { id: item.id } }">
          {{ item.title }}
        </router-link>
      </li>
    </ul>
  </div>
</template>
<script>
  import { mapMixins, mapState } from 'vuet'

  export default {
    mixins: [...mapMixins('cnode/route/list')], // 链接数据的更新逻辑
    data () {
      return {
        // 其实这里的数据是写死的数据,大家可以放到 local 插件中使用的。
        // 具体怎么用,大家自己发挥一下想象力咯
        tabs: [
          {
            label: '全部',
            value: 'all'
          },
          {
            label: '精华',
            value: 'good'
          },
          {
            label: '分享',
            value: 'share'
          },
          {
            label: '问答',
            value: 'ask'
          },
          {
            label: '招聘',
            value: 'job'
          }
        ]
      }
    },
    // 链接数据,重定向向为 list,这样 this.list.xxx 就能访问到我们 vuet 中的数据了
    // 哈哈,是不是好简单
    computed: mapState({ list: 'cnode/route/list' })
  }
</script>

第五步,我们创建详情的组件,Detail.vue

<template>
  <div>
    <h2>{{ detail.title }}</h2>
    <article v-html="detail.content"></article>
  </div>
</template>
<script>
  import { mapMixins, mapState } from 'vuet'

  export default {
    mixins: [...mapMixins('cnode/route/detail')],
    computed: mapState({ detail: 'cnode/route/detail' })
  }
</script>

总结

虽然 vuet 插件目前只内置了 5 个插件,但是他压缩之后的包也就才 6kb,可谓是麻雀虽小,但是五脏俱全。 最后给上vuet 官方的地址,欢迎大家 star

1891 次点击
所在节点    分享创造
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/363124

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX