vue2.0 之 douban (六)axios的簡單使用

weixin_34259232發表於2017-09-14

由於專案中用到了豆瓣api,涉及到跨域訪問,就需要在config的index.js新增代理,例如

proxyTable: { // 設定代理,解決跨域問題
  '/api': {
    target: 'https://api.douban.com/v2',
    changeOrigin: true,
    pathRewrite: {
      '^/api': ''
    }
  }
},

安裝axios

npm install --save axios vue-axios

在main.js引入axios

import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)

在各個元件裡獲取資料,就是這麼簡單

this.axios.get(api).then((response) => {
  console.log(response.data)
})

 

由於豆瓣app首頁的資料,我們不能直接通過api獲取資料,只能先將資料儲存下來進行訪問,大家做專案的時候,訪問靜態資料json會遇到路徑404,這裡我們可以通過在dev-server.js裡新增靜態資料的路由,例如:我們先將豆瓣的首頁資料先儲存到/src/data/homeData.json,
 
dev-server.js 新增
/**************** 靜態資料 start ****************/
var app = express()
var homeData = require('../src/data/homeData.json')
var apiRoutes = express.Router()
apiRoutes.get('/homeData',function(req,res){
  res.json({
    errno: 0,
    data: homeData
  })
})
app.use('/api',apiRoutes)
/**************** 靜態資料  end *****************/
 
在元件裡面訪問
this.axios.get('/api/homeData').then((response) => {
  console.log(response.data)
})

 

接下來我們將靜態資料顯示到首頁中:靜態資料分為熱門和推薦,我麼先fetchData獲取資料,通過判斷card.name,賦值給recommendData、hotData

export default {
  name: 'index',
  components: {
    mHeader,
    mSwipe,
    mCell,
    mCellMedia
  },
  data() {
    return {
      recommendData: [],
      hotData: []
    }
  },
  created() {
    this.fetchData();
  },
  methods: {
    fetchData() {
      this.axios.get('/api/homeData').then((response) => {
        let data = response.data.data.recommend_feeds;
        let recommend = [];
        let hot = [];
        for (var i in data) {
          if (data[i].card && data[i].card.name == '為你推薦') {
            recommend.push(data[i]);
          } else {
            hot.push(data[i]);
          }
        }
        this.recommendData = recommend;
        this.hotData = hot;
      })
    }
  }
}

 

在Index.vue迴圈media-cell元件

<m-cell-media :author="item.target.author.name" :column="item.source_cn" :img="item.target.cover_url" v-for="(item,index) in hotData"
          :key="item.id">
  <span slot="title">{{item.title}}</span>
  <span slot="describe">{{item.target.desc}}</span>
</m-cell-media>

 

Index.vue

