lzxb / lzxb.github.com

狼族小狈的博客
1 stars 0 forks source link

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

Closed lzxb closed 2 years ago

lzxb commented 7 years ago

在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