对mvc、mvvm、mvp的理解
mvc
Models: 数据层,负责数据的请求和存储以及处理
View: 展示层,负责View和动画效果的展示,以及用户的交互
Controller: 控制器层,负则连接View和Model,对view的交互事件有controller层处理传递给model,model处理再交互传递给Controller,Controller传递给view
M和View应该是完全隔离的,由C作为中间人来负责二者的交互,同时三者是完全独立分开的,这样可以保证M和V的可测试性和复用性,但是一般由于C都是为特别的应用场景下的M和V做中介者,所以很难复用。
优点
增强代码复用性耦合性低: V对外只暴露Set方法,对M甚至C都是个例状态,复用没问题
解决代码臃肿: 布局转移到了View层,业务逻辑转移到了Model层
易拓展:无论产品想增加或者模块,只需增加响应的MVC模块
可维护:各个模块相互隔离,哪里出错改哪里,不影响其他模块。
缺点
简单的小型项目,使用MVC设计反而会降低开发效率层和层虽然相互分离,但是之间关联性太强,没有做到独立的重用。
对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率
视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
mvvm
MVVM其实是在MVP的基础上发展起来的。那么MVVM在MVP的基础上改良了啥呢?答案就是数据绑定。从 Model-View-ViewModel 这个名字来看,它由三个部分组成,也就是 Model、View 和 ViewModel;其中视图模型(ViewModel)其实就是 MVP 模式中的P,在 MVVM 中叫做VM。
除了我们非常熟悉的 Model、View 和 ViewModel 这三个部分,在 MVVM 的实现中,还引入了隐式的一个 Binder层,这也是MVVM相对MVP的进步,而声明式的数据和命令的绑定在 MVVM 模式中就是通过binder层来完成的,RAC是iOS下binder的优雅实现,当然MVVM没有RAC也完全可以运行。
缺点
View和Viewmodel因为双向绑定所以没有复用性。
mvp
VC层:
生成的View添加到self.view上面
管理View的声明周期
通过P层去获取数据然后渲染到View上面展示。
Controller层:
生成view,实现view的代理和数据源
绑定view和presenter
调用presenter执行业务逻辑
负责界面跳转
View层:
监听P层数据更新通知,刷新页面展示
点击事件触发时调用P层响应的方法
界面元素搭建,动画展示
接受用户操作并提供反馈
Model层:
与MVC的model层一样
Persneter层:
实现view的事件处理逻辑,暴露相应的接口给view的事件调用
调用model的接口获取数据,然后加工数据,封装成view可以直接用来显示的数据和状态
这里又有两种不同的实现方式:
让P持有V,P通过V的暴露接口改变V的显示数据和状态,P通过V的事件回调来执行自身的业务逻辑
让V持有P,V通过P的代理回调来改变自身的显示数据和状态,V直接调用P的接口来执行事件响应对应的业务逻辑
第一种方式保持了view的纯粹,只是作为被动view来展示数据和更改状态,但是却导致了P耦合了V,这样业务逻辑和业务展示有糅合到了一起,和上面的MVC一样了。
第二种方式保证了P的纯粹,让P只做业务逻辑,至于业务逻辑引发的数据显示的变化,让view实现对应的代理事件来实现即可。这增加了view的复杂和view对于P的耦合。
MVP相对于MVC, 它其实只做了一件事情, 即分割业务展示和业务逻辑. 展示和逻辑分开后, 只要我们能保证V在收到P的数据更新通知后能正常刷新页面, 那么整个业务就没有问题. 因为V收到的通知其实都是来自于P层的数据获取/更新操作, 所以我们只要保证P层的这些操作都是正常的就可以了. 即我们只用测试P层的逻辑, 不必关心V层的情况
对$nexttick的理解及使用场景
vue是依靠数据驱动视图更新的,该更新的过程是异步的。即:当侦听到你的数据发生变化时, Vue将开启一个队列(该队列被Vue官方称为异步更新队列)。视图需要等队列中所有数据变化完成之后,再统一进行更新。
Vue 实现的响应式并不是数据发生变化之后视图立即变化。
我们可以通过$nextTick() 获取到更新之后的DOM。
因为 $nextTick() 返回一个 Promise 对象,所以我们也可以使用async/await语法完成相同的事情
应用场景
1、如果要在created()钩子函数中进行的DOM操作,由于created()钩子函数中还未对DOM进行任何渲染,所以无法直接操作,需要通过$nextTick()来完成。
2、更新数据后,想要使用js对新的视图进行操作时。
3、在使用某些第三方插件时 ,这些插件需要dom动态变化后重新应用该插件,这时候就需要使用$nextTick()来重新应用插件的方法。
对渐进式框架的理解
渐进式框架的大概意思就是你可以只用我的一部分,而不是用了我这一点就必须用我的所有部分。
Vue的核心的功能,是一个视图模板引擎,但这不是说Vue就不能成为一个框架。我们可以通过添加组件系统、客户端路由、大规模状态管理来构建一个完整的框架。更重要的是,这些功能相互独立,你可以在核心功能的基础上任意选用其他的部件,不一定要全部整合在一起。可以看到,所说的“渐进式”,其实就是Vue的使用方式,同时也体现了Vue的设计的理念
渐进式代表的含义是:主张最少。
每个框架都不可避免会有自己的一些特点,从而会对使用者有一定的要求,这些要求就是主张,主张有强有弱,它的强势程度会影响在业务开发中的使用方式。
比如说,Angular,它两个版本都是强主张的,如果你用它,必须接受以下东西:
- 必须使用它的模块机制- 必须使用它的依赖注入- 必须使用它的特殊形式定义组件(这一点每个视图框架都有,难以避免)
所以Angular是带有比较强的排它性的,如果你的应用不是从头开始,而是要不断考虑是否跟其他东西集成,这些主张会带来一些困扰。
比如React,它也有一定程度的主张,它的主张主要是函数式编程的理念,比如说,你需要知道什么是副作用,什么是纯函数,如何隔离副作用。它的侵入性看似没有Angular那么强,主要因为它是软性侵入。
Vue可能有些方面是不如React,不如Angular,但它是渐进的,没有强主张,你可以在原有大系统的上面,把一两个组件改用它实现,当jQuery用;也可以整个用它全家桶开发,当Angular用;还可以用它的视图,搭配你自己设计的整个下层用。你可以在底层数据逻辑的地方用OO和设计模式的那套理念,也可以函数式,都可以,它只是个轻量视图而已,只做了自己该做的事,没有做不该做的事,仅此而已。
渐进式的含义,我的理解是:没有多做职责之外的事。
组件样式属性scoped问题及解决方法
在父组件中无法修改子组件样式问题
一、混合使用全局属性和局部属性
二、关于子组件的根元素
使用了scoped属性之后,父组件的style样式将不会渗透到子组件中,然而子组件的根节点元素会同时被设置了scoped的父css样式和设置了scoped的子css样式影响,这么设计的目的是父组件可以对子组件根元素进行布局。
.vue模板中的样式是根据需要按需加载,访问一个页面该组件中的样式就会追加到head标签中,如果父子组件中都对某个子组件根节点元素进行了控制,则父组件里的样式会被后来的覆盖。
三、深选择器
如果想对设置了scoped的子组件里的元素进行控制可以使用 ’>>>’ 或者 ’deep’
四、动态生成的内容
使用v-html动态创建的DOM内容,不受设置scoped的样式影响,但你依然可以使用深选择器进行控制