1.对MVC 、MVVM、MVP的理解
答:
1. MVC
M 表示 Model , 专门用来处理数据模型。
V 表示View, 专注页面布局和数据显示。
C 表示Controller 专注于控制,执行业务逻辑,操作模型和视图。
MVC的数据之间通信都是单向的
View(视图层) 传送指令到 Controller(控制层)
Controller(控制层) 完成业务逻辑后,要求 Model(模型层) 改变状态
Model(模型层) 将新的数据发送到 View(视图层),用户得到反馈
在MVC中,虽然View与Model之间的耦合度非常小,只需要Model修改的时候通知View发生改变即可,但是它们之间还有有很重要的联系,于是,就有了MVP
(2)MVP
M 表示 Model,专门用来处理数据模型
V 表示View,专门用来处理用户视图
P 表示Presenter,用来处理业务逻辑,在MVC的基础上,修改了通信方向
MVP中,View和Model之间没有任何通信关系,所有的通信和业务逻辑都放在Presenter层中
View(视图层) 发送指令到 Presenter层,
Presenter层 处理业务逻辑,要求 Model(模型层) 改变状态
Model(模型层) 修改状态之后,发送指令到 Presenter层
Presenter层通知View(视图层)做出改变
在MVP中,所有的通信都是双向的,View和Model不会直接发生通信,都通过Presenter层进行传递
在MVP中,所有的业务逻辑都写在Presenter层中,会导致Presenter层过于臃肿
在MVP中,View只负责显示视图,不包含任何业务逻辑,导致View层过薄,不具备任何主动性
由于在MVP模式中,所有的业务逻辑都放在Presenter层中,必须通过Presenter层来修改View层的界面,所以出现了MVVM
3.MVVM
M表示 Model,专门用来处理数据模型
V表示View,专门用来处理用户视图
VM表示ViewModel,用来使的View视图层与Model层双向绑定,View的任何变动都会通知ViewModel,而Model的任何变动,也都会通知ViewModel,而不论哪一项发生改变,都会使对应的视图/数据模型同步发生改变
在MVVM中,与MVP一样,所有的通信都是双向的,数据与视图不直接发生依赖,全部通过VM层来进行双向绑定
所有的业务逻辑都由VM来进行处理,但是在View层和Model层修改都会通过VM来双向的绑定修改
2.详述Vuex工作流程
答: 首先通过dispatch提交一个action
在action中我们可以执行一些异步的操作,或者根据不同的情况分发不同的mutation
接着在action中调用commit,触发一个mutation
所有修改state的操作,全部应该放在mutation中来做
而state更新之后,会调用Vue的底层方法,通知视图进行更新渲染
3.谈谈对对$nextTick的理解及使用场景
答:
如果要在created()钩子函数中进行的DOM操作,由于created()钩子函数中还未对DOM进行任何渲染,所以无法直接操作,需要通过$nextTick()来完成。在created()钩子函数中进行的DOM操作,不使用$nextTick()会报错
更新数据后,想要使用js对新的视图进行操作时
在使用某些第三方插件时 ,这些插件需要dom动态变化后重新应用该插件,这3时候就需要使用$nextTick()来重新应用插件的方法
nextTick原理
1、异步说明
nextTick的使用场景
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新
2、事件循环说明
简单来说,Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
created、mounted
在 created 和 mounted 阶段,如果需要操作渲染后的试图,也要使用 nextTick 方法。
注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
以下使用nexttick的三种情况
(1) 点击按钮显示原本以 v-show = false 隐藏起来的输入框,并获取焦点。
showsou(){
this.showit = true //修改 v-show
document.getElementById("keywords").focus() //在第一个 tick 里,获取不到输入框,自然也获取不到焦点
}
修改为:
showsou(){
this.showit = true
this.$nextTick(function () {
// DOM 更新了
document.getElementById("keywords").focus()
})
}
(2.)点击获取元素宽度。
{{ message }}
getMyWidth() {
this.showMe = true;
//this.message = this.$refs.myWidth.offsetWidth;
//报错 TypeError: this.$refs.myWidth is undefined
this.$nextTick(()=>{
//dom元素更新后执行,此时能拿到p元素的属性
this.message = this.$refs.myWidth.offsetWidth;
})
}
(3.)使用 swiper 插件通过 ajax 请求图片后的滑动问题。
应用场景
需要在视图更新之后,基于新的视图进行操作
1、如果要在created()钩子函数中进行的DOM操作,由于created()钩子函数中还未对DOM进行任何渲染,所以无法直接操作,需要通过$nextTick()来完成。
created(){
this.$nextTick(()=>{
this.$refs.myP.innerText = "我是一只小小小小鸟,想要飞,却怎么样也飞不高!";
});
}
注:在created()钩子函数中进行的DOM操作,不使用$nextTick()会报错:
// Error in created hook: "TypeError: Cannot set property 'innerText' of undefined"
created(){
this.$refs.myP.innerText = "我是一只小小小小鸟,想要飞,却怎么样也飞不高!";
}
2、更新数据后,想要使用js对新的视图进行操作时。
3、在使用某些第三方插件时 ,这些插件需要dom动态变化后重新应用该插件,这时候就需要使用$nextTick()来重新应用插件的方法。
4.渐进式框架的理解
答:对于渐进式框架来说,主要就代表着它的主张性最小,没有多做职责之外的事。
什么是主张性?
在你使用一个框架的时候,如果你使用了它的一部分,你就必须使用它的全部,或是很大一部分东西,这个就叫强主张
而说Vue的主张性最小,是因为你可以只使用它的一部分东西,它可以很容易的集成到你原有的项目中去,甚至说你只是用它来改造一下一些公共的组件,你可以在传统的html页面中使用它,也可以使用脚手架工具来搭建一个大型的项目
在学习方面,Vue的学习代价也不是很大,你可以非常容易的上手,我们没有必要一上来就搞明白Vue的所有功能,可以先从核心功能扩展,然后在逐步学习,当你需要的时候,你再去使用它的其他功能,并且你可以非常容易的使用Vue结合其他的框架来进行搭配
5.组件样式属性 scoped 问题及解决方法
答:在Vue组件中,为了使样式私有化(模块化),不对全局造成污染,可以在style标签上添加scoped属性以表示它的只属于当下的模块,局部有效。
Vue中的scoped属性的效果主要通过PostCSS转译实现,给所有的样式动态的生成一个属性,然后通过在编译后使用属性选择器加原有选择器的方式来设置样式,这样就不会对其它组件造成影响,当前组件的样式只对当前组件生效
然而,我们在使用scoped的时候,经常会遇到样式问题,比如说
要在父组件中修改子组件的布局样式等
要修改v-html渲染出的内容的样式时
使用一些UI框架时,修改样式的问题
对于这些问题的解决方案:
1.同时使用scoped局部样式和全局样式
/*全局样式*/
/*局部样式*/
2. 子组件的根节点元素会同时被设置了scoped的父css样式和设置了scoped的子css样式影响,这么设计的目的是父组件可以对子组件根元素进行布局。
3. 使用深选择器,>>>或者/deep/进行样式穿透
在Vue中,可以使用>>>或者/deep/来进行样式穿透,达到修改样式的功能
在sass或者less这种预编译器中,不支持>>>,可以使用/deep/
.el-form >>> .el-input {
// 修改样式
}
.el-form /deep/ .el-input {
// 修改样式
}
建议使用第三种方法,这样既不会对全局样式造成污染,也可以达到修改样式的功能