File tree 8 files changed +301
-0
lines changed
49-router-link-router-view
8 files changed +301
-0
lines changed Original file line number Diff line number Diff line change 54
54
42 . [ Vue实例挂载的过程中发生了什么?] ( public/42-instance-mount/README.md )
55
55
43 . [ vue-loader是什么?它有什么作用?] ( public/43-vue-loader/README.md )
56
56
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 )
57
62
58
63
### 欢迎把你想听的题目以issue的方式提给我
59
64
### 欢迎你加入村长的项目已pr形式提交题目和解答
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 >
Original file line number Diff line number Diff line change
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
+
Original file line number Diff line number Diff line change
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进一步优化大数据更新性能。其他可以采用的是交互方式优化,无线滚动、懒加载等方案。
Original file line number Diff line number Diff line change
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
+ ```
Original file line number Diff line number Diff line change
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 number Diff line number Diff line change
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
You can’t perform that action at this time.
0 commit comments