vue组件实践-开发图片预览

框架

浏览数:320

2019-8-21

甲方需求

开发一个像微信朋友圈图片预览界面,可以左右滑动查看图片

需求分析

了解客户基本需求,从需求点上去获取功能需求与具体的代码实现,需求分析也是很重要滴~~
需求分析.png

功能分析

根据需求分析实际上代码要实现的需求,是否需要改善,或则选择合理的方案,不要客户的需求就全盘接受,需要适当权衡客户所需。所以继需求分析后就是功能分析,该功能具体实现有什么难点,是否需要调整方案等。
功能分析.png

版式设计

虽然对于许多开发人员而言认为并不需要会什么设计,但是作为新一代的开发人员会点相关的技能还是有必要的,至少自己脑海里得有一个图形知道自己要做什么,这样可以在设计师未设计前提前做好准备,先人一步。
版式设计

开始开发

开始开发是否也不要立马就拿起键盘就一波走,管他三七二十一就是干,万一卡带了怎么办,那么就理一理功能实现思路走走流程吧。
开发流程导图.png

HTML代码

<template>
    <div id="masking" class="masking" v-show="isshow" @click="commitExit">
        <div class="toast" v-show="isend">最后一张图</div>
        <!--显示图片-->
        <img class="masking-img" :src="showimg" />
        <div class="del_click" @click.stop="commitExit">
            删除
        </div>
        <div class="controler">
            <!--左移-->
            <img @click.stop="onLeft" class="controler_icon contro-left" src="../../assets/icon_left.png" />
            <!--右移-->
            <img @click.stop="onRight" class="controler_icon contro-right" src="../../assets/icon_right.png" />
        </div>
    </div>
</template>

CSS样式代码

<style scoped="scoped">
    .masking {
        z-index: 999;
        width: 100%;
        height: 100%;
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        background-color: #000000;
        display: inline-block;
        vertical-align: middle;
        padding: 0px;
    }
    
    .toast {
        border: solid 1px red;
        border-radius: 6px;
        position: absolute;
        bottom: 5rem;
        left: 5rem;
        right: 5rem;
        text-align: center;
        margin-left: 0;
        margin-right: 0;
        color: red;
        padding: 0.2rem;
    }
    
    .masking-img {
        width: 100%;
        height: auto;
        margin-bottom: auto;
        margin-top: auto;
        position: absolute;
        top: 0;
        bottom: 0;
        background-size: 100%;
        vertical-align: middle;
        display: inline-block;
    }
    
    .del_click {
        position: absolute;
        top: 3rem;
        right: 3rem;
        border: solid 1px #04BE02;
        color: #04BE02;
        padding: 2px 10px;
        border-radius: 6px;
        font-weight: bold;
    }
    
    .controler {
        position: absolute;
        top: 0;
        bottom: 0;
        vertical-align: middle;
        width: 100%;
        height: 40px;
        margin-bottom: auto;
        margin-top: auto;
        display: flex;
        padding: 10px;
    }
    
    .controler_icon {
        width: 1.5rem;
        height: 1.5rem;
        padding: 0.2rem;
        background-color: #CCCCCC;
    }
    
    .contro-right {
        position: absolute;
        right: 2rem;
    }
</style>

JS功能代码

<script>
    export default {
        name: 'masking',
        data() {
            return {
                showimg: "",
                showindex: 0,
                baseimgs: [],
                isend: false
            }
        },
        created() {
            //初始化显示状态
            this.isshow = false;
        },
        //接受父对象传递数据
        props: {
            imgs: Array,
            isshow: false
        },
        watch: {
            //监听图片数组
            imgs: {
                handler: function(val, oldval) {
                    if(val != oldval) {
                        this.$nextTick(() => {
                            if(this.isEmptry(this.imgs)) {
                                //更新数组
                                this.baseimgs = this.imgs[0];
                                //初始化下标
                                this.showindex = 0;
                                //初始化隐藏最后一张图提示
                                this.isend=false;
                                //更新设置图片
                                this.onUpdataImg();
                            }
                        })
                    }
                },
                immediate: true, //关键
                deep: true
            },
        },
        methods: {
            //通知父组件关闭
            commitExit() {
                //关闭方法为onmaskclose
                this.$emit('onmaskclose', false);
            }, //左移
            onLeft: function() {
                this.showindex--;
                if(this.showindex > 0) {
                    this.onUpdataImg();
                } else {
                    this.showindex = 0;
                    this.onUpdataImg();
                }
                //关闭最后一页提示
                if(this.isend) {
                    this.isend = false;
                }

            }, //右移
            onRight: function() {
                this.showindex++;
                if(this.showindex < this.baseimgs.length) {
                    this.onUpdataImg();
                } else {
                    //提示最后一张图
                    this.isend = true;
                    //设置当前下标为数组有效下标最大值
                    this.showindex = this.baseimgs.length - 1;
                    //设置为最后一张图
                    this.onUpdataImg();
                }

            }, //判断数组是否为空
            isEmptry: function(value) {
                if(value != undefined && value.length > 0) {
                    return true;
                } else {
                    return false;
                }
            },//更新设置图片
            onUpdataImg: function() {
                //判断数组
                if(this.isEmptry(this.baseimgs)) {
                    this.showimg = this.baseimgs[this.showindex];
                }else{
                    this.isshow = false;
                    this.commitExit();
                }
            }
        }
    }
