Skip to content

Commit 53440e7

Browse files
committed
update: 45-49题
1 parent 24717cf commit 53440e7

File tree

8 files changed

+301
-0
lines changed

8 files changed

+301
-0
lines changed

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@
5454
42. [Vue实例挂载的过程中发生了什么?](public/42-instance-mount/README.md)
5555
43. [vue-loader是什么?它有什么作用?](public/43-vue-loader/README.md)
5656
44. [如何获取动态路由并获取其参数?](public/44-dynamic-route/README.md)
57+
45. [如果让你从零开始写一个vuex,说说你的思路](public/45-vuex-design/README.md)
58+
46. [vuex中actions和mutations有什么区别?](public/46-mutations-actions/README.md)
59+
47. [使用vue渲染大量数据时应该怎么优化?说下你的思路!](public/47-big-data-performance/README.md)
60+
48. [怎么监听vuex数据的变化?](public/48-watch-vuex-state/README.md)
61+
49. [router-link和router-view是如何起作用的?](public/49-router-link-router-view/README.md)
5762

5863
### 欢迎把你想听的题目以issue的方式提给我
5964
### 欢迎你加入村长的项目已pr形式提交题目和解答

public/45-vuex-design/README.md

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
## 如果让你从零开始写一个vuex,说说你的思路
2+
3+
### 思路分析
4+
5+
这个题目很有难度,首先思考`vuex`解决的问题:存储用户全局状态并提供管理状态API。
6+
7+
- `vuex`需求分析
8+
- 如何实现这些需求
9+
10+
11+
---
12+
13+
### 回答范例
14+
15+
1. 官方说`vuex`是一个状态管理模式和库,并确保这些状态以可预期的方式变更。可见要实现一个`vuex`
16+
17+
- 要实现一个`Store`存储全局状态
18+
- 要提供修改状态所需API:`commit(type, payload)`, `dispatch(type, payload)`
19+
20+
2. 实现`Store`时,可以定义Store类,构造函数接收选项options,设置属性state对外暴露状态,提供commit和dispatch修改属性state。这里需要设置state为响应式对象,同时将Store定义为一个Vue插件。
21+
22+
3. `commit(type, payload)`方法中可以获取用户传入`mutations`并执行它,这样可以按用户提供的方法修改状态。 `dispatch(type, payload)`类似,但需要注意它可能是异步的,需要返回一个Promise给用户以处理异步结果。
23+
24+
25+
26+
27+
---
28+
29+
### 实践
30+
31+
Store的实现:
32+
33+
```js
34+
class Store {
35+
constructor(options) {
36+
this.state = reactive(options.state)
37+
this.options = options
38+
}
39+
commit(type, payload) {
40+
this.options.mutations[type].call(this, this.state, payload)
41+
}
42+
}
43+
```
44+
45+
46+
47+
### 知其所以然
48+
49+
Vuex中Store的实现:
50+
51+
https://github1s.com/vuejs/vuex/blob/HEAD/src/store.js#L19-L20

public/45-vuex-design/test.html

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script src="https://unpkg.com/vue@3"></script>
2+
<script>
3+
const { reactive } = Vue
4+
class Store {
5+
constructor(options) {
6+
this.state = reactive(options.state)
7+
this.options = options
8+
}
9+
commit(type, payload) {
10+
this.options.mutations[type].call(this, this.state, payload)
11+
}
12+
}
13+
14+
const store = new Store({
15+
state: {
16+
username: 'tom'
17+
},
18+
mutations: {
19+
SET_USERNAME(state, payload) {
20+
state.username = payload
21+
}
22+
}
23+
})
24+
console.log(store.state.username);
25+
store.commit('SET_USERNAME', 'jerry')
26+
console.log(store.state.username);
27+
</script>

