从实际出发,前端如何解决需求问题!

前言

晚上app上线,下午五点多产品临时提出需求,须要把一个H5页面的二维码图片保存到手机相册!这个二维码是公众号二维码,保存到相册的目的是让用户在微信中可以识别二维码从而关注公众号!css

拿到此需求,只有不到3个小时的开发时间,没时间去扯皮也没时间想太多,干就完了!html

移动端长按功能

H5图片保存,通常是长按保存,因此,首先要实现一个长按功能。前端

移动端使用touchstarttouchend来作长按功能,prevent阻止浏览器默认行为,浏览器不少事件有默认行为,不阻止默认行为的话,浏览器会执行它的默认行为,咱们用 JavaScript 处理一个事件,一般不须要浏览器动做,因此阻止掉!prevent是vue中的修饰符,关于修饰符的更多内容,能够去这里看事件修饰符vue

htmlandroid

<img class="code" src="@/images/cloudStallUp/xyhd_05@3x.png" @touchstart.prevent="touchin" @touchend.prevent="cleartime" />
复制代码

jsios

touchin() {
  clearInterval(this.Loop); //再次清空定时器,防止重复注册定时器
  this.Loop = setTimeout(() => {
   // 这里长按后执行的操做
  }, 1000);
},

// 这个方法主要是用来将每次手指移出以后将计时器清零
cleartime() {
  clearInterval(this.Loop);
},
复制代码

实现一个dialog弹窗

UI框架基本都有自带的dialog弹窗,若是你的项目使用了某个UI框架,直接使用它的就行。若是你的项目没有使用UI框架,那么就颇有必要本身实现一个dialog弹窗git

tips:不是全部项目都须要使用UI框架,若是项目很是简单,就不须要,原谅我这轮子党,喜欢本身造轮子,哪怕很差用!github

使用H5的dialog标签写弹窗。web

htmlnpm

<dialog ref="dialog">
  <div @click="saveImage">保存图片</div>
  <div @click="closeDialog">取消</div>
</dialog>
复制代码

css

@function vw($px) {
    @return ($px / 750) * 100vw;
}

$c_dd: #dddddd;

dialog {
  border: none;
  padding: 0;

  div {
    width: vw(750);
    font-size: vw(30);
    height: vw(80);
    line-height: vw(80);

    &:last-child {
      border-top: 1px solid $c_dd;
    }
  }
}

/* 设置背景色 */
dialog::backdrop {
  background: rgba(0, 0, 0, 0.6);
}
复制代码

js

touchin() {
  clearInterval(this.Loop); //再次清空定时器,防止重复注册定时器
  this.Loop = setTimeout(() => {
   // 显示
   this.$refs.dialog.showModal();
  }, 1000);
},
......
复制代码

效果展现:

dialog标签的兼容性颇有些问题

so,咱们须要一个polyfill

安装

npm install dialog-polyfill
复制代码

在页面中引入

import dialogPolyfill from 'dialog-polyfill'
复制代码

新建一个dialog-polyfill.scss

dialog {
  position: absolute;
  left: 0; right: 0;
  width: -moz-fit-content;
  width: -webkit-fit-content;
  width: fit-content;
  height: -moz-fit-content;
  height: -webkit-fit-content;
  height: fit-content;
  margin: auto;
  border: solid;
  padding: 1em;
  background: white;
  color: black;
  display: block;
}

dialog:not([open]) {
  display: none;
}

dialog + .backdrop {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  background: rgba(0,0,0,0.1);
}

._dialog_overlay {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
}

dialog.fixed {
  position: fixed;
  top: 50%;
  transform: translate(0, -50%);
}
复制代码

在页面中引入

@import "@/style/dialog-polyfill.scss";
复制代码

设置了polyfill 后,背景的css和原生的有所区别

/* 支持dialog */
dialog::backdrop { 
  background-color: green;
}
/* polyfill */
dialog + .backdrop { 
  background-color: green;
}
复制代码

使用polyfill

