20%的工作汇报将决定你80%的工作效率和工作成果。

前言

虽然之前有好几次技术分享,但是真正的项目复盘还是第一次做,从业务到技术,全方面的梳理。从不同的开发视角去刨析业务和技术。

传统项目开发,后端开发人员常考虑的是「 我需要几张表,怎么设计表结构,提供几个接口等等」。而前端开发人员常考虑的是「 页面怎么布局,我需要多少接口,怎么与其他模块衔接等等」。视角不一样,对业务的理解还是有些区别。

今天主要分享和记录一下项目中遇到的bug和容易忽略的技术点。有「 referrer防盗链iphoneX底部黑条遮挡scrollIntoView图片压缩webview加载url汉字转码、max-width设置最大宽度失效 」等。

max-width失效

一般情况下,我们展示变化的文本有两种可能性:

  • 输入框输入

  • 接口返回

以上两种方式都是我们无法预测的。一般情况下,我们传统的观念中认为,只要超出指定宽度,文本是自动换行的比如设置max-width。但其实是不对的,容易忽略的小细节就是,如果文本是数字和字母组成,max-width将会失效。

<style>

.ad{

    max-width: 20px;

}

style>

//不会自动换行

<div class="ad">12123hdfghdfgfhgdfghd合gfhfhgfhdfh好div>

//会自动换行

<div class="ad">桑吉内蒂就是奶粉接口放假div>

这个时候三个属性登场了:

  • white-space:nowrap 用来控制空白字符的显示,nowrap强制不换行,直接忽略max-width。

  • word-break:break-all 控制单词如何被拆分换行的,break-all 所有单词碰到边界一律拆分换行。

  • word-wrap:break-word 又叫做overflow-wrap,这个属性也是控制单词如何被拆分换行的,实际上是作为word-break的互补,它只有两个值:normal | break-word,只有当一个单词一整行都显示不下时,才会拆分换行该单词。

多行显示,溢出显示省略号

如果只在chrome浏览器或者微信浏览器中使用,可以:

{

  /* W3C */

  display:box;

  box-orient:vertical;

  /* Firefox */

  display:-moz-box;

  -moz-box-orient:vertical;

  /* Safari、Opera 以及 Chrome */

  display:-webkit-box;

  -webkit-box-orient:vertical;

  -webkit-line-clamp: 3;

  overflow: hidden;

  word-break:break-all;

  white-space:nowrap

    /*IE 不支持 box-orient 属性。*/

}

使用这几条css属性不兼容火狐和IE 所以采用插件的形式clamp.js

line-clamp控制文本行数。box-orient 属性规定框的子元素应该被水平或垂直排列。

webview加载url,遇汉字需转码

当我们在百度输入汉字查询的时候,观察url会发现有汉字直接拼接在url上,当然相对于浏览器来说这没有什么大不了,但是在webview中,如果我们想要加载一个带汉字的url,此url将会无法被识别。所以我们需要转码,浏览器提供了encodeURIComponent() 函数对url参数进行转码。encodeURI()着眼于对整个URL进行编码,特殊含义的符号"; / ? : @ & = + $ , #“不进行编码,与之相对应的是decodeURI。
encodeURIComponent()对URL的组成部分进行个别编码,所以”; / ? : @ & = + $ , #"在这里是可以进行编码。与之相对应带的是decodeuricomponent。

图片压缩

图片体积太大,加载慢会严重影响用户体验。所以图片压缩是必然的。图片压缩的流程是:本地上传file文件==>转成base64格式=>动态创建img标签=>在img的onload方法中创建canvas=>canvas绘制=>通过canvas.toDataURL转化为base64但当图片体积太大的时候,img.onload方法将不会被触发,而是直接触发onerror方法,猜测可能的原因是图片体积过大会导致base64字串过长,使得浏览器不能完全获取。所以我们需要判断图片体积大小。

/**

* 获取base64大小

* @param{*}base64url

*/

function getImgSize(base64url) {

//获取base64图片大小,返回KB数字

let str = base64url.replace("data:image/jpeg;base64,", ""); //这里根据自己上传图片的格式进行相应修改

let strLength = str.length;

let fileLength = parseInt(strLength - (strLength / 8) * 2);

// 由字节转换为KB

let size = "";

size = (fileLength / 1024).toFixed(2);

return parseInt(size);

}

我们还需要把本地图片文件转化成为base64。

/**

* 图片转base64

* @param{*}file

* @param{*}obj

* @param{*}callback

*/

function photoCompress(file, obj, callback) {

const ready = new FileReader();

ready.readAsDataURL(file);

ready.onload = function () {

const re = this.result;

if (getImgSize(re) / 1024 > 4) {

Modal.alert("", "上传图片不超过4M", [{

text: "确定",

style: {

color: "#868894",

}

}]);

callback(null);

return null;

}

canvasDataURL(re, obj, callback);

};

}

压缩图片

/**

* 压缩图片

* @param{*}re //base64

* @param{*}obj //option

* @param{*}callback

*/

