2024-06-03
经纬恒润-演示


演示

JSON-TO-PAGE 介绍

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
// type 标记了 这是一个列表页面
// runOnSaveId 对应这个页面的ID,代表使用该组件时的pageId。
// 页面json配置 通过配置对应flowId 去执行某些接口操作,
// config去配置一些表格相关的配置
// handleBtns 配置了每条数据,后面操作列对应按钮的操作逻辑和显隐控制等信息。
// formConfig 配置了该页面的筛选区域的配置。
{
"runOnSaveId": 218,
"name": "材料管理_管理",
"updateTime": "2024-05-28 15:53:12",
"id": 218,
"type": "table",
"flows": {
"getTableData": {
"flowId": 219
}
},
"handleBtns": [
{
"handleType": "openDialogPage",
"params": {
"pageId": 222,
"dialogProps": {
"dialogType": "updateFormData",
"height": "400px",
"width": "580px",
"title": "选择新的协作者",
"initFormData": {
"companyId": "{{targetId}}",
"companyName": "{{companyName}}"
}
}
},
"successTip": {
"content": "更换成功"
},
"btn": {
"color": "blue",
"size": "small",
"elevation": "0",
"density": "comfortable",
"label": "更换协作者"
},
"runFlowId": "223"
},
{
"handleType": "openFullDialogPage",
"params": {
"pageId": 236,
"dialogProps": {
"dialogType": "updateFormData",
"showFooter": false,
"width": "100%",
"theme": "myCustomLightTheme",
"title": "查看审批材料表数据",
"params": {
"id": "{{id}}"
}
}
},
"btn": {
"color": "blue",
"size": "small",
"elevation": "0",
"density": "comfortable",
"label": "查看审批"
},
"runFlowId": "231",
"runCancelFlowId": "232"
}
],
"config": {
"returnDataKey": "data.rows",
"returnTotalKey": "data.count",
"columns": [
{
"field": "title",
"title": "数据表名称"
},
{
"field": "brandName",
"title": "品牌"
},
{
"field": "companyName",
"title": "公司名称"
},
{
"field": "fitTypeStr",
"title": "类型"
},
{
"field": "user_name",
"title": "协作者"
},
{
"width": "80px",
"field": "status",
"title": "状态",
"fixed": "right",
"params": {
"renderProps": {
"size": "x-small",
"variant": "elevated",
"elevation": 0,
"rounded": "4px"
},
"renderOptions": [
{
"title": "未发起",
"value": -1,
"props": {
"color": "#58637D33",
"style": "color: #58637D"
}
},
{
"title": "审批中",
"value": 1,
"props": {
"color": "#3175FB33",
"style": "color: #3175FB"
}
},
{
"title": "通过",
"value": 2,
"props": {
"color": "#83C44733",
"style": "color: #83C447"
}
},
{
"title": "不通过",
"value": 3,
"props": {
"color": "#FF5B5833",
"style": "color: #FF5B58"
}
},
{
"title": "已撤回",
"value": 4,
"props": {
"color": "#58637D33",
"style": "color: #58637D"
}
}
]
},
"slots": {
"default": "tag"
}
},
{
"width": "220px",
"title": "操作",
"fixed": "right",
"slots": {
"default": "handleBtn"
}
}
],
"toolbarConfig": {
"buttons": [
{
"code": "uploadDatas",
"name": "添加材料表",
"handleType": "openDialogPage",
"status": "primary",
"runFlowId": 212,
"successTip": {
"content": "生成成功"
},
"pageId": 215,
"dialogProps": {
"width": "580px",
"height": "600px",
"dialogType": "getFormData",
"theme": "dark",
"title": "录入材料表信息"
}
}
],
"refresh": true,
"export": true,
"custom": true
},
"baseConfig": {
"border": true,
"showHeaderOverflow": true,
"showOverflow": "true",
"keepSource": true,
"id": "TEST_TABLE",
"height": "auto",
"rowConfig": {
"keyField": "id",
"isHover": true
},
"columnConfig": {
"resizable": true
},
"editConfig": {
"trigger": "click",
"mode": "cell"
}
},
"pagerConfig": {
"pageSize": 100,
"pageSizes": [
30,
50,
100
]
},
"formConfig": {
"titleWidth": 60,
"titleAlign": "left",
"items": [
{
"field": "brand_name",
"title": "品牌",
"titleWidth": "85px",
"span": 8,
"itemRender": {
"name": "$input",
"props": {
"placeholder": "请输入品牌"
}
}
},
{
"field": "fitType",
"title": "类型",
"titleWidth": "85px",
"span": 8,
"itemRender": {
"name": "$select",
"props": {
"placeholder": "请选择类型",
"clearable": true,
"transfer": false,
"options": [
{
"label": "主材",
"value": 1
},
{
"label": "基材",
"value": 2
}
]
}
}
},
{
"field": "user_name",
"title": "协作者",
"titleWidth": "85px",
"span": 8,
"itemRender": {
"name": "$input",
"props": {
"placeholder": "请输入协作者姓名"
}
}
},

{
"field": "companyId",
"title": "公司",
"span": 8,
"itemRender": {
"name": "$select",
"props": {
"placeholder": "请选择公司",
"transfer": false,
"clearable": true,
"option-props": {
"value": "value",
"label": "title"
},
"flowId": 216
}
}
},
{
"span": 24,
"align": "center",
"itemRender": {
"name": "$buttons",
"children": [
{
"props": {
"type": "submit",
"content": "筛选",
"status": "primary"
}
},
{
"props": {
"type": "reset",
"content": "重置",
"status": "primary"
}
}
]
}
}
]
}
}
}

