Vue
1. 什么是 MVVM
Model-View-ViewModel 模式
Model 层: 数据模型层
通过 Ajax
、fetch
等 API 完成客户端和服务端业务模型的同步。
View 层: 视图层
作为视图模板存在,其实View 就是⼀个动态模板。
ViewModel 层: 视图模型层
负责暴露数据给 View 层,并对 View 层中的数据绑定声明、 指令声明、 事件绑定声明, 进行实际的业务逻辑实现。
数据变化了, 视图自动更新 => ViewModel 底层会做好监听Object.defineProperty,当数据变化时,View 层会自动更新
视图变化了, 绑定的数据自动更新 => 会监听双向绑定的表单元素的变化,⼀旦变化,绑定的数据也会得到⾃动更新。
2. MVVM的优缺点有哪些?
优点
- 实现了视图(View)和模型(Model)的分离,降低代码耦合、提⾼视图或逻辑的复⽤性
- 提⾼了可测试性:ViewModel 的存在可以帮助开发者更好地编写测试代码
- 能⾃动更新 DOM:利⽤双向绑定,数据更新后视图⾃动更新,让开发者从繁琐的⼿动操作 DOM 中解放出来
缺点
- Bug 难被调试:因为使⽤了双向绑定的模式,当我们看到界⾯发生异常了,有可能是 View 的代码产生的 Bug,
也有可能是Model 代码的问题。数据绑定使得⼀个位置的 Bug 被快速传递到别的位置,
要定位原始出问题的地⽅就变得不那么容易了
可采用的调试方案:
(1) 注释掉一段代码, 确定代码的位置
(2) debugger 打断点 或者 console 进行调试 - 在⼀个⼤的模块中 Model 也会很⼤,虽然使⽤上来说⽅便了,但如果⻓期持有不释放内存,就会造成更多的内存消耗
占用的是 浏览器的 内存
3. 谈谈对Vue生命周期的理解?
生命周期的概念
每个 Vue 实例(每个组件也都是一个vue实例)都有⼀个完整的⽣命周期:
- 开始创建 (空实例)
- 初始化数据
- 编译模版
- 挂载 DOM
- 渲染、更新数据 => 重新渲染
- 卸载
这⼀系列过程我们称之为 Vue 的⽣命周期。
各个生命周期的作用
生命周期 | 执行时机 |
---|---|
beforeCreate | 在组件实例被创建之初、组件的属性⽣效之前被调用 |
created | 在组件实例已创建完毕。此时属性也已绑定,但真实DOM还未⽣成,$el 还不可⽤ |
beforeMount | 在组件挂载开始之前被调⽤。相关的 render 函数⾸次被调⽤ |
mounted | 在 el 被新建的 vm.$el 替换并挂载到实例上之后被调用 |
beforeUpdate | 在组件数据修改了, 视图更新之前调⽤。发⽣在虚拟 DOM 打补丁之前 |
updated | 在组件数据修改了, 视图更新之后被调用 |
activited | 在组件被激活时调⽤(使用了 <keep-alive> |
的情况下) | |
deactivated | 在组件被停用时调⽤(使用了 <keep-alive> |
的情况下) | |
beforeDestory | 在组件销毁前调⽤ (销毁: vue默认会进行释放掉实例所有的监听, 释放掉所有的组件…) |
destoryed | 在组件销毁后调⽤ (像定时器, webscoket连接, … 跟vue没有太大关联的资源, 需要手动释放!) |
生命周期示意图
4. 在Vue中网络请求应该放在哪个生命周期中发起?
至少在 created
之后, 因为数据才基本初始化完毕, 当然 mounted
中也可以 (比created稍晚一些)
5. Vue组件之间如何进行通信?
父传子, 子传父, 非父子, Vuex
5.1 props 和 $emit
(1) 通过 props
将数据在组件树中进行⾃上⽽下的传递;
<jack :money="count" :obj="myobj"></jack>
export default {
// props: ['money']
props: {
money: {
type: Number,
default: 1
},
obj: {
type: Object,
default: () => {
return {
name: 'zs',
age: 18
}
}
}
}
}
附件: props 验证
(2) 通过 $emit
和 @
来作信息的向上传递。
this.$emit('add-action', 参数1, 参数2, ...)
<jack @add-action="fatherFn"></jack>
5.2 eventBus事件总线
可通过 EventBus 进⾏信息的发布与订阅。 (创建一个都能访问到的事件总线)
Vue.prototype.$eventBus = new Vue() // this.$eventBus
// A组件中, 监听 bus的事件
this.$eventBus.$on('事件名', function(参数1, 参数2, ...) {
...
})
// B组件中, 触发 bus的事件
this.$eventBus.$emit('事件名', 参数1, 参数2, ...)
5.3 $children $parent $refs
(1) $children
父组件中, $children 返回的是一个组件集合,如果你能清楚的知道子组件的顺序,你也可以使用下标来操作
// 父组件中
<template>
<div class="hello_world">
<com-a></com-a>
<com-b></com-b>
</div>
</template>
this.$children[0] => <com-a></com-a>
this.$children[1] => <com-b></com-b>
(2) $parent
子组件中, this.$parent 指向父组件
this.$parent.xxx = 200
this.$parent.fn()
(3) $refs
通过添加 ref 和 $refs 配合, 也可以很方便的获取子组件, 访问调用子组件的属性或方法
// 父组件中
<template>
<div class="hello_world">
<com-a ref="coma"></com-a> // this.$refs.coma.count = 200
<com-b ref="comb">