快速构建一个使用axios的vue应用程序

这篇文章讲述了如何快速构建一个vue程序,并使用axios从远程获取数据。
这是原文章的直通门css

一般状况下,在构建JavaScript应用程序时,会从远程获取数据或使用API。我最近研究了一些公用API,发现有不少很酷的东西能够用在这些获取到的数据上。html

我将演示如何构建一个简单的新闻app,它将显示当天的热门新闻,还容许用户经过感兴趣的类别进行过滤。咱们将从纽约时报API获取数据。能够在这里找到本教程的完整代码。vue

下面是最终app的效果:
图片描述webpack

要使用本教程,你将须要了解基本的Vue.js知识。这是一个vue教程直达。教程将使用ES6语法。ios

项目结构

咱们将只用2个文件来保持项目简洁:git

./app.js
./index.html

app.js包含整个app的逻辑,index.html包含整个app的界面。github

咱们从index.html开始:web

<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset="utf-8">
        <title>最伟大的新闻app</title>
    </head>
    <body>
        <div class="container" id="app">
            <h3 class="text-center">Vue新闻</h3>
        </div>
    </body>
</html>

而后,在index.html的底部,在</body>标签以前,引入Vue.jsapp.jsajax

<script src="https://unpkg.com/vue"></script>
<script src="app.js"></script>

可选地,能够引入Foundation,以利用一些预制样式,使咱们的界面看起来更好一点。 将其包含在<head>标签中:json

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css">

建立一个简单Vue应用程序

首先,咱们将在元素div#app上建立一个新的Vue实例,并使用一些测试数据来模拟新闻API的响应:

// ./app.js
const vm = new Vue({
    el: '#app',
    data: {
        results: [
            {title: '第一条新闻', abstract: '我是第一条新闻'},
            {title: '接着是第二条', abstract: '我是第二条新闻'},
            {title: '而后是第三条', abstract: '我是第三条新闻'},
            {title: '我是最后一条了', abstract: '我是第四条新闻'}
        ]
    }
});

咱们经过el参数告诉Vue要挂载的元素,并经过data参数指定咱们的app将使用哪些数据。

要在咱们的应用程序中显示模拟数据,能够在#app元素中写入:

<!-- ./index.html -->
<div class="columns medium-3" v-for="result in results">
    <div class="card">
        <div class="card-divider">
            {{ result.title }}
        </div>
        <div class="card-section">
            <p>{{ result.abstract }}.</p>
        </div>
    </div>
</div>

v-for指令用于渲染咱们的列表。咱们还使用双花括号来显示每个result的内容。

咱们如今有一个基本的布局结构了:
图片描述

从API获取数据

要使用纽约时报API,须要得到一个API密钥。因此若是你没有的话,点击这里,注册以获取Top Stories API的API密钥(注册时API一栏选择Top Stories API)。

使用Ajax请求和处理响应

Axios是一个基于promise的HTTP客户端,用于发送Ajax请求。它提供了简单而丰富的API。它与fetch API很是类似,但不须要为旧版浏览器添加一个polyfill,还有一些其余的细微之处。

引入axios:

<!-- ./index.html -->
<script src="https://cdn.bootcss.com/axios/0.16.0/axios.min.js"></script>

如今,一旦咱们的Vue应用程序挂载(mounted),咱们就发送请求获取top stories的列表:

// ./app.js
const vm = new Vue({
    el: '#app',
    data: {
        results: []
    },
    mounted() {
        axios.get("https://api.nytimes.com/svc/topstories/v2/home.json?api-key=your_api_key")
        .then(response => {
            this.results = response.data.resultes})
    }
});

注意:将your_api_key替换为以前注册得到的API key。

如今咱们能够在咱们的主页上看到新闻列表。不要担忧不美观的界面,咱们会在后面处理:
图片描述

经过Vue Devtools来看看API的响应:
图片描述

