Untitled
# 数据请求缓存实现方案
- 临时存储方案:定义全局变量(建议Map类型),用特定的方法函数去查看 更改 删除该变量,类似Vuex,Redux。后续可以添加一些边缘操作,如过期时间,加密等处理。缺点:当页面被刷新后所有的数据就会清空。
- 持久存储方案:不同上述中运存方案,页面刷新会被垃圾回收机制收回。把数据存于浏览器的Storage中(session Storage,local Storage,cookie)等位置用于持久存储。缺点:性能相对不好,读存说白了就是I/O操作,当数据量过大尤为明显。
- 中和方案:在运存和硬盘中哥存一份,当然你可以在页面执行销毁动作前再存入硬盘中,最好利用js运行机制使用异步方案存入。在读取的时候优先去运存中读取,保证速度,没有的时候再去硬盘中读取,保证质量。
# 请简述虚拟列表的实现原理
不太明白你所谓的虚拟列表具体指什么 vdom还是长列表中性能优化的虚拟列表
vdom: 在Vue 使用 Vue2中使用了三方库snabbdom.js实现模板解析为 render 函数,触发响应式,监听 data 属性 getter setter,执行 render 函数,生成 vnode , patch(elem, vnode),React中原理类似。
长列表虚拟:准确的说都不叫虚拟,叫模拟。在页面列表数据量过大,渲染dom过多时会引起页面卡顿等一些性能问题,特别是还有数据绑定的时间更为致命。对此可以对当前浏览器视口中显示的固定dom做计算渲染,看不见的部分可以结合数据量计算得出高度,固定高度使用块级元素填充整体高度。
# 请输出下述代码得打印结果:
class StateDemo extends React.Component {
state = { number: 0 };
handleClick = () => {
this.setState({ number: this.state.number + 1 }, () => {
console.log("callback1", this.state.number);
});
console.log(this.state.number);
this.setState({ number: this.state.number + 1 }, () => {
console.log("callback2", this.state.number);
});
console.log(this.state.number);
this.setState({ number: this.state.number + 1 }, () => {
console.log("callback3", this.state.number);
});
console.log(this.state.number);
};
render() {
return (
<div>
{this.state.number}
<button onClick={this.handleClick}>number++</button>
</div>
);
}
}
0
0
0
callback1 1
callback2 1
callback3 1
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
32
33
34
35
36
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
32
33
34
35
36
# 一个组件在本地开发过程中没问题,上线后显示错误,请分析下原因:
原因
- 代码在开发环境与生产环境有不一致的地方
- 打包依赖问题
- 线上环境问题,网络 依赖包下载 依赖包版本等等
解决方案
- 确定组件代码中是否引用使用环境变量
- 本地打包并运行排查
- 确定线上环境(网络,依赖包完整度等问题)
# 实现一个消息分发系统
# js 实现
class EventEmitter {
constructor() {
this._events = {};
}
on(event,callback) {
//监听 event 事件,触发时调用 callback 函数
let callbacks = this._events[event] || [];
callbacks.push(callback);
this._events[event] = callbacks;
return this;
}
off(event,callback) {
//停止监听 event 事件
let callbacks = this._events[event];
this._events[event] = callbacks && callbacks.filter(fn => fn !== callback);
return this;
}
emit(event, ...args) {
//触发事件,并把参数传给事件的处理函数
const callbacks = this._events[event];
callbacks.forEach(fn => fn.apply(null,args));
return this;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Vue2 实现, 用作mixins
使用
function broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
const name = child.$options.name;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
broadcast
.apply(child, [componentName, eventName]
.concat([params]));
}
});
}
export default {
methods: {
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root;
let name = parent.$options.name;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.name;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
}
}
};
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
32
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
32
# 如何设计一个通用的弹框类系统
大概思路:
定义弹窗类
- 样式,显隐动画
- 挂载元素(默认body元素上)
- 位置(默认元素正中):上下左右...
- 事件:
- 打开
- 关闭
- 拖动等其他
使用
- 可单独引用,使用实例化类
- 可挂在window对象,app实例原型上,用于全局使用
上次更新: 2022/08/14, 18:58:01