美文网首页
[vue2.0]一步一个坑,仿知乎日报app:banner部分

[vue2.0]一步一个坑,仿知乎日报app:banner部分

作者: Rason00 | 来源:发表于2017-08-05 15:22 被阅读0次

    思路

    banner部分首先的框架部分在mint里面的Swipe就可以直接拿过来用了,然后就是获取到数据源,把图片一个个循环渲染扔进去展示,那么就按着这样的思路来做了。

    开始

    打开

    项目名》src》components》banner

    <template>
      <div class="banner clearfix swiper-container" ref="banner">
        <mt-swipe :auto="4000">
            <mt-swipe-item>1</mt-swipe-item>
            <mt-swipe-item>2</mt-swipe-item>
            <mt-swipe-item>3</mt-swipe-item>
        </mt-swipe>  
      </div>
    </template>
    
    <script>
    export default {
      name: 'banner',
      data() {
        return {
         
        }
      },
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    .banner {
      width: 100%;
      height: 300px;
    }
    </style>
    

    直接搬过来(加了点样式)然后就会是这样的显示效果

    5.png

    如此样子就长出来了,那就捣鼓里面的内容去了。

    首先是数据源,我们看一下api的数据长什么样子(先找到要用的数据先)

    Api:https://zhihu-daily.leanapp.cn/api/v1/last-stories

    打开后找到最下面

    6.png

    用的是chrom浏览器,装上插件JSONView即可格式化json(看得方便,感兴趣的可以装上。)

    找到了红框中需要的数据源了,那么就把它在代码中获取过来

    打开

    项目名》src》components》banner

    <script>
    // 载入axios
    import axios from 'axios'
    
    export default {
      name: 'banner',
      data() {
        return {
         
        }
      },
       mounted() {
        // 调用函数,不然没调用怎么会有操作
        this.fetchData()
      },
    
      methods: {
        fetchData() {
          // 获取数据
          axios.get('https://zhihu-daily.leanapp.cn/api/v1/last-stories')
            // 正确输出
            .then(response => {
             var items = response.data.STORIES.top_stories;
             console.log(items);
            })
            // 错误输出
            .catch(function (error) {
              console.log(error);
            });
        },
      }
    }
    </script>
    

    如上图代码(我只拿取了script部分展示出来),先载入axios,这里就有个坑不太懂的了我,就是网上有说只要在main.js里面加上

    import axios from 'axios';
    Vue.prototype.$http = axios;
    

    然后在其他组件用的时候就用 this.$http.get() ...的就可以了。

    但是我自己实践的却会报错(不知道是不是我代码有问题,如果有知道正确用法的请告知一声,反正我暂时就是搞不来,最后只好在要用axios的组件上直接引用了,就像上面的代码一样)。

    当中的mounted() {this.fetchData()}我是网上查找的调用vue函数的方法(一开始我就是没调用,结果愣是看着浏览器发呆,为什么没有数据显示呢??--你都只有这个函数方法,没用到,有数据就见鬼了!!!)

    如无意外,打开浏览器开发者模式里的Console就可以看到获取到了这样的数据

    7.png

    这就说明数据获取成功了,那么就想办法把里面关联的数据放到banner上吧。

    先在data里加上原始元素属性,然后把axios里面得到的数据赋值给data里面的属性,跟着使用到了vue的v-for来把数据循环输出到banner上那么就可以实现banner了(主要是用到了数据源当中的image地址,和title标题:分析api上的数据可以得到)

    8.png

    想法就是上面这样的,那么就动手实践一下

    继续打开

    项目名》src》components》banner

    <script>
    import axios from 'axios'
    
    export default {
      name: 'banner',
      data() {
        return {
        //创建数组items,用来装载axios获取到的数据
          items: [],
        }
      },
    
      methods: {
        fetchData() {
          // 获取数据
          axios.get('https://zhihu-daily.leanapp.cn/api/v1/last-stories')
            // 正确输出
            .then(response => {
              // 在axios中,这里只有用箭头函数this才指向vue
              this.items = response.data.STORIES.top_stories;
              console.log(this.items);
            })
            // 错误输出
            .catch(function (error) {
              console.log(error);
            });
        },
      }
    }
    </script>
    

    这样写好的话,在浏览器上看到的应该会和之前一样的效果(上一张Console里面看得的数据内容),这就说明赋值是成功的了。

    这里有个坑,就像我注释里一样。

    //在axios中,这里只有用箭头函数this才指向vue

    这个开始的时候,我是直接在axios的github上复制了一段代码过来使用的,代码如下

    // Make a request for a user with a given ID
    axios.get('/user?ID=12345')
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });
    

    结果就是我在里面用this的时候一直报错,后面查了下资料才知道只有用上箭头函数时,axios里面的this才是指向vue的。

    好了数据获取到了,那么就该摆放上去banner上了,这里用到了v-for

    打开

    项目名》src》components》banner

    <template>
      <div class="banner clearfix swiper-container" ref="banner">
         <mt-swipe :auto="4000">
            <!-- 以items为数据源,循环 -->
          <mt-swipe-item v-for="item in items" class="banner-img">
            <!-- 图片地址用v-bind缩写":" -->
            <img :src=“item.image” alt="banner">
            <span>{{item.title}}</span>
          </mt-swipe-item>
        </mt-swipe>
    
      </div>
    </template>
    

    使用v-for="item in items"把items上的数据循环输出到item上,然后里面主要是展示图片,所以加了img标签获取图片,还有一个span标签用于获取标题。(上面图片行代码<img :src=“item.image” alt="banner">用了中文符号,半角打上去发布就变了,奇怪~)

    其中图片地址用v-bind缩写":"来绑定,不让的话你显示的地址会是直接字符串item.image(此坑我也是掉过进去)

    当然为了更好的在浏览器上看到效果,我们把一些样式也加进去先

    <style scoped>
    .banner {
      width: 100%;
      height: 300px;
      position: relative;
    }
    
    .banner-img img {
      display: block;
      width: 100%;
      /*height: 100%; */
      position: absolute;
      left: 50%;
      margin-left: -50%;
    }
    
    .banner-img span {
      font-size: 22px;
      display: block;
      position: absolute;
      bottom: 35px;
      color: #fff;
      padding: 0 20px;
    }
    </style>
    

    当让加上上面的样式后你看看浏览器会发现

    9.png

    图片地址是有了,而且正确了,但是每一张图片都报错403!!!

    这其实是因为知乎服务器做了图片防盗链的操作,那么我们要用到他的图片就只能够处理一下图片地址了,具体方法就是转接一下,如运用这个Images.weserv.nl的网站(感兴趣的可以去看看,挺简单的原理),我们要做的就是更改下图片的前缀,加上images.weserv.nl/?url=p后面接上原图片地址,就可以从他们的网站作为图片源了。

    所以我们需要多写一个函数方法来改变一下图片地址。

      methods: {
        fetchData() {
          // 获取数据
          axios.get('https://zhihu-daily.leanapp.cn/api/v1/last-stories')
            // 正确输出
            .then(response => {
              // 在axios中,这里只有用箭头函数this才指向vue
              this.items = response.data.STORIES.top_stories;
            })
            // 错误输出
            .catch(function (error) {
              console.log(error);
            });
        },
        // 更改图片地址
        changeImageUrl(srcUrl) {
          if (srcUrl !== undefined) {
            return srcUrl.replace(/http\w{0,1}:\/\/p/g, 'https://images.weserv.nl/?url=p');
          }
        },
      }
    }
    </script>
    

    然后在使用到图片地址的地方调用这个方法

    <template>
      <div class="banner clearfix swiper-container" ref="banner">
         <mt-swipe :auto="4000">
            <!-- 以items为数据源,循环 -->
          <mt-swipe-item v-for="item in items" class="banner-img">
            <!-- 更改图片地址,否则知乎图片防盗链无法显示 -->
            <img :src=“changeImageUrl(item.image)” alt="banner">
            <span>{{item.title}}</span>
          </mt-swipe-item>
        </mt-swipe>
    
      </div>
    </template>
    

    上面<img :src=“changeImageUrl(item.image)” alt="banner">
    用了中文符号注意!

    很好!大功告成!

    10.png

    结束

    banner部分就此完成了,显示的效果虽然达成了,但是当中不知道运用的技术是否得当,如有更好的实现方法请留言告诉我,最后把banner组件的完整代码写一下。

    <template>
      <div class="banner clearfix swiper-container" ref="banner">
         <mt-swipe :auto="4000">
            <!-- 以items为数据源,循环 -->
          <mt-swipe-item v-for="item in items" class="banner-img">
            <!-- 更改图片地址,否则知乎图片防盗链无法显示 -->
            <img :src=“changeImageUrl(item.image)” alt="banner">
            <span>{{item.title}}</span>
          </mt-swipe-item>
        </mt-swipe>
    
      </div>
    </template>
    
    <script>
    import axios from 'axios'
    
    export default {
      name: 'banner',
      data() {
        return {
          items: [],
        }
      },
      mounted() {
        // 监听方法
        this.fetchData()
        this.getHeight()
      },
      methods: {
        fetchData() {
          // 获取数据
          axios.get('https://zhihu-daily.leanapp.cn/api/v1/last-stories')
            // 正确输出
            .then(response => {
              // 在axios中,这里只有用箭头函数this才指向vue
              this.items = response.data.STORIES.top_stories;
            })
            // 错误输出
            .catch(function (error) {
              console.log(error);
            });
        },
        // 更改图片地址
        changeImageUrl(srcUrl) {
          if (srcUrl !== undefined) {
            return srcUrl.replace(/http\w{0,1}:\/\/p/g, 'https://images.weserv.nl/?url=p');
          }
        },
        // 获取banner块的高度
        getHeight() {
          // 获取屏幕高度
          let h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
          //  更改样式,用到了vue中$refs方法
          this.$refs.banner.style.height = h / 2 - 80 + 'px';
        }
      }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    .banner {
      width: 100%;
      position: relative;
    }
    
    .banner-img {
      width: 100%;
      height: 100%;
      overflow: hidden;
      margin: 0 auto;
      position: relative;
    }
    
    .banner-img img {
      display: block;
      width: 100%;
      /*height: 100%; */
      position: absolute;
      left: 50%;
      margin-left: -50%;
    }
    
    .banner-img span {
      font-size: 22px;
      display: block;
      position: absolute;
      bottom: 35px;
      color: #fff;
      padding: 0 20px;
    }
    </style>
    

    和上面文章唯一不同的是,我把banner的高度改了一下,其他完全一样。(上面<img :src=“changeImageUrl(item.image)” alt="banner">
    用了中文符号注意!)

    相关文章

      网友评论

          本文标题:[vue2.0]一步一个坑,仿知乎日报app:banner部分

          本文链接:https://www.haomeiwen.com/subject/qpzilxtx.html