<template>
  <div>
    <!-- 頭部 -->
    <header class="m-header is-fixed is-bg top-search">
      <div class="search-wrap">
        <img src="../../assets/images/ic_search_gray.png" alt="">
        <span class="placeholder">影視 圖書 唱片 小組 舞臺劇等</span>
        <img src="../../assets/images/ic_scan_gray.png" alt="">
      </div>
      <!-- <div class="m-header-button is-right" style="text-align: center;width: 50px;">
        <a href="javascript:;"><img class="m-icon-img" src="../../assets/images/ic_chat_white.png" /></a>
      </div> -->
    </header>
    <!-- 主體 -->
    <div class="page-content">
      <!-- 輪播圖 -->
      <m-swipe swipeid="swipe01" :autoplay="1000" paginationDirection="right">
        <div class="swiper-slide " slot="swiper-con"><img src="../../assets/images/banner/01.jpg" alt=""></div>
        <div class="swiper-slide " slot="swiper-con"><img src="../../assets/images/banner/02.jpg" alt=""></div>
        <div class="swiper-slide " slot="swiper-con"><img src="../../assets/images/banner/03.jpg" alt=""></div>
      </m-swipe>
      <!-- cell -->
      <m-cell title="提醒" icon>
        <img src="../../assets/images/ic_mine_notification.png" slot="icon">
        <a href="javascript:;" slot="cell-right"><img src="../../assets/images/ic_arrow_gray_small.png" alt=""></a>
      </m-cell>
      <m-cell title="設定">
        <a href="javascript:;" slot="cell-right"><img src="../../assets/images/ic_arrow_gray_small.png" alt=""></a>
      </m-cell>
      <!--熱門-->
      <div class="hot-wrap">
        <m-cell title="熱門" label="hot">
          <!--<a href="javascript:;" slot="cell-right">更多<img src="../../assets/images/ic_arrow_gray_small.png" alt=""></a>-->
        </m-cell>
        <m-cell-media :author="item.target.author.name" :column="item.source_cn" :img="item.target.cover_url" v-for="(item,index) in hotData"
          :key="item.id">

          <span slot="title">{{item.title}}</span>
          <span slot="describe">{{item.target.desc}}</span>
        </m-cell-media>
      </div>

      <!--推薦-->
      <!-- <div class="recommend-wrap">
        <m-cell title="推薦" label="recommend"></m-cell>
        <m-cell-media  :author="item.target.author.name" :column="item.source_cn" :bg="item.target.cover_url" v-for="(item,index) in recommendData" :key="item.id">
          <span slot="title">{{item.title}}</span>
          <span slot="describe">{{item.target.desc}}</span>
        </m-cell-media>
      </div> -->
    </div>
  </div>
</template>

<script>
  import mHeader from '../../components/header'
  import mSwipe from '../../components/swipe'
  import mCell from '../../components/cell'
  import mCellMedia from '../../components/cell-media'
  export default {
    name: 'index',
    components: {
      mHeader,
      mSwipe,
      mCell,
      mCellMedia
    },
    data() {
      return {
        recommendData: [],
        hotData: []
      }
    },
    created() {
      this.fetchData();
    },
    methods: {
      fetchData() {
        this.axios.get('/api/homeData').then((response) => {
          let data = response.data.data.recommend_feeds;
          let recommend = [];
          let hot = [];
          for (var i in data) {
            if (data[i].card && data[i].card.name == '為你推薦') {
              recommend.push(data[i]);
            } else {
              hot.push(data[i]);
            }
          }
          this.recommendData = recommend;
          this.hotData = hot;
        })
      }
    }
  }
</script>

<style lang="less">
  // 頭部
  header.m-header {
    padding: 0 0 0 10px;
  }

  .is-fixed~.page-content {
    padding-top: 44px;
    padding-bottom: 50px;
  }

  .top-search {
    .search-wrap {
      // width: 100%;
      height: 30px;
      background: #fff;
      border-radius: 4px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      color: #c0c0c0;
      padding: 0 12px;
      .placeholder {
        flex: 1;
        text-align: left;
        padding-left: 12px;
      }
      img {
        width: 20px;
        height: 20px;
      }
    }
  }
  // 熱門
  .hot-wrap,
  .recommend-wrap {
    padding-top: 12px;
  }
</style>

  

header.vue

<template>
  <header class="m-header" :class="{'is-bg':bg,'is-fixed':fixed}">
    <div class="m-header-button is-left" v-show="leftShow">
      <slot name="left"></slot>
    </div>
    <h1 class="m-header-title" v-text="title"></h1>
    <div class="m-header-button is-right">
      <slot name="right"></slot>
    </div>
  </header>
</template>
<script>
  /**
   * @param title - header顯示的標題
   * @param bg - header是否顯示的標題背景
   * @param {slot} [left] - 左側的圖片內容和文字
   * @param {slot} [right] - 右側的圖片內容和文字
   * @exmaple
   * <m-header title="豆瓣app" :bg="true">
   *        <a href="javascript:;" slot="left"><img class="m-icon-img" src="../../assets/images/ic_bar_back_white.png"/>返回</a>
   *        <a href="javascript:;" slot="right">分享</a>
   * </m-header>
   */
  export default {
    props: {
      title: {
        type: String,
        default: ''
      },
      bg: {
        type: Boolean,
        default: false
      },
      fixed: {
        type: Boolean,
        default: false
      },
      leftShow: {
        type: Boolean,
        default: true
      }
    }
  }
