7

前言

上一篇文章 ,已经搭建好所需要的开发环境了,接下来让开发一个简单的项目吧。
关于 less 我就不贴代码了。

源码地址

正题

先对默认的文件进行改造一下。
删除了默认的 App.vue、Hello.vue。
然后加了一个 list.vue。
修改一下main.js
然后看到页面打印出一个 “列表页” 三个字的时候,就表示成功了。

列表页1
列表页2

1、实例1

先弄个最简单的实例看看是不是能跑起来。
列表页3

so easy。

2、实例2

接下来弄个有动态数据的列表,就是这篇文章的主菜,
大概效果长这样。
1.上一页
2.下一页
3.分类

列表页4

3、导入

先装上我们需要的东西。

cnpm i mint-ui -D
cnpm i vue-router -D
cnpm i less less-loader -S
cnpm i jquery -S

mint-ui => 组件库,暂时只用到了其中的loading
vue-router => 路由
less => css的预处理器
jquery => 老朋友

4、配置

路由(vue-router):现在只有一个列表页,那就只写一个列表页的路径,配置 文件放在跟 main.js 同级的地方。

{
    path: '/list',
    name: 'list',
    component: List
}

关于 vue-router 更多的信息,点这里
图片描述

如果有更多页面需要配置的地方,比如编辑页,详情页之类的在这里添加就对了。

入口(main.js): 函数入口,改了一下之前的配置。

图片描述

5、列表页结构

页面分为了三层,所以对应的页面也有三层。
图片描述
图片描述

6、列表页代码

分类

<div class="type-pnl">
    <ul class="type-list">
        <li v-for="type in types" @click="onTabSelect(type.value)" :key="type.value">{{type.text}}</li>
    </ul>
</div>

循环列表,展示内容。

<ul class="list-container">
    <li v-for="(item, i) in list" :key="item.id">
        <span class="index" :title="i + 1">{{(i + 1) > 9999 ? "..." : (i + 1)}}</span>
        <span class="face">
            <img :src="item.author.avatar_url" alt="" :title="item.author.loginname"/>
        </span>
        <span :class="{type: item.tab, good: item.good}" v-if="item.tab">{{item.tab | tab}}</span>
        <span class="name" :title="item.title">{{item.title}}</span>
    </li>
</ul>

分页

<div class="load-more">
    <span class="prev" @click="prev" v-show="page != 1">上一页</span>
    <span class="next" @click="next">下一页</span>
</div>

mounted 做了三件事:
1.从路由获取数据,也就是从地址栏里面获取 分类 和 页数。
2.请求列表数据
3.设置 分类 的数据

之所以在mounted里面设置 分类 的数据,是因为不想data里面数据太乱。 如果把 请求数据那一段话注释掉的话,就可以看到 分类 的数据了。

mounted() {
    // 设置默认页数
    this.page = parseInt(this.$route.query.page) || 1;
    // 设置默认分类
    this.tab = this.$route.query.tab;
    // 请求数据
    this.getData();
    // 设置默认头部分类
    this.types = [{
        text: "全部",
        value: ""
    }, {
        text: "精华",
        value: "good"
    }, {
        text: "分享",
        value: "share"
    }, {
        text: "招聘",
        value: "job"
    }, {
        text: "回答",
        value: "ask"
    }];
}

methods 里面添加 getData() 方法,将 ajax 请求回来的数据保存到 list 数据,然后把页面滚到顶层,这样子就能够看到数据了。
至于 common.ajaxGet() 方法,我吧所有的 ajax 请求进行了封装到公共方法里面了。

getData() {
    // 打开loading
    Indicator.open();
    // 请求数据
    common.ajaxGet(common.api + '/topics', {
        page: this.page, // 页数
        tab: this.tab // 分类
    }).then(data => {
        if (data.success) {
            // 填充数据
            this.list = data.data;
            // 移动到顶层
            $(".list").animate({
                scrollTop: 0
            }, 200);
        }
        // 关闭loading
        Indicator.close();
    });
}

新建一个文件 src/lib/common.js,这个文件主要放公共的方法,现在暂时只用到里面的 ajaxGet() 这个方法,ajaxGet() 用了个 promise 包装了一下。

import $ from 'jquery';
let common = {
    api: " https://cnodejs.org/api/v1",
    isPhone() {
        let u = navigator.userAgent;
        let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
        let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
        return isAndroid || isiOS;
    },
    getType(value) {
        let result = value;
        switch (value) {
            case "job":
                result = "招聘";
                break;
            case "good":
                result = "精华";
                break;
            case "share":
                result = "分享";
                break;
            case "ask":
                result = "问答";
                break;
            default:
                result = "全部"
                break;
        }
        return result;
    },
    ajaxGet(url, data) {
        return new Promise((resolve, reject) => {
            $.ajax({
                url: url,
                data: data || {},
                success: data => {
                    resolve(data);
                },
                error: data => {
                    reject();
                    console.error("数据请求失败");
                }
            })
        });
    }
}
export default common;

data里面加上几个使用的参数就OK了。

data() {
    return {
        list: [],
        types: [],
        tab: "",
        page: 1
    }
}

使用 getType() 方法,对数据过滤一下。

filters: {
    tab(value) {
        return common.getType(value);
    }
}

加上css的话,上面几个步骤应该就可以看到页面效果了。
图片描述

这里 分页 还有 分类 其实都是请求同一个接口,为了在地址栏直接改变 分类 和 分页 有效,所以只要监控地址栏的变化,然后动态的改数据就ok了,不必再写重复的请求接口了。

watch: {
    $route() {
        // 检测路由变化
        this.page = this.$route.query.page || 1;
        this.tab = this.$route.query.tab;

        // 获取数据
        this.getData();
    }
}

这三个方法都是改变地址栏然后通过 wacth 检测地址栏变化去请求数据。

prev() {
    this.page--;

    // 改变路由
    let query = {
        page: this.page
    }
    if (this.tab) {
        query.tab = this.tab;
    }
    this.$router.push({
        path: 'list',
        query: query
    })
},
next() {
    // 改变当前页数
    this.page++;

    // 改变路由
    let query = {
        page: this.page
    }
    if (this.tab) {
        query.tab = this.tab;
    }
    this.$router.push({
        path: 'list',
        query: query
    })
},
onTabSelect(value) {
    // 改变当前分类
    this.tab = value;
    this.page = 1;

    // 改变路由
    let query = {
        page: this.page
    }
    if (this.tab) {
        query.tab = this.tab;
    }
    this.$router.push({
        path: 'list',
        query: query
    })
}

输入 http://localhost:8080/list?pa... 看看页面是不是就会跳到对应的页面了呢,这样子把链接分享出去的话,也能定位到当时的状态。
图片描述

项目结构
图片描述

最后

如果有什么想跟我讨论的话,请私信。

viewweiwu
660 声望104 粉丝

咸鱼也是有梦想的!