vue-cli3.0搭建项目+图片瀑布流布局

4,482 阅读4分钟

前言

本文将vue-cli的使用和图片瀑布流放在一起来讲,主要是我自己做着两方面的练习。其实如果只是写个单页面的图片瀑布流效果也不用专门搭建一个vue-cli项目。需要看代码的小伙伴可以在我的github中自行查看。

vue-cli搭建项目

1、首先检查你的node版本,vue-cli需要node8.9以上的版本,如果版本不够请自行升级

2、安装vue-cli

npm install -g @vue/cli

注意:如果以前安装过全局的旧版vue-cli的话,你需要先卸载然后再安装新版本

npm uninstall vue-cli -g
npm install -g @vue/cli

3、搭建项目

vue create xxx(这里的xxx是你的项目名称)

4、选择配置方式

default 是使用默认配置      Manually select features 是自定义配置

如果选择默认配置的话就一路回车,如果是自定义配置的话后面会陆续弹出一些选项

5、自定义配置选项


Babel:支持es6语法转换

TypeScript:微软提供的js超集

Progressive Web App (PWA) Support:渐进式的网页应用程序。 

Router:路由 

Vuex:Vuex是Vue.js应用程序的状态管理模式+库 

CSS Pre-processors:Sass/Less预处理器 

Linter / Formatter:代码风格检查 

Unit Testing:支持单元测试 

E2E Testing:支持E2E测试

注意:空格是选中/取消,选择完之后enter就行了






6、配置完毕,等待下载

7、启动项目

cd project-name // 进入项目根目录
npm run serve // 运行项目

8、项目目录分析


在src里面


图片瀑布流布局

什么是图片瀑布流呢,简单来说就是将很多大小不一的图片尽量整齐的排列起来了,本文采用的是等宽布局,固定列宽,然后每次往最短的列里面填充图片。



基本思路:

1、根据窗口宽度和列数计算每列的宽度

2、找到最短的列

3、根据列号,图片宽度,高度等计算位置

4、往里面添加图片

5、优化,自适应窗口宽度(监听窗口的resize事件)

现在来看一下代码,我会在相应的地方放上注释:

<template>
  <div class="v-waterfall-content" id="v-waterfall">
    <div v-for="(img,index) in waterfallList"
         :key="index"
         class="v-waterfall-item"
         :style="{top:img.top+'px',left:img.left+'px',width:ImgWidth+'px',height:img.height}">
      <img :src="img.src" alt="">
    </div>
  </div>
</template>

<script>
    export default {
        name: "pic-waterfall",
        data(){
            return {
                waterfallList:[],
                imgArr:[
                    require('./assets/images/1 (13).jpeg'),
                    require('./assets/images/1 (12).jpeg'),
                    require('./assets/images/1 (11).jpeg'),
                    require('./assets/images/1 (10).jpeg'),
                    require('./assets/images/1 (9).jpeg'),
                    require('./assets/images/1 (8).jpeg'),
                    require('./assets/images/1 (7).jpeg'),
                    require('./assets/images/1 (6).jpeg'),
                    require('./assets/images/1 (5).jpeg'),
                    require('./assets/images/1 (4).jpeg'),
                    require('./assets/images/1 (3).jpeg'),
                    require('./assets/images/1 (2).jpeg'),
                    require('./assets/images/1 (1).jpeg'),
                    require('./assets/images/1 (1).gif'),
                    require('./assets/images/1.jpg'),
                    require('./assets/images/2.jpg'),
                    require('./assets/images/3.jpg'),
                    require('./assets/images/4.jpg'),
                    require('./assets/images/5.jpg'),
                    require('./assets/images/6.jpg'),
                    require('./assets/images/7.jpg'),
                    require('./assets/images/8.jpg'),
                    require('./assets/images/9.jpg'),
                    require('./assets/images/10.jpg'),
                    require('./assets/images/11.jpg'),
                    require('./assets/images/12.jpg'),
                    require('./assets/images/13.jpg'),
                    require('./assets/images/14.jpg'),
                    require('./assets/images/15.jpg'),
                    require('./assets/images/16.jpg'),
                    require('./assets/images/17.jpg'),
                    require('./assets/images/18.jpg'),
                    require('./assets/images/19.jpg'),
                    require('./assets/images/20.jpg'),
                ],
                ImgWidth:'',
                ImgCol:5,
                ImgRight:10,
                ImgBottom:10,
                deviationHeight:[],
                imgList:[],
                screenWidth:document.body.clientWidth,
            }
        },
        created() {
            for (let i = 0;i < this.imgArr.length;i++){
                this.imgList.push(this.imgArr[i]);
            }
        },
        mounted(){
            this.calculationWidth();
            const that = this;
            //挂载window的resize事件
            window.onresize = () => {
                return (() => {
                    window.screenWidth = document.body.clientWidth
                    that.screenWidth = window.screenWidth
                })()
            }
        },
        watch:{
             //使用vue的watch来处理窗口的变化
            screenWidth(val){
                // 为了避免频繁触发resize函数导致页面卡顿,使用定时器
                if(!this.timer){
                    // 一旦监听到的screenWidth值改变,就将其重新赋给data里的screenWidth
                    this.screenWidth = val
                    this.timer = true
                    let that = this
                    setTimeout(function(){
                        that.calculationWidth();  //重新计算图片宽度
                        that.timer = false
                    },400)
                }
            },
        },
        methods:{
            //计算每个图片的宽度
            calculationWidth(){
                this.ImgWidth = (this.screenWidth-this.ImgRight*this.ImgCol)/this.ImgCol;
                //初始化偏移高度数组
                this.deviationHeight = new Array(this.ImgCol);
                for (let i = 0;i < this.deviationHeight.length;i++){
                    this.deviationHeight[i] = 0;
                }
                this.imgPreloading()
            },
            //图片预加载
            imgPreloading(){
                this.waterfallList=[];
                for (let i = 0;i < this.imgList.length;i++){
                    let aImg = new Image();
                    aImg.src = this.imgList[i];
                    aImg.onload = aImg.onerror = ()=>{
                        let imgData = {};
                        imgData.height = this.ImgWidth/aImg.width*aImg.height; //按比例计算图片高度
                        imgData.src = this.imgList[i];
                        this.waterfallList.push(imgData);
                        this.rankImg(imgData); //渲染页面
                    }
                }
            },
            //瀑布流布局
            rankImg(imgData){
                let {ImgWidth,ImgRight,ImgBottom,deviationHeight} = this;
                let minIndex = this.filterMin();//获得高度最小的一列的下标
                imgData.top = deviationHeight[minIndex];//插入图片的top值
                imgData.left = minIndex*(ImgRight+ImgWidth);//插入图片的left值
                deviationHeight[minIndex] += imgData.height + ImgBottom;//更新当前列的高度
            },
            //找到最短的列并返回下标
            filterMin(){
                const min = Math.min.apply(null, this.deviationHeight);
                return this.deviationHeight.indexOf(min);
            },
        }
    }
</script>

css代码:

.v-waterfall-content{
    width: 100%;
    height: 100%;
    position: relative;
}
.v-waterfall-item{
    position: absolute;
}
.v-waterfall-item img{
    width: 100%;
    height: 100%;
}

这样就完成了图片瀑布流的布局啦,来看一下效果图


如果需要看项目的完整代码请移步github查看