为了使咱们的项目更加整洁,可复用,咱们将作一些小的重构,并介绍一个帮助函数来构建咱们的URL。 咱们还将注册getPosts做为咱们应用程序的一个方法((将其添加到vue对象的method参数中):

// ./app.js
const NYTBaseUrl = "https://api.nytimes.com/svc/topstories/v2/";
const Apikey = "your_api_key";

function buildUrl(url) {
    return NYTBaseUrl + url + ".json?api-key=" + Apikey;
}

const vm = new Vue ({
    el: '#app',
    data: {
        results: []
    },
    mounted () {
        this.getPosts('home');
    },
    methods: {
        getPosts(section) {
            let url = buildUrl(section);
            axios.get(url).then((response) => {
                this.results = response.data.results;
            }).catch(error => {
                console.log(error);
            });
        }
    }
});

咱们能够经过引入计算属性(computed property)对API得到的原始结果进行一些修改,从而对咱们的视图的外观进行一些更改。

const vm = new Vue ({
    el: '#app',
    data: {
        results: []
    },
    mounted () {
        this.getPosts('home');
    },
    methods: {
        getPosts(section) {
            let url = buildUrl(section);
            axios.get(url).then((response) => {
                this.results = response.data.results;
            }).catch(error => {
                console.log(error);
            });
        }
    },
    computed: {
        processedPosts() {
            let posts = this.results;
            
            //添加image_url属性
            posts.map(post => {
                let imgObj = post.multimedia.find(media => media.format === "superJumbo");
                post.image_url = imgObj ? imgObj.url : "http://placehold.it/300x200?text=N/A";
            });
            
            //将数据分组
            let i, j, chunkedArray = [], chunk = 4;
            for (i = 0, j = 0; i < posts.length; i += chunk, j++) {
                chunkedArray[j] = posts.slice(i, i + chunk);
            }
            return chunkedArray;
        }
    }
});

在上述代码中,在计算属性processedPosts中,咱们附加一个image_url属性给每一个新闻对象:
咱们经过循环遍历API的results,并经过在multimedia数组中对单个元素搜索来查找所需格式的媒体,而后将该媒体的URL赋值给image_url属性。在媒体不可用的状况下,咱们将默认图片地址设置为来自Placehold.it的图像。

咱们还写了一个循环来将咱们的results数组分为四个一组,这将会处理咱们前面看到的不美观界面。

Note: 你也可使用像Lodash这样的库进行分块。

计算属性很是适合操纵数据。每当咱们须要将results数组分组时,咱们能够将它定义为一个计算属性,按照咱们的意愿使用它,由于Vue会在results改动时自动更新processedPosts

计算属性也基于它们的依赖关系进行缓存,所以只要results不改变,processedPosts属性将返回自身的缓存值。这将有助于性能,特别是在进行复杂的数据操做时。

接下来,咱们在index.html中修改咱们的html标签,以显示咱们的计算结果:

<!-- ./index.html -->
<div class="row" v-for="posts in processedPosts">
    <div class="columns large-3 medium-6" v-for="post in posts">
        <div class="card">
            <div class="card-divider">
                {{ post.title }}
            </div>
            <a :href="post.url" target="_blank">
                <img :src="post.image_url">
            </a>
            <div class="card-section">
                <p>{{ post.abstract }}</p>
            </div>
        </div>
    </div>
</div>

如今咱们的app看起来美观一些了:
图片描述

新闻列表组件

组件用于将应用程序模块化。“新闻列表”能够重构为一个组件,例如,若是咱们的app成长起来,而且决定在别的地方也使用新闻列表,组件将会使这变得很容易。

// ./app.js
Vue.component('news-list', {
    props: ['results'],
    template: `
        <section>
            <div class="row" v-for="posts in processedPosts">
                <div class="columns large-3 medium-6" v-for="post in posts">
                    <div class="card">
                        <div class="card-divider">
                        {{ post.title }}
                        </div>
                        <a :href="post.url" target="_blank"><img :src="post.image_url"></a>
                        <div class="card-section">
                            <p>{{ post.abstract }}</p>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    `,
    computed: {
        processedPosts() {
            //...
        }
    }
});

在上面的代码中,咱们注册了一个全局组件:
Vue.component(tagName,options)。建议在定义tagName时使用连字符,这样它们不会与标准HTML标签发生冲突。

咱们来简单看一下其余几个参数:

  • props:这是一个咱们但愿从父做用域传递给组件的数组。 咱们传递了results,由于咱们从主应用程序实例加载组件。

  • template:在这里咱们定义新闻列表的html。注意,咱们将列表包装在<section>标签中。这是由于组件须要有一个单独的根元素,而不是多个元素。

调整咱们的html代码以使用咱们的新闻列表组件,并传递results数据:

<!-- ./index.html -->
<div class="container" id="app">
    <h3 class="text-center">Vue新闻</h3>
    <news-list :results="results"></news-list>
</div>

注意:组件也能够建立为单个文件(.vue文件),而后由构建工具(如webpack)解析。虽然这超出了本教程的范围,但建议用于更大或更复杂的应用程序。

实现类别过滤

为了使咱们的应用程序更加丰富,咱们如今能够引入类别过滤器,以容许用户仅显示某些类别的新闻。

首先,咱们注册如今应用程序里展现的以及即将会展现的类别列表:

const SECTIONS = "home, arts, automobiles, books, business, fashion, food, health, insider, magazine, movies, national, nyregion, obituaries, opinion, politics, realestate, science, sports, sundayreview, technology, theater, tmagazine, travel, upshot, world";

const vm = new Vue({
    el: '#app',
    data: {
        results: [],
        //设置展现的类别数组
        sections: SECTIONS.split(', '),
        //设置默认的展现类别
        section: 'home',
    },
    mounted () {
        this.getPosts(this.section);
    },
    //...
});

接下来,咱们在div#app容器中添加:

<!-- ./index.html -->
<section class="callout secondary">
    <h5 class="text-center">分类</h5>
    <form>
        <div class="row">
            <div class="large-6 columns">
                <select v-model="section">
                    <option v-for="section in sections" :value="section">
                        {{ section }}
                    </option>
                </select>
            </div>
            <div class="medium-6 columns">
                <a @click="getPosts(section)" class="button expanded">我要看新闻</a>
            </div>
        </div>
    </form>
</section>

当单击“我要看新闻”按钮时,触发所选分类的getPosts方法。

最终demo

我决定添加一些小的(可选的)交互,使应用程序体验更好一些,如引入加载图像。

能够看看以下效果:
https://codepen.io/mengmengpr...

也能够在此处查看实时版本。

结尾

在本教程中,咱们已经学会了如何从头开始建立一个Vue.js项目,如何使用axios从API获取数据,以及如何使用组件和计算属性去处理数据。

如今咱们有一个功能齐全的基于API服务构建的Vue.js 2.0应用程序。经过引入其余API能够进行大量的改进。例如,咱们能够:

  • 使用Buffer API从分类中自动排列社交媒体。

  • 使用Pocket API标记文章稍后阅读。

  • 等等

该项目的整个代码也托管在Github上,所以你能够克隆,运行并进行改进。

这篇文章对于vue初学者是一个不错的教程,它讲述了如何快速的搭建起一个vue应用程序,其余详细的vue特性,能够去官网学习以后基于本项目进行改进。