前端面试题总结04
前端面试总结04
一、介绍mvvm模式以及它的优势
MVVM模式主要包含一下三个组件:
- Model(模型):模型代表应用程序的数据和业务逻辑。它负责处理数据的存储,检索和修改,以及应用程序的业务逻辑。
- View(视图):视图是用户界面的呈现层。负责展示数据给用户并与用户交互。视图通常是由数据绑定到视图元素上的模板组成。
- ViewModel(视图模型):视图模型是连接模型和视图的桥梁,负责处理视图的展示逻辑和用户交互,并与模型进行交互。视图模型包含视图所有的数据和方法,它通过双向数据绑定将视图和模型连接起来。
MVVM模式的优势:
- 分离关注点。MVVM模式将用户界面的展示逻辑从业务逻辑和数据处理逻辑中分离出来,使得代码更加模块化和易于维护。
- 双向数据绑定:MVVM模式通过双向数据绑定机制实现视图和模型之间的自动同步,当模型数据发生变化时,视图自动更新;反之,用户在视图上的操作也会直接影响模型数据。
- 可测试性:由于MVVM模式将视图和业务逻辑分离得很清晰,因此可以更容易地编写单元测试来测试视图模型的逻辑,而不需要依赖于用户界面。
- 代码复用:MVVM模式鼓励将视图模型和数据逻辑分开,这样可以更好地复用视图模型,使得在不同的视图中共享相同的逻辑变得更加容易。
- 增强开发效益:MVVM模式使得前端开发更叫高效,开发人员可以专注于不同层面的工作,提高团队协作效率。
二、双向数据绑定是如何实现的
双向绑定是MVVM模式的一个重要的特性,它实现了视图和视图模型之间的数据同步。当一个地方的数据发生改变时,另一个地方的数据也会随之更新。
实现方式:
- 数据劫持:Vue中使用数据劫持方法实现双向数据绑定。当创建Vue实例时,Vue会遍历data选项中的属性,使用Object.defineProperty()方法将这些属性转为getter和setter,从而在数据发生变化时能够通知到订阅者。
- 脏检查(Angular):在Angular中使用脏检查机制来实现双向数据绑定。在Angular中,会创建一个脏检查机制,定期检查数据模型和视图之间的变化。如果数据模式发生变化,Angular会更新视图,反之亦然。
- 事件监听(原生):在JavaScript中通过事件监听来实现简单的数据双向绑定。例如,可以通过监听输入框的input事件来实时更新数据模型,同时也可以在数据模型发生变化时更新视图。
- Angular的双向数据绑定指令:Angular中提供了一些指令来实现双向数据绑定,这些指令会自动处理数据模型和视图之间的同步,简化开发过程。
三、动态路由如何实现
动态路由是根据特定的参数或条件来动态地加载不同的页面或组件。
在React中,可以通过React Router来实现动态路由。
示例:
-
下载依赖
npm install react-router-dom
-
在主组件中设置路由:
1 |
|
- 创建一个对应的User.jsx组件,展示自定义信息。
1 |
|
- 在其他组件中,也可以通过动态链接来访问User组件。
1 |
|
在Vue中,可以使用Vue Router来实现动态路由。
示例:
-
下载依赖
npm install vue-router
-
在router/index.js中设置路由
1 |
|
- 创建User.vue来显示自定义内容。
1 |
|
- 在其他组件中,也可以使用
来生成动态链接,同理于React。
1 |
|
四、vue中如何深度监听数组
以下方法可以监听数组的变化并触发重新渲染:
- 使用Vue.set方法
1 |
|
- 使用Object.assign方法
1 |
|
- 使用splice方法
1 |
|
五、路由传参方式以及如何获取参数
在Vue中有三种路由传参的方法,分别为params传参和query传参,其中params传参又分为显示参数和不显示参数两种。
- params传参(显示参数)
1 |
|
- params传参(不显示参数)
params传参不显示参数与显示参数不同的是,此时需要路由的别名name
进行传值。(不显示参数的方式会导致在刷新页面的时候,传递的值会丢失)
1 |
|
- query传参
1 |
|
React中路由传参的方式有:
- params传参:useParams()
1 |
|
- search传参:useSearchParams()
1 |
|
- state传参:useLocation()
1 |
|
六、介绍Vuex
Vuex是Vue的状态管理模式。
主要概念:
-
State状态:
Vuex中的State类似于组件中的data,所有组件都共享这些数据,并且可以通过
this.$store.state
进行访问。 -
Getter获取器:
类似于组件中的计算属性,组件可以通过
this.$store.getters
来访问这些状态。 -
Mutations突变:
Mutations是用来修改state的唯一方式,且它必须是同步函数,通过提交一个mutation来改变状态,可以通过
this.$store.commit
来调用。 -
Actions动作:
actions
用于处理异步操作,通过提交mutation来改变状态。通过this.$store.dispatch
来调用。 -
Modules模块:
modules
可以将store分隔成模块,一般在store状态过多时使用。每个模块都有自己的state,getters,mutations,actions。
一个简单的store写法为:
1 |
|
七、vuex中actions可以直接修改state中的数据吗?
严格来说,actions
不应该直接修改state
中的数据。actions
主要用于处理异步操作,触发mutations
来改变state的值。
这样做的好处是:
- 可追踪性质:通过提交mutations来修改state,可以更加清晰地追踪数据的变化,了解数据是如何被修改的。
- 数据流的明确性:严格遵守数据流的规则:actions复杂处理异步操作和业务逻辑,而mutations复杂修改state,各司其职。
- 易于调试:将修改state的逻辑集中在mutations中,可以使得代码逻辑更加清晰,易于调试和理解代码。
八、组件之间的通信方式
Vue中组件的通信方式有:
-
Props和Events:
父组件可以通过props属性向子组件传递数据
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<!--父组件-->
<template>
<ChildComponent :message='parentMessage'></ChildComponent>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default{
data(){
return {
parentMessage:'这是父组件传给子组件的数据'
}
},
components:{
ChildComponent
}
}
</script>
<!--子组件-->
<template>
<div>
{{messgae}}
</div>
</template>
<script>
export default {
props:['message']
}
</script>子组件可以通过event事件触发来通知父组件
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<!--子组件-->
<template>
<div>
<button @click='sendMessageToParent'>
向父组件发送事件
</button>
</div>
</template>
<script>
export default {
methods:{
sendMessageToParent(){
this.$emit('message-to-parent','这是子组件向父组件传递的数据');
}
}
}
</script>
<!--父组件-->
<!--接收数据-->
<template>
<ChildComponent @message-to-parent='handleMessageFromChild'></ChildComponent>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default{
components:{
ChildComponent
},
methods:{
handleMessageFromChild(message){
console.log("获取到子组件传递来的数据",message);
}
}
}
</script> -
Vuex:
使用Vuex进行全局的状态管理,实现组件之间的通信。
1
2
3
4
5
6
7
8
9
10
11
12
13
14// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state:{
message:"一个全局数据",
},
mutations:{
changeMessage(state,newMessage){
state.message=newMessage;
}
}
});1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<!--在组件中使用store中的数据-->
<template>
<div>
{{message}}
</div>
</template>
<script>
export default {
computed:{
message(){
//获取Vuex中的数据
return this.$store.state.message;
}
}
}
</script> -
Event Bus:
事件总线实现组件之间的通信,相当于在组件之间架起了一个桥梁。
1
2
3// EventBus.js
import Vue from 'vue';
export const EventBus=new Vue();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<!--在组件中使用事件总线发送数据-->
<template>
<button @click='sendMessage'>
发送数据
</button>
</template>
<script>
import {EventBus} from './EventBus.js';
export default {
methods:{
sendMessage(){
EventBus.$emit('message-to-other','发送一条数据');
}
}
}
</script>
<!--在组件中使用事件总线接收数据-->
<template>
<div>
{{message}}
</div>
</template>
<script>
import {EventBus} from './EventBus.js';
export default {
data(){
return {
massage:""
}
}
created(){
EventBus.$on('message-to-other',message=>{
this.message=message;
})
}
}
</script>