面试指南
发表于
|
分类于
HTML、CSS、JS
面试指南
HTML
html5语义化
- 为什么需要语义化
- 易修改、易维护
- 无障碍阅读支持
- 搜索引擎友好,利于 SEO
- 面向未来的 HTML,浏览器在未来可能提供更丰富的支持
- 结构语义化
- 语义元素均有一个共同特点——他们均不做任何事情。换句话说,语义元素仅仅是页面结构的规范化,并不会对内容有本质的影响
- eg:
- 标准盒模型与低版本IE盒模型
- 标准盒模型 宽度 = 内容的宽度(content)+ border+ padding + margin
- 低版本IE盒模型 宽度 = 内容的宽度(content+ border+ padding)+ margin
- box-sizing属性
- 用来控制元素的盒子模型的解析模式,默认为content-box
- context-box:W3C的标准盒子模型,设置元素的 height/width 属性指的是content部分的高/宽
- border-box:IE传统盒子模型。设置元素的height/width属性指的是border + padding + content部分的高/宽
- CSS选择器有哪些?哪些属性可以继承?
- CSS选择符:id选择器(#myid)、类选择器(.myclassname)、标签选择器(div, h1, p)、相邻选择器(h1 + p)、子选择器(ul > li)、后代选择器(li a)、通配符选择器(*)、属性选择器(a[rel=”external”])、伪类选择器(a:hover, li:nth-child)
- 可继承的属性:font-size, font-family, color
- 不可继承的样式:border, padding, margin, width, height
- 优先级(就近原则):!important > [ id > class > tag ]
- !important 比内联优先级高
CSS优先级算法如何计算?
- 元素选择符: 1
- class选择符: 10
- id选择符:100
- 元素标签:1000
- !important声明的样式优先级最高,如果冲突再进行计算
- 如果优先级相同,则选择最后出现的样式
- 继承得到的样式的优先级最低
CSS3新增伪类有那些?
- p:first-of-type 选择属于其父元素的首个元素
- p:last-of-type 选择属于其父元素的最后元素
- p:only-of-type 选择属于其父元素唯一的元素
- p:only-child 选择属于其父元素的唯一子元素
- p:nth-child(2) 选择属于其父元素的第二个子元素
- :enabled :disabled 表单控件的禁用状态
- :checked 单选框或复选框被选中
如何居中div?如何居中一个浮动元素?如何让绝对定位的div居中?(更优方法flexbox)
1
2
3
4border: 1px solid red;
margin: 0 auto;
height: 50px;
width: 80px;
1 | border: 1px solid red; |
1 | border: 1px solid black; |
display有哪些值?说明他们的作用?
- inline(默认)–内联
- none–隐藏
- block–块显示
- table–表格显示
- list-item–项目列表
- inline-block
- flex grid
position的值?
- static(默认):按照正常文档流进行排列;
- relative(相对定位):不脱离文档流,参考自身静态位置通过 top, bottom, left, right 定位;
- absolute(绝对定位):参考距其最近一个不为static的父级元素通过top, bottom, left, right 定位;
- fixed(固定定位):所固定的参照对像是可视窗口。
more…
JS
js常见面试题
浅拷贝和深拷贝的区别
浅拷贝:一般指的是把对象的第一层拷贝到一个新对象上去,比如
1
2
3
4let a = { count: 1, deep: { count: 2 } };
let b = Object.assign({}, a);
// 或者
let b = {...a};深拷贝:一般需要借助递归实现,如果对象的值还是个对象,要进一步的深入拷贝,完全替换掉每一个复杂类型的引用。
1
2
3
4
5
6
7
8let deepCopy = (obj) => {
let ret = {};
for (let key in obj) {
let value = obj[key];
ret[key] = typeof value === 'object' ? deepCopy(value) : value;
}
return ret;
}
每日面试题
发表于
每日面试题
输出以下代码运行结果,为什么?如果希望每隔 1s 输出一个结果,应该如何改造?注意不可改动 square 方法
1 | const list = [1, 2, 3] |
- forEach是不能阻塞的,默认是请求并行发起,所以是同时输出1、4、9
- 解决方案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32async function test() {
for (let i = 0; i < list.length; i++) {
let x = list[i]
const res = await square(x)
console.log(res)
}
}
async function test() {
for (let x of list) {
const res = await square(x)
console.log(res)
}
}
## axios 源码里所用到的,利用 promise 本身的链式调用来实现串行
let promise = Promise.resolve()
function test(i = 0) {
if (i === list.length) return
promise = promise.then(() => square(list[i])).then((res) => {
console.log(res);
})
test(i + 1)
}
## 利用promise的链式调用
function test() {
let promise = Promise.resolve()
list.forEach(x => {
promise = promise.then(() => square(x)).then((res) => {
console.log(res)
})
})
}
标记的模板字符串
- 第一个参数包含所有的静态字符串,以表达式变量进行分割成数组(类似split(‘$’)的效果);然后逐一解析变量表达式,传到对应的参数第二个参数、第三个参数
- 拓展:参数传递的对象和我们用于检查相等性的对象在内存中位于不同位置,所以它们的引用是不同的。
1
2
3
4
5
6
7
8
9
10function getPersonInfo(one, two, three) {
console.log(one);
console.log(two);
console.log(three);
}
const person = "Lydia";
const age = 21;
getPersonInfo`${person} is ${age} years old`;
* ["", "is", "years old"] Lydia 21
* 第一个参数'${person} is ${age} years old'.split('$') =》 ["", "{person} is ", "{age} years old"]
eval
- eval会为字符串传递的代码求值。 如果它是一个表达式,它会计算表达式
1
const sum = eval("10*10+5"); // 105
对象键
- 所有对象键(不包括Symbols)都会被存储为字符串,即使你没有给定字符串类型的键
- 拓展
- 如果对象有两个具有相同名称的键,则将替换前面的键。它仍将处于最开始的位置,但具有最后指定的值。
- JavaScript全局执行上下文为你创建了两个东西:全局对象和this关键字.
- 基本执行上下文是全局执行上下文:它是代码中随处可访问的内容。
- 对象键自动转换为字符串,它变成了[object Object]
- JavaScript只有原始类型和对象,原始类型是boolean,null,undefined,bigint,number,string和symbol。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);
obj.hasOwnProperty("1"); // true
obj.hasOwnProperty(1); // true
set.has("1"); // false
set.has(1); // true
const obj = { a: "one", b: "two", a: "three" };
console.log(obj); // { a: "three", b: "two" }
const a = {};
const b = { key: "b" };
const c = { key: "c" };
a[b] = 123;
a[c] = 456;
console.log(a[b]); // 456
continue 声明终止当前循环或标记循环的当前迭代中的语句执行,并在下一次迭代时继续执行循环
1 | let text = ''; |
JavaScript 精简技巧
发表于
|
分类于
JS
JavaScript 精简技巧
快速浮点数转整数
- 将浮点数转换为整数,可以使用Math.floor()、Math.ceil()或Math.round()。但是还有一种更快的方法可以使用|(位或运算符)将浮点数截断为整数。
1
console.log(23.2 | 0); // Result: 23
JavaScript 浮点数陷阱及解法
- 数据展示类 如:1.4000000000000001 取整
1
2
3
4
5
6parseFloat(1.4000000000000001.toPrecision(12)) === 1.4 // true
<!-- 简单封装 -->
function strip(num, precision = 12) {
return +parseFloat(num.toPrecision(precision));
}
<!-- 为什么选择 12 做为默认精度?这是一个经验的选择,一般选12就能解决掉大部分0001和0009问题,而且大部分情况下也够用了,如果你需要更精确可以调高 -->
数据运算类
- 对于运算类操作,如 +-*/,就不能使用 toPrecision 了。正确的做法是把小数转成整数后再运算
1
2
3
4
5
6
7
8
9
10/**
* 精确加法
*/
function add(num1, num2) {
const num1Digits = (num1.toString().split('.')[1] || '').length;
const num2Digits = (num2.toString().split('.')[1] || '').length;
const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
return (num1 * baseNum + num2 * baseNum) / baseNum;
}
add(0.1, 0.2); // 0.3
Switch 简记法
1 | // 长 |
css特效
发表于
|
分类于
CSS
CSS特效
search 搜索
1 | <input class="search" type="text" placeholder="搜索..."> |
若隐若现,鼠标放上显示
1 | .banner{ |
博客可用效果1
1 | .banner{ |
博客可用效果2
1 | .wrapper { |
hover效果
小程序数据过滤的实现
发表于
|
分类于
微信小程序
场景应用
- 微信小程序的wxml和js的内部实现机制是分开编译的,在wxml是没办法调用js的函数的。导致WXML缺少一个我们常用的功能,没有办法在视图层对数据进行格式化处理。
- 比如我们从后端获取到一个包含了时间戳数据的数组,需要在界面上把这些日期都格式化显示为2017-01-01这种格式的日期形式,在Vue, Angular之类的前端Web框架中,一般在视图层都提供了如filter之类相应比较好用的方案。微信小程序推出了wxs类型文件解决这类问题的
实现方式
新建filter.wxs文件(一般作为公共方法存在)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var formatDate = function (timestamp, option) {
var date = getDate(parseInt(timestamp));
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
if (option == 'notime') { //不需要时间
return [year, month, day].map(formatNumber).join('-');
}
return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':');
}
var formatNumber = function(n) {
n = n.toString();
return n[1] ? n : '0' + n;
}
module.exports = {
formatDate: formatDate,
}在wxml文件中使用
1
2
3<wxs src='../../utils/filter.wxs' module='filter' />
<view>日期:{{filter.formatDate('1599013002483')}}</view>
<view>日期:{{filter.formatDate('1599013002483', 'notime')}}</view>
在.wxs模块中引用其他 wxs 文件模块,可以使用 require 函数
- 引用的时候,要注意如下几点:
- 只能引用 .wxs 文件模块,且必须使用相对路径。
- wxs 模块均为单例,wxs 模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs 模块对象。
- 如果一个 wxs 模块在定义之后,一直没有被引用,则该模块不会被解析与运行
- 了解更多,参照小程序官方文档(wxs是不同于js文件的。所以很多js的api是不支持的)
微信小程序兼容性
发表于
|
分类于
微信小程序
IOS常见兼容性
iOS中input的placeholder属性字体不居中
- 对placeholder设置line-height及font-size
- 对input设置高度
iOS中滚动卡顿
- 设置-webkit-overflow-scrolling:touch
1
-webkit-overflow-scrolling: touch
iOS中new Date() 时间格式不兼容
- 在实现倒计时,根据后台返回的时间格式转换时,后台返回了时间格式为”2018-11-12 11:12:11”,然后利用new Date() 转换时,ios中无法展示,安卓中显示正常
1
2
3
4
5
6
7
8
9
10
11
12
13let time = '2018-12-10 11:11:11';
let formateTIme = new Date(time);
this.setData({
formateTIme
})
/* 利用正则表达式替换时间中的”-”为”/”即可 */
let time = '2018-12-10 11:11:11';
let temporaryTime = new Date(time.replace(/-/g,'/'));
let temporaryTime1 = new Date(time);
this.setData({
timeRemain: temporaryTime,
timeRemain1: temporaryTime1,
})
scroll-view隐藏滚动条方法
1 | ::-webkit-scrollbar{ |
图片本地资源名称,尽量使用小写命名
在解决iPhone X适配时,底部多余部分使用图片时
1
<image class='iphonexImg' src="/imgs/iphoneBGT.png" mode="aspectFill" />
路径是 src=’imgs/iphoneBGT.png’(发现在pc IDE上面可以显示出来,但是真机调试时,图片找不到),将图片名称改为iphonex.png真机调试就可以了
1
<image class='iphonexImg' src="/imgs/iphonex.png" mode="aspectFill" />
微信小程序限制转发
发表于
|
分类于
微信小程序
义务场景
- 用户希望某个页面只能自己转发分享,不希望被别人再次分享出去
限制用户转发需要解决两个问题:
- 关闭系统右上角菜单栏中的转发功能
- 调用微信 API:wx.hideShareMenu({ }) 关闭当前页面转发功能。
隐藏群聊会话中长按转发分享的功能
- 设置 withShareTicket 参数为 true ,即带有参数的转发卡片,即分享到群聊的小程序卡片,长按就不再有转发功能了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14onShareAppMessage() {
return {
title: '分享标题',
path: '分享路径(/pages/index/index)',
imageUrl: '分享图片',
success: () => {
wx.showShareMenu({
withShareTicket: true
})
},
fail: () => {},
complete: () => {}
}
},
- 设置 withShareTicket 参数为 true ,即带有参数的转发卡片,即分享到群聊的小程序卡片,长按就不再有转发功能了。
只适用于分享到群聊,如果分享给个人用户,个人用户依然是可以通过长按小程序卡片来转发的,这就需要我们再做进一步检测,检测用户进入小程序的场景
- 用户从带 shareTicet 的小程序消息卡片打开小程序,进入场景值为 1044 ,可以通过判断场景值来判断用户是否通过群聊卡片打开
1
2
3
4// 检测用户进入小程序的场景值
if (options.scene == 1044) {
return;
}
css常见功能代码
发表于
|
分类于
CSS
CSS3 animation实现点点点loading动画
1 | @supports (display:none) { |
按钮加一个类名自动变菊花loading状态无图片版
1 | /* 按钮loading */ |
CSS经典布局
发表于
|
分类于
CSS
CSS经典布局
空间居中对齐
- 空间居中布局指的是,不管容器的大小,项目总是占据中心点。
1
2
3
4
5
6.container {
display: grid;
place-items: center/end/start;
}
/* place-items: <align-items> <justify-items>; */
并列式布局
并列式布局就是多个项目并列。如果宽度不够,放不下的项目就自动折行。
1
2
3
4
5
6
7
8
9.container {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.item{
flex: 0 1 150px;
margin: 5px;
}flex属性是flex-grow、flex-shrink、flex-basis这三个属性的简写形式。
- flex:
; - flex-basis:项目的初始宽度。
- flex-grow:指定如果有多余宽度,项目是否可以扩大。
- flex-shrink:指定如果宽度不足,项目是否可以缩小。
- flex: 0 1 150px;的意思就是,项目的初始宽度是150px,且不可以扩大,但是当容器宽度不足150px时,项目可以缩小。
- 如果写成flex: 1 1 150px;,就表示项目始终会占满所有宽度
两栏式布局
- 两栏式布局就是一个边栏,一个主栏。
- 边栏始终存在,主栏根据设备宽度,变宽或者变窄。如果希望主栏自动换到下一行,可以参考上面的”并列式布局”。
1
2
3
4
5.container {
display: grid;
grid-template-columns: minmax(150px, 25%) 1fr;
}
/* grid-template-columns指定页面分成两列。第一列的宽度是minmax(150px, 25%),即最小宽度为150px,最大宽度为总宽度的25%;第二列为1fr,即所有剩余宽度。 */
三明治布局
- 三明治布局指的是,页面在垂直方向上,分成三部分:页眉、内容区、页脚。
- 这个布局会根据设备宽度,自动适应,并且不管内容区有多少内容,页脚始终在容器底部(粘性页脚)。也就是说,这个布局总是会占满整个页面高度。
1
2
3
4
5.container {
display: grid;
grid-template-rows: auto 1fr auto;
}
/* 指定采用 Grid 布局。核心代码是grid-template-rows那一行,指定垂直高度怎么划分,这里是从上到下分成三部分。第一部分(页眉)和第三部分(页脚)的高度都为auto,即本来的内容高度;第二部分(内容区)的高度为1fr,即剩余的所有高度,这可以保证页脚始终在容器的底部。 */