vue项目——文章列表模块

项目地址:https://gitee.com/liangPromise/vue-app-toutiaoAdmin/tree/article/

创建组件并配置路由

        我们首先在views文件夹下面创article文件夹 里面存放的是文章列表组件

        并在组件中配置了路由信息

{
    path: '/home',
    component: () => import('@/views/home/Home.vue'),
    children: [
      {
        path: '',
        component: () => import('@/views/home/indexHoem.vue')
      },
      {
        // 文章列表
        name: 'article',
        path: 'article',
        component: () => import('@/views/article')
      },
      {
        // 发布文章
        name: 'publish',
        path: 'publish',
        component: () => import('@/views/publish')
      }
    ]
  }

页面布局

        在文章列表组件中我们使用了大量的element-ui组件 包括 :卡片、面包屑导航、from表单、表格、分页、等等···

        使用了大量的组件来实现页面的基本结构 并给相关的组件绑定数据和事件

        内容管理页面总共分为两大部分 使用两个卡片组件所包裹 上面展示表单功能 下面使用表格来渲染数据,在表单中

        

<template>
  <div>
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <el-breadcrumb separator-class="el-icon-arrow-right">
          <el-breadcrumb-item :to="{ path: 'home' }">首页</el-breadcrumb-item>
          <el-breadcrumb-item>内容管理</el-breadcrumb-item>
        </el-breadcrumb>
      </div>
      <el-form ref="form" :model="form" label-width="80px">
        <el-form-item label="状态">
          <el-radio-group v-model="form.status">
            <!-- el-radio 默认把 label 作为文本和选中之后的 value 值 -->
            <el-radio :label="null">全部</el-radio>
            <el-radio :label="0">草稿</el-radio>
            <el-radio :label="1">待审核</el-radio>
            <el-radio :label="2">审核通过</el-radio>
            <el-radio :label="3">审核失败</el-radio>
            <el-radio :label="4">已删除</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="频道">
          <el-select v-model="form.channel_id" placeholder="请选择频道">
            <el-option label="全部" :value="null"></el-option>
            <el-option
              v-for="item in channels"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="日期">
          <el-date-picker
            v-model="date"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            format="yyyy 年 MM 月 dd 日"
            value-format="yyyy-MM-dd"
            onPick="abc"
          >
          </el-date-picker>
        </el-form-item>
        <el-form-item>
          <el-button
            type="primary"
            size="medium"
            @click="onSubmit"
            :disabled="loading"
            >查询</el-button
          >
        </el-form-item>
      </el-form>
    </el-card>
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span
          >根据筛选条件共查询到<b>{{ totalAll }}</b
          >条结果</span
        >
      </div>
      <el-table :data="articles" stripe v-loading="loading" style="width: 100%">
        <el-table-column prop="cover.images" label="封面">
          <template slot-scope="scope">
            <el-image
              style="width: 100px; height: 50px"
              :src="scope.row.cover.images[0]"
            ></el-image>
            <!-- <el-image style="width: 100px; height: 50px" src="./no-cover.gif"></el-image> -->
          </template>
        </el-table-column>
        <el-table-column prop="title" label="标题"></el-table-column>
        <el-table-column label="状态">
          <template slot-scope="scope">
            <!-- <el-tag v-if="scope.row.status == 0" type="info">草稿</el-tag> -->
            <el-tag :type="articleStatus[scope.row.status].type">{{
              articleStatus[scope.row.status].text
            }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="pubdate" label="发布时间"></el-table-column>
        <el-table-column prop="address" label="操作">
          <template slot-scope="scope">
            <el-button type="primary" icon="el-icon-edit" @click="editArticleFn(scope.row.id)" circle></el-button>
            <el-button
              type="danger"
              icon="el-icon-delete"
              @click="removeArticleFn(scope.row.id)"
              circle
            ></el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        :disabled="loading"
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage4"
        :page-sizes="[10, 20, 30, 40]"
        :page-size="100"
        layout="total, sizes, prev, pager, next, jumper"
        :total="totalAll"
      >
      </el-pagination>
    </el-card>
  </div>
</template>

文章接口

        在api文件夹下新建了一个article.js文件,里面用来编写跟文章有关的api接口,随后向外暴露出去。

        在文章相关的组件中,引入api方法调用,将获取的到的数据渲染到页面中 

// 文章相关的接口调用
import request from '@/utils/request.js'

// 获取文章频道
const getChannels = () => {
  return request.get('/mp/v1_0/channels')
}

// 获取文章列表
const getArticles = params => {
  return request.get('/mp/v1_0/articles', { params })
}

// 删除文章
const removeArticle = params => {
  return request.delete(`/mp/v1_0/articles/${params}`)
}

// 发布文章
const addArticle = (data, params) => {
  console.log(data, params)
  return request({
    method: 'POST',
    url: '/mp/v1_0/articles',
    params: {
      draft: params // 是否存为草稿(true 为草稿)
    },
    data
  })
}

// 查询文章
const inquireArticle = params => {
  return request.get(`/mp/v1_0/articles/${params}`)
}

// 修改文章
const editArticle = (data, params) => {
  return request.put(`/mp/v1_0/articles/${params}`, data)
}

// 导出
export {
  getChannels,
  getArticles,
  removeArticle,
  addArticle,
  inquireArticle,
  editArticle
}

数据分页

        分页的目的是为了缓解查询数据的压力,提高页面的响应速度,让用户更快的看到页面的内容。

        假如是固定的数据,例如10条,20条,以后不会增加了。那就没有必要分页,没有意义。

        如果是动态产生的数据,例如文章列表,商品列表,评论列表。

        数据量增加的越来越多,就需要使用分页来缓解数据查询和渲染的压力的。

       

数据库中有 100 条数据:

        - 第几页

        - 每页大小

后端会从数据库中获取数据,

        假设每页10条数据

        请求第1页数据,

        1-10 - 请求第2页数据,

        1-20 - 请求第3页数据,

        21-30 - ... 然后后端通过接口提供给前端使用。

- page 页码,

        默认第1页 - per_page 每页大小,默认每页 10 条数据

数据筛选:

        - 接口的参数

        - 通过表单的交互得到接口参数

使用步骤

1、传递分页参数

2、注册分页组件的 current-change 事件

3、当页码改变,请求对应页码数据

     <el-pagination
        :disabled="loading"
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage4"
        :page-sizes="[10, 20, 30, 40]"
        :page-size="100"
        layout="total, sizes, prev, pager, next, jumper"
        :total="totalAll"
      >
      </el-pagination>
---------------------------------------------------------------

 // 分页功能
    handleSizeChange (value) {
      this.form.per_page = value
      this.getArticlesFn(this.form)
    },
    handleCurrentChange (value) {
      this.form.page = value
      this.getArticlesFn(this.form)
    },

总页码处理

1、将数据列表接口中返回的总数据条数存储到 data 数据中

2、将总记录数和每页大小绑定到分页组件

数据筛选

把视图处理成接口需要的数据提交给后端。

1、在 data 中初始化 form并传递给请求方法

2、处理表单绑定获取 form数据

3、点击查询的时候,调用 onSubmit方法加载数据

    // 查询按钮
    onSubmit () {
      console.log(this.form)
      this.getArticlesFn(this.form)
    },

------------------------------------------------------------------

    // 获取文章列表
    async getArticlesFn (params) {
      this.loading = true
      const articles = await getArticles(params).catch(err => err)
      if (articles.status !== 200) {
        this.loading = false
        return this.$message.error('文章列表取失败')
      }
      this.articles = articles.data.data.results
      this.totalAll = articles.data.data.total_count
      console.log(articles.data.data)
      this.loading = false
    },

加载中 loading

        在表格中我们设置了加载中loading...状态,在请求期间表格处于loading状态,使项目有更好的交互状态。

1、初始化 loading 数据

      // 是否加载中
      loading: true

2、设置表格的 loading 状态

<el-table :data="articles" stripe v-loading="loading" style="width: 100%">
</el-table>

----------------------------------------------------------------------------
    // 请求期间会开启表格的loading 状态
    // 获取文章列表
    async getArticlesFn (params) {
      this.loading = true
      const articles = await getArticles(params).catch(err => err)
      if (articles.status !== 200) {
        this.loading = false
        return this.$message.error('文章列表取失败')
      }
      this.articles = articles.data.data.results
      this.totalAll = articles.data.data.total_count
      console.log(articles.data.data)
      this.loading = false
    },

删除文章 

        在这里我们遇到了一个问题,在后端返回的数中包含大数字,在js中无法正确读取 ,我们这里使用了第三方插件json-bigint解决了这个问题 。

        具体怎么解决的请看我的另一篇文章,里面有详细的解决过程解决js中后端返回数据中的大数字问题

删除操作

1、封装了删除文章请求方法

2、注册删除按钮点击事件

3、删除成功,更新当前页数据

 <el-button type="primary" icon="el-icon-edit" @click="editArticleFn(scope.row.id)" circle></el-button>

----------------------------------------------------------

  // 删除文章
    removeArticleFn (id) {
      this.$confirm('此操作将永久删除该文章, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async () => {
          const data = await removeArticle(id).catch(err => err)
          console.log(data)
          if (data.status !== 204) return this.$message.error('文章删除失败')
          this.$message.success('文章删除成功')
          this.getArticlesFn(this.form)    // 删除成功更新当前页面
        })
        .catch(() => {
          this.$message.error('已取消删除')
        })
    },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李公子丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值