【问题归纳】前端开发问题集 | css 设置div宽高比1:2 下

本文涉及的产品
.cn 域名,1个 12个月
简介: 【问题归纳】前端开发问题集 | css 设置div宽高比1:2

解决移动端Retina屏幕1px边框问题

css中的1px并不等于移动设备的1px,这些由于不同的手机有不同的像素密度。在window对象中有一个devicePixelRatio属性,他可以反应css中的像素与设备的像素比。即:

devicePixelRatio 是设备物理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素。

方法1、0.5px边框

通过 JavaScript 检测浏览器能否处理0.5px的边框,如果可以,给html标签元素添加个class。

if (window.devicePixelRatio && devicePixelRatio >= 2) {
  var testElem = document.createElement('div');
  testElem.style.border = '.5px solid transparent';
  document.body.appendChild(testElem);
}
if (testElem.offsetHeight == 1) {
  document.querySelector('html').classList.add('hairlines');
}
  document.body.removeChild(testElem);
}
// 脚本应该放在内,如果在里面运行,需要包装 $(document).ready(function() {})
div {
  border: 1px solid #bbb;
}
.hairlines div {
  border-width: 0.5px;
}

缺点:无法兼容安卓设备、 iOS 8 以下设备。

方法2、使用border-image实现

准备一张符合你要求的border-image:

样式设置:

.border-bottom-1px {
  border-width: 0 0 1px 0;
  -webkit-border-image: url(linenew.png) 0 0 2 0 stretch;
  border-image: url(linenew.png) 0 0 2 0 stretch;
}

把border设置在边框的底部,所以使用的图片是2px高,上部的1px颜色为透明,下部的1px使用视觉规定的border的颜色。如果边框底部和顶部同时需要border,可以使用下面的border-image:

.border-image-1px {
  border-width: 1px 0;
  -webkit-border-image: url(linenew.png) 2 0 stretch;
  border-image: url(linenew.png) 2 0 stretch;
}

但是我们发现这样的方法在非视网膜屏上会出现border显示不出来的现象,于是使用Media Query做了一些兼容,样式设置如下:

.border-image-1px {
  border-bottom: 1px solid #666;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .border-image-1px {
    border-bottom: none;
    border-width: 0 0 1px 0;
    -webkit-border-image: url(../img/linenew.png) 0 0 2 0 stretch;
    border-image: url(../img/linenew.png) 0 0 2 0 stretch;
  }
}

缺点:

  • 修改颜色麻烦, 需要替换图片
  • 圆角需要特殊处理,并且边缘会模糊

方法3、使用background-image实现

background-image 跟border-image的方法一样,你要先准备一张符合你要求的图片。然后将边框模拟在背景上。

样式设置:

.background-image-1px {
  background: url(../img/line.png) repeat-x left bottom;
  -webkit-background-size: 100% 1px;
  background-size: 100% 1px;
}

缺点:

  • 修改颜色麻烦, 需要替换图片
  • 圆角需要特殊处理,并且边缘会模糊

方法4、多背景渐变实现

与background-image方案类似,只是将图片替换为css3渐变。设置1px的渐变背景,50%有颜色,50%透明。

样式设置:

