1.HTML语义化
- a. 为了在没有CSS的情况下,页面也能呈现出很好地内容结构、代码结构:为了裸奔时好看;
- b. 用户体验:例如title、alt用于解释名词或解释图片信息的标签尽量填写有含义的词语、label标签的活用;
- c. 有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
- d. 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以有意义的方式来渲染网页;
- e. 便于团队开发和维护,语义化更具可读性,遵循W3C标准的团队都遵循这个标准,可以减少差异化。
5. CSS3新特性
BFC介绍(block format context) 块级格式化上下文(内容)
- 页面中渲染一块独立区域,内部不会影响到外部。倘若没BFC区域,两个相邻的BOX若都有相对方向的margin距离,则只有较大距离的margin会生效
- 在上面的例子中我们可以看到,我们给第一个盒子设置下边距
30px,第二个盒子上边距设置20px,按照理论来说,这两个盒子的实际间距应该为 30+20 也就是50px,但事实上是这两个盒子的距离只有30px| 就是因为没有BFC触发导致外边距折叠。下面列出触发条件
触发条件:
- 浮动元素(
float除none以外的值)。 - 绝对定位元素(
position为absolute或fixed)。 overflow值不为visible的块级元素(如hidden、auto或scroll)。display属性为flow-root、inline-block、table-cell、table-caption、flex或grid。
2.export和export default的区别?
本质上是一样的
| export | export default | |
|---|---|---|
| 导入差异 | {}解构引入 | 直接引入 |
| 导出差异 | 可以导出多个 | 只可有一个 |
3.localstorage和sessionstorage和cookie区别?
- 同:都存在客户端
| 区别 | localStorage | sessionStorage | cookie |
|---|---|---|---|
| 生命周期是永久,不因浏览器关闭而关闭,除非主动删除。 | 仅存储在当前窗口中,就算是同一浏览器的不同窗口都是不一样的。关闭浏览器就销毁 | 只在有效期内有效。 | |
| 适用范围 | 同一域名 | 单一页面 | |
| 存储大小 | 5M | 5M | 4K |
6. 数组去重
const arr = [1,2,2,3,4,5,5,8]
let arr2 = arr.reduce((initArr,currentVal)=>{
// 若不存在初始化数组内 压入到初始化数组内
if(!initArr.includes(currentVal)) initArr.push(currentVal)
return initArr
},[])
// ↑为初始值,initArr为上一次调用回调返回的值,或者是提供的初始值(initialValue)
7. reduce函数
arr.reduce(callback,initVal)
callback (执行数组中每个值的函数,包含下方四个参数)
- 1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initVal))
- 2、currentValue (数组中当前被处理的元素)
- 3、index (当前元素在数组中的索引)
- 4、array (调用 reduce 的数组)
initVal (作为第一次调用 callback 的第一个参数。)
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
})
console.log(arr, sum);
node中对ES6模块化的支持
从node v13.2.0开始,node才对ES6模块化提供了支持: node v13.2.0之前,需要进行如下操作: 在package.json中添加属性: "type": "module"; 在执行命令中添加如下选项:node --experimental-modules src/index.js; node v13.2.0之后,只需要进行如下操作: 在package.json中添加属性: "type": "module";
- 在加了上述参数后,不支持require/module.export导入/出,仅支持import/export。
- 并且得把后缀'.js'加上。
express的post-control层收不到前端发来的body参数
- 困惑了一下午:>
- body-parse已被弃用,其相关方法已经融入到express中。但是其相关配置时机必须在路由挂载之前!,不然无效
//所以↓是没问题的,顺序才是关键
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// load router
router(app);
样式部分
介绍下盒子模型
-
html中的元素都可看作盒子,盒子由:margin+border+padding+content组成。
-
box-sizing属性,IE盒模型和标准盒模型(默认)↓表
| box-sizing: | border-box | border-box(default) |
|---|---|---|
| 宽度组成 | margin+(padding+border+content) | margin+padding+border+content |
| 若设总宽为200 | 内边+边框+内容区总大小为200 | 单内容区就200,边框+内边+内容200=总宽 |
属性种类与优先级 ↓排列权重
- !important
- 内联行内样式
- id
- 并列(class类选择器、[title]属性、伪类:hover)
- 元素选择器:div{...}
- 通配/全局选择器:*{...}
- 继承选择器
PX和REM..单位的区别
- px是绝对概念,是显示器显示的像素。
- rem是相对概念,相对html根节点上的font-size大小
- vw/vh是相对概念,相对与屏幕宽度/高度
- vmin/vmax同上,适用于需要适配横屏的场景(vmin取值:原先的vw竖屏宽度->横屏时的vh高度,取较小值)
vue部分
vue2和vue3的区别?
- vue2的数据绑定使用的是Object.defineProperty来劫持属性 | vue3使用proxy属性
- vue3使用ts重构,对ts支持更友好
- vue2只能有一个根节点,vue3可以有多个
- 生命周期不同,befCreate/create == setup
- 3用组合式API
| VUE2 | VUE3 | |
|---|---|---|
| 数据绑定 | Object.defineProperty来劫持属性 | proxy属性 |
| TS支持 | 因为用TS重写,所以支持较好 | |
| API | 组合式API | 声明式API |
| 数据定义 | 在data中定义 | 用ref/reactive定义 |
| 生命周期 | befCreate/create => | setup |
| 根节点 | 只能有一个根节点 | 可有多个 |
| ... |
$nextTick()是?
1.用于获取DOM更新后的状态
8. 简述vuex
- VUEX是什么?是vue的状态管理工具
| state | VUEX的仓库,存放响应式数据。若数据改变,对应的组件中数据会响应式改变 | mapState |
|---|---|---|
| action | action通过dispatch被异步调用,再通过commit方法同步调用mutation中定义的的方法来改变state的数据,不可直接改变state的数据 | mapActions(用的少) |
| mutation | 响应式更改state中数据的唯一方法,是同步的 | mapMutations |
| modules | 将vuex模块化 | |
| getter | store的计算属性 | mapGetters |
9. watch和computed区别
| 区别 | watch | computed |
|---|---|---|
| 使用 | 监听data中的值、路由。 | 计算属性,只要当函数定义的内部数据发生变化,即会触发函数。函数返回的值便是函数接收处的新值。 |
| 缓存 | 无 | 有,被dom调用多次也只会执行一次 |
| 使用场景 | 如果需要在某个数据变化时做一些事情,使用watch来观察这个数据变化 | 如果一个数据依赖于其他数据的简易计算处理的,那么使用computed比较合适 |
路由模式的区别?
-hash: 带个#警号;兼容性好到IE8
-history: 兼容到IE10 ....
vue3部分
ref和reactive区别?
都需要按需引用
| ref | reactive | |
|---|---|---|
| 本质 | ref是reactive的升级版 | 都是处理响应式数据的 |
| 使用 | 用于简单变量 | 对象/表单数据 |
| 调用 | 需要.value或用$语法糖 | 直接改变数据 |
纯JS部分
变量提升
- 先理解暂存性死区Temporal Dead Zone,虽然被变量提升了,但在被赋值之前仍是一个自闭的变量。(可理解为仍是未初始化状态)
- let const var class都能得到变量提升!,但是只有var会被附上初始值undefined (JavaScript在编译阶段会找到
var关键字声明的变量会添加到词法环境中,并初始化一个值undefined,在之后执行代码到赋值语句时,会把值赋值到这个变量) - 匿名函数不会提升
console.log(x)
let x // 进入暂存死区,未初始化
=> Uncaught ReferenceError: x is not defined
console.log(ss)
var ss // 初始化成undefined
=> undefined
let const 异同
同
- 不可重复声明
- 都有提升,但会进暂存死区
异
- const定义的是常量,不可修改,但若定义的是object,对象内数据可以修改
==和===比较
开发中可开启/关闭eslint, 强制/放开规范。
| == | === |
|---|---|
| 非严格相等 | 严格相等 |
| 比较值相同即可 | 比较两边数据类型和值大小,值和引用地址都等才行 |
forEach/map比较
- 异
| forEach | map |
|---|---|
| 没返回值,改原数组 | 带上return能返回处理后的数据,没return返回undefined |
- 同
| forEach | map |
|---|---|
| 三个入参,item/index/原数组 | |
| 都遍历数组每一项 | |
| 不能直接遍历对象,要遍历对象先处理{Object.keys(obj).map...} |
开发中解决跨域
只记录用过的,过时的不用!
- 前端
- 开发中proxy配置代理
- 生产中在nginx配反向代理
- node后端
- 配置域名白名单
- 直接摆烂,配*通配符,放开跨域
为什么有跨域?
因为同源策略
什么是同源策略?
协议//域名:端口 皆一样才叫同源
JS数据类型
7大基本数据类型
- 加深印象:onb sun: obj num boolean string undefined null
| 基本类型 | |
|---|---|
| Boolean | 布尔型 |
| String | 字符串 |
| Null | 空指针->空变量 |
| Undefined | 变量未初始化->空对象 |
| Number | 数字(包含NaN) |
| Object | 复合数据类型 |
| Symbol * | 每个Symbol()返回的值都是唯一的,不可new Symbol( ) |
5大引用类型
| 引用类型 | |
|---|---|
| Object | (包含Date、function、Array) |
| Array | 数组 |
| Date | 日期 |
| Function | 函数 |
| RegExp | 正则式 |
| Set | ES6新定义,只能存唯一值的数组 |
基本/引用类型区别?
| 类型 | 基本类型 | 引用类型 |
|---|---|---|
| 存储 | 栈存储 | 堆存储,存储在变量内的是一个指针,指向存储对象内存地址 |
| 存储原理 | 开辟新栈 | 开辟新内存地址 |
复制变量时的区别?var a=b
- 所有基本类型操作都是赋上原值的副本,a=b后,b只是与a值相同,其他部分完全独立。
- 所有引用类型的复制变量都是,将a的内存地址赋值给b,复制后b与a指向同一个内存地址,改b等于在改a
数据类型判断
- typeof只可判断基本数据类型 如:undefined、Object、Number、String、Symbol、function、Boolean。但null、object、Array、Date都判断为Object。
- instanceof只可判断复合/引用数据类型
- Array.isArray([123])用于判断数组
- 无敌判断 Object.prototype.String.call(v)
// 1.判断数据类型
var typelist = [{}, 123, 'ssdw', false, null, undefined, [], function () { }, new Date()]
// Date、null、array都不能正常判断
console.log('-------typeof判断--------------')
typelist.map(v => {
// 普通判断 typeof
console.log(typeof (v), v)
})
console.log('-------------------------------')
console.log('-------无敌判断--------------')
typelist.map(v => {
// 普通判断 typeof
let res = Object.prototype.toString.call(v) // => [object,Array]
res = res.slice(8, -1) // 从 [到,正好8位,再算到-1结束 正好是 Array
console.log(res, v)
})
console.log('-------------------------------')
ES6新特性?
- async/await
- promise
- let/const
- Class
- 解构赋值
- 数据类型:map/set/symbol
- 箭头函数
- 模板字符串
哈哈${data} 你好
加强记忆
class Enchance extend PureComponent{
async foo()=>{
let b = `哈哈${data}你好`
await const bar = {...b}
}
}
解构赋值
// 解构对象重命名
let { f1: rename, f2 } = { f1: 'test1', f2: 'test2' }
console.log(rename, f2) <em>// test1, test2</em>
内存泄漏
- 定义:程序已分配的堆内存由于某种原因导致未释放或无法释放引发的问题,可能带来:崩溃、变慢
- 可造成的原因:
- 无用定时器未清除
- 无意中定义的全局变量
- ...
深浅拷贝
赋值分三种,①普通赋值/②深拷贝/③浅拷贝。
①普通赋值
let a = 1
let b = a
②深拷贝
- 常见的深拷贝有JSON.stringfiy/JSON.parse
- 但👆方法原理是将对象先stringify转为字符串,再转为对象。若遇到function,则会使拷贝后的函数失效
const a = [1,2,[33,44]]
const b = JSON.parse(JSON.stringify(a))
/*简单拷贝👆*/
/*递归深拷贝👇*/
function deepClone(source, hash = new WeakMap()) {
if (typeof source !== 'object' || source === null) {
return source;
}
if (hash.has(source)) {
return hash.get(source);
}
const target = Array.isArray(source) ? [] : {};
Reflect.ownKeys(source).forEach(key => {
const val = source[key];
if (typeof val === 'object' && val != null) {
target[key] = deepClone(val, hash);
} else {
target[key] = val;
}
})
return target;
}
补充
- Object.keys()返回属性key,但不包括不可枚举的属性
- Reflect.ownKeys()返回所有属性key
// 上面的DEEPCLONE用到的Reflect.ownKeys()方法和Object.key()差不多,
// 前者可以返回其所有属性,包括length/defineProperty等,
// 在deepclone前者肯定比后者更准确
var obj = {
a: 1,
b: 2
}
Object.defineProperty(obj, 'met1hod', {
value: function () {
alert("GTR")
},
enumerable: false
})
console.log(Object.keys(obj))
// ["a", "b"]
console.log(Reflect.ownKeys(obj))
// ["a", "b", "met1hod"]
③浅拷贝
- 只拷贝内存地址,改b会影响a的原址的原值,遇到引用数据类型就寄
let a = [1,2] / {cs:'go',pu:'bg'}
let b = a
性能优化
资源
- 压缩图片(精灵图,熊猫压缩)
- 压缩代码(Gzip)
- 本地或CDN的第三方资源,依赖(选择.min版本)
- 视情况将资源放靠谱的CDN服务器上(如字节,避雷bootcdn^^)
代码
- 减少DOM操作
- 按需利用防抖和节流
- *服务端渲染(SSR)和预渲染(Prerender)美文
加载
- 减少网络请求
- 路由/图片懒加载
component: () => import('@/components/HelloWorld') - 项目到了后期页面数量庞大可以按需加载路
- 小程序路由页面分包
- 使用组件懒加载在不可见时只需要渲染一个骨架屏,不需要真正渲染组件
- 按需加载依赖中的组件