20. 管理后台--时间段选择框宽度设置成自适应,会出现什么问题?
管理后台,列表查询表单,大多采用栅格布局,将一行分为24等份, 如果对栅格布局使用不当,就会出现如下的情况,在屏幕比较窄的PC机器上,长一点的时间段选择器选择的时间会显示不全,如下图所示:
我想到的处理方式就是给时间段选择器设置一个最小宽度,为了展示美观,可以给所有的栅格容器,都设置一个最小宽度,这样就兼顾了上下排列整齐和屏幕太小选择日期被遮挡问题
19. 页面一片空白的排查思路?
- 查看网页资源加载路径是否正确
- 查看控制台日志,js脚本有无报错
- 查看登陆授权接口是否报错或返回结果有误
- 查看静态服务器的nginx配置是否正确
- 如果后端存在登陆重定向页面地址逻辑,而在前端找不到任何线索,那就需要后端看看登陆重定向逻辑。
18. /bin/sh: nx:command not found
如何解决?
如下图所示, 提示在/bin/sh
下,找不到nx命令
解决方法是全局安装nx
bash
npm install -g @nrwl/cli
如果安装完之后还有问题,可用这个命令查看 npm 放置全局安装包的路径
bash
npm config get prefix
可参考此文,用export PATH指令设置Linux系统下的环境变量。
17. 给一个div设置了上下左右四个方向负的margin值,表现有什么不同?
左边和上边设置了负的margin值比较好理解,是当前元素向左或向上偏移
html
<div class="container">
<div class="left"></div>
</div>
<style>
.container {
width: 10rem;
height: 10rem;
border: 1px solid #666666;
margin: 100px auto;
.left {
width: 3.125rem;
height: 3.125rem;
background-color: #ffcc66;
opacity: 0.8;
/* margin-left: -20px; */
margin-top: -20px;
}
}
</style>
而右边或下边设置了负的外边距,情况就不太一样了,对当前元素不会产生任何影响,移动的效果体现在当前元素右侧或下侧紧邻的元素上。
html
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
<style>
.container{
width: 10rem;
height: 10rem;
border: 1px solid #666666;
margin: 100px auto;
/* display:flex; */
.left,
.right{
width: 3.125rem;
height: 3.125rem;
}
.left{
opacity: 0.8;
background-color: green;
margin-bottom: -20px;
}
.right{
opacity: 0.5;
background-color: #333;
}
}
</style>
16. 一台机器,要通过正向代理访问外网指定资源,这个指定的资源文件应该放在那台服务器上,才能被访问?
这是正向代理配置,正向代理有三个特征:
- 不能有hostname。
- 必须有resolver, 即dns,即下面的114.114.114.114
- 正向代理参数,均是由 Nginx 变量组成。
bash
server {
listen 80;
server_name localhost;
resolver 114.114.114.114;
proxy_connect;
proxy_connect_allow 443 80;
proxy_connect_connect_timeout 10s;
proxy_connect_read_timeout 10s;
proxy_coneect_send_timeout 10s;
location / {
proxy_pass $scheme://$http_host$request_uri;
}
}
这是目标服务器配置,应该把要访问的证书文件,配置在目标服务器,才能被访问到。
bash
location /zT8d0hxWrk.txt{
alias /你的服务器根路径/cert/zT8d0hxWrk.txt;
}
15. [Vue warn]: Component inside renders non-element root node that cannot be animated. 解决方法?
这种路由写法:
html
<router-view v-slot="{ Component, route }">
<transition>
<keep-alive :include="keepAliveList">
<component :is="Component" />
</keep-alive>
</transition>
</router-view>
当页面没有被根元素包裹时,会提示没有根节点时,<Transition>
组件无法渲染动画。
解决方法有三种:
- 在警告提示的页面,添加根元素
- 在全局路由处,添加根元素, 但这种修改方式,会让页面多出两级嵌套的div
html
<router-view v-slot="{ Component, route }">
<transition>
<div :key="route.fullPath">
<keep-alive :include="keepAliveList">
<component :is="Component" />
</keep-alive>
</div>
</transition>
</router-view>
- 移除路由过渡动画效果, 路由切换过渡动画属于锦上添花,去除了也没关系
html
<router-view v-slot="{ Component, route }">
<keep-alive :include="keepAliveList">
<component :is="Component" />
</keep-alive>
</router-view>
14. 发送短信验证码按钮需要做的UI优化
- 发现很多网站及应用,发送短信验证码按钮宽度会随文字长短变化,如果设置了圆角,按钮宽度变短了,按钮完全变了样,看着比较丑陋
- 比较好的做法是保持短信验证码按钮宽度固定
13. 循环中的判断优化的一个小技巧分享
把大概率会命中的判断条件放在前面,不太容易命中的放在后面
js
const arr = Array.from(Array(10), (item, index)=>index);
arr.forEach((item, index)=>{
if(index !== 4){
// do something
}else{
// do else
}
})
12. vue的template中,父组件传入的属性,在引用的时候,是否可以省略props?
常规写法:
html
<div :style="props.gridStyle.backgroundFrameImg && `background-image: url(${props.gridStyle.backgroundFrameImg})`">
偷懒写法,在template中用到props属性时,可以省略
html
<div :style="gridStyle.backgroundFrameImg && `background-image: url(${gridStyle.backgroundFrameImg})`">
11. 前端有没有可以加解密的算法库?
项目中要实现一个加解密功能,要js-md5加解密算法的话,只能加密,不能解密。那么前端领域,有没有对称的加解密库,在网上找了一下,找到了crypto-js
,测试了一下,知道加密字符串的情况下,可以解密加密之后的字符。测试用例如下:
js
import CryptoJS from 'crypto-js';
// 密钥一致才能进行解密
const aseKey = 'hello,crypto!!!!';
// 原始字符串
const encrpytText = 'abc12345';
// 加密之后的字符串
const decryptText = 'NplXcmyLdw6AikuQ7hBUGA==';
//调用加密方法
console.log(cryptoEncryption(aseKey, encrpytText));
//调用解密方法
console.log(cryptoDecrypt(aseKey, decryptText));
// crypto-js加密
// aseKey为密钥(必须为:8/16/32位),message为要加密的密文
function cryptoEncryption(aseKey, message) {
var encrypt = CryptoJS.AES.encrypt(message, CryptoJS.enc.Utf8.parse(aseKey), {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
}).toString();
return encrypt;
}
// crypto-js解密
function cryptoDecrypt(aseKey, message) {
var decrypt = CryptoJS.AES.decrypt(message, CryptoJS.enc.Utf8.parse(aseKey), {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
}).toString(CryptoJS.enc.Utf8);
return decrypt;
}
另外一种选择就是用base64加解密,效果也不错
js
import {encode, decode } from 'js-base64';
const str='hello-base64';
const enctryStr=encode(str);
console.log( enctryStr, decode(enctryStr) );
10. 动态加载图片时,发现第一次会出现资源请求报错,是什么原因引起的?
如下图所示, 抓包发现,出现一个undefined的图片加载请求,不知道从哪里发出的, 经过一番排查,终于找到了元凶。是因为页面中有张背景图片,值是通过接口获取的,刚开始时背景图片未设置初始值,可是浏览器也发起了资源加载请求,于是就出现了一个undefined的图片资源加载错误。
所以加载的图片如果是通过接口获取的,那么要判断一下,这个图片资源是否为空,如果不为空,才去加载。
错误写法:
html
<div :style="`background-image: url(${props.gridStyle.backgroundFrameImg})`">
正确写法:
html
<div :style="props.gridStyle.backgroundFrameImg && `background-image: url(${props.gridStyle.backgroundFrameImg})`">
9.vue3 style中的css变量, 如果是个对象,该如何书写?
直接这样写,会提示错误
css
background-color: v-bind(props.gridStyle.prizeUnderpainting);
正确写法:
css
background-color: v-bind('props.gridStyle.prizeUnderpainting');
8.ts中如何设置泛型默认的类型定义?
首先给网络请求方法request
添加一个泛型定义
ts
export default function request<T = { [key: string]: any }>
apiConfig: Apis.IApiProps,
params: Apis.IReqParams = {},
options: Apis.IOptionsParams = {}
): Promise<Apis.IResDataProps<T>>
重点来了,在这里给泛型设置一个默认值
ts
// 请求返回类型
type IResDataProps<T> = {
// 业务代码
ret: number;
// 业务数据
retdata: T;
// 业务消息
retmsg: string;
};
在接口定义的地方,用具体属性定义替代泛型。
ts
getActivityInfo: (params: Apis.IReqParams) => {
const apiConfig: Apis.IApiProps = {
method: 'GET',
url: '/url/xxx/xxx',
};
return request<ILotteryProps>(apiConfig, params);
},
另外在使用的地方,不能这样写,这样写retdata的类型是ILotteryProps | {}
js
http.getActivityInfo({}).then(({ retdata={} }) => {
应该这样写,retdata的类型才是ILotteryProps
js
http.getActivityInfo({}).then(({ retdata }) => {
7.ts定义了对象类型之后,如何避免还要把对象的每个属性都初始化一次?
如果这样写, 会提示{}
缺少很多属性
ts
const activityInfo = ref<ILotteryProps>({});
这样写才是正确的姿势
ts
// 活动信息
const activityInfo = ref({} as ILotteryProps);
6. v-text/v-html 提示 will override element children的原因是什么?
是因为标签中还有其它内容, 即使是注释也不行。需要删除干净
错误写法:
html
<div v-html="content">
<!-- 里面有注释也会引起告警 -->
</div>
正确写法:
html
<!-- 里面有注释也会引起告警 -->
<div v-html="content">
</div>
5. rem在个别IOS机型上,展示效果不正常,如何解决?
rem的动态计算方法如下:
js
(function (doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
clientWidth > 750 && (clientWidth = 750),
clientWidth < 375 && (clientWidth = 375),
// if (!clientWidth) return;
(docEl.style.fontSize = 100 * (clientWidth / 750) * (window.devicePixelRatio || 1) + 'px');
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
rem单位在计算的时候,可能不是整数,如果一个元素尺寸是 0.625px,那么其染尺寸应该是 1px,空出的 0.375px 空间由其临近的元素填充;同样道理,如果一个元素尺寸是 0.375px,其渲染尺寸就应该是 0,但是其会占据临近元素 0.375px 的空间。这样就会造成用rem设置的宽度,前半部分长一些表现的效果就是部分文字被遮挡,最朴素的处理思路就是对个别误差表现明显的地方,给rem单位后面多加几位小数,参考此文。
4. 在企业微信中,打开H5自建应用,报证书不可信的错误,怎么解决?
有三种可能:
- 证书确实出了问题问题,比如说过期了,一般这种可能性比较小
- 当时那段时间网络不好,多刷新几次页面
- 三是之前访问时错误的页面也被缓存下来,而且通过刷新页面的情况缓存无用。需要深度清除缓存,错误的要通过高级功能==>通用==>存储空间的方式来清理,如果还不行,就用手机管理--清理加速功能来清理。
3. 评估工时总是心里没底,如何破解?
有这个困惑的人,不是不知道要开发的业务的详细流程步骤,不清楚具体要做哪些事情;就是不知道功能的实现方案,开发时间是多久。这就要求我们,除了花时间敲代码,也要抽出时间,熟悉业务流程,尤其是那些比较繁琐的业务流程。第二,要记录自己开发每项功能的开发用时,要完整的记录各个阶段的开发耗时,从需求理解,到UI实现,到编码开发,到联调测试,到提测,以及这个过程中对需求含糊不清,有遗漏的地方的沟通确认时间,对测试提的一些缺陷,感觉有分歧,有歧义的沟通时间,把这些时间加起来,就是开发一个业务功能的必要时间。
- 前端评估工时按照 页面开发(结构+表现)+页面交互(行为)+接口联调 三部分去评估
- 需求+技术实现方案明确 按必要工时*1去评估
- 需求不明确+技术实现方案明确 按必要工时*1.2去评估
- 需求明确+技术实现方案不明确 按必要工时*1.5去评估
- 需求+技术实现方案都不明确 按必要工时*2去评估
- 平时要记录自己的工作任务耗时, 需求细节沟通花费了多长时间+开发编码花费了多长时间+缺陷修复花费了多少时间(按正常情况统计,先不考虑意外情况比如说需求变更, UI设计稿太毛糙导致返工,后端主流程接口阻塞,开发过程中评审会议很多, 历史功能出现棘手的bug得优先处理等等)
2. 站点换肤方案,该如何选?
页面站点换肤,大体说来,有两种方案,一是给需要换肤的地方,添加一个换肤类; 二是通过定义css变量的方式,通过js代码修改换肤的css变量颜色。第一种是在多处要添加换肤样式判断逻辑,第二种是一次性设置到位,第二种效率更高,更易维护。
1. 如下的代码,会引发什么问题?
下面的代码,是实现一个下拉加载更多的功能。每次请求分页数据的过程中,会展示loading动画。这种实现方式会造成一个bug, 每次分页数据请求结束后,分页列表会滚动到列表第一条所在位置。而且这个问题还比较隐蔽。只有在部分机型上才有。究其原因,是因为loading展示设置不合理,不应该在loading动画结束后,重新渲染列表数据,应该改成要么在列表上方悬浮一个loading动画,要么在列表最下方展示loading动画。
html
<template>
<Loading v-if="isLoading" />
<--! 分页列表组件 -->
<ScrollList v-else />
</template>