简述MVVM
MVVM是Model-View-ViewModel的缩写。MVVM是一种设计思想。Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
Vue.js的优点
- 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
- 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
- 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
- 可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写
- 易用灵活高效
Vue基础知识点
1. 实例生命周期钩子
- created: 实例出现在内存中(在实例被创建后被调用)
- mounted: 实例出现在页面中(当编译好的HTML被挂载到对应的位置,这个操作完成后触发)
- updated: 实例更新了(当data中的数据改变,并且虚拟DOM重新渲染完成后触发)
- destroyed: 实例从页面和内存中消亡了 2. computed 和 watch 的区别
- computed 是指计算属性, watch 是侦听的意思。
- 可以使用计算属性来处理任何复杂逻辑,它可以用来计算出一个值。调用时不需要加括号,且计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
- watch 用来侦听。当数据发生变化时,执行一个函数,watch 允许执行异步操作。它有两个选项: immediate 来选择是否在第一次渲染的时候执行这个函数; deep 则是在监听一个对象的时候, 选择是否监听对象里面属性的变化。 这就是 computed 和 watch 的区别。
3. v-if vs v-show
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
4. Vue的双向绑定 - v-model
官网教程:表单输入绑定
v-model 实际是 v-bind:value 和 v-on:input 的语法糖。
v-on:input="xxx = $event.targent.value"
5. 对组件的理解
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用 is 特性进行了扩展的原生 HTML 元素。所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。
6. 组件间的数据传递
- 父组件给子组件传递数据:通过props
<div id="app">
<child-component msg="这是来自父组件的内容"></child-component>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {},
components: {
"child-component": {
props: ["msg"],
template: "<div>{{msg}}</div>",
},
},
});
</script>
- 子组件给父组件传递数据:给组件绑定自定义事件(用v-on来监听子组件触发的事件)
<div id="app">
<p>您现在的银行卡余额是:{{total}}</p>
<child-component @change="handleTotal"></child-component>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
total: 1000,
},
components: {
"child-component": {
template:
"<div><button @click='add'>+100</button><button @click='sub'>-100</button></div>",
data: function () {
return {
money: 1000,
};
},
methods: {
add: function () {
this.money = this.money + 100;
this.$emit("change", this.money);
},
sub: function () {
this.money = this.money - 100;
this.$emit("change", this.money);
},
},
},
},
methods: {
handleTotal: function (value) {
this.total = value;
},
},
});
</script>
3. 非父子组件通信
- 简单的场景---采用空实例作为中央事件总线,原理就是找一个人来当作一个中转站!
- 复杂的场景---专门的状态管理模式vuex
<div id="app">
<child-component1></child-component1>
<hr />
<child-component2></child-component2>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
bus: new Vue(),
},
components: {
"child-component1": {
template:
"<div>子组件1<button @click='trans'>点击向组件2发送数据</button></div>",
data: function () {
return {
aaa: "我是来自组件1的内容",
};
},
methods: {
trans: function () {
this.$root.bus.$emit("hello", this.aaa);
},
},
},
"child-component2": {
template: "<div>子组件2</div>",
data: function () {
return {};
},
created: function () {
this.$root.bus.$on("hello", function (value) {
alert(value);
});
},
},
},
});
</script>