function canvasDataURL(re, obj, callback) {

const img = new Image();

img.onload = function () {

let that = this;

let w = that.width / 4,

h = that.height / 4,

scale = w / h;

w = obj.width || w;

h = obj.height || w / scale;

let quality = 0.7;

let canvas = document.createElement("canvas");

let ctx = canvas.getContext("2d");

const anw = document.createAttribute("width");

anw.nodeValue = w;

const anh = document.createAttribute("height");

anh.nodeValue = h;

canvas.setAttributeNode(anw);

canvas.setAttributeNode(anh);

canvas.clearRect(0, 0, w, h)

ctx.drawImage(that, 0, 0, w, h);

// 图像质量

if (obj.quality && obj.quality <= 1 && obj.quality > 0) {

quality = obj.quality;

}

// quality值越小,所绘制出的图像越模糊

const base64 = canvas.toDataURL("image/jpeg", quality);

// 回调函数返回base64的值

callback(base64);

};

img.onerror = (err) => {

//如果图片过大,就会直接走err方法

Modal.alert("图片太大,请重新上传");

console.log(err);

};

img.src = re;

}

iphoneX底部黑条适配

一般情况下收集浏览器已经处理了iphonx顶部(刘海)和底部对页面的影响,但是在微信浏览器中可能会出现系统底部黑条对移动页面输出框或底部横向滚动条的影响官方给的解决方案是

<meta name=“viewport” content=“width=device-width, viewport-fit=cover”>

//不会自动换行

@supports (bottom: env(safe-area-inset-bottom)) {

    .footer_view {

        padding-bottom: env(safe-area-inset-bottom);

    }

}

viewport-fit:cover表示网页内容全面覆盖手机显示屏。ios11 增加新特性,添加了4个css函数,四个预定义变量为设定安全区域和边界的距离,如下:

  • safe-area-inset-left:安全区域距离左边边界距离

  • safe-area-inset-right:安全区域距离右边边界距离

  • safe-area-inset-top:安全区域距离顶部边界距离;在刘海全屏的时候 top 为 44px

  • safe-area-inset-bottom:安全区域距离底部边界距离;刘海全屏的条件下是 34px。

css 函数 env和 constant只有在 webkit 内核下才支持,env必须在 ios >= 11.2 才支持,constant必须 ios < 11.2 支持。

env 和 constant 只有在 viewport-fit=cover 时候才能生效。

referrer防盗链

当我们加载网络图片的时候,常常会遇到403。我同通常的解决办法是在head标签里,添加meta。

<meta name="referrer" content="no-referrer"/>

这不是一个好的解决方案,可能产生对网络请求有影响。所以针对img标签,我们可以单独处理。referrer表示网站来路,它是一个Dom属性,通过Dom设置来影响请求,它可以在两个地方设置:

  • head里meta标签

  • img、a、link、iframe等标签属性

如果遇到img403,我们可以这样处理

<img referrer="no-referrer" alt="" />

referrer的默认策略是no-referrer-when-downgrade,在同等安全等级下(例如https页面请求https地址),发送referer,但当请求方低于发送方(例如https页面请求http地址),不发送referer origin。需要注意的一点是Fetch支持referrer的更改,

let promise = fetch(url, {

    method: "GET", // POST,PUT,DELETE,等。

    headers: {

        // 内容类型 header 值通常是自动设置的

        // 取决于 request body

        "Content-Type": "text/plain;charset=UTF-8"

    },

    body: undefined // string,FormData,Blob,BufferSource,或 URLSearchParams

    referrer: "about:client", // 或 "" 以不发送 Referer header,

    // 或者是当前源的 url

    referrerPolicy: "no-referrer-when-downgrade", // no-referrer,origin,same-origin...

    mode: "cors", // same-origin,no-cors

    credentials: "same-origin", // omit,include

    cache: "default", // no-store,reload,no-cache,force-cache,或 only-if-cached

    redirect: "follow", // manual,error

    integrity: "", // 一个 hash,像 "sha256-abcdef1234567890"

    keepalive: false, // true

    signal: undefined, // AbortController 来中止请求

    window: window // null

});

referer 选项允许设置在当前域的任何 Referer,或者移除它。referrerPolicy 选项为 Referer 设置一般的规则。一般请求分为3种请求:

  • 同源请求。

  • 跨域请求。

  • 从 HTTPS 到 HTTP 的请求 (从安全协议到不安全协议)。

与 referrer 选项允许设置确切的 Referer 值不同,referrerPolicy 告诉浏览器针对各个请求类型的一般的规则。

scrollIntoView

Element.scrollIntoView() 方法让当前的元素滚动到浏览器窗口的可视区域内。它接受两种类型的参数:

  • 布尔值

  • 对象

//窗口滚动之后会让调动元素顶部和视窗顶部尽可能齐平,

//相应的 scrollIntoViewOptions: {block: "start", inline: "nearest"}。这是这个参数的默认值。

element.scrollIntoView(true)

//窗口滚动之后会让调动元素顶部和视窗底部尽可能齐平

//相应的scrollIntoViewOptions: {block: "end", inline: "nearest"}。

element.scrollIntoView(false)

