一.css样式问题
1.一行省略以及多行省略问题
一行省略样式:
width: 200px; // 必须是定宽
overflow: hidden; // 超出隐藏
text-overflow: ellipsis; // 隐藏部分用省略号代替
white-space: nowrap; // 文本内容不换行(默认在定宽的情况下换行)
多行省略样式:
width: 200px; // 必须是定宽
overflow: hidden; // 超出隐藏
text-overflow: ellipsis; // 隐藏部分用省略号代替
display: -webkit-box; // 将对象作为弹性伸缩盒子模型显示
-webkit-box-orient: vertical; // 和上面那两行,规定框的子元素应该被水平或垂直排列,替代以前box-orient 属性
-webkit-line-clamp: 2; // 限制在一个块元素显示的文本的行数
2.两端对齐问题
样式如下:
width: 200px; // 定宽
text-align-last: justify; // 这段文字的最后一行两端对齐
text-align: justify; // 整段文字两端对齐
text-justify: distribute-all-lines; // 兼容ie浏览器
text-align-last属性可写也可不写(默认左对齐),有三个属性值可选择,效果如下:
3.自己写table样式,属性display:table无效
在css里面写display: -webkit-flex也无效,然后解决如下,在html里面写上如下样式,参考如下链接,暂时找不到对这个的解释,只有在网上搜到这个.
:style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"
4.z-index不奏效
问题描述:z-index不奏效。
分析:有三种情况:
1、父标签position属性为relative;
2、问题标签无position属性(不包括static);
3、问题标签含有浮动(float)属性。
解决方法:
1、position:relative;改为position:absolute;
2、浮动元素添加position属性(如relative,absolute等);
3、去除浮动。
5.margin: 0 auto;不奏效
问题描述:margin: 0 auto;
分析:产生的原因有下面几种情况:
1、问题元素没有指定宽度;
2、浮动、绝对定位、固定定位的盒子失效;
3、行内元素失效;
4、其实同3,类似display:table-cell;只display不是block就会失效。
解决方法:
问题元素定宽,没有定位,display:block。
6.box-shadow效果
问题描述:设计图要求有些只有其中一边显示阴影效果,有些需要全部阴影效果。
解决方法:
语法:box-shadow: h-shadow(水平阴影的位置) v-shadow(垂直阴影的位置) blur(模糊距离) spread(阴影大小) color_inset;
直观效果如下:
1、top
2、right
3、bottom
4、left
5、四边都显示(阴影大小一定要比水平、垂直任一位置大,不然四边显示不出来)
7.“流体布局”和“自适应布局”
流体布局:利用元素“流”的特性实现的各类布局效果。因为:流本身具有自适应特性,所以“流体布局”往往都是具有自适应性的,但是“流体布局”并不等同于“自适应布局”。
自适应布局:是对凡是具有自适应特性的一类布局的统称。
详细的可以参考这个链接:布局
二.js问题
1.因为前一个页面数据过多,点击按钮时,浏览器给出的反应会很慢.
在按钮点击时,把过多的数据清空,用length=0的方法.(这应该涉及到浏览器的进程了,没有过多的涉及,至于原因就不知道了.)
2.因为浏览器兼容问题无法获取点击事件冒泡路径。
描述:用vue写h5动态加载元素,点击事件无法渲染出来(或者说是函数没法指向window),就想用冒泡路径来获取元素的点击事件。
问题:在安卓上是没有问题的,但是到了ios的safari浏览器上,就没有了触发事件。
排除了很多原因后,发现其实是在safari环境下其冒泡路径不能通过event.path来获取,存在兼容问题(火狐也存在这种情况),需要用composedPath。
let path = event.path || (event.composedPath && event.composedPath());
3.针对2中window的指向问题
描述:使用了框架后,this指向的都是vue实例,而原生函数指向的是window,所以在初始化时,就把函数赋值给window就可以,比如:
// html部分,注意原生的点击事件是需要括号的
<div onclick="example()"></div>
// js部分
created() {
window.example = this.example;
},
methods: {
example() {},
}
4.数字三位数以逗号进行分割
1、利用原生方法
如果你对小数点后的位数没有这么高的要求,可以使用toLocaleString()方法,它只可以保留小数点后三位数(四舍五入)。
let num = 111111.111111;
num.toLocaleString(); // "111,111.111"
需要注意的是,这个方法将数字类型转换为了字符串。
Number.toLocaleString() 方法返回这个数字在特定语言环境下的表示字符串。
2、使用正则
function thousands(num){
var str = num.toString();
var reg = str.indexOf(".") > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g;
return str.replace(reg,"$1,");
}
3、字符打散
function thousands(num){
var splits=[],res=[];
var splits = num.toString().split(".");
splits[0].split("").reverse().map(function(item,i){
if(i%3 == 0 && i!=0){ res.push(","); }
res.push(item);
});
return res.reverse().join("")+(splits.length>1 ? "."+splits[1] : "");
}
把数字分成整数和小数两部分,然后把整数部分差成单字符数组,反向排列后每3位插入一个逗号(因为逗号是从后向前加)。然后再一次反向排列并合成字符串,加上小数部分就完成了。
5.获取URL参数
用js的方式获取URL参数。
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
6. 0.1+0.2不等于0.3
问题描述
一直都知道0.1+0.2是不等于0.3的,因浮点数缘故,一直都没弄清其中的缘故。
分析
计算机只认识二进制,运算时需将其他进制的数值转为二进制再进行计算。而浮点数用二进制表达是无穷的:
0.1+0.2; //0.30000000000000004
0.1.toString(2); // 0.0001100110011001100110011001100110011001100110011001101
0.2.toString(2); // 0.001100110011001100110011001100110011001100110011001101
IEEE 754标准的64位双精度浮点数的小数部分最多支持53位二进制位,两者相加后,因浮点数0.1的小数位的限制而截取的二进制数字,此时误差产生;再转为十进制,结果为0.30000000000000004.
注:二进制能精确地表示位数有限且分母是2的倍数的小数。
7. js中引入js
问题描述
要做前端项目优化,高德地图要做按需加载,而不是在index.html引入地图。
问题分析
如果用npm安装的,直接用import就可以了,但是这样的话,性能上提高的并不是很多,借助cdn可以提高更多。这样就遇到了一个问题,在script中如何引入其他的script。
解决方案
const scriptMap = document.createElement("script"); // 创建script标签节点
scriptMap.setAttribute("type", "text/javascript"); // 设置script类型
scriptMap.setAttribute(
"src",
"https://webapi.amap.com/maps?v=2.0&key=xxxx"
); // 设置js地址
document.body.appendChild(scriptMap); // 将js追加为body的子标签
// 判断scriptMap是否加载成功
scriptMap.onload = scriptMap.onreadystatechange = () => {}
需要注意的是,像地图这类的,只有将库加载完才能调用的(也就是引入的script要比本页面的script先加载),一定要等上一个script加载完再操作!
三、vue项目
1.导航重复
问题描述
从同一页面跳到同一页面,会报错,这是导航重复的原因,报错如下:
解决方案
在引入vue-router页面,需要加上以下内容:
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err);
};
2.元素拖拽
问题描述:要求有一个即可拖拽,又有点击事件的元素。拖拽的时候,应该只执行拖拽操作,但是点击事件也会被执行。
分析:鼠标点击事件过程如下:
- onClick:点击事件
- onDblClick:双击事件
- onMouseDown:鼠标上的按钮被按下
- onMouseUp:鼠标按下后,松开时激发的事件
- onMouseOver:当鼠标移动到某对象范围的上方时触发的事件
- onMouseMove:鼠标移动时触发的事件
- onMouseOut:当鼠标离开某对象范围时触发的事件
顺序如下:
解决方法:介于只监听了onmousedown和onmousemove,且移动计算在onmousemove事件里,所以按照如下方式进行。
1、在onmousedown里给元素加上监听事件(防止上一次移除);
2、在onmousemove里去除监听事件(因为只要该事件触发,就说明这是拖拽事件)。
需要注意的是$emit只能在Vue自定义组件中使用,在常规的DOM元素中用.dispath event发送DOM事件。(例如: vnode.elm.dispatchEvent(new CustomEvent(eventName, {key: value}));)
3.代理跨域
问题描述:本地代理,报错如下:
分析:这是因为代理从http发出请求,请求的确实https,两者协议不一样,造成跨域。
解决方法:可以参考链接代理跨域
如果cli3项目,可以在vue.config.js更改如下(cli3以下的在config.js里面修改):
4.本地ip访问
问题描述:项目运行时只能用localhost访问,在局域网下,无法通过其ip地址访问。
解决方法:参考链接项目运行
5.使用router-view进行跳转
问题描述:用router-view判断进入二级页面,刷新页面时,父页面的created以及mounted等声明周期也会被调用。
解决方法:如果没有额外操作(比如:刷新页面)进入父页面再进入子页面,他的正常流程是这样的:
父级created => 父级mounted => 父级watch => 子级created => 子级mounted
但是你在子级页面刷新时,你会发现执行顺序是这样的:
父级created => 子级created => 子级mounted => 父级mounted
这都是正常的流程,而要避免第二种情况,最好是在父级页面深度监听路由。
6.导航守卫
问题描述:有一个这样的需求,只用从登录页跳转过来的才去请求数据,其他页面跳转过来的都不请求。
分析:首先想到这个跟路由有关系,从路由下手。第一次尝试深度监听路由,你会发现它的oldVal一直都是undefined(这也很容易理解,从上一个页面跳转过来时,下一个页面无法监听,因为下一个页面的实例还没创建好),根本无法区分上一个页面是否是登录页。搜索了很久,发现导航守卫beforeRouteUpdate
可以做到。
导航守卫
额外的收获:参数或查询的改变并不会触发进入/离开的导航守卫,但是可以用beforeRouteUpdate
(比如用path: 'xxx/:id'和params的形式传递参数,从这个详情页到另一个详情页)。
7.computed和watch的区别
本质:两者处理的数据关系场景不同。
watch擅长处理的场景:一个数据影响多个数据
computed擅长处理的场景:一个数据受多个数据影响
computed是计算属性,依赖其他属性计算值,并且computed的值有缓存,只有当计算值变化才会返回内容。
watch监听到值的变化就会执行回调,在回调中可以进行一些逻辑操作。
所以一般来说需要依赖别的属性来动态获得值的时候可以使用computed,对于监听到值的变化需要做一些复杂业务逻辑的情况可以使用watch。
8.高德地图与阿里巴巴矢量库“冲突”
问题:高德地图与阿里巴巴矢量库曾多次一起使用,但是最近这个项目刚引入高德地图,在本地是好的,打包后上传到测试服上,测试服的图标都不显示。调试了好久,刚开始以为是高德地图采用异步引入,覆盖了阿里巴巴矢量库的图标,但是发现并不是,最后也不知道做了什么,突然就好了,到现在也不知道原因????那个问题也无法复原了。。。
9.版本统一
问题:要求两个项目用到的技术栈统一。
分析:先删除技术栈,,然后引用指定版本的技术栈。
npm uninstall **
npm install **@x.x.x
还有一个问题,技术栈要如何准确配置在dependencies和devDependencies下。
npm install **@x.x.x -D // 表示放在devDependencies下
npm install **@x.x.x -S // 表示放在dependencies下
想要了解具体的可以参考:dependencies和devDependencies配置详解
四、ES6
1.async/await调用不成功
问题描述:一个数组批量调用接口
分析:首先想到的是async/await和Promise.all,习惯的选用了async/await,然后它报错了,以下是一个仿照着写的demo。
然后陷入了迷茫。。。
解决方法:项目里用Promise.all代替了async/await,用Promise.all完全没问题。
现在返回找答案,原来是forEach的原因!
原代码:
需要改成这样(注意看async的位置!!!)
看看上面两段代码async的位置就可以知晓答案了,因为es6中提倡用箭头函数代替普通函数,造成的结果就是时常会忘记forEach()也是一个函数,而await是要紧跟async,所以会报错。
当然用for循环就可以完美地避开这个问题了。
MDN官方文档给出的例子是这样的:
2.Scoped CSS 深度作用选择器无效
问题描述:项目所有的style都加了scope,然后修改第三方组件时,样式无效果。更糟糕的是它的父元素是body,无法添加额外的类名。
分析:如果它的父元素不是body的,可以添加类名,然后通过深度作用选择器进行添加样式,深度作用选择器可以参考Scoped CSS
但父元素是body的情况下,深度作用选择器就没有用了,我采用的方式比较粗暴,直接获取需要修改的元素,用js直接赋值。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。