</script>
<style lang="less">
  /*匯入顏色變數*/
  @import "../assets/less/var.less";
  .m-header {
    display: flex;
    align-items: center;
    height: 44px;
    padding: 0 10px;
    background: #fff;
    color: @headerDefaultColor;
    position: relative;
    &:after {
      content: '';
      position: absolute;
      left: 0;
      bottom: 0;
      right: 0;
      height: 1px;
      background: @headerBorderColor;
      transform: scaleY(0.5);
    }
    a {
      color: @headerDefaultColor;
    }
    .m-header-button {
      width: 70px;
      align-items: stretch;
      &.is-left {
        text-align: left;
      }
      &.is-right {
        text-align: right;
      }
      .m-icon-img {
        width: 20px;
        height: 20px;
      }
      .margin-right-10 {
        margin-right: 10px;
      }
    }
    .m-header-title {
      flex: 1;
      text-align: center;
      font-size: 16px;
      text-overflow: ellipsis;
      white-space: nowrap;
      overflow: hidden;
    }
    &.is-bg {
      background: @headerBg;
      color: #fff;
      a {
        color: #fff;
      }
      .m-header-title {
        color: #fff;
      }
      &:after {
        content: '';
        position: absolute;
        left: 0;
        bottom: 0;
        right: 0;
        height: 0px;
        background: @headerBorderColor;
        transform: scaleY(0.5);
      }
    }
    &.is-fixed {
      position: fixed;
      left: 0;
      right: 0;
      top: 0;
      z-index: 9;
    }
  }
</style>

  

swipe.vue

<template>
  <div class="swiper-container" :class="swipeid">
    <div class="swiper-wrapper">
      <slot name="swiper-con"></slot>
    </div>
    <!-- 分頁器 -->
    <div :class="{'swiper-pagination':pagination}" :style="{'text-align':paginationDirection}"></div>
  </div>
</template>
<script>
  import '../assets/lib/swiper/js/swiper.js'
  export default {
    props: {
      swipeid: {
        type: String,
        default: ''
      },
      effect: {
        type: String,
        default: 'slide'
      },
      loop: {
        type: Boolean,
        default: true
      },
      direction: {
        type: String,
        default: 'horizontal'
      },

      autoplay: {
        type: Number,
        default: 5000,
      },
      paginationType: {
        type: String,
        default: 'bullets'
      },
      pagination: {
        type: Boolean,
        default: true
      },
      paginationDirection:{
        type:String,
        default:'center'
      }
    },
    mounted() {
      var That = this;
      new Swiper('.'+That.swipeid, {
        //迴圈
        loop: That.loop,
        //分頁器
        pagination: '.swiper-pagination',
        //分頁型別
        paginationType: That.paginationType, //fraction,progress,bullets
        //自動播放
        autoplay: That.autoplay,
        //方向
        direction: That.direction,
        //特效
        effect: That.effect, //slide,fade,coverflow,cube
        //使用者操作swiper之後,是否禁止autoplay
        autoplayDisableOnInteraction : false,
      })
    }
  }
</script>
<style>
  @import '../assets/lib/swiper/css/swiper.css';

  .swiper-container img{
    width: 100%
  }
  .swiper-pagination-bullet-active {
    background: #fff;
  }
</style>

  

cell.vue

<template>
  <div class="m-cell normal" :class="label">
    <div class="m-cell-title">
      <slot name="icon"></slot> {{title}}
    </div>
    <div class="m-cell-right">
      <slot name="cell-right"></slot>
    </div>
  </div>