public/46-mutations-actions/README.md

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
## vuex中actions和mutations有什么区别?
2+
3+
### 题目分析
4+
5+
`mutations``actions``vuex`带来的两个独特的概念。新手程序员容易混淆,所以面试官喜欢问。
6+
7+
我们只需记住修改状态只能是`mutations``actions`只能通过提交`mutation`修改状态即可。
8+
9+
---
10+
11+
### 体验
12+
13+
看下面例子可知,`Action` 类似于 `mutation`,不同在于:
14+
15+
- `Action` 提交的是 `mutation`,而不是直接变更状态。
16+
- `Action` 可以包含任意异步操作。
17+
18+
```js
19+
const store = createStore({
20+
state: {
21+
count: 0
22+
},
23+
mutations: {
24+
increment (state) {
25+
state.count++
26+
}
27+
},
28+
actions: {
29+
increment (context) {
30+
context.commit('increment')
31+
}
32+
}
33+
})
34+
```
35+
36+
---
37+
38+
### 答题思路
39+
40+
1. 给出两者概念说明区别
41+
2. 举例说明应用场景
42+
3. 使用细节不同
43+
4. 简单阐述实现上差异
44+
45+
---
46+
47+
### 回答范例
48+
49+
1. 官方文档说:更改 Vuex 的 store 中的状态的唯一方法是提交 `mutation``mutation` 非常类似于事件:每个 `mutation` 都有一个字符串的**类型 (type)\**和一个\**回调函数 (handler)**`Action` 类似于 `mutation`,不同在于:`Action`可以包含任意异步操作,但它不能修改状态, 需要提交`mutation`才能变更状态。
50+
2. 因此,开发时,包含异步操作或者复杂业务组合时使用action;需要直接修改状态则提交mutation。但由于dispatch和commit是两个API,容易引起混淆,实践中也会采用统一使用dispatch action的方式。
51+
3. 调用dispatch和commit两个API时几乎完全一样,但是定义两者时却不甚相同,mutation的回调函数接收参数是state对象。action则是与Store实例具有相同方法和属性的上下文context对象,因此一般会解构它为`{commit, dispatch, state}`,从而方便编码。另外dispatch会返回Promise实例便于处理内部异步结果。
52+
4. 实现上commit(type)方法相当于调用`options.mutations[type](state)``dispatch(type)`方法相当于调用`options.actions[type](store)`,这样就很容易理解两者使用上的不同了。
53+
54+
---
55+
56+
### 知其所以然
57+
58+
我们可以像下面这样简单实现`commit``dispatch`,从而辨别两者不同:
59+
60+
```js
61+
class Store {
62+
constructor(options) {
63+
this.state = reactive(options.state)
64+
this.options = options
65+
}
66+
commit(type, payload) {
67+
// 传入上下文和参数1都是state对象
68+
this.options.mutations[type].call(this.state, this.state, payload)
69+
}
70+
dispatch(type, payload) {
71+
// 传入上下文和参数1都是store本身
72+
this.options.actions[type].call(this, this, payload)
73+
}
74+
}
75+
```
76+
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
## 使用vue渲染大量数据时应该怎么优化?说下你的思路!
2+
### 分析
3+
4+
企业级项目中渲染大量数据的情况比较常见,因此这是一道非常好的综合实践题目。
5+
6+
### 思路
7+
8+
1. 描述大数据量带来的问题
9+
2. 分不同情况做不同处理
10+
3. 总结一下
11+
12+
### 回答
13+
14+
1. 在大型企业级项目中经常需要渲染大量数据,此时很容易出现卡顿的情况。比如大数据量的表格、树。
15+
2. 处理时要根据情况做不通处理:
16+
- 可以采取分页的方式获取,避免渲染大量数据
17+
- [vue-virtual-scroller](https://github.com/Akryum/vue-virtual-scroller)等虚拟滚动方案,只渲染视口范围内的数据
18+
- 如果不需要更新,可以使用`v-once`方式只渲染一次
19+
- 通过[v-memo](https://vuejs.org/api/built-in-directives.html#v-memo)可以缓存结果,结合`v-for`使用,避免数据变化时不必要的VNode创建
20+
- 可以采用懒加载方式,在用户需要的时候再加载数据,比如tree组件子树的懒加载
21+
3. 总之,还是要看具体需求,首先从设计上避免大数据获取和渲染;实在需要这样做可以采用虚表的方式优化渲染;最后优化更新,如果不需要更新可以v-once处理,需要更新可以v-memo进一步优化大数据更新性能。其他可以采用的是交互方式优化,无线滚动、懒加载等方案。

public/48-watch-vuex-state/README.md

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
## 41-怎么监听vuex数据的变化?
2+
3+
### 分析
4+
5+
vuex数据状态是响应式的,所以状态变视图跟着变,但是有时还是需要知道数据状态变了从而做一些事情。
6+
7+
既然状态都是响应式的,那自然可以`watch`,另外vuex也提供了订阅的API:`store.subscribe()`
8+
9+
---
10+
11+
### 思路
12+
13+
- 总述知道的方法
14+
15+
- 分别阐述用法
16+
17+
- 选择和场景
18+
19+
20+
21+
---
22+
23+
### 回答范例
24+
25+
- 我知道几种方法:
26+
27+
- 可以通过watch选项或者watch方法监听状态
28+
- 可以使用vuex提供的API:store.subscribe()
29+
30+
- watch选项方式,可以以字符串形式监听`$store.state.xx`;subscribe方式,可以调用store.subscribe(cb),回调函数接收mutation对象和state对象,这样可以进一步判断mutation.type是否是期待的那个,从而进一步做后续处理。
31+
32+
- watch方式简单好用,且能获取变化前后值,首选;subscribe方法会被所有commit行为触发,因此还需要判断mutation.type,用起来略繁琐,一般用于vuex插件中。
33+
34+
35+
36+
### 实践
37+
38+
watch方式
39+
40+
```js
41+
const app = createApp({
42+
watch: {
43+
'$store.state.counter'() {
44+
console.log('counter change!');
45+
}
46+
}
47+
})
48+
```
49+
50+
subscribe方式:
51+
52+
```js
53+
store.subscribe((mutation, state) => {
54+
if (mutation.type === 'add') {
55+
console.log('counter change in subscribe()!');
56+
}
57+
})
58+
```

public/48-watch-vuex-state/test.html

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<div id="app">{{$store.state.counter}}</div>
2+
3+
<script src="http://unpkg.com/vue@3"></script>
4+
<script src="http://unpkg.com/vuex@4"></script>
5+
<script>
6+
const { createApp } = Vue
7+
const { createStore } = Vuex
8+
const app = createApp({
9+
mounted() {
10+
setInterval(() => {
11+
this.$store.commit('add')
12+
}, 1000);
13+
},
14+
watch: {
15+
'$store.state.counter'() {
16+
console.log('counter change!');
17+
}
18+
}
19+
})
20+
const store = createStore({
21+
state: {
22+
counter: 1
23+
},
24+
mutations: {
25+
add(state) {
26+
state.counter++
27+
}
28+
}
29+
})
30+
store.subscribe((mutation, state) => {
31+
if (mutation.type === 'add') {
32+
console.log('counter change in subscribe()!');
33+
}
34+
})
35+
app.use(store).mount('#app')
36+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
## router-link和router-view是如何起作用的?
2+
3+
### 分析
4+
5+
vue-router中两个重要组件`router-link``router-view`,分别起到导航作用和内容渲染作用,但是回答如何生效还真有一定难度哪!
6+
7+
### 思路
8+
9+
- 两者作用
10+
- 阐述使用方式
11+
- 原理说明
12+
13+
### 回答范例
14+
15+
- vue-router中两个重要组件`router-link``router-view`,分别起到路由导航作用和组件内容渲染作用
16+
- 使用中router-link默认生成一个a标签,设置to属性定义跳转path。实际上也可以通过custom和插槽自定义最终的展现形式。router-view是要显示组件的占位组件,可以嵌套,对应路由配置的嵌套关系,配合name可以显示具名组件,起到更强的布局作用。
17+
- router-link组件内部根据custom属性判断如何渲染最终生成节点,内部提供导航方法navigate,用户点击之后实际调用的是该方法,此方法最终会修改响应式的路由变量,然后重新去routes匹配出数组结果,router-view则根据其所处深度deep在匹配数组结果中找到对应的路由并获取组件,最终将其渲染出来。
18+
19+
### 知其所以然
20+
21+
- RouterLink定义
22+
23+
https://github1s.com/vuejs/router/blob/HEAD/src/RouterLink.ts#L184-L185
24+
25+
- RouterView定义
26+
27+
https://github1s.com/vuejs/router/blob/HEAD/src/RouterView.ts#L43-L44

0 commit comments

Comments
 (0)