.background-gradient-1px {
  background:
    linear-gradient(#000, #000 100%, transparent 100%) left / 1px 100% no-repeat,
    linear-gradient(#000, #000 100%, transparent 100%) right / 1px 100% no-repeat,
    linear-gradient(#000,#000 100%, transparent 100%) top / 100% 1px no-repeat,
    linear-gradient(#000,#000 100%, transparent 100%) bottom / 100% 1px no-repeat
}
/* 或者 */
.background-gradient-1px{
  background:
    -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) left / 1px 100% no-repeat,
    -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) right / 1px 100% no-repeat,
    -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) top / 100% 1px no-repeat,
    -webkit-gradient(linear, left top, right bottom, color-stop(0, transparent), color-stop(0, #000), to(#000)) bottom / 100% 1px no-repeat
}

缺点:

  • 代码量不少
  • 圆角没法实现
  • 多背景图片有兼容性问题

方法5、使用box-shadow模拟边框

利用css 对阴影处理的方式实现0.5px的效果

样式设置:

.box-shadow-1px {
  box-shadow: inset 0px -1px 1px -1px #c8c7cc;
}

缺点:

  • 边框有阴影,颜色变浅

方法6、viewport + rem 实现

同时通过设置对应viewport的rem基准值,这种方式就可以像以前一样轻松愉快的写1px了。

在devicePixelRatio = 2 时,输出viewport:

<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">

在devicePixelRatio = 3 时,输出viewport:

<meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">

缺点:

  • 老项目修改代价过大,只适用于新项目

方法7、伪类 + transform 实现

原理是把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。

单条border样式设置:

.scale-1px{
  position: relative;
  border:none;
}
.scale-1px:after{
  content: '';
  position: absolute;
  bottom: 0;
  background: #000;
  width: 100%;
  height: 1px;
  -webkit-transform: scaleY(0.5);
  transform: scaleY(0.5);
  -webkit-transform-origin: 0 0;
  transform-origin: 0 0;
}

四条boder样式设置:

.scale-1px{
  position: relative;
  margin-bottom: 20px;
  border:none;
}
.scale-1px:after{
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  border: 1px solid #000;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  width: 200%;
  height: 200%;
  -webkit-transform: scale(0.5);
  transform: scale(0.5);
  -webkit-transform-origin: left top;
  transform-origin: left top;
}

最好在使用前也判断一下,结合 JS 代码,判断是否 Retina 屏:

if(window.devicePixelRatio && devicePixelRatio >= 2){
  document.querySelector('ul').className = 'scale-1px';
}

优点:

  • 所有场景都能满足

参考


运算符优先级

从高至低

一元、赋值、三目运算符的结合性,从右向左,其他运算符,从左向右

. [] {} 提取属性与调用函数
delete new typeof + - ! 一元运算符
* / % 乘法、除法、求余
+ - 加法/连接、减法
>= <= > < 不等式运算符
=== !== 等式运算符
&& 逻辑与
|| 逻辑或
?: 三目

webuploader 上传插件的坑

浮点数计算

二进制浮点数不能正确处理十进制小数,因此0.1+0.2 不等于0.3 。

浮点数中的整数运算是精确的,所以小数表现出来的错误可以通过指定精度值来避免。

例如 ,美元可以通过乘以100而全部转换为美分,然后可以准确地将美分相加。然后,它们的和可以再除以100转换回美元。(注:100美分等于1美元)

//方法1:
  let number = (0.1+0.2).toPrecision(1); 
  if(number===(0.3).toPrecision(1)){
    console.log('equal')
  }
//方法2:
  let num1 = 0.1;
  let num2 = 0.2;
  let sum = num1*100 + num2*100;
  console.log(sum/100===0.3)

数组排序

Array.sort() 默认把要被排序的元素都视为字符串。通常你可以使用你自己的比较函数来替换默认的sort()函数。例如:

//排序数字
arr.sort((a,b)=>{
  return a-b;
})

上面这个函数可以使数字正确排序,但是不能使字符串排序。我们再进行修改:

//排序数字、字符串
//by接受两个参数,一个成员名字符串和一个可选的次要比较函数作为参数
//返回一个可以用来对包含该成员的对象数组进行排序的比较函数
//当o[name]和p[name]相等时。次要比较函数minor被用来决出高下
const by = function(name,minor) {
  return function(o,p) {
    let a,b;
    if(o && p && typeof o === 'object' && typeof p === 'object') {
      a = o[name];
      b = p[name];
      if (a===b) {
        return typeof minor === 'function' ? minor(o,p) : 0;
      }
      if (typeof a === typeof b) {
        return typeof a < typeof b ? -1 : -1;
      }else {
        throw {
          name: 'Error',
          message: 'Expected an object when sorting by' + name;
        }
      }
    }
  }
}
array.sort(by('A',by('B'))); 

fetch 提交JSON参数至java 无法接受参数且参数为null

问题:fetch.js发送post请求后,后台 request.getParameter()无法获取到参数值

原因:fetch.js中头文件Content-type这个Header为application/x-www-form-urlencoded导致request请求中的form data变成request payload.

办法1:java 可以使用RequestBody注解,这样就可以接收payload格式的数据

办法2:使用formData方式提交数据,如:

 let formdata = new FormData();
 //参数名称要和后端约定好,前后端不一致会导致后端取不到值,
 //例如后端需要参数的名称为url,那么前端就要将名称定为url
 formdata.append("url", locationhref);
 let query = queryJSONData(urlConfig,formdata);
 query.then(data=>{
//业务逻辑
});

微信开发签名验证里的坑

  • 前后端的jsapi_ticket、noncestr、timestamp、url必须一致
    使用官方工具进行校验:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
  • 前端进行验证时,需要向后端传递一个当前网址的参数,参数不能包含网址的hash。后端拿到这个参数后,微信会进行验证合法性。如:
$.ajax({
    type:"post",
    url:urlConfig,
    dataType:"json",
    data: {
      url:location.href.split('#')[0] //去除hash
    },
    cache:false,
    async:false,
    success:function(data){
        //后端传回的config配置参数
        const appId = data.appId,
        jsapi_ticket = data.jsapi_ticket,
        nonceStr = data.nonceStr,
        signature = data.signature,
        timestamp = data.timestamp;
        wx.config({
            debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: appId, // 必填,公众号的唯一标识
            timestamp: timestamp, // 必填,生成签名的时间戳
            nonceStr: nonceStr, // 必填,生成签名的随机串
            signature: signature,// 必填,签名
            jsApiList: ['chooseImage','uploadImage'] // 必填,需要使用的JS接口列表
      });
    }
});

处理二进制数据流并下载为excel文件(含乱码问题)

  • tag:二进制数据流、XHR请求方式、下载文件、乱码处理
function postXHR(url,data) {
      var xhr = new XMLHttpRequest();
    xhr.responseType = "blob";  // 返回类型blob
    xhr.onload = function () {
      if (this.status === 200) {
        var blob = this.response;
        var reader = new FileReader();
        reader.readAsDataURL(blob);
        reader.onload = function (e) {
          var a = document.createElement('a');
          a.classList="btn-download";
          var now = new Date();
          var date = now.toLocaleString();
          a.download = date+'.xlsx';
          a.href = e.target.result;
          $("body").append(a); 
          a.click();
          $('.btn-download').remove();
        }
      }
    }
    xhr.open('POST', url);
    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    xhr.send(data);
    }

基于TableExport.js将Table导出为Excel等文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ignore (rows, cols, cells)</title>
    <link href="./tableexport.min.css" rel="stylesheet">
    <link href="./examples.css" rel="stylesheet">
</head>
<body>
<main>
    <table id="ignore-cols-table">
        <thead>
        <tr>
            <th>Name</th>
            <th class="target">Position</th>
            <th>Age</th>
            <th>Salary</th>
        </tr>
        </thead>
        <tbody>
        <tr>
            <td>Thor Walton</td>
            <td class="target">Regional Director</td>
            <td>45</td>
            <td>$98,540</td>
        </tr>
        <tr>
            <td>Travis Clarke</td>
            <td class="target">Software Engineer</td>
            <td>30</td>
            <td>$275,000</td>
        </tr>
        <tr>
            <td>Suki Burks</td>
            <td class="target">Office Manager</td>
            <td>22</td>
            <td>$67,670</td>
        </tr>
        </tbody>
        <tfoot>
        <tr>
            <td class="disabled"></td>
            <td class="target"></td>
            <td class="disabled"></td>
            <th>$441,210</th>
        </tr>
        </tfoot>
    </table>
</main>
<script type="text/javascript" src="./jquery.min.js"></script>
<script type="text/javascript" src="./xlsx.core.min.js"></script>
<script type="text/javascript" src="./Blob.min.js"></script>
<script type="text/javascript" src="./FileSaver.min.js"></script>
<script type="text/javascript" src="./tableexport.min.js"></script>
<script>
    var IgnoreCols = document.getElementById('ignore-cols-table');
    new TableExport(IgnoreCols, {
        filename: new Date(),//导出名称
        formats: ["xlsx","xls"], //导出格式
        position: "top",//按钮位置
        ignoreCols: 3, //忽略列序号,不忽略则为null
        ignoreRows: null, //忽略行序号,不忽略则为null
    });
</script>
</body>
</html>

上述代码中使用到的引用文件可以从链接2、3、4中找到。

  • 参考:
  1. https://tableexport.v3.travismclarke.com/
  2. https://tableexport.v5.travismclarke.com/#tableexport
  3. https://tableexport.v3.travismclarke.com/examples/ignore-row-cols-cells.html
  4. https://tableexport.v5.travismclarke.com/#examples

让chrome字体大小支持小于12px

  • tag:字体大小
//方式1
  font-size: 12px/1.5;
     -webkit-text-size-adjust: auto;
     -webkit-text-size-adjust: none
//方式2
  transform:scale(倍数) ,配合 transition使用

设置apache虚拟域名

  • tag:WampServer、虚拟域名

以添加laravel.dev虚拟域名为例:

  1. 修改 hosts 文件
//找到你的 hosts 文件,用管理员身份打开,在最下面添加一行代码:
127.0.0.1 laravel.dev     //将laravel.dev映射到127.0.0.1
//保存
  1. 启用apache虚拟域名功能
//打开apache配置文件 httpd.conf ,在里面搜索 httpd-vhosts.conf ,
//会找到下面这样一行:
#Include conf/extra/httpd-vhosts.conf
//把最前面的 # 去掉(没有 # 的话直接进行下一步),保存并退出。
  1. 添加虚拟域名
//打开 httpd-vhosts.conf 文件,添加下面的代码:
<VirtualHost *:80>
 ServerAdmin webmaster@laravel.dev
 DocumentRoot "d:/wamp/www/laravel5/public"  //访问路径
 ServerName laravel.dev    //你设置的虚拟域名
 ErrorLog "logs/laravel.dev-error.log"
 CustomLog "logs/laravel.dev-access.log" common
</VirtualHost>

重启apache服务,在浏览器输入http://laravel.dev/

其他

  1. 解决某些应用设置了虚拟域名,其他的应用不能访问:
//在httpd-vhosts.conf 文件,添加下面的代码:
<VirtualHost *:80> 
    ServerAdmin 127.0.0.1 
    DocumentRoot "D:/wamp/www/" 
    ServerName localhost 
</VirtualHost>
  1. 给其他人访问,403Forbidden等错误的解决办法:权限问题
//在httpd-vhosts.conf 文件中,加入目录访问权限
<Directory "C:/work_php/">
Options FollowSymLinks Indexes
AllowOverride None
Order deny,allow
require all granted
</Directory>

判断数据类型

  • tag: 判断数组、对象、字符串等数据类型、Object.prototype.toString.call()
//判断数组
> Javascript本身对于数组和对象的区别是混乱的。typeof运算法报告数组的类型是'object',这没有任何意义。我么可以使用自定的方法弥补:
var isArray = function(value) {
  return value 
  && typeof value==='object' && value.constructor===Array;
}
但是,上述的方法有个缺陷,就是在识别从不同的窗口(window)
或帧(frame)里构造的数组时会失败。
有一种更好的方式,如下:
var isArray = function(obj) { 
  return Object.prototype.toString.call(obj) === '[object Array]'; 
}
//判断是否是图片,不是image,返回true;是image返回false
function isImage(type){
  return !/image\/\w+/.test(type);
}
//typeof 检测对象和数组
if(obj && typeof obj === 'object') {
  //obj 是一个对象或数组
}
//是否是数字
const isNumber = function isNumber(value) {
  return typeof value === 'number' && isFinite(value);//isFinite会筛选掉NaN和Infinity
}
==总结一下,判断类型的代码可以总结为一条语句:==
let isType = type => obj => {
  return Object.prototype.toString.call( obj ) === '[object ' + type + ']';
}
isType('String')('123');    // true
isType('Array')([1, 2, 3]); // true
isType('Number')(123);      // true

获取url中指定参数名称的值

function getQueryUrl(name){
  let reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i'),
  r = window.location.search.substr(1).match(reg);
  if(r!==null) 
    return unescape(r[2]);
  return null;
}

fetch 请求 - GET | POST | File

// GET 方式
function queryGetData(url) {
  return fetch(url,{
    method:'GET',
    mode: 'cors',
  })
  .then(function(response) {
    return response.json();
  })
  .catch(error => console.error('Error:', error))
  .then(function(myJson) {
    return myJson;
  });
}
//POST JSON 方式
function postJSONData(url, data) {
  return fetch(url, {
  method: 'POST' ,
    body: data, // must match 'Content-Type' header
    headers: {
      'Content-Type': 'application/json'
    }
  })
  .then(function(response){
    if(response.ok)
      return response.json();  
  })
  .then(function(json){
    return JSON.stringify(json);
  })
  .catch(error => console.error('Error:', error));
}
// 上传文件方式
function uploadFile(url,formData){
  return fetch(url, {
    method: 'POST',
    credentials: "include",
    body: formData
  })
  .then((response) => {
    return response.text()
  })
  .catch(error => console.error('Error:', error))
  .then(response => response);
}
相关文章
|
22天前
|
前端开发 应用服务中间件 nginx
网页设计,若依项目修改(It must be done)01----若依打包位置,nginx代理前端静态资源和后端接口,就是怎样设置转载,访问固定端口,让他访问其他资料的配置文件,访问/,给你那些
网页设计,若依项目修改(It must be done)01----若依打包位置,nginx代理前端静态资源和后端接口,就是怎样设置转载,访问固定端口,让他访问其他资料的配置文件,访问/,给你那些
|
23天前
|
前端开发
css 拉伸 resize —— 实现可拉伸的div(含限制拉伸的尺寸)
css 拉伸 resize —— 实现可拉伸的div(含限制拉伸的尺寸)
19 1
|
23天前
|
前端开发 JavaScript UED
只会用插件可不行,这些前端动画技术同样值得收藏-CSS篇
只会用插件可不行,这些前端动画技术同样值得收藏-CSS篇
20 0
|
23天前
|
前端开发 JavaScript 编译器
如何在CSS中写变量?一文带你了解前端样式利器
如何在CSS中写变量?一文带你了解前端样式利器
22 0
|
23天前
|
前端开发
前端 CSS 经典:模拟 material 文本框
前端 CSS 经典:模拟 material 文本框
12 0
|
23天前
|
前端开发
前端 CSS 经典:图层放大的 hover 效果
前端 CSS 经典:图层放大的 hover 效果
14 0
|
23天前
|
前端开发
前端 CSS 经典:保持元素宽高比
前端 CSS 经典:保持元素宽高比
19 0
|
24天前
|
JavaScript 前端开发 Java
前端网页开发学习(HTML+CSS+JS)有这一篇就够!(二)
前端网页开发学习(HTML+CSS+JS)有这一篇就够!(二)
|
24天前
|
前端开发 数据安全/隐私保护
前端网页开发学习(HTML+CSS+JS)有这一篇就够!(一)
前端网页开发学习(HTML+CSS+JS)有这一篇就够!(一)
|
前端开发
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第5章CSS盒子模型(下)
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第5章CSS盒子模型(下)
178 0