</template>
<script>
  export default {
    props: {
      title: {
        type: String,
        default: ''
      },
      hot: {
        type: Boolean,
        default: false
      },
      recommend: {
        type: Boolean,
        default: false
      },
      icon: {
        type: Boolean,
        default: false
      },
      label: {
        type: String,
        default: 'normal'
      }
    }
  }
</script>
<style lang="less">
  .m-cell {
    position: relative;
    padding: 10px 5px 10px 15px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    &:before {
      content: '';
      position: absolute;
      left: 0;
      bottom: 0;
      right: 0;
      height: 1px;
      background: #eee;
      transform: scaleY(0.5);
    }
    .m-cell-title {
      font-size: 15px;
      img {
        width: 20px;
        height: 20px;
      }
    }
    .m-cell-right {
      font-size: 12px;
      a {
        color: #666;
      }
      img {
        width: 20px;
        height: 20px;
      }
    }
    &.normal {}
    &.hot {
      padding: 0px 5px 0px 15px;
      height: 22px;
      &:after {
        content: '';
        position: absolute;
        width: 5px;
        left: 0;
        top: 0px;
        bottom: 0px;
        background: #ff8447;
      }
      &:before {
        height: 0
      }
    }
    &.recommend {
      padding: 0px 5px 0px 15px;
      height: 22px;
      &:after {
        content: '';
        position: absolute;
        width: 5px;
        left: 0;
        top: 0px;
        bottom: 0px;
        background: #42bd56;
      }
      &:before {
        height: 0
      }
    }
  }
</style>

  

cell-media.vue

<template>
  <div class="m-cell-media-wrap">
    <a href="javascript:;">
      <div class="m-cell-media-top">
        <div class="m-cell-media">
          <div class="m-cell-title m-ellipsis-2">
            <slot name="title"></slot>
          </div>
          <div class="m-cell-detail m-ellipsis-2">
            <slot name='describe'></slot>
          </div>
        </div>
        <div class="m-pull-right right-img" :style="{'background-image':'url('+img+')'}">
        </div>
      </div>
      <div class="m-cell-media-bottom">
        <p v-if="author">作者:{{author}}</p>
        <p v-if="column">{{column}}</p>
      </div>
    </a>
  </div>
</template>
<script>
  export default {
    props: ['author', 'column', 'img']
  }
</script>
<style lang="less">
  .m-cell-media-wrap {
    display: flex;
    flex-direction: column;
    padding: 18px 20px;
    position: relative;
    &:after {
      content: '';
      position: absolute;
      left: 0;
      bottom: 0;
      right: 0;
      height: 1px;
      background: #eee;
      transform: scaleY(0.5);
    }
    .m-cell-media-top {
      display: flex;
      flex-direction: row;
      .m-cell-media {
        flex: 1;
        padding-right: 45px;
      }
      .m-cell-title {
        font-size: 17px;
        line-height: 22px;
        color: #333;
        font-weight: bold;
      }
      .m-cell-detail {
        font-size: 12px;
        padding-top: 12px;
        color: #939393;
      }
      .m-pull-right {
        width: 94px;
        height: 94px;
        overflow: hidden;
        background-position: center center;
        background-size: cover;
        img {
          width: 100%;
        }
      }
    }
    .m-cell-media-bottom {
      display: flex;
      justify-content: space-between;
      padding-top: 20px;
      margin-top: 12px;
      color: #bfbfbf;
      position: relative;
      &:before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 20px;
        height: 1px;
        background: #eee;
      }
    }
  }
</style>

  

 var.less
//APP預設顏色
@defaultColor:#42bd56;
//header
@headerBg:@defaultColor;
@headerDefaultColor:rgb(73,73,73);
@headerBorderColor:#e4e4e4;
//tabbar
@tabbarBorderColor:#e4e4e4;
@tabbarActiveColor: @defaultColor;

 

新增 reset.css

效果圖

 

相關文章