列表页面

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// type 表示了这是一个form组组件,在使用的时候去通过定义 pageId: 215,调用这个form组件。
{
"runOnSaveId": 215,
"name": "选择材料信息",
"updateTime": "2024-03-14 16:27:23",
"id": 215,
"type": "form",
"config": {
"formConfig": {
"style": {
"padding": "20px"
},
"itemStyle": {
"margin-bottom": "8px"
},
"textProps": {
"clearable": true
}
},
"formItems": [
{
"key": "companyId",
"value": "",
"requestFlowId": "216",
"watched": true,
"type": "select",
"handleChange": "initItemOptions",
"handleChangeParams": {
"initKeys": [
"brandId",
"user"
]
},
"rules": [
{
"type": "required",
"name": "公司"
}
],
"props": {
"label": "公司",
"variant": "solo-filled"
}
},
{
"key": "user",
"type": "autocomplete",
"requestFlowId": "241",
"requestParams": {
"companyId": "{{companyId}}"
},
"watched": true,
"rules": [
{
"type": "required",
"name": "员工手机号"
}
],
"props": {
"label": "员工手机号",
"placeholder": "选择材料专员飞书所绑定的手机号",
"variant": "solo-filled"
}
},
{
"key": "materialType",
"value": "",
"type": "select",
"watched": true,
"rules": [
{
"type": "required",
"name": "类型"
}
],
"props": {
"label": "类型",
"variant": "solo-filled",
"items": [
{
"title": "主材",
"value": 1
},
{
"title": "基材",
"value": 2
}
]
}
},
{
"key": "brandId",
"value": "",
"type": "autocomplete",
"requestFlowId": "217",
"requestParams": {
"companyId": "{{companyId}}"
},
"watched": true,
"rules": [
{
"type": "required",
"name": "品牌ID"
}
],
"props": {
"label": "品牌",
"variant": "solo-filled"
}
}
]
}
}

弹窗组件

Read More

2023-07-24
快手本地生活前端一面


面试时间 2023年7月20日16点

1. TCP协议为什么是三次握手,四次挥手,为什么断开时会多一次?

因为一个连接建立之前,并不需要考虑其他因素,但是在连接断开之前,客户端和服务端可能还存在其他通信操作,所以就需要多一次连接用来通知双方取消其他通信操作。

2. VUE&SSR 原理,在注水时框架做了什么操作,对比CSR有什么缺点?

Vue框架在浏览器注水时,会根据服务端返回的HTML文本对应生成VNode(虚拟DOM),并且将HTML文本中的静态State等数据初始化在VNode中作为初始化状态数据,以及绑定事件等操作。

3. HTTP协议在每个版本都改进了什么?
http各版本的改进都是什么?

4. WebPack&Vue组件在编译过程是什么样的,Vue3比Vue2做了哪些优化?
编译图示


  1. 将模板进行词法分析,转化为对应的ast树(JS描述对象,与虚拟DOM原理差不多)。

  2. 转换流程transform,对动态节点做一些标记

    • 标记动态节点(Block):指令、事件、插槽、动态属性、模板语法等,渲染时进行动态节点比对即可(靶向更新)。
    • 标记节点动态类型(patchFlag),后续更新时只更新该部分即可,减少比对内容(如文本、class)。
  3. 生成代码codegen – 虚拟dom

  4. 经过render方法将该虚拟dom挂载到宿主元素上

  5. render时直接比对动态节点。


Vue3源码-运行时编译模板&优化总结
Vue3模板编译优化

5. 笔试题
笔试内容

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
37
38
39
40
41
42
43
44
45
46
class Lottery {
users: string[] = []
count: number
constructor(users: string[], count: number) {
users.sort(() => Math.random() > .5 ? 1 : -1)
this.users = users
this.count = count
}

getRadomIndex() {
return Math.floor(Math.random() * (this.users.length + 1))
}

timer: any = null
goUsers: string[] = []
go() {
const startIndex = this.getRadomIndex()
this.timer = setTimeout(() => {
this.goUsers.push(this.users[startIndex])
this.timer && clearTimeout(this.timer)
this.timer = null
this.go()
}, 100)
}

clearTimeout() {
if (this.timer) {
clearTimeout(this.timer)
this.timer = null
}
}

getRes() {
return this.goUsers[this.goUsers.length - 1]
}

runTime = 0
start() {
this.runTime++
this.go()
}

stop() {
return this.runTime <= this.count ? this.getRes() : null
}
}
Read More