element.scrollIntoView({

    //定义动画过渡效果

    behavior:"auto"  | "instant" | "smooth",

    //定义垂直方向的对齐,默认start

    block:"start" | "end" | "center" | "nearest",

    //定义水平方向的对齐,默认nearest

    inline:"start" | "end"| "center" | "nearest",

})

scanner一次输入多行_记一次项目复盘,技术盘点(易忽略的细节)相关推荐

  1. python中如何输入多行字符_在python中输入多行字符串有哪些方法

    在python中输入多行字符串有哪些方法 发布时间:2020-04-11 13:46:24 来源:亿速云 阅读:39 作者:小新 今天小编给大家分享的是在python中输入多行字符串有哪些方法,很多人 ...

  2. python从键盘输入列表有缺陷_程序员必知的Python陷阱与缺陷列表-阿里云开发者社区...

    代码看起来可以工作,但不是以你"想当然""的方式.如果一段代码直接出错,抛出了异常,我不认为这是陷阱.比如,Python程序员应该都遇到过的"UnboundLo ...

  3. 学习笔记_记一次植物大战僵尸的破解

    学习笔记_记一次植物大战僵尸的破解 1.学习目标 2.学习工具 3.开始操作 3.1 理清思路 3.2 开始操作 4.总结 1.学习目标 了解二进制.十六进制对于计算机的意义 掌握二/八/十/十二/十 ...

  4. android什么控件能够输入多行文字,Android开发:文本控件详解——EditText(一)基本属性...

    一.简单实例: EditText输入的文字样式部分的属性,基本都是和TextView中的属性一样. 除此之外,EditText还有自己独有的属性. 二.基本属性: hint 输入框显示的提示文本 te ...

  5. java输入一个字符串_在java中如何用键盘输入一个数,字符,字符串

    一,利用 Scanner 实现从键盘读入integer或float 型数据 1 import java.util.*;2 public classtest {3 public static voidm ...

  6. python多行字符串输入_python中怎么输入多行字符串

    python中怎么输入多行字符串,疾风,不言,努力,人生,起风了 python中怎么输入多行字符串 易采站长站,站长之家为您整理了python中怎么输入多行字符串的相关内容. Python中输入多行字 ...

  7. SAP MM初阶之事务代码MIGO界面批次拆分最多输入15行?

    SAP MM初阶之事务代码MIGO界面批次拆分最多输入15行? 1, 执行MIGO事务代码对工单或者采购订单执行收货. 对要收货的数量做批次拆分, 系统出现如下窗口, 2, 某项目的业务人员问,这个界 ...

  8. Java学习笔记之[ 利用扫描仪Scanner进行数据输入 ]

    /*********数据的输入********/ /**利用扫描仪Scanner进行数据输入 怎么使用扫描仪Scanner *1.放在类声明之前,引入扫描仪 import java.util.Scan ...

  9. python输入多行字符串_python中怎么输入多行字符串

    Python中输入多行字符串: 方法一:使用三引号>>> str1 = '''Le vent se lève, il faut tenter de vivre. 起风了,唯有努力生存 ...

最新文章

  1. w10查询自己电脑ip
  2. UA MATH574M 统计学习II 二元分类
  3. 构建用于Openstack Heat的Linux映像
  4. python列表有哪些操作_python列表的基本操作有哪些
  5. 【LeetCode】【HOT】543. 二叉树的直径(递归)
  6. Java 基础系列:异常
  7. QT_在循环中刷新界面
  8. 安装Electron
  9. python自动化学习_Python自动化学习笔记(二)
  10. 手机壳定制商城小程序系统 手机壳定制商城小程序源码
  11. 智能解方程计算机在线使用,作业帮计算器在线使用
  12. 大学生发明文言文编程语言!李白杜甫棺材板压不住啦!
  13. 一个不知名前辈的创业史(血泪)
  14. mysql jemalloc_jemalloc优化MySQL、Nginx内存管理
  15. LaTeX插入参考文献手把手教学 | BibTeX教程
  16. 大数据平台任务调度与监控系统
  17. 深入理解操作系统实验——bomb lab(phase_4)
  18. 在线android机型测试,免费兼容测试/MonkeyTest/100款安卓机型真机测试
  19. java hash 数组_Java数组 哈希表 属性类 -解道Jdon
  20. Android JNI for Android Studio 2.2 or higher

热门文章

  1. springboot教程(一)
  2. 肝!不需要一行 Python 代码,也可以自动获取数据
  3. 程序员的私藏好书中,一定有这7本!
  4. 我用Python分析了“青你2”漂亮小姐姐的颜值,结果真香了!
  5. 周董新歌搞崩QQ,透过20W评论,看看歌迷在说啥
  6. 基于梯度下降法的——线性回归拟合
  7. c语言判断用户名重负,判定方阵的正定负定在C语言中写法.docx
  8. linux周期记录内存信息,linux top显示信息详解
  9. 打开程序时固定位置_新手入门第五课:免费开源图像处理程序GIMP之矩形选择工具...
  10. python 通过什么来判断是否存在分支结构_python通过缩进来判断操作是否在分支结构的方法...