js

data() {
    return {
        dialog: null
    };
},
mounted() {
    this.dialog =  this.$refs.dialog;
    dialogPolyfill.registerDialog(this.dialog);
},
methods: {
    touchin() {
      clearInterval(this.Loop); //再次清空定时器,防止重复注册定时器
      this.Loop = setTimeout(() => {
       this.dialog.showModal();
      }, 1000);
    },
    ......
}

复制代码

保存图片到手机相册

使用a标签保存

// 首先考虑使用a标签下载
saveImage(url) {
  if (!url) {
    return new Error("图片地址不正确");
  }

  let a = document.createElement("a");
  a.href = url;
  a.download = "xxxxx";

  if (document.all) {
    a.click();
  } else {
    // 兼容 Firfox
    var evt = document.createEvent("MouseEvents");
    evt.initEvent("click", true, true);
    a.dispatchEvent(evt);
  }
  this.closeDialog();
},

closeDialog() {
  this.dialog.close();
},
复制代码

自测发如今pc有用,可是在手机端无用,此方案放弃

使用H5+ API

saveImage() {
    if (!window.plus) return;
    /* eslint-disable */
    plus.gallery.save(
      this.codeImg,
      () => {
        plus.nativeUI.alert("保存图片到相册成功");
      },
      () => {
        plus.nativeUI.alert("保存失败");
      }
    );
    /* eslint-enable */
    this.closeDialog();
},
......
复制代码

写完后悲催的发现,咱们最开始架构设计的时候没有使用这个,无奈下也放弃了。关于更多的相关内容能够去这里了解5+ App开发入门指南

调用app方面原生的能力实现保存功能

在mixin.js中封装

// 调用app方法
// androidName->安卓方法名
// iosName->ios方法名
// androidData->传给安卓的参数
// iosData->传给ios的参数
// h5Fuc->不属于安卓和ios时调用的函数
callAPPFunction(androidName, iosName, androidData, iosData, h5Fuc) {
  switch (true) {
    case this.UTILS.isAndroid:
      window.hitumedia_android_js[androidName](androidData);
      break;
    case this.UTILS.isIOS:
      window.webkit.messageHandlers[iosName].postMessage(iosData);
      break;
    default:
      h5Fuc;
  }
},
复制代码

在main.js中使用

// 导入全局混入
import Mixin from "@/utils/mixin.js";
Vue.mixin(Mixin);
复制代码

在页面使用

data() {
    return {
      codeImg: require("@/images/cloudStallUp/xyhd_05@3x.png")
    };
},
...
    saveImage() {
        const url = location.href.split("/")[2];
        // 获取到图片地址,架构缘由,咱们没有图片服务器,因此暂时只能使用使用项目的地址了
        const postUrl = `http://${url}/activity/${this.codeImg}`;
        this.callAPPFunction("onDownImgs", "", postUrl, "");
        this.closeDialog();
    },
...
复制代码

OK,完美实现需求。

最后

写完此功能,自测经过后,提交产品验收,而后!!!产品说:“貌似app中不多看见保存二维码的吧,这个功能不要了~~~”

此功能不要了~~~~~~~~~~~~~~~

从这个实际的例子,得出总结,前端如何解决需求问题:

  • 一、来一个需求后,必定要先和产品肯定这个需求是否必须
  • 二、必定要和项目经理沟通好时间,若是预估某个时间段完不成,必定要提早说明白
  • 三、不要高估本身的能力,不会的必定不能说会,会的东西,得要留出变量的时间
  • 四、临时需求不要接,让产品去和项目经理沟通
  • 五、开发的时候,要镇定,某一个技术在pc有用,在移动没用或者是在某一个手机没用的状况很正常,换一个技术就好了
  • 六、想法要开阔,某些web端实现不了的功能,就让APP端去作,口才必定要练好
  • 七、不要发怒,不要发怒,一个功能开发完,不要了也很正常,千万不要发怒,fuck!
相关文章
相关标签/搜索