</script>

测试调用

接下来开始在父类组建中使用组建:
1.引用组件,使用 import 名称 from 路径
2.在template中写入组建名称,注意以标签的方式,如果有下划线可以用大写单词首字母拼接。
3.需要在组件标签上写上对应的传参或则回调方法。

<template>
<maskbox :imgs="showimg" :isshow="isShowMask" @onmaskclose="onMaskClose"></maskbox>
</template>
<script>
import maskbox from "../element/maskingBox.vue"
export default {
    components: { maskbox },
        data() {return {
                  showimg:[],
                  isShowMask:false
                    }
        },methods: { 
      //获取预览图片回调
      onMaskClose:function(value){
          this.isShowMask=value;
      }
    }
}
</script>

知识点解析

1.scoped属性:
在style设置该属性,表示该样式只适用当前模板下;如果想要在该样式下使用预处理语言less,配置好less加载引擎后在style标签上添加lang=”less”就可以使用。
2.父组建向子组建通信
需要使用props,它可以是一个json对象,也可以是一个数组,如:

props{value1:String,value2:Array},
props["value1","value2"]

*注意写好参数类型语法报错
3.子组件向父组建通信
需要使用emit(方法名,参数)调用,如:

this.$emit('onmaskclose', false);

*其中方法名使用全小写,不然可能会出问题。
4.watch的作用
用于监听data中值的变化,大概的使用方式:

export default {
    data: {
      valueName: 'abc'
    },
    watch: {
      valueName(newValue, oldValue) {
      // 值更新
    },
     immediate: true, //关键
     deep: true
    } 
}
  1. 加载延迟回调:
this.$nextTick(() => {
    //延时回调代码
})

nextTick是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM。
6.在编写代码时要保持代码整洁:
*变量或者定义方法尽量保证命名规范,见名知意;
*代码中尽量不要出现重复功能代码块,能够封装的就封装起来;
*代码编写过程中写好注释,不要认为自己能够看懂或则都是英文会英文的都能看懂之类的想法。

甲方新增需求三连(甲方加钱¥2000)

需求1连:

需求内容:当图片大于一张时,顶部显示总张数与当前张数,底部根部添加滑动指引,可以点击具体指引跳转具体某一张图。
完成状态:待完成

需求2连:

需求内容:当图片大于一张时,添加手势滑动切换,手势滑动到最后一页后从头开始。
完成状态:待完成

需求3连:

需求内容:当图片大于一张时,图片可点击跳转打开对应图片链接。
完成状态:待完成

甲方更改需求三连(甲方加钱¥5000)

需求1连:

需求内容:查看当前图片时,支持图片放大缩小。
完成状态:待完成

需求2连:

需求内容:如果当前图片为全景图片时,可支持360度全景查看视角,并支持陀螺仪旋转查看。
完成状态:待完成

工具&环境

*思维导图工具:MindMaster
*原型图工具:Mockplus
*开发IDE:HBuilder
*编译环境:node+npm

结语

本篇文章也算自己在平时开发中的一些总结,并且对此进行记录,希望能够给看这篇文章的你们也能留下一点点收获。
最后提醒自己:
一切的焦虑不安都源自于自己不会总结与归零,还有让自己从零开始。

作者:雨墨异乡人